Java tutorial
/******************************************************************************* * Copyright (c) 2010 Australian Nuclear Science and Technology Organisation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Norman Xiong (nxi@Bragg Institute) - initial API and implementation ******************************************************************************/ package org.gumtree.vis.hist2d; import java.awt.Color; import java.awt.Cursor; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import org.eclipse.swt.SWT; import org.gumtree.vis.awt.JChartPanel; import org.gumtree.vis.core.internal.StaticValues; import org.gumtree.vis.dataset.DatasetUtils; import org.gumtree.vis.dataset.DatasetUtils.ExportFormat; import org.gumtree.vis.hist2d.color.ColorScale; import org.gumtree.vis.interfaces.IDataset; import org.gumtree.vis.interfaces.IExporter; import org.gumtree.vis.interfaces.IHelpProvider; import org.gumtree.vis.interfaces.IHist2D; import org.gumtree.vis.interfaces.IXYZDataset; import org.gumtree.vis.listener.XYZChartMouseEvent; import org.gumtree.vis.mask.Abstract2DMask; import org.gumtree.vis.mask.AbstractMask; import org.gumtree.vis.mask.ChartMaskingUtilities; import org.gumtree.vis.mask.EllipseMask; import org.gumtree.vis.mask.RectangleMask; import org.jfree.chart.ChartMouseListener; import org.jfree.chart.JFreeChart; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.EntityCollection; import org.jfree.chart.entity.XYItemEntity; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.PaintScale; import org.jfree.chart.renderer.xy.XYBlockRenderer; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.chart.title.PaintScaleLegend; import org.jfree.chart.title.Title; import org.jfree.data.general.DatasetChangeEvent; import org.jfree.data.general.DatasetChangeListener; import org.jfree.data.xy.XYZDataset; import org.jfree.ui.ExtensionFileFilter; /** * @author nxi * */ public class Hist2DPanel extends JChartPanel implements IHist2D, DatasetChangeListener { /** * */ public static final Color MASK_INCLUSIVE_COLOR = new Color(0, 220, 0, 75); public static final Color MASK_EXCLUSIVE_COLOR = new Color(220, 220, 220, 75); private static final long serialVersionUID = -6844570933617261485L; private static final String RESET_COLOR_SCALE_COMMAND = "resetColorScale"; /** * Masking parameters */ // private final static int numberOfMaskColors = 8; private static final Color axisTraceColor = Color.cyan; /** Remove the selected mask command. */ private Point2D maskPoint = null; private JMenuItem resetColorScaleMenuItem; private Abstract2DMask currentMaskRectangle = null; // private List<RectangleMask> exclusiveMaskList; private Point2D maskMovePoint; private double chartZ = Double.NaN; private int mouseFollowerXPrecision; private int mouseFollowerYPrecision; private int mouseFollowerZPrecision; // private static final Cursor defaultCursor = Cursor.getPredefinedCursor( // Cursor.DEFAULT_CURSOR); // private static final Cursor westResizeCursor = Cursor.getPredefinedCursor( // Cursor.W_RESIZE_CURSOR); // private static final Cursor eastResizeCursor = Cursor.getPredefinedCursor( // Cursor.E_RESIZE_CURSOR); // private static final Cursor northResizeCursor = Cursor.getPredefinedCursor( // Cursor.N_RESIZE_CURSOR); // private static final Cursor southResizeCursor = Cursor.getPredefinedCursor( // Cursor.S_RESIZE_CURSOR); // private static final Cursor northwestResizeCursor = Cursor.getPredefinedCursor( // Cursor.NW_RESIZE_CURSOR); // private static final Cursor northeastResizeCursor = Cursor.getPredefinedCursor( // Cursor.NE_RESIZE_CURSOR); // private static final Cursor southwestResizeCursor = Cursor.getPredefinedCursor( // Cursor.SW_RESIZE_CURSOR); // private static final Cursor southeastResizeCursor = Cursor.getPredefinedCursor( // Cursor.SE_RESIZE_CURSOR); // private static final Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); // private static final Cursor MOVE_CURSOR = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); /** * @param chart */ public Hist2DPanel(JFreeChart chart) { this(chart, StaticValues.PANEL_WIDTH, StaticValues.PANEL_HEIGHT, StaticValues.PANEL_MINIMUM_DRAW_WIDTH, StaticValues.PANEL_MINIMUM_DRAW_HEIGHT, StaticValues.PANEL_MAXIMUM_DRAW_WIDTH, StaticValues.PANEL_MAXIMUM_DRAW_HEIGHT, DEFAULT_BUFFER_USED, true, // properties true, // save true, // print true, // zoom true // tooltips ); } /** * @param chart * @param useBuffer */ public Hist2DPanel(JFreeChart chart, boolean useBuffer) { this(chart, StaticValues.PANEL_WIDTH, StaticValues.PANEL_HEIGHT, StaticValues.PANEL_MINIMUM_DRAW_WIDTH, StaticValues.PANEL_MINIMUM_DRAW_HEIGHT, StaticValues.PANEL_MAXIMUM_DRAW_WIDTH, StaticValues.PANEL_MAXIMUM_DRAW_HEIGHT, useBuffer, true, // properties true, // save true, // print true, // zoom true // tooltips ); } /** * @param chart * @param properties * @param save * @param print * @param zoom * @param tooltips */ public Hist2DPanel(JFreeChart chart, boolean properties, boolean save, boolean print, boolean zoom, boolean tooltips) { this(chart, StaticValues.PANEL_WIDTH, StaticValues.PANEL_HEIGHT, StaticValues.PANEL_MINIMUM_DRAW_WIDTH, StaticValues.PANEL_MINIMUM_DRAW_HEIGHT, StaticValues.PANEL_MAXIMUM_DRAW_WIDTH, StaticValues.PANEL_MAXIMUM_DRAW_HEIGHT, DEFAULT_BUFFER_USED, properties, save, print, zoom, tooltips); } /** * @param chart * @param width * @param height * @param minimumDrawWidth * @param minimumDrawHeight * @param maximumDrawWidth * @param maximumDrawHeight * @param useBuffer * @param properties * @param save * @param print * @param zoom * @param tooltips */ public Hist2DPanel(JFreeChart chart, int width, int height, int minimumDrawWidth, int minimumDrawHeight, int maximumDrawWidth, int maximumDrawHeight, boolean useBuffer, boolean properties, boolean save, boolean print, boolean zoom, boolean tooltips) { this(chart, width, height, minimumDrawWidth, minimumDrawHeight, maximumDrawWidth, maximumDrawHeight, useBuffer, properties, true, save, print, zoom, tooltips); } /** * @param chart * @param width * @param height * @param minimumDrawWidth * @param minimumDrawHeight * @param maximumDrawWidth * @param maximumDrawHeight * @param useBuffer * @param properties * @param copy * @param save * @param print * @param zoom * @param tooltips */ public Hist2DPanel(JFreeChart chart, int width, int height, int minimumDrawWidth, int minimumDrawHeight, int maximumDrawWidth, int maximumDrawHeight, boolean useBuffer, boolean properties, boolean copy, boolean save, boolean print, boolean zoom, boolean tooltips) { super(chart, width, height, minimumDrawWidth, minimumDrawHeight, maximumDrawWidth, maximumDrawHeight, useBuffer, properties, copy, save, print, zoom, tooltips); String showColorScaleProperty = System.getProperty(StaticValues.SHOW_COLORSCALE_PROPERTY); if (showColorScaleProperty != null) { boolean showColorScale = true; try { showColorScale = Boolean.valueOf(showColorScaleProperty); chart.setShowSubtitle(showColorScale); } catch (Exception e) { } } createMaskColors(true); mouseFollowerXPrecision = 2; mouseFollowerYPrecision = 2; mouseFollowerZPrecision = 2; } // @Override // public void actionPerformed(ActionEvent event) { // String command = event.getActionCommand(); // if (command.equals(REMOVE_SELECTED_MASK_COMMAND)) { // removeSelectedMask(); // repaint(); // } else if (command.equals(DESELECT_MASK_COMMAND)) { // selectMask(null); // repaint(); // } else if (command.startsWith(SELECT_MASK_COMMAND)) { // String[] commands = command.split("-", 2); // if (commands.length > 1) { // selectMask(commands[1]); // repaint(); // } // } else { // super.actionPerformed(event); // } // } private void changeMaskXMax(double x) { Rectangle2D frame = getSelectedMask().getRectangleFrame(); getSelectedMask().setRectangleFrame(new Rectangle2D.Double(Math.min(frame.getMinX(), x), frame.getMinY(), Math.abs(frame.getMinX() - x), frame.getHeight())); } private void changeMaskXMin(double x) { Rectangle2D frame = getSelectedMask().getRectangleFrame(); getSelectedMask().setRectangleFrame(new Rectangle2D.Double(Math.min(frame.getMaxX(), x), frame.getMinY(), Math.abs(frame.getMaxX() - x), frame.getHeight())); } private void changeMaskYMax(double y) { Rectangle2D frame = getSelectedMask().getRectangleFrame(); getSelectedMask().setRectangleFrame(new Rectangle2D.Double(frame.getMinX(), Math.min(frame.getMinY(), y), frame.getWidth(), Math.abs(frame.getMinY() - y))); } private void changeMaskYMin(double y) { Rectangle2D frame = getSelectedMask().getRectangleFrame(); getSelectedMask().setRectangleFrame(new Rectangle2D.Double(frame.getMinX(), Math.min(frame.getMaxY(), y), frame.getWidth(), Math.abs(frame.getMaxY() - y))); } private void changeSelectedMask(Point2D point) { switch (getMaskDragIndicator()) { case Cursor.MOVE_CURSOR: moveMask(point); break; case Cursor.W_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getDomainAxis().isInverted()) { changeMaskXMax(point.getX()); } else { changeMaskXMin(point.getX()); } break; case Cursor.E_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getDomainAxis().isInverted()) { changeMaskXMin(point.getX()); } else { changeMaskXMax(point.getX()); } break; case Cursor.N_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getRangeAxis().isInverted()) { changeMaskYMin(point.getY()); } else { changeMaskYMax(point.getY()); } break; case Cursor.S_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getRangeAxis().isInverted()) { changeMaskYMax(point.getY()); } else { changeMaskYMin(point.getY()); } break; case Cursor.NW_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getDomainAxis().isInverted()) { changeMaskXMax(point.getX()); } else { changeMaskXMin(point.getX()); } if (((XYPlot) getChart().getPlot()).getRangeAxis().isInverted()) { changeMaskYMin(point.getY()); } else { changeMaskYMax(point.getY()); } break; case Cursor.NE_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getDomainAxis().isInverted()) { changeMaskXMin(point.getX()); } else { changeMaskXMax(point.getX()); } if (((XYPlot) getChart().getPlot()).getRangeAxis().isInverted()) { changeMaskYMin(point.getY()); } else { changeMaskYMax(point.getY()); } break; case Cursor.SW_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getDomainAxis().isInverted()) { changeMaskXMax(point.getX()); } else { changeMaskXMin(point.getX()); } if (((XYPlot) getChart().getPlot()).getRangeAxis().isInverted()) { changeMaskYMax(point.getY()); } else { changeMaskYMin(point.getY()); } break; case Cursor.SE_RESIZE_CURSOR: if (((XYPlot) getChart().getPlot()).getDomainAxis().isInverted()) { changeMaskXMin(point.getX()); } else { changeMaskXMax(point.getX()); } if (((XYPlot) getChart().getPlot()).getRangeAxis().isInverted()) { changeMaskYMax(point.getY()); } else { changeMaskYMin(point.getY()); } break; default: break; } fireMaskUpdateEvent(getSelectedMask()); } // @Override // public void createChartPrintJob() { // setCursor(WAIT_CURSOR); // PrinterJob job = PrinterJob.getPrinterJob(); // setCursor(WAIT_CURSOR); // PageFormat pf = job.defaultPage(); // PageFormat pf2 = job.pageDialog(pf); // if (pf2 != pf) { // job.setPrintable(this, pf2); // try { // job.print(); // } // catch (PrinterException e) { // JOptionPane.showMessageDialog(this, e); // } finally { // setCursor(defaultCursor); // } // } // setCursor(defaultCursor); // } // @Override // protected JPopupMenu createPopupMenu(boolean properties, boolean copy, // boolean save, boolean print, boolean zoom) { // JPopupMenu result = super.createPopupMenu(properties, copy, save, print, zoom); // this.removeSelectedMaskMenuItem = new JMenuItem(); // this.removeSelectedMaskMenuItem.setActionCommand(REMOVE_SELECTED_MASK_COMMAND); // this.removeSelectedMaskMenuItem.addActionListener(this); // result.addSeparator(); // result.add(removeSelectedMaskMenuItem); // maskManagementMenu = new JMenu("Mask Management"); // result.add(maskManagementMenu); // return result; // } // private void createMaskColors() { // inclusiveMaskColor = new Color[numberOfMaskColors]; // exclusiveMaskColor = new Color[numberOfMaskColors]; // int interval = 155 / numberOfMaskColors; // for (int i = 0; i < numberOfMaskColors; i++) { // int value = 255 - i * interval; // inclusiveMaskColor[i] = new Color(0, value, 0, 100); // exclusiveMaskColor[i] = new Color(value, value, value, 100); // } // } // @Override // protected void displayPopupMenu(int x, int y) { // if (this.removeSelectedMaskMenuItem != null) { // boolean isRemoveMenuEnabled = false; // if (this.selectedMask != null) { // Abstract2DMask screenMask = ChartMaskingUtilities.translateChartRectangle( // selectedMask, getScreenDataArea(), getChart()); // if (screenMask.getShape().contains(x, y)) { // isRemoveMenuEnabled = true; // } // } // this.removeSelectedMaskMenuItem.setEnabled(isRemoveMenuEnabled); // if (isRemoveMenuEnabled) { // removeSelectedMaskMenuItem.setVisible(true); // removeSelectedMaskMenuItem.setText("Remove " + selectedMask.getName()); // } else { // // removeSelectedMaskMenuItem.setText("Mask Management"); // removeSelectedMaskMenuItem.setVisible(false); // } // } // maskManagementMenu.removeAll(); // if (maskList.size() > 0) { // maskManagementMenu.setEnabled(true); // JMenuItem selectNoneMaskItem = new JRadioButtonMenuItem(); // selectNoneMaskItem.setText("Select None"); // selectNoneMaskItem.setActionCommand(DESELECT_MASK_COMMAND); // selectNoneMaskItem.addActionListener(this); // maskManagementMenu.add(selectNoneMaskItem); // boolean isInShade = false; // for (Abstract2DMask mask : maskList) { // Abstract2DMask screenMask = ChartMaskingUtilities.translateChartRectangle( // mask, getScreenDataArea(), getChart()); // if (screenMask.getShape().contains(x, y)) { // JMenuItem selectMaskItem = new JRadioButtonMenuItem(); // selectMaskItem.setText("Select " + mask.getName()); // selectMaskItem.setActionCommand(SELECT_MASK_COMMAND // + "-" + mask.getName()); // if (mask == selectedMask) { // selectMaskItem.setSelected(true); // } // selectMaskItem.addActionListener(this); // maskManagementMenu.add(selectMaskItem); // isInShade = true; // } // } // if (isInShade) { // if (selectedMask == null) { // selectNoneMaskItem.setSelected(true); // } // } else { // for (Abstract2DMask mask : maskList) { // JMenuItem selectMaskItem = new JRadioButtonMenuItem(); // selectMaskItem.setText("Select " + mask.getName()); // selectMaskItem.setActionCommand(SELECT_MASK_COMMAND // + "-" + mask.getName()); // if (mask == selectedMask) { // selectMaskItem.setSelected(true); // } // selectMaskItem.addActionListener(this); // maskManagementMenu.add(selectMaskItem); // } // selectNoneMaskItem.setSelected(selectedMask == null); // } // } else { // maskManagementMenu.setEnabled(false); // } // super.displayPopupMenu(x, y); // } // /** // * Copies the current chart to the system clipboard. // * // * @since 1.0.13 // */ // @Override // public void doCopy() { // final Clipboard systemClipboard // = Toolkit.getDefaultToolkit().getSystemClipboard(); // Rectangle2D screenArea = getScreenDataArea(); // final ChartTransferableWithMask selection = new ChartTransferableWithMask( // getChart(), getWidth(), getHeight(), screenArea, maskList); // Cursor currentCursor = getCursor(); // setCursor(WAIT_CURSOR); // systemClipboard.setContents(selection, null); // setCursor(currentCursor); // } private void showPropertyEditor(int tabIndex) { Hist2DChartEditor editor = new Hist2DChartEditor(getChart(), this); editor.getTabs().setSelectedIndex(tabIndex); int result = JOptionPane.showConfirmDialog(this, editor, localizationResources.getString("Chart_Properties"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result == JOptionPane.OK_OPTION) { editor.updateChart(getChart()); } } @Override public void doEditChartProperties() { showPropertyEditor(0); } public void doEditMaskProperties() { showPropertyEditor(1); } // @Override // public void doSaveAs() throws IOException { // // Display.getDefault().asyncExec(new Runnable() { // // Shell shell; // // private void handleException(Exception e) { // if (shell != null) { // MessageDialog.openError(shell, "Failed to Save", "failed to save " + // "the image: " + e.getMessage()); // // } // } // // @Override // public void run() { // try { // shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); // }catch (Exception e) { // e.printStackTrace(); // } // if (shell != null) { // FileDialog fileDialog = new FileDialog(shell, SWT.SAVE); // String[] extensions = {"*.png", "*.jpg"}; // String[] typeNames = {"PNG IMAGE FILE", "JPEG IMAGE FILE"}; // String systemSavePath = System.getProperty("SYSTEM_SAVE_PATH"); // if (systemSavePath != null) { // fileDialog.setFilterPath(systemSavePath); // } // fileDialog.setFilterExtensions(extensions); // fileDialog.setFilterNames(typeNames); // String filename = fileDialog.open(); // // if (filename != null) { // int filterIndex = fileDialog.getFilterIndex(); // if (filterIndex == 0) { // if (!filename.endsWith(".png")) { // filename = filename + ".png"; // } // try { // ChartMaskingUtilities.writeChartAsPNG(new File(filename), getChart(), // getWidth(), getHeight(), null, getScreenDataArea(), // getMasks()); // } catch (IOException e) { // handleException(e); // } // } else if (filterIndex == 1) { // if (!filename.endsWith(".jpg")) { // filename = filename + ".jpg"; // } // try { // ChartMaskingUtilities.writeChartAsJPEG(new File(filename), getChart(), // getWidth(), getHeight(), null, getScreenDataArea(), getMasks()); // } catch (IOException e) { // handleException(e); // } // } // System.setProperty("SYSTEM_SAVE_PATH", fileDialog.getFilterPath()); // } // } else { // try { // superDoSaveAs(); // } catch (IOException e) { // handleException(e); // } // } // // } // }); // } protected int findCursorOnSelectedItem(int x, int y) { if (getSelectedMask() != null && !getSelectedMask().getRectangleFrame().isEmpty()) { Rectangle2D screenArea = getScreenDataArea(); Rectangle2D maskArea = ChartMaskingUtilities .translateChartRectangle(getSelectedMask(), getScreenDataArea(), getChart()) .getRectangleFrame(); Rectangle2D intersect = screenArea.createIntersection(maskArea); Point2D point = new Point2D.Double(x, y); double minX = maskArea.getMinX(); double maxX = maskArea.getMaxX(); double minY = maskArea.getMinY(); double maxY = maskArea.getMaxY(); double width = maskArea.getWidth(); double height = maskArea.getHeight(); if (!intersect.isEmpty() && screenArea.contains(point)) { // if (y > minY && y < maxY) { // if (minX > screenArea.getMinX() + 1 // && minX < screenArea.getMaxX() - 1) { // if (x > minX - 4 && x < minX + (width < 8 ? width / 2 : 4)) { // return Cursor.W_RESIZE_CURSOR; // } // } // if (maxX > screenArea.getMinX() + 1 // && maxX < screenArea.getMaxX() - 1) { // if (x > maxX - (width < 8 ? width / 2 : 4) && x < maxX + 4) { // return Cursor.E_RESIZE_CURSOR; // } // } // } if (height > 8 && width > 8) { Rectangle2D center = new Rectangle2D.Double(minX + 4, minY + 4, width - 8, height - 8); if (screenArea.createIntersection(center).contains(point)) { return Cursor.MOVE_CURSOR; } } if (height > 8) { Rectangle2D west = new Rectangle2D.Double(minX - 4, minY + 4, width < 8 ? width / 2 + 4 : 8, height - 8); if (screenArea.createIntersection(west).contains(point)) { return Cursor.W_RESIZE_CURSOR; } Rectangle2D east = new Rectangle2D.Double(maxX - (width < 8 ? width / 2 : 4), minY + 4, width < 8 ? width / 2 + 4 : 8, height - 8); if (screenArea.createIntersection(east).contains(point)) { return Cursor.E_RESIZE_CURSOR; } } if (width > 8) { Rectangle2D north = new Rectangle2D.Double(minX + 4, minY - 4, width - 8, height < 8 ? height / 2 + 4 : 8); if (screenArea.createIntersection(north).contains(point)) { return Cursor.N_RESIZE_CURSOR; } Rectangle2D south = new Rectangle2D.Double(minX + 4, maxY - (height < 8 ? height / 2 : 4), width - 8, height < 8 ? height / 2 + 4 : 8); if (screenArea.createIntersection(south).contains(point)) { return Cursor.S_RESIZE_CURSOR; } } Rectangle2D northwest = new Rectangle2D.Double(minX - 4, minY - 4, width < 8 ? width / 2 + 4 : 8, height < 8 ? height / 2 + 4 : 8); if (screenArea.createIntersection(northwest).contains(point)) { return Cursor.NW_RESIZE_CURSOR; } Rectangle2D northeast = new Rectangle2D.Double(maxX - (width < 8 ? width / 2 : 4), minY - 4, width < 8 ? width / 2 + 4 : 8, height < 8 ? height / 2 + 4 : 8); if (screenArea.createIntersection(northeast).contains(point)) { return Cursor.NE_RESIZE_CURSOR; } Rectangle2D southwest = new Rectangle2D.Double(minX - 4, maxY - (height < 8 ? height / 2 : 4), width < 8 ? width / 2 + 4 : 8, height < 8 ? height / 2 + 4 : 8); if (screenArea.createIntersection(southwest).contains(point)) { return Cursor.SW_RESIZE_CURSOR; } Rectangle2D southeast = new Rectangle2D.Double(maxX - (width < 8 ? width / 2 : 4), maxY - (height < 8 ? height / 2 : 4), width < 8 ? width / 2 + 4 : 8, height < 8 ? height / 2 + 4 : 8); if (screenArea.createIntersection(southeast).contains(point)) { return Cursor.SE_RESIZE_CURSOR; } } // System.out.println("intersect X:[" + intersect.getMinX() + ", " + // (intersect.getMinX() + intersect.getWidth()) + // "], Y:[" + intersect.getMinY() + ", " + // (intersect.getMinY() + intersect.getHeight()) + // "], x=" + point.getX() + ", y=" + point.getY() + // " " + intersect.contains(point)); } return Cursor.DEFAULT_CURSOR; } // private Color getNextMaskColor(boolean isInclusive){ // Color[] colorSeries = isInclusive ? inclusiveMaskColor : exclusiveMaskColor; // for (int i = 0; i < numberOfMaskColors; i++) { // boolean isUsed = false; // for (Abstract2DMask mask : maskList) { // if (colorSeries[i].equals(mask.getFillColor())) { // isUsed = true; // break; // } // } // if (!isUsed) { // return colorSeries[i]; // } // } // Color lastColor = null; // for (int i = maskList.size() - 1; i >= 0; i--) { // Abstract2DMask mask = maskList.get(i); // if (mask.isInclusive() == isInclusive) { // lastColor = maskList.get(i).getFillColor(); // break; // } // } // int nextColorIndex = 0; // for (int i = 0; i < numberOfMaskColors; i++) { // if (colorSeries[i].equals(lastColor)) { // nextColorIndex = i + 1; // if (nextColorIndex >= numberOfMaskColors) { // nextColorIndex = 0; // } // } // } // return colorSeries[nextColorIndex]; // } // public boolean isChartPointInScreen(Point point) { // XYPlot plot = getChart().getXYPlot(); // Range domainSection = plot.getDomainAxis().getRange(); // Range rangeSection = plot.getDomainAxis().getRange(); // return domainSection.contains(point.x) && rangeSection.contains(point.y); // } /** * Receives notification of mouse clicks on the panel. These are * translated and passed on to any registered {@link ChartMouseListener}s. * * @param event Information about the mouse event. */ public void mouseClicked(MouseEvent event) { Insets insets = getInsets(); int x = (int) ((event.getX() - insets.left) / getScaleX()); int y = (int) ((event.getY() - insets.top) / getScaleY()); double chartX = 0; double chartY = 0; double chartZ = 0; setAnchor(new Point2D.Double(x, y)); if (getChart() == null) { return; } // this.chart.setNotify(true); // force a redraw // new entity code... // Object[] listeners = this.chartMouseListeners.getListeners( // ChartMouseListener.class); ChartEntity entity = null; if (getChartRenderingInfo() != null) { EntityCollection entities = getChartRenderingInfo().getEntityCollection(); if (entities != null) { entity = entities.getEntity(x, y); } } if (entity instanceof XYItemEntity) { IDataset dataset = (IDataset) ((XYItemEntity) entity).getDataset(); int item = ((XYItemEntity) entity).getItem(); chartX = dataset.getXValue(0, item); chartY = dataset.getYValue(0, item); chartZ = ((XYZDataset) dataset).getZValue(0, item); // System.out.println("px=" + x + ", py=" + y); // System.out.println("x=" + chartX + ", y=" + chartY + ", z=" + chartZ); // Point2D trsPoint = translateChartPoint(new Point2D.Double(chartX, chartY)); // System.out.println("tx=" + trsPoint.getX() + ", y=" + trsPoint.getY()); // if ((event.getModifiers() & maskingSelectionMask) != 0) { // selectMask(chartX, chartY); // repaint(); // } else { // if (getSelectedMask() != null && (event.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 // && !getSelectedMask().getShape().contains(chartX, chartY)) { // selectMask(null); // repaint(); // } // } if ((event.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) { selectMask(chartX, chartY); repaint(); } } Object[] listeners = getListeners(ChartMouseListener.class); XYZChartMouseEvent chartEvent = new XYZChartMouseEvent(getChart(), event, entity); chartEvent.setXYZ(chartX, chartY, chartZ); for (int i = listeners.length - 1; i >= 0; i -= 1) { ((ChartMouseListener) listeners[i]).chartMouseClicked(chartEvent); } } /** * Handles a 'mouse dragged' event. * * @param e the mouse event. */ public void mouseDragged(MouseEvent e) { setHorizontalTraceLocation(e.getX()); setVerticalTraceLocation(e.getY()); Insets insets = getInsets(); int x = (int) ((e.getX() - insets.left) / getScaleX()); int y = (int) ((e.getY() - insets.top) / getScaleY()); EntityCollection entities = null; ChartEntity entity = null; if (getChartRenderingInfo() != null) { entities = getChartRenderingInfo().getEntityCollection(); if (entities != null) { entity = entities.getEntity(x, y); } } if (entity instanceof XYItemEntity) { IDataset dataset = (IDataset) ((XYItemEntity) entity).getDataset(); int item = ((XYItemEntity) entity).getItem(); setChartX(dataset.getXValue(0, item)); setChartY(dataset.getYValue(0, item)); setChartZ(((XYZDataset) dataset).getZValue(0, item)); } // if (isMaskingEnabled() && (e.getModifiers() & maskingKeyMask) != 0) { if (isMaskingEnabled()) { int cursorType = findCursorOnSelectedItem(e.getX(), e.getY()); setCursor(Cursor.getPredefinedCursor(cursorType)); } else if (getCursor() != defaultCursor) { setCursor(defaultCursor); } // we can only generate events if the panel's chart is not null // (see bug report 1556951) Object[] listeners = getListeners(ChartMouseListener.class); if (getChart() != null) { XYZChartMouseEvent event = new XYZChartMouseEvent(getChart(), e, entity); event.setXYZ(getChartX(), getChartY(), getChartZ()); for (int i = listeners.length - 1; i >= 0; i -= 1) { ((ChartMouseListener) listeners[i]).chartMouseMoved(event); } } if (getMaskDragIndicator() != Cursor.DEFAULT_CURSOR && getSelectedMask() != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) { changeSelectedMask(e, entities); } else if (isMaskingEnabled() && (e.getModifiers() & maskingKeyMask) != 0) { makeNewMask(e, entities); } else { super.mouseDragged(e); } } private void changeSelectedMask(MouseEvent e, EntityCollection entities) { // Do masking service // if no initial masking point was set, ignore dragging... Rectangle2D screenArea = getScreenDataArea(); Point2D screenPoint = translateScreenToJava2D(e.getPoint()); // System.out.println("screen point is [" + screenPoint.getX() + ", " + // screenPoint.getY() + "]"); if (screenArea.contains(screenPoint)) { Point2D chartPoint = translateScreenToChart(screenPoint); if (chartPoint != null) { // System.out.println("chart point is [" + chartPoint.getX() + ", " + // chartPoint.getY() + "]"); changeSelectedMask(chartPoint); repaint(); } } } private void makeNewMask(MouseEvent e, EntityCollection entities) { if (this.maskPoint == null) { return; } Graphics2D g2 = (Graphics2D) getGraphics(); // erase the previous zoom rectangle (if any). We only need to do // this is we are using XOR mode, which we do when we're not using // the buffer (if there is a buffer, then at the end of this method we // just trigger a repaint) if (!isDoubleBuffered()) { // drawZoomRectangle(g2, true); ChartMaskingUtilities.drawMasks(g2, getScreenDataArea(), getMaskMap(), getSelectedMask(), getChart()); } // boolean hZoom = false; // boolean vZoom = false; // if (this.orientation == PlotOrientation.HORIZONTAL) { // hZoom = this.rangeZoomable; // vZoom = this.domainZoomable; // } // else { // hZoom = this.domainZoomable; // vZoom = this.rangeZoomable; // } Rectangle2D scaledDataArea = getScreenDataArea((int) this.maskPoint.getX(), (int) this.maskPoint.getY()); // Working on the current mask. Only create one new mask per drag-drawing. if (currentMaskRectangle == null) { boolean isInclusive = (e.getModifiers() & maskingExclusiveMask) == 0; boolean isEllipse = (e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0; if (isEllipse) { currentMaskRectangle = new EllipseMask(isInclusive); } else { currentMaskRectangle = new RectangleMask(isInclusive); } // currentMaskRectangle.setFillColor(getNextMaskColor(isInclusive)); // getMasks().add(currentMaskRectangle); addMask(currentMaskRectangle); } // selected rectangle shouldn't extend outside the data area... double xmax = Math.min(e.getX(), scaledDataArea.getMaxX()); double ymax = Math.min(e.getY(), scaledDataArea.getMaxY()); // Update the current mask. ChartEntity startEntity = null; ChartEntity endEntity = null; boolean isMaskUpdated = false; if (entities != null) { // EntityCollection entities = this.info.getEntityCollection(); // if (entities != null) { Insets insets = getInsets(); double screenX = (maskPoint.getX() - insets.left) / getScaleX(); double screenY = (maskPoint.getY() - insets.top) / getScaleY(); startEntity = entities.getEntity(screenX, screenY); screenX = (xmax - insets.left) / getScaleX(); screenY = (ymax - insets.top) / getScaleY(); if (screenX >= scaledDataArea.getMaxX()) { screenX = scaledDataArea.getMaxX() - 0.001; } if (screenY >= scaledDataArea.getMaxY()) { screenY = scaledDataArea.getMaxY() - 0.001; } endEntity = entities.getEntity(screenX, screenY); // System.out.println("Try to update mask"); if (startEntity instanceof XYItemEntity && endEntity instanceof XYItemEntity) { isMaskUpdated = updateCurrentMaskRectangle((XYItemEntity) startEntity, (XYItemEntity) endEntity); } // } } if (!isMaskUpdated) { currentMaskRectangle.setRectangleFrame(new Rectangle2D.Double(maskPoint.getX(), this.maskPoint.getY(), xmax - this.maskPoint.getX(), ymax - this.maskPoint.getY())); } // Draw the new zoom rectangle... if (isDoubleBuffered()) { repaint(); } else { // with no buffer, we use XOR to draw the rectangle "over" the // chart... ChartMaskingUtilities.drawMasks(g2, getScreenDataArea(), getMaskMap(), getSelectedMask(), getChart()); } g2.dispose(); } /** * Implementation of the MouseMotionListener's method. * * @param e the event. */ public void mouseMoved(MouseEvent e) { if (getHorizontalAxisTrace()) { setHorizontalTraceLocation(e.getX()); } if (getVerticalAxisTrace()) { setVerticalTraceLocation(e.getY()); } Insets insets = getInsets(); int x = (int) ((e.getX() - insets.left) / getScaleX()); int y = (int) ((e.getY() - insets.top) / getScaleY()); ChartEntity entity = null; if (getChartRenderingInfo() != null) { EntityCollection entities = getChartRenderingInfo().getEntityCollection(); if (entities != null) { entity = entities.getEntity(x, y); } } if (entity instanceof XYItemEntity) { IDataset dataset = (IDataset) ((XYItemEntity) entity).getDataset(); int item = ((XYItemEntity) entity).getItem(); setChartX(dataset.getXValue(0, item)); setChartY(dataset.getYValue(0, item)); setChartZ(((XYZDataset) dataset).getZValue(0, item)); } if (getHorizontalAxisTrace() || getVerticalAxisTrace() || isToolTipFollowerEnabled()) { repaint(); } // if ((e.getModifiers() & maskingKeyMask) != 0) { // int cursorType = findSelectedMask(e.getX(), e.getY()); // setCursor(Cursor.getPredefinedCursor(cursorType)); // } else if (getCursor() != defaultCursor) { // setCursor(defaultCursor); // } // // we can only generate events if the panel's chart is not null // (see bug report 1556951) Object[] listeners = getListeners(ChartMouseListener.class); if (getChart() != null) { XYZChartMouseEvent event = new XYZChartMouseEvent(getChart(), e, entity); event.setXYZ(getChartX(), getChartY(), getChartZ()); for (int i = listeners.length - 1; i >= 0; i -= 1) { ((ChartMouseListener) listeners[i]).chartMouseMoved(event); } } super.mouseMoved(e); } @Override public void mousePressed(MouseEvent e) { // int mods = e.getModifiers(); // if (isMaskingEnabled() && (mods & maskingKeyMask) != 0) { if (isMaskingEnabled()) { // Prepare masking service. int cursorType = findCursorOnSelectedItem(e.getX(), e.getY()); if (cursorType == Cursor.DEFAULT_CURSOR) { Rectangle2D screenDataArea = getScreenDataArea(e.getX(), e.getY()); if (screenDataArea != null) { this.maskPoint = getPointInRectangle(e.getX(), e.getY(), screenDataArea); } else { this.maskPoint = null; } } else { if (cursorType == Cursor.MOVE_CURSOR) { Point2D point = translateScreenToChart(translateScreenToJava2D(e.getPoint())); if (point != null) { this.maskMovePoint = point; } } setMaskDragIndicator(cursorType); } } if (getMaskDragIndicator() == Cursor.DEFAULT_CURSOR) { if (e.getX() < getScreenDataArea().getMaxX()) { super.mousePressed(e); } } } /** * Handles a 'mouse released' event. On Windows, we need to check if this * is a popup trigger, but only if we haven't already been tracking a zoom * rectangle. * * @param e information about the event. */ public void mouseReleased(MouseEvent e) { if (currentMaskRectangle != null) { // reset masking service. maskPoint = null; currentMaskRectangle = null; } else { // } else if (getScreenDataArea().contains(e.getPoint())){ super.mouseReleased(e); } setMaskDragIndicator(Cursor.DEFAULT_CURSOR); this.maskMovePoint = null; } private void moveMask(Point2D point) { if (maskMovePoint != null && getSelectedMask() != null) { Rectangle2D frame = getSelectedMask().getRectangleFrame(); getSelectedMask().setRectangleFrame(new Rectangle2D.Double( frame.getMinX() + point.getX() - maskMovePoint.getX(), frame.getMinY() + point.getY() - maskMovePoint.getY(), frame.getWidth(), frame.getHeight())); maskMovePoint = point; fireMaskUpdateEvent(getSelectedMask()); } } @Override public void moveSelectedMask(int direction) { Abstract2DMask selectedMask = getSelectedMask(); if (selectedMask == null) { return; } double blockWidth = 0; double blockHeight = 0; try { XYBlockRenderer render = (XYBlockRenderer) ((XYPlot) getChart().getPlot()).getRenderer(); blockWidth = render.getBlockWidth(); blockHeight = render.getBlockHeight(); if (getChart().getXYPlot().getDomainAxis().isInverted()) { blockWidth = -blockHeight; } if (getChart().getXYPlot().getRangeAxis().isInverted()) { blockHeight = -blockHeight; } } catch (Exception e) { e.printStackTrace(); return; } Rectangle2D frame = selectedMask.getRectangleFrame(); switch (direction) { case SWT.ARROW_UP: selectedMask.setRectangleFrame(new Rectangle2D.Double(frame.getMinX(), frame.getMinY() + blockHeight, frame.getWidth(), frame.getHeight())); break; case SWT.ARROW_LEFT: selectedMask.setRectangleFrame(new Rectangle2D.Double(frame.getMinX() - blockWidth, frame.getMinY(), frame.getWidth(), frame.getHeight())); break; case SWT.ARROW_RIGHT: selectedMask.setRectangleFrame(new Rectangle2D.Double(frame.getMinX() + blockWidth, frame.getMinY(), frame.getWidth(), frame.getHeight())); break; case SWT.ARROW_DOWN: selectedMask.setRectangleFrame(new Rectangle2D.Double(frame.getMinX(), frame.getMinY() - blockHeight, frame.getWidth(), frame.getHeight())); break; default: break; } repaint(); fireMaskUpdateEvent(getSelectedMask()); } @Override protected void drawToolTipFollower(Graphics2D g2, int x, int y) { Rectangle2D dataArea = getScreenDataArea(); if (((int) dataArea.getMinX() < x) && (x < (int) dataArea.getMaxX()) && ((int) dataArea.getMinY() < y) && (y < (int) dataArea.getMaxY())) { String text = String.format("(%." + mouseFollowerXPrecision + "f, %." + mouseFollowerYPrecision + "f, %." + mouseFollowerZPrecision + "f)", getChartX(), getChartY(), getChartZ()); int xLoc = x + 10; int yLoc = y + 20; double width = text.length() * 5.5; double height = 15; if (xLoc + width > dataArea.getMaxX()) { xLoc = (int) (x - width); } if (yLoc + height > dataArea.getMaxY()) { yLoc = (int) (y - height); } Rectangle2D toolTipArea = new Rectangle2D.Double(xLoc, yLoc, width, height); g2.setColor(Color.white); g2.fill(toolTipArea); g2.setColor(Color.black); g2.drawString(text, xLoc + 3, yLoc + 11); } } // @Override // public void paintComponent(Graphics g) { // super.paintComponent(g); // Graphics2D g2 = (Graphics2D) g.create(); // ChartMaskingUtilities.drawMaskRectangle(g2, getScreenDataArea(), // maskList, selectedMask, getChart()); // if (getHorizontalAxisTrace()) { // drawHorizontalAxisTrace(g2, horizontalTraceLocation); // } // if (getVerticalAxisTrace()) { // drawVerticalAxisTrace(g2, verticalTraceLocation); // } // if (isToolTipFollowerEnabled) { // drawToolTipFollower(g2, horizontalTraceLocation, verticalTraceLocation); // } // g2.dispose(); // } // /** // * Prints the chart on a single page. // * // * @param g the graphics context. // * @param pf the page format to use. // * @param pageIndex the index of the page. If not <code>0</code>, nothing // * gets print. // * // * @return The result of printing. // */ // @Override // public int print(Graphics g, PageFormat pf, int pageIndex) { // // if (pageIndex != 0) { // return NO_SUCH_PAGE; // } // Graphics2D g2 = (Graphics2D) g; // double x = pf.getImageableX(); // double y = pf.getImageableY(); // double w = pf.getImageableWidth(); // double h = pf.getImageableHeight(); // double screenWidth = getWidth(); // double screenHeight = getHeight(); // double widthRatio = w / screenWidth; // double heightRatio = h / screenHeight; // double overallRatio = 1; // overallRatio = widthRatio < heightRatio ? widthRatio : heightRatio; // Rectangle2D printArea = new Rectangle2D.Double(x, y, screenWidth * overallRatio, // screenHeight * overallRatio); // XYPlot plot = (XYPlot) getChart().getPlot(); // Font domainFont = plot.getDomainAxis().getLabelFont(); // int domainSize = domainFont.getSize(); // Font rangeFont = plot.getRangeAxis().getLabelFont(); // int rangeSize = rangeFont.getSize(); // Font titleFont = getChart().getTitle().getFont(); // int titleSize = titleFont.getSize(); // Font domainScaleFont = plot.getDomainAxis().getTickLabelFont(); // int domainScaleSize = domainScaleFont.getSize(); // Font rangeScaleFont = plot.getRangeAxis().getTickLabelFont(); // int rangeScaleSize = rangeScaleFont.getSize(); // plot.getDomainAxis().setLabelFont(domainFont.deriveFont( // (float) (domainSize * overallRatio))); // plot.getRangeAxis().setLabelFont(rangeFont.deriveFont( // (float) (rangeSize * overallRatio))); // getChart().getTitle().setFont(titleFont.deriveFont( // (float) (titleSize * overallRatio))); // plot.getDomainAxis().setTickLabelFont(domainScaleFont.deriveFont( // (float) (domainScaleSize * overallRatio))); // plot.getRangeAxis().setTickLabelFont(rangeScaleFont.deriveFont( // (float) (rangeScaleSize * overallRatio))); // // Rectangle2D chartArea = (Rectangle2D) printArea.clone(); // getChart().getPadding().trim(chartArea); // AxisUtilities.trimTitle(chartArea, g2, getChart().getTitle(), getChart().getTitle().getPosition()); // // Axis scaleAxis = null; // Font scaleAxisFont = null; // int scaleAxisFontSize = 0; // for (Object object : getChart().getSubtitles()) { // Title title = (Title) object; // if (title instanceof PaintScaleLegend) { // scaleAxis = ((PaintScaleLegend) title).getAxis(); // scaleAxisFont = scaleAxis.getTickLabelFont(); // scaleAxisFontSize = scaleAxisFont.getSize(); // scaleAxis.setTickLabelFont(scaleAxisFont.deriveFont( // (float) (scaleAxisFontSize * overallRatio))); // } // AxisUtilities.trimTitle(chartArea, g2, title, title.getPosition()); // } // AxisSpace axisSpace = AxisUtilities.calculateAxisSpace( // getChart().getXYPlot(), g2, chartArea); // Rectangle2D dataArea = axisSpace.shrink(chartArea, null); // getChart().getXYPlot().getInsets().trim(dataArea); // getChart().getXYPlot().getAxisOffset().trim(dataArea); // //// Rectangle2D screenArea = getScreenDataArea(); //// Rectangle2D visibleArea = getVisibleRect(); //// Rectangle2D printScreenArea = new Rectangle2D.Double(screenArea.getMinX() * overallRatio + x, //// screenArea.getMinY() * overallRatio + y, //// printArea.getWidth() - visibleArea.getWidth() + screenArea.getWidth(), //// printArea.getHeight() - visibleArea.getHeight() + screenArea.getHeight()); // // getChart().draw(g2, printArea, getAnchor(), null); // ChartMaskingUtilities.drawMaskRectangle(g2, dataArea, // maskList, null, getChart(), overallRatio); // plot.getDomainAxis().setLabelFont(domainFont); // plot.getRangeAxis().setLabelFont(rangeFont); // getChart().getTitle().setFont(titleFont); // plot.getDomainAxis().setTickLabelFont(domainScaleFont); // plot.getRangeAxis().setTickLabelFont(rangeScaleFont); // if (scaleAxis != null) { // scaleAxis.setTickLabelFont(scaleAxisFont); // } // return PAGE_EXISTS; // // } // public void removeSelectedMask() { // if (selectedMask != null) { // maskList.remove(selectedMask); // selectedMask = null; // repaint(); // } // } // private void selectMask(String maskName) { // if (maskName == null) { // selectedMask = null; // } else { // for (Abstract2DMask mask : maskList) { // if (maskName.equals(mask.getName())) { // selectedMask = mask; // break; // } // } // } // } protected void selectMask(double chartX, double chartY) { Abstract2DMask selectedMask = getSelectedMask(); if (selectedMask == null) { for (AbstractMask mask : getMasks()) { if (mask instanceof Abstract2DMask) { if (((Abstract2DMask) mask).getShape().contains(chartX, chartY)) { setSelectedMask(mask); break; } } } } else { Abstract2DMask newSelection = null; if (getMasks().contains(selectedMask)) { int index = getMasks().indexOf(selectedMask); for (int i = index + 1; i < getMasks().size(); i++) { AbstractMask mask = getMasks().get(i); if (mask instanceof Abstract2DMask) { if (((Abstract2DMask) mask).getShape().contains(chartX, chartY)) { newSelection = (Abstract2DMask) mask; break; } } } if (newSelection == null) { for (int i = 0; i < index; i++) { AbstractMask mask = getMasks().get(i); if (mask instanceof Abstract2DMask) { if (((Abstract2DMask) mask).getShape().contains(chartX, chartY)) { newSelection = (Abstract2DMask) mask; break; } } } } setSelectedMask(newSelection); } else { selectedMask = null; selectMask(chartX, chartY); } } // if (selectedMask != null) // System.out.println("selected mask: x[" + selectedMask.x + ", " // + (selectedMask.x + selectedMask.width) + "] y[" + // selectedMask.y + ", " + (selectedMask.y + selectedMask.height)); } // private Point2D translateScreenToChart(Point2D point) { // EntityCollection entities = getChartRenderingInfo().getEntityCollection(); // ChartEntity entity = entities.getEntity(point.getX(), point.getY()); // if (entity instanceof XYItemEntity) { // XYDataset dataset = ((XYItemEntity) entity).getDataset(); // int item = ((XYItemEntity) entity).getItem(); // double chartX = dataset.getXValue(0, item); // double chartY = dataset.getYValue(0, item); //// double chartZ = ((XYZDataset) dataset).getZValue(0, item); // return new Point2D.Double(chartX, chartY); // } // return point; // } private boolean updateCurrentMaskRectangle(XYItemEntity startEntity, XYItemEntity endEntity) { if (currentMaskRectangle != null) { if (startEntity != null && endEntity != null) { IDataset startDataset = (IDataset) startEntity.getDataset(); IDataset endDataset = (IDataset) endEntity.getDataset(); if (startDataset instanceof XYZDataset && endDataset instanceof XYZDataset) { XYZDataset start = (XYZDataset) startDataset; XYZDataset end = (XYZDataset) endDataset; double xStart = start.getXValue(0, startEntity.getItem()); double yStart = start.getYValue(0, startEntity.getItem()); double xEnd = end.getXValue(0, endEntity.getItem()); double yEnd = end.getYValue(0, endEntity.getItem()); currentMaskRectangle.setRectangleFrame(new Rectangle2D.Double(Math.min(xStart, xEnd), Math.min(yStart, yEnd), Math.abs(xStart - xEnd), Math.abs(yStart - yEnd))); // System.out.println("[" + xStart + ", " + yStart + ", " + xEnd + ", " + yEnd); fireMaskUpdateEvent(currentMaskRectangle); return true; } } } return false; } @Override public Abstract2DMask getSelectedMask() { return (Abstract2DMask) super.getSelectedMask(); } /** * @return the chartZ */ public double getChartZ() { return chartZ; } /** * @param chartZ the chartZ to set */ protected void setChartZ(double chartZ) { this.chartZ = chartZ; } @Override protected Color getAxisTraceColor() { return axisTraceColor; } @Override public ColorScale getColorScale() { XYItemRenderer renderer = getXYPlot().getRenderer(); if (renderer instanceof XYBlockRenderer) { PaintScale scale = ((XYBlockRenderer) renderer).getPaintScale(); if (scale instanceof ColorPaintScale) { return ((ColorPaintScale) scale).getColorScale(); } } return StaticValues.DEFAULT_COLOR_SCALE; } @Override public boolean isLogarithmScaleEnabled() { XYItemRenderer renderer = getXYPlot().getRenderer(); if (renderer instanceof XYBlockRenderer) { PaintScale scale = ((XYBlockRenderer) renderer).getPaintScale(); if (scale instanceof ColorPaintScale) { return ((ColorPaintScale) scale).isLogScale(); } } return false; } @Override public void setColorScale(ColorScale colorScale) { XYItemRenderer renderer = getXYPlot().getRenderer(); if (renderer instanceof XYBlockRenderer) { PaintScale scale = ((XYBlockRenderer) renderer).getPaintScale(); if (scale instanceof ColorPaintScale) { ((ColorPaintScale) scale).setColorScale(colorScale); } } } @Override public void setLogarithmScaleEnabled(boolean enabled) { XYItemRenderer renderer = getXYPlot().getRenderer(); if (renderer instanceof XYBlockRenderer) { PaintScale scale = ((XYBlockRenderer) renderer).getPaintScale(); if (scale instanceof ColorPaintScale) { ((ColorPaintScale) scale).setLogScale(enabled); updatePlot(); } } } @Override public PaintScaleLegend getPaintScaleLegend() { for (Object object : getChart().getSubtitles()) { Title title = (Title) object; if (title instanceof PaintScaleLegend) { return (PaintScaleLegend) title; } } return null; } @Override public void updatePaintScaleLegend() { PaintScaleLegend legend = getPaintScaleLegend(); double max = ((IXYZDataset) getDataset()).getZMax(); double min = ((IXYZDataset) getDataset()).getZMin(); if (legend != null) { ((ColorPaintScale) legend.getScale()).setLowerBound(min); ((ColorPaintScale) legend.getScale()).setUpperBound(max); legend.getAxis().setLowerBound(min); legend.getAxis().setUpperBound(max); } } @Override protected JPopupMenu createPopupMenu(boolean properties, boolean copy, boolean save, boolean print, boolean zoom) { JPopupMenu menu = super.createPopupMenu(properties, copy, save, print, zoom); this.resetColorScaleMenuItem = new JMenuItem("Reset Color Scale"); this.resetColorScaleMenuItem.setActionCommand(RESET_COLOR_SCALE_COMMAND); this.resetColorScaleMenuItem.addActionListener(this); menu.addSeparator(); menu.add(resetColorScaleMenuItem); return menu; } @Override public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); if (command.equals(RESET_COLOR_SCALE_COMMAND)) { PaintScaleLegend legend = getPaintScaleLegend(); if (legend != null && legend.getScale() instanceof ColorPaintScale) { ((ColorPaintScale) legend.getScale()).resetBoundPercentage(); updatePlot(); } } else { super.actionPerformed(event); } } @Override public void updatePlot() { updatePaintScaleLegend(); super.updatePlot(); } @Override public void setDataset(IDataset dataset) { if (getDataset() != null) { dataset.removeChangeListener(this); } super.setDataset(dataset); XYBlockRenderer renderer = (XYBlockRenderer) getXYPlot().getRenderer(); renderer.setBlockHeight(((IXYZDataset) dataset).getYBlockSize()); renderer.setBlockWidth(((IXYZDataset) dataset).getXBlockSize()); PaintScaleLegend legend = getPaintScaleLegend(); if (legend != null) { ((ColorPaintScale) legend.getScale()).resetBoundPercentage(); } dataset.addChangeListener(this); } @Override public void addMask(AbstractMask mask) { if (mask instanceof Abstract2DMask) { super.addMask(mask); } } @Override public void doHelp() { showPropertyEditor(5); } @Override public void doExport(IExporter exporter) throws IOException { JFileChooser fileChooser = new JFileChooser(); String currentDirectory = System.getProperty(StaticValues.SYSTEM_SAVE_PATH_LABEL); if (currentDirectory != null) { File savePath = new File(currentDirectory); if (savePath.exists() && savePath.isDirectory()) { fileChooser.setCurrentDirectory(savePath); } } String fileExtension = exporter.getExtensionName(); ExtensionFileFilter extensionFilter = new ExtensionFileFilter(exporter.toString(), "." + fileExtension); fileChooser.addChoosableFileFilter(extensionFilter); int option = fileChooser.showSaveDialog(this); if (option == JFileChooser.APPROVE_OPTION) { String filename = fileChooser.getSelectedFile().getPath(); // String selectedDescription = fileChooser.getFileFilter().getDescription(); if (!filename.toLowerCase().endsWith("." + fileExtension)) { filename = filename + "." + fileExtension; } File selectedFile = new File(filename); int confirm = JOptionPane.YES_OPTION; if (selectedFile.exists()) { confirm = JOptionPane.showConfirmDialog(this, selectedFile.getName() + " exists, overwrite?", "Confirm Overwriting", JOptionPane.YES_NO_OPTION); } else { selectedFile.createNewFile(); } if (confirm == JOptionPane.YES_OPTION) { exporter.export(selectedFile, getDataset()); System.setProperty(StaticValues.SYSTEM_SAVE_PATH_LABEL, fileChooser.getSelectedFile().getParent()); } } } @Override public void datasetChanged(DatasetChangeEvent event) { XYBlockRenderer renderer = (XYBlockRenderer) getXYPlot().getRenderer(); renderer.setBlockHeight(((IXYZDataset) getDataset()).getYBlockSize()); renderer.setBlockWidth(((IXYZDataset) getDataset()).getXBlockSize()); getXYPlot().configureDomainAxes(); getXYPlot().configureRangeAxes(); // PaintScaleLegend legend = getPaintScaleLegend(); // if (legend != null) { // ((ColorPaintScale) legend.getScale()).resetBoundPercentage(); // } } @Override public void setLogarithmEnabled(boolean enabled) { setLogarithmScaleEnabled(enabled); } @Override public boolean isLogarithmEnabled() { return isLogarithmScaleEnabled(); } @Override public IHelpProvider getHelpProvider() { return new Hist2DHelpProvider(); } @Override protected void saveAsText(BufferedWriter writer) throws IOException { IDataset dataset = getDataset(); if (dataset != null) { DatasetUtils.export((IXYZDataset) dataset, writer, ExportFormat.XYZ); } } @Override public void setMouseFollowerXPrecision(int xPrecision) { mouseFollowerXPrecision = xPrecision; } @Override public void setMouseFollowerYPrecision(int yPrecision) { mouseFollowerYPrecision = yPrecision; } @Override public void setMouseFollowerZPrecision(int zPrecision) { mouseFollowerZPrecision = zPrecision; } }