/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ package org.opensourcephysics.frames; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.util.ArrayList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.event.MouseInputAdapter; import org.opensourcephysics.display.DisplayRes; import org.opensourcephysics.display.Drawable; import org.opensourcephysics.display.DrawingFrame; import org.opensourcephysics.display.InteractivePanel; import org.opensourcephysics.display.PlottingPanel; import org.opensourcephysics.display2d.ByteRaster; /** * A DrawingFrame that displays data using a ByteRaster. * * @author W. Christian * @version 1.0 */ public class RasterFrame extends DrawingFrame { protected ByteRaster raster = new ByteRaster(1, 1); MouseInputAdapter mouseAdapter; int[] editValues = new int[2]; int dragV; Color[] customColors; /** * Constructs a RasterFrame with the given axes labels and frame title. * @param xlabel String * @param ylabel String * @param frameTitle String */ public RasterFrame(String xlabel, String ylabel, String frameTitle) { super(new PlottingPanel(xlabel, ylabel, null)); setTitle(frameTitle); ((PlottingPanel) drawingPanel).getAxes().setShowMajorXGrid(false); ((PlottingPanel) drawingPanel).getAxes().setShowMajorYGrid(false); addMenuItems(); drawingPanel.addDrawable(raster); setAnimated(true); setAutoclear(true); } /** * Constructs a RasterFrame with the given frame title but without axes. * @param frameTitle String */ public RasterFrame(String frameTitle) { super(new InteractivePanel()); setTitle(frameTitle); addMenuItems(); drawingPanel.addDrawable(raster); setAnimated(true); setAutoclear(true); } /** * Adds Views menu items on the menu bar. */ protected void addMenuItems() { JMenuBar menuBar = getJMenuBar(); if(menuBar==null) { return; } JMenu helpMenu = this.removeMenu(DisplayRes.getString("DrawingFrame.Help_menu_item")); //$NON-NLS-1$ JMenu menu = getMenu(DisplayRes.getString("DrawingFrame.Views_menu")); //$NON-NLS-1$ if(menu==null) { menu = new JMenu(DisplayRes.getString("DrawingFrame.Views_menu")); //$NON-NLS-1$ menuBar.add(menu); menuBar.validate(); } else { // add a separator if tools already exists menu.addSeparator(); } if(helpMenu!=null) { menuBar.add(helpMenu); } // add a menu item to show the data table JMenuItem menuItem = new JMenuItem(DisplayRes.getString("RasterFrame.MenuItem.Color")); //$NON-NLS-1$ ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { setColorPalette(); } }; menuItem.addActionListener(actionListener); menu.add(menuItem); // add a menu item to show the data table menuItem = new JMenuItem(DisplayRes.getString("RasterFrame.MenuItem.B&W")); //$NON-NLS-1$ actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { setBWPalette(); } }; menuItem.addActionListener(actionListener); menu.add(menuItem); } /** * Sets black and white palette. */ public void setBWPalette() { raster.setBWPalette(); repaint(); } public void setColorPalette() { if(customColors==null) { raster.createDefaultColors(); } else { raster.setColorPalette(customColors); } repaint(); } public void showLegend() { raster.showLegend(); } /** * Sets the color palette. * * @param colors */ public void setColorPalette(Color[] colors) { customColors = colors; raster.setColorPalette(colors); repaint(); } /** * Clears drawable objects added by the user from this frame. */ public void clearDrawables() { drawingPanel.clear(); // removes all drawables drawingPanel.addDrawable(raster); } /** * Gets Drawable objects added by the user to this frame. * * @return the list */ public synchronized ArrayList<Drawable> getDrawables() { ArrayList<Drawable> list = super.getDrawables(); list.remove(raster); return list; } /** * Gets Drawable objects added by the user of an assignable type. The list contains * objects that are assignable from the class or interface. * * @param c the type of Drawable object * * @return the cloned list * * @see #getObjectOfClass(Class c) */ public synchronized <T extends Drawable> ArrayList<T> getDrawables(Class<T> c) { ArrayList<T> list = super.getDrawables(c); list.remove(raster); return list; } /** * Clears the lattice data by setting all values to zero. */ public void clearData() { raster.setBlock(0, 0, new byte[raster.getNx()][raster.getNy()]); drawingPanel.invalidateImage(); } /** * Randomizes the lattice values. */ public void randomize() { raster.randomize(); } /** * Resizes the number of columns and rows in the raster and centers the raster. * * @param nx int * @param ny int */ private void resizeRaster(int nx, int ny) { drawingPanel.setPreferredSize(new java.awt.Dimension(Math.max(nx+drawingPanel.getLeftGutter()+drawingPanel.getRightGutter(), 50), Math.max(ny+drawingPanel.getTopGutter()+drawingPanel.getBottomGutter(), 50))); pack(); raster.resizeLattice(nx, ny); drawingPanel.invalidateImage(); drawingPanel.repaint(); } /** * Sets the color for a single index. * @param index * @param color */ public void setIndexedColor(int index, Color color) { raster.setIndexedColor(index, color); } /** * Sets the raster's values and scale. * * @param val int[][] the new values * @param xmin double * @param xmax double * @param ymin double * @param ymax double */ public void setAll(byte val[][], double xmin, double xmax, double ymin, double ymax) { setAll(val); raster.setMinMax(xmin, xmax, ymin, ymax); } /** * Sets the raster's values using byte values. * * @param val */ public void setAll(byte val[][]) { if((val.length!=raster.getNx())||(val[0].length!=raster.getNy())) { this.resizeRaster(val.length, val[0].length); } raster.setBlock(0, 0, val); } /** * Sets the raster's values using integer values. * * @param val */ public void setAll(int val[][]) { if((val.length!=raster.getNx())||(val[0].length!=raster.getNy())) { resizeRaster(val.length, val[0].length); } raster.setBlock(0, 0, val); } /** * Sets the raster's values and scale. * * @param val int[][] the new values * @param xmin double * @param xmax double * @param ymin double * @param ymax double */ public void setAll(int val[][], double xmin, double xmax, double ymin, double ymax) { setAll(val); raster.setMinMax(xmin, xmax, ymin, ymax); } /** * Sets the raster's values and scale. * * @param val int[] the new values * @param nx * @param xmin double * @param xmax double * @param ymin double * @param ymax double */ public void setAll(int val[], int nx, double xmin, double xmax, double ymin, double ymax) { if(val.length%nx!=0) { throw new IllegalArgumentException("Raster dimension must match number of values."); //$NON-NLS-1$ } resizeRaster(nx, val.length/nx); setAll(val); raster.setMinMax(xmin, xmax, ymin, ymax); } /** * Sets an array v of int values into the raster, starting at (x=0,y=0). * Values are in row-major format such that the index corresponds to iy*ny+ix. * * @param v */ public void setAll(int[] v) { if(v.length!=raster.getNx()*raster.getNy()) { throw new IllegalArgumentException("Raster size must be set before using row-major format."); //$NON-NLS-1$ } for(int i = 0; i<v.length; i++) { setAtIndex(i, v[i]); } } /** * Sets the ith indexed pixel to value v * Values are in row-major format such that the index corresponds to iy*ny+ix. * * @param i * @param v */ public void setAtIndex(int i, int v) { int nx = raster.getNx(); setValue(i%nx, i/nx, v); } /** * Sets the (ix,iy) cell or the site of the raster to store value v * * @param ix * @param iy * @param v */ public void setValue(int ix, int iy, int v) { raster.setValue(ix, iy, (byte) v); } /** * Gets the ith indexed pixel of the raster * Values are in row-major format such that the index corresponds to iy*ny+ix. * * @param i * @return value indexed by i */ public int getAtIndex(int i) { int Nx = raster.getNx(); return get(i%Nx, i/Nx); } /** * Gets the (x,y) pixel of the raster * * @param ix * @param iy * @return value at (ix,iy) */ public int get(int ix, int iy) { return(raster.getValue(ix, iy)+128); } /** * Gets the entire raster contents in an int array * Values are in row-major format such that the index corresponds to iy*ny+ix. * * @return array containing entire lattice contents */ public int[] getAll() { int N = raster.getNx()*raster.getNy(); int[] ret = new int[N]; for(int i = 0; i<N; i++) { ret[i] = getAtIndex(i); } return ret; } /** * Sets an action to toggle the grid betweem the given values when the mouse is pressed. * @param enable boolean * @param v1 int * @param v2 int */ public void setToggleOnClick(boolean enable, int v1, int v2) { editValues = new int[] {v1, v2}; if(enable) { drawingPanel.addMouseListener(getMouseAdapter()); drawingPanel.addMouseMotionListener(getMouseAdapter()); } else { drawingPanel.removeMouseListener(getMouseAdapter()); drawingPanel.removeMouseMotionListener(getMouseAdapter()); } } void mouse(MouseEvent e, boolean pressed) { // button three is used for popup menu if(e.getButton()==MouseEvent.BUTTON3) { return; } double x = drawingPanel.pixToX(e.getX()); double y = drawingPanel.pixToY(e.getY()); int i = indexFromPoint(x, y); if(i==-1) { return; } if(pressed) { dragV = editValues[0]; int len = editValues.length; for(int j = 0; j<len; j++) { if(getAtIndex(i)==editValues[j]) { dragV = editValues[(j+1)%len]; } } } if(getAtIndex(i)!=dragV) { setAtIndex(i, dragV); drawingPanel.render(); } } /** * Gets the x coordinate for the given index. * * @param i int * @return double the x coordiante */ public double indexToX(int i) { if(raster==null) { throw new IllegalStateException("Data has not been set. Invoke setAll before invoking this method."); //$NON-NLS-1$ } return raster.indexToX(i); } /** * Gets the index that is closest to the given x value * * @return double the x coordiante */ public int xToIndex(double x) { if(raster==null) { throw new IllegalStateException("Data has not been set. Invoke setAll before invoking this method."); //$NON-NLS-1$ } return raster.xToIndex(x); } /** * Gets the index that is closest to the given y value * * @return double the y coordiante */ public int yToIndex(double y) { if(raster==null) { throw new IllegalStateException("Data has not been set. Invoke setAll before invoking this method."); //$NON-NLS-1$ } return raster.yToIndex(y); } /** * Gets the y coordinate for the given index. * * @param i int * @return double the y coordiante */ public double indexToY(int i) { if(raster==null) { throw new IllegalStateException("Data has not been set. Invoke setAll before invoking this method."); //$NON-NLS-1$ } return raster.indexToY(i); } /** * Determines the lattice index (row-major order) from given x and y world coordinates * * @param x * @param y * @return index */ public int indexFromPoint(double x, double y) { return raster.indexFromPoint(x, y); } synchronized MouseInputAdapter getMouseAdapter() { if(mouseAdapter==null) { return new MouseInputAdapter() { public void mousePressed(MouseEvent e) { mouse(e, true); } public void mouseDragged(MouseEvent e) { mouse(e, false); } }; } return mouseAdapter; } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */