Java tutorial
/** * Copyright 2010 Latiz Technologies, LLC * * This file is part of Latiz. * * Latiz is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Latiz 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 Latiz. If not, see <http://www.gnu.org/licenses/>. */ package com.AandR.beans.plotting.imagePlotPanel; import com.AandR.beans.plotting.data.AbstractNavigatableData; import com.AandR.beans.plotting.data.SimpleNavigatableData; import com.AandR.beans.plotting.imagePlotPanel.colormap.AbstractColorMap; import com.AandR.beans.plotting.imagePlotPanel.colormap.ColorMapChooser; import com.AandR.beans.plotting.imagePlotPanel.colormap.ColorMapFactory; import com.AandR.beans.plotting.imagePlotPanel.overlays.ArrowOverlay; import com.AandR.beans.plotting.imagePlotPanel.overlays.BasicShape; import com.AandR.beans.plotting.imagePlotPanel.overlays.BasicShapeEditor; import com.AandR.beans.plotting.imagePlotPanel.overlays.EllipticalAnnulusShape; import com.AandR.beans.plotting.imagePlotPanel.overlays.Overlay; import com.AandR.beans.plotting.imagePlotPanel.overlays.OverlayPopup; import com.AandR.beans.plotting.imagePlotPanel.overlays.TextBox; import com.AandR.library.math.MoreMath; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JRadioButton; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ToolTipManager; import net.miginfocom.swing.MigLayout; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.util.ImageUtilities; /** * @author Dr. Richard St. John * @version $Revision: 1.11 $, $Date: 2007/10/09 17:39:22 $ */ public class CanvasPanel extends ImagePanel implements ActionListener { public static final int RANGE_AUTO_SCALE = 0; public static final int RANGE_SERIES_RANGE = 1; public static final int RANGE_GLOBAL_RANGE = 2; public static final int RANGE_USER_RANGE = 3; public static final int INITIAL_SCALE_NONE = 0; public static final int INITIAL_SCALE_ONE_TO_ONE = 1; public static final int INITIAL_SCALE_WIDTH = 2; public static final int INITIAL_SCALE_HEIGHT = 3; private boolean isToolTipVisible; private boolean isLogPlot = false; private boolean isLogPlotRequested = false; private boolean isAutoScaled = true; private boolean isSeriesRangeComputed = false; private boolean isTableDataViewable = true; private double dataMin, dataMax, logDataMin, logDataMax, linDataMin, linDataMax, gridSpacingX, gridSpacingY; private double seriesMin, seriesMax; private double currentVerticalLocation = 0, currentHorizontalLocation = 0, currentRotation = 0; private double[][] data; private int minMaxSelection = RANGE_AUTO_SCALE; private AbstractColorMap colorMap = ColorMapFactory.createColorMap(ColorMapFactory.JET); private AbstractNavigatableData abstractNavigatableData; private ArrayList<CanvasPanelListener> observers; private BufferedImage linBuffer, logBuffer; private CanvasListener canvasListener; private HashSet<Overlay> overlays; private JPopupMenu popupMenu; private String currentDirectory; public CanvasPanel(int canvasWidth, int canvasHeight) { super(canvasWidth, canvasHeight); isToolTipVisible = ToolTipManager.sharedInstance().isEnabled(); gridSpacingX = gridSpacingY = 1; currentDirectory = System.getProperty("user.home"); canvasListener = new CanvasListener(); observers = new ArrayList<CanvasPanelListener>(); setToolTipText("No File Loaded"); addBindings(); createPopupMenu(); addMouseListener(canvasListener); addMouseMotionListener(canvasListener); addMouseWheelListener(canvasListener); addKeyListener(canvasListener); overlays = new HashSet<Overlay>(); this.canvasWidth = canvasWidth; this.canvasHeight = canvasHeight; setMinimumSize(new Dimension(canvasWidth, canvasHeight)); } private void createPopupMenu() { popupMenu = new JPopupMenu(); popupMenu.add(createPopupMenuItem("Toggle Log Plot", null, KeyStroke.getKeyStroke(KeyEvent.VK_L, 0))); popupMenu.add(createPopupMenuItem("Slice Here", null, KeyStroke.getKeyStroke(KeyEvent.VK_C, 10))); popupMenu.addSeparator(); JMenu navigateMenu = new JMenu("Navigate"); navigateMenu.add(createPopupMenuItem("View First Frame", null, KeyStroke.getKeyStroke(KeyEvent.VK_F, 2))); navigateMenu .add(createPopupMenuItem("View Previous Frame", null, KeyStroke.getKeyStroke(KeyEvent.VK_P, 2))); navigateMenu .add(createPopupMenuItem("Choose Frame To View", null, KeyStroke.getKeyStroke(KeyEvent.VK_C, 2))); navigateMenu.add(createPopupMenuItem("View Next Frame", null, KeyStroke.getKeyStroke(KeyEvent.VK_N, 2))); navigateMenu.add(createPopupMenuItem("View Last Frame", null, KeyStroke.getKeyStroke(KeyEvent.VK_L, 2))); popupMenu.add(navigateMenu); popupMenu.addSeparator(); popupMenu.add(createPopupMenuItem("Set Zoom Level", null, KeyStroke.getKeyStroke(KeyEvent.VK_Z, 2))); popupMenu.add(createPopupMenuItem("Set Min/Max", null, KeyStroke.getKeyStroke(KeyEvent.VK_R, 2))); popupMenu.add(createPopupMenuItem("Set Physical Extent", null, KeyStroke.getKeyStroke(KeyEvent.VK_E, 2))); popupMenu.addSeparator(); popupMenu.add(createPopupMenuItem("Recenter on Viewport", null, KeyStroke.getKeyStroke(KeyEvent.VK_C, 0))); popupMenu.addSeparator(); popupMenu.add(createPopupMenuItem("Set Colormap", null, KeyStroke.getKeyStroke(KeyEvent.VK_M, 2))); popupMenu.addSeparator(); JMenu overlayMenu = new JMenu("Overlays"); overlayMenu.add(createPopupMenuItem("Add Text Overlay", null, KeyStroke.getKeyStroke(KeyEvent.VK_T, 2))); overlayMenu.add(createPopupMenuItem("Add Shape Overlay", null, KeyStroke.getKeyStroke(KeyEvent.VK_O, 2))); overlayMenu.add(createPopupMenuItem("Add Annulus Overlay", null, KeyStroke.getKeyStroke(KeyEvent.VK_U, 2))); overlayMenu.add(createPopupMenuItem("Add Arrow Overlay", null, KeyStroke.getKeyStroke(KeyEvent.VK_A, 2))); popupMenu.add(overlayMenu); popupMenu.addSeparator(); JMenu pngMenu = new JMenu("To PNG"); pngMenu.add(createPopupMenuItem("Export Original Image", null, KeyStroke.getKeyStroke(KeyEvent.VK_S, 10))); pngMenu.add(createPopupMenuItem("Export Viewport Image", null, KeyStroke.getKeyStroke(KeyEvent.VK_S, 2))); pngMenu.addSeparator(); pngMenu.add(createPopupMenuItem("Export Viewport Series", null, KeyStroke.getKeyStroke(KeyEvent.VK_S, 8))); JMenu pdfMenu = new JMenu("To PDF"); pdfMenu.add(createPopupMenuItem("Export Original Image", null, KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.SHIFT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK))); pdfMenu.add(createPopupMenuItem("Export Viewport Image", null, KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.ALT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK))); JMenu exportMenu = new JMenu("Export"); exportMenu.add(pngMenu); exportMenu.add(pdfMenu); popupMenu.add(exportMenu); popupMenu.addSeparator(); JMenu losslessMenu = new JMenu("Lossless Modifications"); losslessMenu.add(createPopupMenuItem("Flip Horizontally", null, KeyStroke.getKeyStroke(KeyEvent.VK_H, 10))); losslessMenu.add(createPopupMenuItem("Flip Vertically", null, KeyStroke.getKeyStroke(KeyEvent.VK_V, 10))); losslessMenu.addSeparator(); losslessMenu.add(createPopupMenuItem("Rotate +90", null, KeyStroke.getKeyStroke(KeyEvent.VK_R, 10))); losslessMenu.add(createPopupMenuItem("Rotate -90", null, KeyStroke.getKeyStroke(KeyEvent.VK_L, 10))); popupMenu.add(losslessMenu); } /** * Access to the method used to create the popup menu items used in the Canvas Popup Menu. * @param label * @param icon * @param keyStroke * @return */ public JMenuItem createPopupMenuItem(String label, Icon icon, KeyStroke keyStroke) { JMenuItem menuItem = new JMenuItem(label, icon); menuItem.setAccelerator(keyStroke); menuItem.addActionListener(this); menuItem.setBackground(Color.WHITE); menuItem.setEnabled(true); return menuItem; } /** * */ public void actionPerformed(ActionEvent e) { JMenuItem item = (JMenuItem) e.getSource(); int modifiers = item.getAccelerator().getModifiers(); int keyCode = item.getAccelerator().getKeyCode(); dispatchEvent(new KeyEvent(this, KeyEvent.KEY_PRESSED, 0, modifiers, keyCode, KeyEvent.CHAR_UNDEFINED)); } /** * */ @Override public void paintComponent(Graphics g) { super.paintComponent(g); setBackground(Color.GRAY); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (bufferedImage != null) { scaleGraphicsContext(g2); g2.drawImage(bufferedImage, 0, 0, null); drawTextBoxes(g2); } } public void setColorMap(AbstractColorMap colorMap) { this.colorMap = colorMap; canvasListener.updateCanvasImage(data); } public AbstractColorMap getColorMap() { return colorMap; } /** * */ @Override public void scaleGraphicsContext(Graphics2D g2) throws IllegalArgumentException { if (currentScaleFactor > 0.0f) { g2.scale(currentScaleFactor, currentScaleFactor); g2.translate(currentTranslationX, currentTranslationY); } else { throw new IllegalArgumentException("An attempt was made to scale with a height or width value of 0"); } } private void drawTextBoxes(Graphics2D g2) { Overlay thisOverlay; Iterator<Overlay> thisBox = overlays.iterator(); while (thisBox.hasNext()) { thisOverlay = thisBox.next(); g2.setFont(thisOverlay.getFont()); g2.setColor(thisOverlay.getShapeColor()); thisOverlay.paintItem(g2); } } /** * Add action bindings * */ private void addBindings() { // Bind First Frame getActionMap().put("FirstFrame", new AbstractAction("FirstFrame") { public void actionPerformed(ActionEvent evt) { canvasListener.actionPlotFirstFrame(); } }); getInputMap().put(KeyStroke.getKeyStroke("control F"), "FirstFrame"); // Bind Next Frame getActionMap().put("NextFrame", new AbstractAction("NextFrame") { public void actionPerformed(ActionEvent evt) { canvasListener.actionPlotNextFrame(); } }); getInputMap().put(KeyStroke.getKeyStroke("control N"), "NextFrame"); // Bind Choose Frame getActionMap().put("ChooseFrame", new AbstractAction("ChooseFrame") { public void actionPerformed(ActionEvent evt) { canvasListener.actionChooseFrame(); } }); getInputMap().put(KeyStroke.getKeyStroke("control C"), "ChooseFrame"); // Bind Previous Frame getActionMap().put("PreviousFrame", new AbstractAction("PreviousFrame") { public void actionPerformed(ActionEvent evt) { canvasListener.actionPlotPreviousFrame(); } }); getInputMap().put(KeyStroke.getKeyStroke("control P"), "PreviousFrame"); // Bind Last Frame getActionMap().put("LastFrame", new AbstractAction("LastFrame") { public void actionPerformed(ActionEvent evt) { canvasListener.actionPlotLastFrame(); } }); getInputMap().put(KeyStroke.getKeyStroke("control L"), "LastFrame"); // Bind Toggle Log Plot getActionMap().put("LogPlot", new AbstractAction("LogPlot") { public void actionPerformed(ActionEvent evt) { canvasListener.actionToggleLogPlot(); } }); getInputMap().put(KeyStroke.getKeyStroke("L"), "LogPlot"); // Bind SLice Plot getActionMap().put("SlicePlot", new AbstractAction("SlicePlot") { public void actionPerformed(ActionEvent evt) { canvasListener.actionSlicePlot(); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt C"), "SlicePlot"); // Bind Recenter On Viewport getActionMap().put("RecenterOnViewport", new AbstractAction("RecenterOnViewport") { public void actionPerformed(ActionEvent evt) { canvasListener.actionCenterOnViewport(); } }); getInputMap().put(KeyStroke.getKeyStroke("C"), "RecenterOnViewport"); // Bind Flip Horizontally getActionMap().put("FlipHorz", new AbstractAction("FlipHorz") { public void actionPerformed(ActionEvent evt) { canvasListener.actionFlipHorizontally(); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt H"), "FlipHorz"); // Bind Flip Vertically getActionMap().put("FlipVert", new AbstractAction("FlipVert") { public void actionPerformed(ActionEvent evt) { canvasListener.actionFlipVertically(); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt V"), "FlipVert"); // Bind Rotate Right getActionMap().put("RotateRight", new AbstractAction("RotateRight") { public void actionPerformed(ActionEvent evt) { canvasListener.actionRotate(90.0f); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt R"), "RotateRight"); // Bind Rotate Left getActionMap().put("RotateLeft", new AbstractAction("RotateLeft") { public void actionPerformed(ActionEvent evt) { canvasListener.actionRotate(-90.0f); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt L"), "RotateLeft"); // Bind Export Viewport getActionMap().put("ExportViewport", new AbstractAction("ExportViewport") { public void actionPerformed(ActionEvent evt) { canvasListener.actionSaveImageFile(true); } }); getInputMap().put(KeyStroke.getKeyStroke("control S"), "ExportViewport"); // Bind Export Original getActionMap().put("ExportOriginal", new AbstractAction("ExportOriginal") { public void actionPerformed(ActionEvent evt) { canvasListener.actionSaveImageFile(false); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt S"), "ExportOriginal"); // Bind Zoom Dialog getActionMap().put("ZoomDialog", new AbstractAction("ZoomDialog") { public void actionPerformed(ActionEvent evt) { canvasListener.actionShowZoomDialog(); } }); getInputMap().put(KeyStroke.getKeyStroke("control Z"), "ZoomDialog"); // Bind export image series getActionMap().put("ExportSeries", new AbstractAction("ExportSeries") { public void actionPerformed(ActionEvent e) { canvasListener.actionExportSeries(); } }); getInputMap().put(KeyStroke.getKeyStroke("alt S"), "ExportSeries"); // Bind export image to pdf getActionMap().put("ExportToPDF", new AbstractAction("ExportToPDF") { public void actionPerformed(ActionEvent e) { canvasListener.actionExportToPDF(false); } }); getInputMap().put(KeyStroke.getKeyStroke("control shift P"), "ExportToPDF"); // Bind export image to pdf getActionMap().put("ExportToPDF2", new AbstractAction("ExportToPDF2") { public void actionPerformed(ActionEvent e) { canvasListener.actionExportToPDF(true); } }); getInputMap().put(KeyStroke.getKeyStroke("control alt P"), "ExportToPDF2"); // Bind Range Dialog getActionMap().put("RangeDialog", new AbstractAction("RangeDialog") { public void actionPerformed(ActionEvent evt) { canvasListener.actionShowRangeDialog(); } }); getInputMap().put(KeyStroke.getKeyStroke("control R"), "RangeDialog"); // Bind View Extend Dialog getActionMap().put("PhysicalExtentDialog", new AbstractAction("PhysicalExtentDialog") { public void actionPerformed(ActionEvent evt) { canvasListener.actionShowPhysicalDialog(); } }); getInputMap().put(KeyStroke.getKeyStroke("control E"), "PhysicalExtentDialog"); // Bind Add Basic Shape Overlay getActionMap().put("AddBasicShape", new AbstractAction("AddBasicShape") { public void actionPerformed(ActionEvent evt) { canvasListener.actionAddShapeOverlay(); } }); getInputMap().put(KeyStroke.getKeyStroke("control O"), "AddBasicShape"); // Bind Add Basic Shape Overlay getActionMap().put("AddAnnulusShape", new AbstractAction("AddAnnulusShape") { public void actionPerformed(ActionEvent evt) { canvasListener.actionAddAnnulusOverlay(); } }); getInputMap().put(KeyStroke.getKeyStroke("control U"), "AddAnnulusShape"); // Bind Add Text Overlay getActionMap().put("AddTextOverlay", new AbstractAction("AddTextOverlay") { public void actionPerformed(ActionEvent evt) { canvasListener.actionAddTextOverlay(); } }); getInputMap().put(KeyStroke.getKeyStroke("control T"), "AddTextOverlay"); // Bind Arrow Overlay getActionMap().put("AddArrowOverlay", new AbstractAction("AddArrowOverlay") { public void actionPerformed(ActionEvent evt) { canvasListener.actionAddArrowOverlay(); } }); getInputMap().put(KeyStroke.getKeyStroke("control A"), "AddArrowOverlay"); // Bind Colormap Chooser getActionMap().put("ColorMapChooser", new AbstractAction("ColorMapChooser") { public void actionPerformed(ActionEvent e) { canvasListener.actionColormapChooser(); } }); getInputMap().put(KeyStroke.getKeyStroke("control M"), "ColorMapChooser"); // Bind Refresh Action getActionMap().put("ReloadFile", new AbstractAction("ReloadFile") { public void actionPerformed(ActionEvent e) { canvasListener.actionReloadFile(); } }); getInputMap().put(KeyStroke.getKeyStroke("F5"), "ReloadFile"); } public boolean setNavigatableData(AbstractNavigatableData navigatableData) { this.abstractNavigatableData = navigatableData; canvasListener.updateCanvasData(data = abstractNavigatableData.getFirstDataset()); if (data == null) { return false; } nodifyNewDataLoaded(); return true; } public void clearCanvas() { setNavigatableData(new SimpleNavigatableData(new double[][] { { 0 } })); } public AbstractNavigatableData getNavigatableData() { return abstractNavigatableData; } public void plot(int index) { canvasListener.updateCanvasData(abstractNavigatableData.getDatasetAt(index)); } public void plotNext() { canvasListener.actionPlotNextFrame(); } /** * * @param dataLocal * @param isAutoScaled * @return */ public BufferedImage convertDataToImage(double[][] data, double dataMin, double dataMax) { BufferedImage image = new BufferedImage(data.length, data[0].length, BufferedImage.TYPE_INT_RGB); WritableRaster raster = image.getRaster(); double thisValue; int[] thisRowOfPixels = new int[3 * data.length]; int[] thisPixelValue = new int[3]; int i, j; double scale = 255.0 / (dataMax - dataMin); for (j = 0; j < data[0].length; j++) { for (i = 0; i < data.length; i++) { thisValue = scale * (data[i][j] - dataMin); //if(thisValue<0.0) // thisValue = 0.0; //else if(thisValue>255.0) // thisValue = 255.0; thisPixelValue = colorMap.getColorValue((int) thisValue); thisRowOfPixels[3 * i + 0] = thisPixelValue[0]; thisRowOfPixels[3 * i + 1] = thisPixelValue[1]; thisRowOfPixels[3 * i + 2] = thisPixelValue[2]; } raster.setPixels(0, j, data.length, 1, thisRowOfPixels); } return image; } /** * * @param dataLocal * @param isAutoScaled * @return public BufferedImage convertDataToImage(float[][] dataLocal, boolean isAutoScaled) { if(isAutoScaled) { float[] range = MoreMath.minMax(dataLocal); dataMin = range[0]; dataMax = range[1]; } BufferedImage image = new BufferedImage(dataLocal.length, dataLocal[0].length, BufferedImage.TYPE_INT_RGB); WritableRaster raster = image.getRaster(); double thisValue; int i, j; double scale = 255.0 / (dataMax - dataMin); for(j=0; j<dataLocal[0].length; j++) { for(i=0; i<dataLocal.length; i++) { thisValue = scale*(dataLocal[i][j]-dataMin); if(thisValue<0.0) thisValue = 0.0; else if(thisValue>255.0f) thisValue = 255.0f; raster.setPixel(i, j, colorMap.getColorValue((int) thisValue)); } } return image; } */ public BufferedImage convertDataToImage(double[][] data) { double min = data[0][0]; double max = data[0][0]; for (int j = 0; j < data[0].length; j++) { for (int i = 0; i < data.length; i++) { min = data[i][j] < min ? data[i][j] : min; max = data[i][j] > max ? data[i][j] : max; } } dataMin = min; dataMax = max; return convertDataToImage(data, min, max); } private final double[] computeMinMax(double[][] data) { double[] minMax = new double[] { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; for (int j = 0; j < data[0].length; j++) { for (int i = 0; i < data.length; i++) { minMax[0] = data[i][j] < minMax[0] ? data[i][j] : minMax[0]; minMax[1] = data[i][j] > minMax[1] ? data[i][j] : minMax[1]; } } return minMax; } /* */ public double[] computeSeriesMinMax(int stepSize) { double[][] dataLocal = abstractNavigatableData.getFirstDataset(); double[] minMax = computeMinMax(dataLocal); double[] thisMinMax = isLogPlot ? new double[] { Math.log(minMax[0]), Math.log(minMax[1]) } : minMax; if (thisMinMax[0] < minMax[0]) { minMax[0] = thisMinMax[0]; } if (thisMinMax[1] > minMax[1]) { minMax[1] = thisMinMax[1]; } int currentSkip = 1; while (abstractNavigatableData.hasNext()) { if (currentSkip < stepSize) { currentSkip++; continue; } dataLocal = abstractNavigatableData.getNextDataset(); minMax = computeMinMax(dataLocal); thisMinMax = isLogPlot ? new double[] { Math.log(minMax[0]), Math.log(minMax[1]) } : minMax; currentSkip = 1; } seriesMin = minMax[0]; seriesMax = minMax[1]; return minMax; } /** * Computes the maximum and minimum values from a dataLocal series. * @return * @throws LargeArrayException * @throws IOException */ public double[] computeSeriesMinMax() { return computeSeriesMinMax(1); } /** * Returns the dataLocal minimum. * @return */ public double getDataMin() { return isLogPlot ? logDataMin : linDataMin; } /** * Returns the maximum dataLocal value. * @return */ public double getDataMax() { return isLogPlot ? logDataMax : linDataMax; } /** * Set the min and max dataLocal values. * @param dataMin * @param dataMax */ public void setDataRange(double dataMin, double dataMax) { if (isLogPlot) { this.logDataMin = dataMin; this.logDataMax = dataMax; this.linDataMin = Math.exp(dataMin); this.linDataMax = Math.exp(dataMax); } else { this.linDataMin = dataMin; this.linDataMax = dataMax; this.logDataMin = Math.log(dataMin); this.logDataMax = Math.log(dataMax); } } /** * Returns the x-grid point spacing of the currently loaded dataLocal file. * @return */ public double getGridSpacingX() { return gridSpacingX; } /** * Returns the y-grid point spacing of the currently loaded dataLocal file. * @return */ public double getGridSpacingY() { return gridSpacingY; } /** * Sets the grid point spacing for the currently loaded dataLocal file. * @param dx * @param dy */ public void setGridSpacing(double dx, double dy) { this.gridSpacingX = dx; this.gridSpacingY = dy; } /** * * @param logBuffer */ public void setLogBuffer(BufferedImage logBuffer) { this.logBuffer = logBuffer; } /** * * @param linBuffer */ public void setLinBuffer(BufferedImage linBuffer) { this.linBuffer = linBuffer; } /** * Get the currenlty loaded dataLocal. * @return */ public double[][] getData() { return data; } /** * * @return */ public double getSeriesMax() { return seriesMax; } /** * * @return */ public double getSeriesMin() { return seriesMin; } /** * * @return */ public boolean isSeriesRangeComputed() { return isSeriesRangeComputed; } public boolean isShowToolTip() { return canvasListener.showToolTip; } public void setShowToolTip(boolean showToolTip) { canvasListener.showToolTip = showToolTip; } /** * * @param isSeriesRangeComputed */ public void setSeriesRangeComputed(boolean isSeriesRangeComputed) { this.isSeriesRangeComputed = isSeriesRangeComputed; } /** * * @return */ public JPopupMenu getPopupMenu() { return popupMenu; } public void addCanvasPanelInterface(CanvasPanelListener canvasPanelListener) { observers.add(canvasPanelListener); } public void removeCanvasPanelInterface(CanvasPanelListener canvasPanelListener) { int index = observers.indexOf(canvasPanelListener); if (index > -1) { observers.remove(index); } } private void notifyBufferChanged() { for (int i = 0; i < observers.size(); i++) { observers.get(i).bufferChanged(); } } private void nodifyNewDataLoaded() { for (int i = 0; i < observers.size(); i++) { observers.get(i).newDataLoaded(); } } private void nodifyDataChanged() { for (int i = 0; i < observers.size(); i++) { observers.get(i).dataChanged(); } } private void nodifyMouseDragged() { for (int i = 0; i < observers.size(); i++) { observers.get(i).mouseDragged(); } } private void nodifyMouseMoved() { for (int i = 0; i < observers.size(); i++) { observers.get(i).mouseMoved(); } } /** * Determines whether the current buffer is a log plot. * @return */ public boolean isLogPlot() { return isLogPlot; } /** * Returns the current linear buffer. * @return */ public BufferedImage getLinBuffer() { return linBuffer; } /** * Returns the buffer of the log of the currently loaded dataLocal. * @return */ public BufferedImage getLogBuffer() { return logBuffer; } /** * Returns the x-index of the dataLocal that the mouse is currently over. * @return */ public int getSelectedXValue() { return canvasListener.selectedX; } /** * Returns the y-index of the dataLocal that the mouse is currently over. * @return */ public int getSelectedYValue() { return canvasListener.selectedY; } public void setInitialScaleFactor(int flag) { canvasListener.setInitialScaleFactor(flag); } /** * * @return */ public int getMinMaxType() { return canvasListener.getMinMaxSelection(); } /** * * @return */ public boolean isAutoScaled() { return isAutoScaled; } /** * * @param isAutoScaled */ public void setAutoScaled(boolean isAutoScaled) { this.isAutoScaled = isAutoScaled; } public int getPanelWidth() { return getWidth(); } public int[] getGridSize() { return new int[] { data.length, data[0].length }; } public double[] getPhysicalExtent() { return new double[] { data.length * getGridSpacingX(), data[0].length * getGridSpacingY() }; } public int getPanelHeight() { return getHeight(); } public double getCurrentHorizontalLocation() { return currentHorizontalLocation; } public double getCurrentVerticalLocation() { return currentVerticalLocation; } public double getCurrentRotation() { return currentRotation; } public void setCurrentRotation(double currentRotation) { this.currentRotation = currentRotation; } public void setCurrentHorizontalLocation(double currentHorizontalLocation) { this.currentHorizontalLocation = currentHorizontalLocation; } public void setCurrentVerticalLocation(double currentVerticalLocation) { this.currentVerticalLocation = currentVerticalLocation; } public boolean isTableDataViewable() { return isTableDataViewable; } public void setTableDataViewable(boolean isTableDataViewable) { this.isTableDataViewable = isTableDataViewable; } /** * * @author Dr. Richard St. John * @version $Revision: 1.11 $, $Date: 2007/10/09 17:39:22 $ */ private class CanvasListener implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener { private boolean showToolTip = false, isHorizontalFlip = false, isVerticalFlip = false; private double selectedZ; private int startFromX = 0, startFromY = 0, dragFromX = 0, dragFromY = 0; private int selectedX, selectedY; private Overlay selectedOverlay; private OverlayPopup overlayPopupMenu; private Point clickPoint = new Point(0, 0); private CanvasListener() { overlayPopupMenu = new OverlayPopup(new ActionListener() { public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equalsIgnoreCase(OverlayPopup.ACTION_REMOVE_OVERLAY)) { actionRemoveOverlay(); } else if (command.equalsIgnoreCase(OverlayPopup.ACTION_EDIT_OVERLAY)) { selectedOverlay.fireOverlayListener(); if (!BasicShapeEditor.getInstanceOf().isCancelled()) { repaint(); } } else if (command.equalsIgnoreCase(OverlayPopup.ACTION_CENTER_OVERLAY)) { actionCenterOverlay(); } } }); } private void actionSlicePlot() { XYSeries horizSlice = new XYSeries("Horiontal Slice"); double len = data.length; for (int i = 0; i < len; i++) { horizSlice.add((i - len / 2) * gridSpacingX, isLogPlot ? Math.log(data[i][selectedY]) : data[i][selectedY]); } XYSeries vertSlice = new XYSeries("Vertical Slice"); len = data[0].length; for (int i = 0; i < len; i++) { vertSlice.add((i - len / 2) * gridSpacingY, isLogPlot ? Math.log(data[selectedX][i]) : data[selectedX][i]); } XYSeriesCollection seriesCollection = new XYSeriesCollection(); seriesCollection.addSeries(horizSlice); seriesCollection.addSeries(vertSlice); JFreeChart slicePlot = ChartFactory.createXYLineChart( "Sliced at (" + selectedX + ", " + selectedY + ")", "distance (m)", "Slice", seriesCollection, PlotOrientation.VERTICAL, true, true, true); DialogDescriptor dd = new DialogDescriptor(new ChartPanel(slicePlot), "Slice Plot"); DialogDisplayer.getDefault().createDialog(dd).setVisible(true); } private void actionReloadFile() { canvasListener.updateCanvasData(data); } private void actionFlipHorizontally() { if (bufferedImage == null) { return; } isHorizontalFlip = !isHorizontalFlip; flipImageHorizontally(); notifyBufferChanged(); } private void actionFlipVertically() { if (bufferedImage == null) { return; } isVerticalFlip = !isVerticalFlip; flipImageVertically(); notifyBufferChanged(); } private void actionPlotFirstFrame() { if (bufferedImage == null || abstractNavigatableData == null) { return; } updateCanvasData(data = abstractNavigatableData.getFirstDataset()); } private void actionPlotNextFrame() { if (bufferedImage == null || abstractNavigatableData == null) { return; } updateCanvasData(data = abstractNavigatableData.getNextDataset()); } private void actionPlotPreviousFrame() { if (bufferedImage == null || abstractNavigatableData == null) { return; } updateCanvasData(data = abstractNavigatableData.getPreviousDataset()); } private void actionPlotLastFrame() { if (bufferedImage == null || abstractNavigatableData == null) { return; } updateCanvasData(data = abstractNavigatableData.getLastDataset()); } private void actionChooseFrame() { if (bufferedImage == null || abstractNavigatableData == null) { return; } int currentIndex = abstractNavigatableData.getCurrentIndex(); String ans = JOptionPane.showInputDialog("Specify Frame Number To Plot", String.valueOf(currentIndex + 1)); if (ans == null) { return; } try { int index = Integer.parseInt(ans); updateCanvasData(data = abstractNavigatableData.getDatasetAt(index)); } catch (NumberFormatException e) { canvasListener.updateCanvasData(data); } } private void actionExportSeries() { if (bufferedImage == null) { return; } // Compute Min / Max setAutoScaled(false); if (getMinMaxSelection() == RANGE_AUTO_SCALE) { setAutoScaled(true); } else if (getMinMaxSelection() == RANGE_SERIES_RANGE || getMinMaxSelection() == RANGE_GLOBAL_RANGE) { try { //computeSeriesMinMax(); setDataRange(getSeriesMin(), getSeriesMax()); } catch (Exception e) { e.printStackTrace(); } } // Loop through files. File thisFile; while (abstractNavigatableData.hasNext()) { thisFile = new File(abstractNavigatableData.getName() + ".png"); updateCanvasData(data = abstractNavigatableData.getNextDataset()); actionSaveImageFile(thisFile, true); } } private void actionExportToPDF(boolean isViewportSizeUsed) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Rectangle pageSize = null; try { if (isViewportSizeUsed) { BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); paint(g2); g2.dispose(); ImageIO.write(image, "png", baos); pageSize = new Rectangle(image.getWidth(), image.getHeight()); } else { ImageIO.write(bufferedImage, "png", baos); pageSize = new Rectangle(bufferedImage.getWidth(), bufferedImage.getHeight()); } } catch (IOException e) { e.printStackTrace(); return; } File outputFile = new File(abstractNavigatableData.getName() + ".pdf"); // // // step 1: creation of a document-object // Document document = new Document(pageSize, 0f, 0f, 0f, 0f); // document.addAuthor(System.getProperty("user.name")); // // // step 2: // // we create a writer that listens to the document // // and directs a PDF-stream to a file // try { // PdfWriter.getInstance(document, new FileOutputStream(outputFile)); // // // step 3: we open the document // document.open(); // // // step 4: // Image jpg = Image.getInstance(baos.toByteArray()); // //document.newPage(); // document.add(jpg); // // // step 5: we close the document // document.close(); // // } catch (Exception e) { // e.printStackTrace(); // } // // OptionsDialog dialog = new OptionsDialog(CanvasPanel.this, "Export Finished", OptionsDialog.INFORMATION_ICON); // String filename = outputFile.getName(); // String parent = outputFile.getParent(); // dialog.showDialog("<HTML><center><I>" + filename + "</I><BR><BR>was successfully saved to<BR><BR><I>" + parent + "</I></center></HTML>", 0); } private void actionToggleLogPlot() { if (bufferedImage == null) { return; } isLogPlotRequested = true; isLogPlot = !isLogPlot; if (isLogPlot) { if (logBuffer == null) { createLogBuffer(data); } setBufferedImage(logBuffer); } else { setBufferedImage(linBuffer); } nodifyDataChanged(); } private void actionCenterOnViewport() { if (bufferedImage == null) { return; } int bufferWidth = (int) (bufferedImage.getWidth() * currentScaleFactor); int bufferHeight = (int) (bufferedImage.getHeight() * currentScaleFactor); currentHorizontalLocation = (int) ((getPanelWidth() - bufferWidth) / (2.0f * currentScaleFactor)); currentVerticalLocation = (int) ((getPanelHeight() - bufferHeight) / (2.0f * currentScaleFactor)); startFromX = (int) currentHorizontalLocation; startFromY = (int) currentVerticalLocation; transform(currentScaleFactor, (int) currentHorizontalLocation, (int) currentVerticalLocation); notifyBufferChanged(); } private void actionRotate(double angle) { if (bufferedImage == null) { return; } currentRotation += angle; rotateImage(angle); notifyBufferChanged(); } private void actionShowPhysicalDialog() { if (bufferedImage == null) { return; } new PhysicalExtentDialog(); } private void actionShowRangeDialog() { if (bufferedImage == null) { return; } new RangeDialog(); } private void actionAddTextOverlay() { overlays.add(new TextBox("New String", clickPoint.x, clickPoint.y)); repaint(); } private void actionAddAnnulusOverlay() { EllipticalAnnulusShape shape = new EllipticalAnnulusShape(clickPoint.x, clickPoint.y, 10, 10); overlays.add(shape); repaint(); } private void actionAddShapeOverlay() { BasicShape shape = new BasicShape(BasicShape.ELLIPSE, clickPoint.x, clickPoint.y, 10, 10); overlays.add(shape); repaint(); } private void actionAddArrowOverlay() { ArrowOverlay arrow = new ArrowOverlay(clickPoint.x, clickPoint.y, 10, 5, 5, 0f); overlays.add(arrow); repaint(); } private void actionRemoveOverlay() { clickPoint.x = 0; clickPoint.y = 0; overlays.remove(selectedOverlay); repaint(); } private void actionCenterOverlay() { double panelCenterX = (double) (getWidth() / 2.0f); double panelCenterY = (double) (getHeight() / 2.0f); double overlayRadiusX = (selectedOverlay.getWidth() / 2.0) * getCurrentScaleFactor(); double overlayRadiusY = (selectedOverlay.getHeight() / 2.0) * getCurrentScaleFactor(); double offsetX = getCurrentTranslationX() * getCurrentScaleFactor(); double offsetY = getCurrentTranslationY() * getCurrentScaleFactor(); double xPos = (panelCenterX - overlayRadiusX - offsetX) / getCurrentScaleFactor(); double yPos = (panelCenterY - overlayRadiusY - offsetY) / getCurrentScaleFactor(); selectedOverlay.setXPos(xPos + selectedOverlay.getPenWidth() / 2.0); selectedOverlay.setYPos(yPos + selectedOverlay.getPenWidth() / 2.0); repaint(); } private void actionColormapChooser() { ColorMapChooser colorChooser = new ColorMapChooser(new JFrame()); if (!colorChooser.isCancelled()) { if (abstractNavigatableData != null) { setColorMap(colorChooser.getColorMap()); updateCanvasData(data); } } colorChooser = null; } private void updateCanvasData(double[][] data) { if (data == null) { return; } setCursor(new Cursor(Cursor.WAIT_CURSOR)); updateCanvasImage(data); nodifyDataChanged(); setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } private final void createLogBuffer(double[][] data) { logBuffer = null; if (isAutoScaled) { logBuffer = convertDataToImage(MoreMath.log(data)); logDataMin = dataMin; logDataMax = dataMax; } else { logBuffer = convertDataToImage(MoreMath.log(data), logDataMin, logDataMax); } } private final void createLinearBuffer(double[][] data) { linBuffer = null; if (isAutoScaled) { linBuffer = convertDataToImage(data); linDataMin = dataMin; linDataMax = dataMax; } else { linBuffer = convertDataToImage(data, linDataMin, linDataMax); } } private void updateCanvasImage(double[][] data) { if (abstractNavigatableData == null) { return; } createLinearBuffer(data); if (isLogPlotRequested || isLogPlot) { createLogBuffer(data); } if (isLogPlot) { setBufferedImage(logBuffer); } else { setBufferedImage(linBuffer); } if (isHorizontalFlip) { flipImageHorizontally(); } if (isVerticalFlip) { flipImageVertically(); } rotateImage(currentRotation); gridSpacingX = abstractNavigatableData.getDx(); gridSpacingY = abstractNavigatableData.getDy(); updateTooltipString(); notifyBufferChanged(); } private void updateTooltipString() { String physicalExtentX = formatNumber( (double) getPanelWidth() * gridSpacingX / getCurrentScaleFactor()); String physicalExtentY = formatNumber( (double) getPanelHeight() * gridSpacingY / getCurrentScaleFactor()); StringBuffer buffer = new StringBuffer("<html><table>"); buffer.append("<tr><td>Value:</td><td><b>z(" + selectedX + ", " + selectedY + ")=" + formatNumber(selectedZ) + "</b></td></tr>"); if (abstractNavigatableData != null) { buffer.append("<tr><td>Filename:</td><td><b>" + abstractNavigatableData.getID() + "</b></td></tr>"); } int currentFrame = abstractNavigatableData.getCurrentIndex(); int seriesLength = abstractNavigatableData.getNumberOfFrames(); buffer.append("<tr><td>File Index:</td><td><b>" + (currentFrame + 1) + " of " + seriesLength + "</b></td></tr>"); buffer.append("<tr><td>Min/Max:</td><td><b>(" + formatNumber(getDataMin()) + ", " + formatNumber(getDataMax()) + ")</b></td></tr>"); buffer.append("<tr><td>Grid Spacing:</td><td><b>(" + formatNumber(gridSpacingX) + ", " + formatNumber(gridSpacingY) + ")</b></td></tr>"); buffer.append("<tr><td>Mesh Size:</td><td><b>(" + bufferedImage.getWidth() + ", " + bufferedImage.getHeight() + ")</b></td></tr>"); buffer.append("<tr><td>Viewport:</td><td><b>(" + getPanelWidth() + ", " + getPanelHeight() + ")</b></td></tr>"); buffer.append("<tr><td>Physical Extent (m):</td><td><b>(" + physicalExtentX + ", " + physicalExtentY + ")</b></td></tr>"); buffer.append("<tr><td>Zoom Level:</td><td><b>" + getCurrentScaleFactor() + "</b></td></tr>"); buffer.append("</table></html>"); setToolTipText(buffer.toString()); } private String formatNumber(double x) { DecimalFormat df = (x > 1e5 || Math.abs(x) < 1e-5) ? new DecimalFormat("0.0000E00") : new DecimalFormat("0.0000"); return df.format(x); } private void actionSaveImageFile(File imageFile, boolean isViewportSizeUsed) { if (bufferedImage == null) { return; } try { BufferedImage image = null; if (isViewportSizeUsed) { image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); paint(g2); g2.dispose(); ImageIO.write(image, "png", imageFile); } else { ImageIO.write(bufferedImage, "png", imageFile); } } catch (IOException e) { e.printStackTrace(); } } private void actionSaveImageFile(boolean isViewportSizeUsed) { if (bufferedImage == null) { return; } JFileChooser fc = new JFileChooser(currentDirectory); int ans = fc.showSaveDialog(null); if (ans == JFileChooser.CANCEL_OPTION) return; //FileChooser fc = new FileChooser(currentDirectory, "png", "PNG Files", JFileChooser.SAVE_DIALOG, true); currentDirectory = fc.getCurrentDirectory().getPath(); File imageFile = fc.getSelectedFile(); fc = null; actionSaveImageFile(imageFile, isViewportSizeUsed); } private void actionShowZoomDialog() { if (bufferedImage == null) { return; } new ZoomDialog(); } private int getMinMaxSelection() { return minMaxSelection; } public void setInitialScaleFactor(int flag) { if (bufferedImage == null) { return; } if (flag == INITIAL_SCALE_ONE_TO_ONE) { currentScaleFactor = 1.0f; } else if (flag == INITIAL_SCALE_WIDTH) { currentScaleFactor = (double) getPanelWidth() / (double) bufferedImage.getWidth(); } else if (flag == INITIAL_SCALE_HEIGHT) { currentScaleFactor = (double) getPanelHeight() / (double) bufferedImage.getHeight(); } currentHorizontalLocation = 0; currentVerticalLocation = 0; startFromX = 0; startFromY = 0; transform(currentScaleFactor, (int) currentHorizontalLocation, (int) currentVerticalLocation); notifyBufferChanged(); updateTooltipString(); } public void mouseClicked(MouseEvent e) { requestFocus(); try { boolean isOverlaySelected = false; int x = (int) (e.getX() / currentScaleFactor); int y = (int) (e.getY() / currentScaleFactor); Iterator<Overlay> boxes = overlays.iterator(); Overlay thisOverlay = null; boolean isLeft, isRight, isTop, isBottom; while (boxes.hasNext()) { thisOverlay = boxes.next(); isLeft = (x - currentTranslationX) >= thisOverlay.getLeft(); isRight = (x - currentTranslationX) <= (thisOverlay.getLeft() + thisOverlay.getWidth()); isTop = (y - currentTranslationY) >= thisOverlay.getTop(); isBottom = (y - currentTranslationY) <= (thisOverlay.getTop() + thisOverlay.getHeight()); if (isLeft && isRight && isTop && isBottom) { isOverlaySelected = true; selectedOverlay = thisOverlay; break; } } if (e.getClickCount() == 2) { if (bufferedImage == null) { return; } if (isOverlaySelected) { selectedOverlay.fireOverlayListener(); repaint(); } else { setInitialScaleFactor(INITIAL_SCALE_WIDTH); if (e.isControlDown()) { setInitialScaleFactor(INITIAL_SCALE_HEIGHT); } if (e.isShiftDown()) { setInitialScaleFactor(INITIAL_SCALE_ONE_TO_ONE); } notifyBufferChanged(); updateTooltipString(); } } if (e.getButton() == 3) { int xRef = (int) (e.getX() / currentScaleFactor) - (int) currentHorizontalLocation; int yRef = (int) (e.getY() / currentScaleFactor) - (int) currentVerticalLocation; clickPoint = new Point(xRef, yRef); if (isOverlaySelected) { overlayPopupMenu.show(e.getComponent(), e.getX(), e.getY()); } else { popupMenu.show(e.getComponent(), e.getX(), e.getY()); } } } catch (Exception exception) { exception.printStackTrace(); } } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { //requestFocus(); ToolTipManager.sharedInstance().setEnabled(showToolTip); } public void mouseExited(MouseEvent e) { //transferFocus(); ToolTipManager.sharedInstance().setEnabled(isToolTipVisible); } public void mousePressed(MouseEvent e) { startFromX = currentTranslationX; startFromY = currentTranslationY; int x = (int) (e.getX() / currentScaleFactor); int y = (int) (e.getY() / currentScaleFactor); dragFromX = x - startFromX; dragFromY = y - startFromY; selectedOverlay = null; Iterator<Overlay> boxes = overlays.iterator(); Overlay thisOverlay = null; boolean isLeft, isRight, isBottom, isTop; while (boxes.hasNext()) { thisOverlay = boxes.next(); isLeft = (x - currentTranslationX) >= thisOverlay.getLeft(); isRight = (x - currentTranslationX) <= (thisOverlay.getLeft() + thisOverlay.getWidth()); isTop = (y - currentTranslationY) >= thisOverlay.getTop(); isBottom = (y - currentTranslationY) <= (thisOverlay.getTop() + thisOverlay.getHeight()); if (isLeft && isRight && isTop && isBottom) { thisOverlay.isDraggable = true; dragFromX = x - (int) thisOverlay.getXPos(); dragFromY = y - (int) thisOverlay.getYPos(); selectedOverlay = thisOverlay; break; } else { thisOverlay.isDraggable = false; } } } public void mouseDragged(MouseEvent e) { int x = (int) (e.getX() / currentScaleFactor); int y = (int) (e.getY() / currentScaleFactor); boolean isImageDragged = true; Iterator<Overlay> items = overlays.iterator(); Overlay thisOverlay = null; while (items.hasNext()) { thisOverlay = items.next(); if (!thisOverlay.isDraggable) { continue; } isImageDragged = false; thisOverlay.setXPos(x - dragFromX); thisOverlay.setYPos(y - dragFromY); repaint(); break; } if (isImageDragged) { startFromX = x - dragFromX; currentHorizontalLocation = startFromX; startFromY = y - dragFromY; currentVerticalLocation = startFromY; transform(currentScaleFactor, (int) currentHorizontalLocation, (int) currentVerticalLocation); nodifyMouseDragged(); } } public void mouseMoved(MouseEvent e) { if (e.isControlDown()) { return; } int x = (int) (e.getX() / currentScaleFactor); int y = (int) (e.getY() / currentScaleFactor); Iterator<Overlay> boxes = overlays.iterator(); Overlay thisOverlay = null; boolean isLeft, isRight, isBottom, isTop; while (boxes.hasNext()) { thisOverlay = boxes.next(); isLeft = (x - currentTranslationX) >= thisOverlay.getLeft(); isRight = (x - currentTranslationX) <= (thisOverlay.getLeft() + thisOverlay.getWidth()); isTop = (y - currentTranslationY) >= thisOverlay.getTop(); isBottom = (y - currentTranslationY) <= (thisOverlay.getTop() + thisOverlay.getHeight()); if (isLeft && isRight && isTop && isBottom) { setCursor(new Cursor(Cursor.HAND_CURSOR)); thisOverlay.isDraggable = true; break; } else { setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); thisOverlay.isDraggable = false; } } try { selectedX = (int) (e.getX() / getCurrentScaleFactor()) - (int) currentHorizontalLocation; selectedY = (int) (e.getY() / getCurrentScaleFactor()) - (int) currentVerticalLocation; double z; if (isLogPlot) { z = Math.log(data[selectedX][selectedY]); } else { z = data[selectedX][selectedY]; } selectedZ = z; updateTooltipString(); nodifyMouseMoved(); } catch (Exception excep) { } } public void mouseWheelMoved(MouseWheelEvent e) { if (bufferedImage == null) { return; } currentScaleFactor = currentScaleFactor * (1 - e.getWheelRotation() / 20.0f); transform(currentScaleFactor, (int) currentHorizontalLocation, (int) currentVerticalLocation); notifyBufferChanged(); } public void keyPressed(KeyEvent e) { } public void keyTyped(KeyEvent e) { } public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_F2) { showToolTip = !showToolTip; ToolTipManager.sharedInstance().setEnabled(showToolTip); } } } /** * * @author Dr. Richard St. John * @version $Revision: 1.11 $, $Date: 2007/10/09 17:39:22 $ */ private class RangeDialog extends JDialog implements ActionListener { public static final String ACTION_RESTORE_DEFAULTS = "RANGE_DEFAULTS"; public static final String ACTION_PREVIEW = "RANGE_PREVIEW"; private JRadioButton radioFrameRange, radioSeriesRange, radioGridRange, radioUserDefined; private JTextField fieldMax, fieldMin; public RangeDialog() { super(new Frame(), "Range Dialog for Setting Minimum and Maximum", true); setContentPane(createContentPane()); pack(); centerOnScreen(); setResizable(false); setVisible(true); } private JPanel createContentPane() { ButtonGroup rangeGroup = new ButtonGroup(); rangeGroup.add(radioFrameRange = new JRadioButton("Frame Minimum / Maximum", minMaxSelection == RANGE_AUTO_SCALE)); rangeGroup.add(radioSeriesRange = new JRadioButton("This Series Minimum / Maximum", minMaxSelection == RANGE_SERIES_RANGE)); rangeGroup.add(radioGridRange = new JRadioButton("All Series Minimum / Maximum", minMaxSelection == RANGE_GLOBAL_RANGE)); rangeGroup.add( radioUserDefined = new JRadioButton("User Defined Range", minMaxSelection == RANGE_USER_RANGE)); radioFrameRange.setActionCommand("USER_DEFINED"); radioFrameRange.addActionListener(this); radioSeriesRange.setActionCommand("USER_DEFINED"); radioSeriesRange.addActionListener(this); radioGridRange.setActionCommand("USER_DEFINED"); radioGridRange.addActionListener(this); radioUserDefined.setActionCommand("USER_DEFINED"); radioUserDefined.addActionListener(this); JPanel panelType = new JPanel(); panelType.setLayout(new BoxLayout(panelType, BoxLayout.Y_AXIS)); panelType.setBorder(BorderFactory.createTitledBorder("Select Zoom Type")); panelType.add(radioFrameRange); panelType.add(radioSeriesRange); panelType.add(radioGridRange); panelType.add(radioUserDefined); fieldMin = new JTextField(String.valueOf(getDataMin()), 15); fieldMin.setName("Set Minimum Range: "); fieldMin.setEnabled(minMaxSelection == RANGE_USER_RANGE); JLabel labelRangeMin = new JLabel(fieldMin.getName()); fieldMax = new JTextField(String.valueOf(getDataMax()), 15); fieldMax.setName("Set Maximum Range: "); fieldMax.setEnabled(minMaxSelection == RANGE_USER_RANGE); JLabel labelRangeMax = new JLabel(fieldMax.getName()); Dimension labelDim = labelRangeMax.getPreferredSize(); labelRangeMin.setPreferredSize(labelDim); labelRangeMin.setMinimumSize(labelDim); labelRangeMax.setPreferredSize(labelDim); labelRangeMax.setMinimumSize(labelDim); JPanel panelRange = new JPanel(new MigLayout()); panelRange.add(labelRangeMin); panelRange.add(fieldMin, "wrap"); panelRange.add(labelRangeMax); panelRange.add(fieldMax, "wrap"); JPanel panelButton = new JPanel(); panelButton.add(createButton("Preview", this, ACTION_PREVIEW)); panelButton.add(createButton("Default", this, ACTION_RESTORE_DEFAULTS)); panelButton.add(createButton("Close", this, "CLOSE")); JPanel panel = new JPanel(new MigLayout()); panel.add(panelType, "pushx, growx, wrap"); panel.add(panelRange, "pushx, growx, wrap"); panel.add(panelButton); return panel; } private JButton createButton(String title, ActionListener al, String actionCommand) { JButton button = new JButton(title); button.addActionListener(al); button.setActionCommand(actionCommand); return button; } private void centerOnScreen() { Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension screenSize = toolkit.getScreenSize(); int x = (screenSize.width - getPanelWidth()) / 2; int y = (screenSize.height - getPanelHeight()) / 2; setLocation(x, y); } public void actionPerformed(ActionEvent e) { if (radioFrameRange.isSelected()) { minMaxSelection = RANGE_AUTO_SCALE; } else if (radioSeriesRange.isSelected()) { minMaxSelection = RANGE_SERIES_RANGE; } else if (radioGridRange.isSelected()) { minMaxSelection = RANGE_GLOBAL_RANGE; } else { minMaxSelection = RANGE_USER_RANGE; } String command = e.getActionCommand(); if (command.equalsIgnoreCase("CLOSE")) { setVisible(false); } else if (command.equalsIgnoreCase("USER_DEFINED")) { if (radioUserDefined.isSelected()) { fieldMin.setEnabled(true); fieldMax.setEnabled(true); } else { fieldMin.setEnabled(false); fieldMax.setEnabled(false); } } else if (command.equalsIgnoreCase(ACTION_PREVIEW)) { actionRangePreview(); } else if (command.equalsIgnoreCase(ACTION_RESTORE_DEFAULTS)) { isAutoScaled = true; radioFrameRange.setSelected(true); canvasListener.updateCanvasData(data); } } private void actionRangePreview() { if (radioUserDefined.isSelected()) { setDataRange(Double.parseDouble(fieldMin.getText()), Double.parseDouble(fieldMax.getText())); isAutoScaled = false; } else if (radioSeriesRange.isSelected()) { try { isAutoScaled = false; //computeSeriesMinMax(); setDataRange(getSeriesMin(), getSeriesMax()); } catch (Exception e) { e.printStackTrace(); } } else { isAutoScaled = true; } canvasListener.updateCanvasData(data); } } /** * @author Dr. Richard St. John * @version $Revision: 1.11 $, $Date: 2007/10/09 17:39:22 $ */ private class PhysicalExtentDialog extends JDialog implements ActionListener { public static final String ACTION_PREVIEW = "PHYSICAL_EXTENT_PREVIEW"; public static final String ACTION_DEFAULT = "PHYSICAL_EXTENT_DEFAULT"; private JTextField fieldPhysicalExtentX; public PhysicalExtentDialog() { super(new JFrame(), "Physical Extent Dialog", true); setContentPane(createContentPane()); pack(); centerOnScreen(); setResizable(false); setVisible(true); } private JPanel createContentPane() { fieldPhysicalExtentX = new JTextField(8); fieldPhysicalExtentX .setText(String.valueOf(getPanelWidth() * getGridSpacingX() / getCurrentScaleFactor())); JPanel panelExtent = new JPanel(new MigLayout()); panelExtent.setBorder(BorderFactory.createTitledBorder("Set Desired Physical Extent")); panelExtent.add(createLabel("Horizontal Physical Extent (meters)")); panelExtent.add(fieldPhysicalExtentX, "pushx, growx"); JPanel panelButton = new JPanel(); panelButton.add(createButton("Default", this, ACTION_DEFAULT)); panelButton.add(createButton("Preview", this, ACTION_PREVIEW)); panelButton.add(createButton("Close", this, "CLOSE")); JPanel panel = new JPanel(new MigLayout()); panel.add(panelExtent, "pushx, growx, wrap"); panel.add(panelButton, "pushx, growx"); return panel; } private JLabel createLabel(String label) { JLabel jlabel = new JLabel(label); jlabel.setFont(jlabel.getFont().deriveFont(10.0f)); return jlabel; } private JButton createButton(String title, ActionListener al, String actionCommand) { JButton button = new JButton(title); button.addActionListener(al); button.setActionCommand(actionCommand); return button; } private void centerOnScreen() { Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension screenSize = toolkit.getScreenSize(); int x = (screenSize.width - getWidth()) / 2; int y = (screenSize.height - getHeight()) / 2; setLocation(x, y); } public void actionPerformed(ActionEvent e) { double extent = 0; String command = e.getActionCommand(); if (command.equalsIgnoreCase("CLOSE")) { setVisible(false); return; } else if (command.equalsIgnoreCase(PhysicalExtentDialog.ACTION_PREVIEW)) { extent = Double.parseDouble(fieldPhysicalExtentX.getText()); } else if (command.equalsIgnoreCase(PhysicalExtentDialog.ACTION_DEFAULT)) { extent = gridSpacingX * bufferedImage.getWidth(); fieldPhysicalExtentX.setText(String.valueOf(extent)); } currentScaleFactor = getPanelWidth() * gridSpacingX / extent; scaleImage(currentScaleFactor); notifyBufferChanged(); } } /** * @author Dr. Richard St. John * @version $Revision: 1.11 $, $Date: 2007/10/09 17:39:22 $ */ private class ZoomDialog extends JDialog implements ActionListener { public static final String ACTION_PREVIEW = "ZOOM_PREVIEW"; private JComboBox comboInterpMethod; private JTextField zoomField; public ZoomDialog() { super(new Frame(), "Zoom Level Dialog", true); setContentPane(createContentPane()); pack(); centerOnScreen(); setResizable(false); setVisible(true); } private JPanel createContentPane() { zoomField = new JTextField(11); zoomField.setName("Zoom Level"); zoomField.setText(String.valueOf(currentScaleFactor)); comboInterpMethod = new JComboBox(new String[] { "Nearest Neighbor", "Bilinear", "Bicubic" }); JPanel panel = new JPanel(new MigLayout()); panel.add(new JLabel("Zoom Level")); panel.add(zoomField, "pushx, growx, wrap"); panel.add(new JLabel("Interpolation")); panel.add(comboInterpMethod, "pushx, growx, wrap"); panel.add(createButton("Preview", this, ACTION_PREVIEW), "spanx, split 2, tag ok"); panel.add(createButton("Close", this, "CLOSE"), "tag cancel"); return panel; } private JButton createButton(String title, ActionListener al, String actionCommand) { JButton button = new JButton(title); button.addActionListener(al); button.setActionCommand(actionCommand); return button; } private void centerOnScreen() { Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension screenSize = toolkit.getScreenSize(); int x = (screenSize.width - getWidth()) / 2; int y = (screenSize.height - getHeight()) / 2; setLocation(x, y); } public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equalsIgnoreCase("CLOSE")) { setVisible(false); } else if (command.equalsIgnoreCase(ACTION_PREVIEW)) { currentScaleFactor = Double.parseDouble(zoomField.getText()); int interpMethod = 0; switch (comboInterpMethod.getSelectedIndex()) { case 0: interpMethod = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; break; case 1: interpMethod = AffineTransformOp.TYPE_BILINEAR; break; case 2: interpMethod = AffineTransformOp.TYPE_BICUBIC; break; } setInterpolationMethod(interpMethod); scaleImage(currentScaleFactor); setInterpolationMethod(AffineTransformOp.TYPE_NEAREST_NEIGHBOR); notifyBufferChanged(); } } } }