www.pudn.com > jfreechart-0.9.12.zip > ChartPanel.java
/* ======================================
* JFreeChart : a free Java chart library
* ======================================
*
* Project Info: http://www.jfree.org/jfreechart/index.html
* Project Lead: David Gilbert (david.gilbert@object-refinery.com);
*
* (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* ---------------
* ChartPanel.java
* ---------------
* (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): Andrzej Porebski;
* S�ren Caspersen;
* Jonathan Nash;
* Hans-Jurgen Greiner;
* Andreas Schneider;
* Daniel van Enckevort;
* David M O'Donnell;
* Arnaud Lelievre;
*
* $Id: ChartPanel.java,v 1.14 2003/09/09 10:15:13 mungady Exp $
*
* Changes (from 28-Jun-2001)
* --------------------------
* 28-Jun-2001 : Integrated buffering code contributed by S�ren Caspersen (DG);
* 18-Sep-2001 : Updated header and fixed DOS encoding problem (DG);
* 22-Nov-2001 : Added scaling to improve display of charts in small sizes (DG);
* 26-Nov-2001 : Added property editing, saving and printing (DG);
* 11-Dec-2001 : Transferred saveChartAsPNG method to new ChartUtilities class (DG);
* 13-Dec-2001 : Added tooltips (DG);
* 16-Jan-2002 : Added an optional crosshair, based on the implementation by Jonathan Nash.
* Renamed the tooltips class (DG);
* 23-Jan-2002 : Implemented zooming based on code by Hans-Jurgen Greiner (DG);
* 05-Feb-2002 : Improved tooltips setup. Renamed method attemptSaveAs()-->doSaveAs() and made
* it public rather than private (DG);
* 28-Mar-2002 : Added a new constructor (DG);
* 09-Apr-2002 : Changed initialisation of tooltip generation, as suggested by Hans-Jurgen
* Greiner (DG);
* 27-May-2002 : New interactive zooming methods based on code by Hans-Jurgen Greiner. Renamed
* JFreeChartPanel --> ChartPanel, moved constants to ChartPanelConstants
* interface (DG);
* 31-May-2002 : Fixed a bug with interactive zooming and added a way to control if the
* zoom rectangle is filled in or drawn as an outline. A mouse drag
* gesture towards the top left now causes an autoRangeBoth() and is
* a way to undo zooms (AS);
* 11-Jun-2002 : Reinstated handleClick method call in mouseClicked(...) to get crosshairs
* working again (DG);
* 13-Jun-2002 : Added check for null popup menu in mouseDragged method (DG);
* 18-Jun-2002 : Added get/set methods for minimum and maximum chart dimensions (DG);
* 25-Jun-2002 : Removed redundant code (DG);
* 27-Aug-2002 : Added get/set methods for popup menu (DG);
* 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
* 22-Oct-2002 : Added translation methods for screen <--> Java2D, contributed by Daniel
* van Enckevort (DG);
* 05-Nov-2002 : Added a chart reference to the ChartMouseEvent class (DG);
* 22-Nov-2002 : Added test in zoom method for inverted axes, supplied by David M O'Donnell (DG);
* 14-Jan-2003 : Implemented ChartProgressListener interface (DG);
* 14-Feb-2003 : Removed deprecated setGenerateTooltips method (DG);
* 12-Mar-2003 : Added option to enforce filename extension (see bug id 643173) (DG);
* 08-Sep-2003 : Added internationalization via use of properties resourceBundle (RFE 690236) (AL);
*
*/
package org.jfree.chart;
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.ToolTipManager;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.ValueAxisPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ui.ChartPropertyEditPanel;
import org.jfree.ui.ExtensionFileFilter;
import org.jfree.ui.RefineryUtilities;
/**
* A Swing GUI component for displaying a {@link JFreeChart}.
*
* The panel registers with the chart to receive notification of changes to any component of the
* chart. The chart is redrawn automatically whenever this notification is received.
*
* @author David Gilbert
*/
public class ChartPanel extends JPanel implements ChartPanelConstants,
ChartChangeListener,
ChartProgressListener,
ActionListener,
MouseListener,
MouseMotionListener,
Printable {
/** The chart that is displayed in the panel. */
private JFreeChart chart;
/** Storage for registered (chart) mouse listeners. */
private List chartMouseListeners;
/** A flag that controls whether or not the off-screen buffer is used. */
private boolean useBuffer;
/** A flag that indicates that the buffer should be refreshed. */
private boolean refreshBuffer;
/** A buffer for the rendered chart. */
private Image chartBuffer;
/** The height of the chart buffer. */
private int chartBufferHeight;
/** The width of the chart buffer. */
private int chartBufferWidth;
/** The minimum width for drawing a chart (uses scaling for smaller widths). */
private int minimumDrawWidth;
/** The minimum height for drawing a chart (uses scaling for smaller heights). */
private int minimumDrawHeight;
/** The maximum width for drawing a chart (uses scaling for bigger widths). */
private int maximumDrawWidth;
/** The maximum height for drawing a chart (uses scaling for bigger heights). */
private int maximumDrawHeight;
/** The popup menu for the frame. */
private JPopupMenu popup;
/** The drawing info collected the last time the chart was drawn. */
private ChartRenderingInfo info;
/** The scale factor used to draw the chart. */
private double scaleX;
/** The scale factor used to draw the chart. */
private double scaleY;
/** The zoom rectangle (selected by the user with the mouse). */
private Rectangle2D zoomRectangle = null;
/** The zoom rectangle starting point (selected by the user with a mouse
* click)
*/
private Point2D zoomPoint = null;
/** Controls if the zoom rectangle is drawn as an outline or filled. */
private boolean fillZoomRectangle = false;
/** A flag that controls whether or not horizontal zooming is enabled. */
private boolean horizontalZoom = false;
/** A flag that controls whether or not vertical zooming is enabled. */
private boolean verticalZoom = false;
/** A flag that controls whether or not horizontal tracing is enabled. */
private boolean horizontalAxisTrace = false;
/** A flag that controls whether or not vertical tracing is enabled. */
private boolean verticalAxisTrace = false;
/** Menu item for zooming in on a chart (both axes). */
private JMenuItem zoomInBothMenuItem;
/** Menu item for zooming in on a chart (horizontal axis). */
private JMenuItem zoomInHorizontalMenuItem;
/** Menu item for zooming in on a chart (vertical axis). */
private JMenuItem zoomInVerticalMenuItem;
/** Menu item for zooming out on a chart. */
private JMenuItem zoomOutBothMenuItem;
/** Menu item for zooming out on a chart (horizontal axis). */
private JMenuItem zoomOutHorizontalMenuItem;
/** Menu item for zooming out on a chart (vertical axis). */
private JMenuItem zoomOutVerticalMenuItem;
/** Menu item for resetting the zoom (both axes). */
private JMenuItem autoRangeBothMenuItem;
/** Menu item for resetting the zoom (horizontal axis only). */
private JMenuItem autoRangeHorizontalMenuItem;
/** Menu item for resetting the zoom (vertical axis only). */
private JMenuItem autoRangeVerticalMenuItem;
/** A vertical trace line. */
private Line2D verticalTraceLine;
/** A horizontal trace line. */
private Line2D horizontalTraceLine;
/** A flag that controls whether or not file extensions are enforced. */
private boolean enforceFileExtensions;
/** The resourceBundle for the localization. */
static protected ResourceBundle localizationResources =
ResourceBundle.getBundle("org.jfree.chart.LocalizationBundle");
/**
* Constructs a JFreeChart panel.
*
* @param chart the chart.
*/
public ChartPanel(JFreeChart chart) {
this(chart,
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT,
DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT,
DEFAULT_BUFFER_USED,
true, // properties
true, // save
true, // print
true, // zoom
true // tooltips
);
}
/**
* Constructs a panel containing a chart.
*
* @param chart the chart.
* @param useBuffer a flag controlling whether or not an off-screen buffer is used.
*/
public ChartPanel(JFreeChart chart, boolean useBuffer) {
this(chart,
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT,
DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT,
useBuffer,
true, // properties
true, // save
true, // print
true, // zoom
true // tooltips
);
}
/**
* Constructs a JFreeChart panel.
*
* @param chart the chart.
* @param properties a flag indicating whether or not the chart property
* editor should be available via the popup menu.
* @param save a flag indicating whether or not save options should be
* available via the popup menu.
* @param print a flag indicating whether or not the print option
* should be available via the popup menu.
* @param zoom a flag indicating whether or not zoom options should
* be added to the popup menu.
* @param tooltips a flag indicating whether or not tooltips should be
* enabled for the chart.
*/
public ChartPanel(JFreeChart chart,
boolean properties,
boolean save,
boolean print,
boolean zoom,
boolean tooltips) {
this(chart,
DEFAULT_WIDTH,
DEFAULT_HEIGHT,
DEFAULT_MINIMUM_DRAW_WIDTH,
DEFAULT_MINIMUM_DRAW_HEIGHT,
DEFAULT_MAXIMUM_DRAW_WIDTH,
DEFAULT_MAXIMUM_DRAW_HEIGHT,
DEFAULT_BUFFER_USED,
properties,
save,
print,
zoom,
tooltips
);
}
/**
* Constructs a JFreeChart panel.
*
* @param chart the chart.
* @param width the preferred width of the panel.
* @param height the preferred height of the panel.
* @param minimumDrawWidth the minimum drawing width.
* @param minimumDrawHeight the minimum drawing height.
* @param maximumDrawWidth the maximum drawing width.
* @param maximumDrawHeight the maximum drawing height.
* @param useBuffer a flag that indicates whether to use the off-screen
* buffer to improve performance (at the expense of memory).
* @param properties a flag indicating whether or not the chart property
* editor should be available via the popup menu.
* @param save a flag indicating whether or not save options should be
* available via the popup menu.
* @param print a flag indicating whether or not the print option
* should be available via the popup menu.
* @param zoom a flag indicating whether or not zoom options should be added to the
* popup menu.
* @param tooltips a flag indicating whether or not tooltips should be enabled for the chart.
*/
public ChartPanel(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 = chart;
this.chartMouseListeners = new java.util.ArrayList();
this.info = new ChartRenderingInfo();
setPreferredSize(new Dimension(width, height));
this.useBuffer = useBuffer;
this.refreshBuffer = false;
this.chart.addChangeListener(this);
this.minimumDrawWidth = minimumDrawWidth;
this.minimumDrawHeight = minimumDrawHeight;
this.maximumDrawWidth = maximumDrawWidth;
this.maximumDrawHeight = maximumDrawHeight;
// set up popup menu...
this.popup = null;
if (properties || save || print || zoom) {
popup = createPopupMenu(properties, save, print, zoom);
}
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
setDisplayToolTips(tooltips);
addMouseListener(this);
addMouseMotionListener(this);
this.enforceFileExtensions = true;
}
/**
* Returns the chart contained in the panel.
*
* @return The chart.
*/
public JFreeChart getChart() {
return chart;
}
/**
* Sets the chart that is displayed in the panel.
*
* @param chart The chart.
*/
public void setChart(JFreeChart chart) {
// stop listening for changes to the existing chart...
if (this.chart != null) {
this.chart.removeChangeListener(this);
this.chart.removeProgressListener(this);
}
// add the new chart...
this.chart = chart;
this.chart.addChangeListener(this);
this.chart.addProgressListener(this);
if (this.useBuffer) {
this.refreshBuffer = true;
}
Plot plot = chart.getPlot();
ValueAxis horizontalAxis = getHorizontalValueAxis(plot);
this.horizontalZoom = this.horizontalZoom && (horizontalAxis != null);
ValueAxis verticalAxis = getVerticalValueAxis(plot);
this.verticalZoom = this.verticalZoom && (verticalAxis != null);
repaint();
}
/**
* Returns the minimum drawing width for charts.
*
* If the width available on the panel is less than this, then the chart is
* drawn at the minimum width then scaled down to fit.
*
* @return The minimum drawing width.
*/
public int getMinimumDrawWidth() {
return this.minimumDrawWidth;
}
/**
* Sets the minimum drawing width for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available width is
* less than this amount, the chart will be drawn using the minimum width
* then scaled down to fit the available space.
*
* @param width The width.
*/
public void setMinimumDrawWidth(int width) {
this.minimumDrawWidth = width;
}
/**
* Returns the maximum drawing width for charts.
*
* If the width available on the panel is greater than this, then the chart
* is drawn at the maximum width then scaled up to fit.
*
* @return The maximum drawing width.
*/
public int getMaximumDrawWidth() {
return this.maximumDrawWidth;
}
/**
* Sets the maximum drawing width for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available width is
* greater than this amount, the chart will be drawn using the maximum
* width then scaled up to fit the available space.
*
* @param width The width.
*/
public void setMaximumDrawWidth(int width) {
this.maximumDrawWidth = width;
}
/**
* Sets the minimum drawing height for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available height is
* less than this amount, the chart will be drawn using the minimum height
* then scaled down to fit the available space.
*
* @param height The height.
*/
public void setMinimumDrawHeight(int height) {
this.minimumDrawHeight = height;
}
/**
* Returns the minimum drawing height for charts.
*
* If the height available on the panel is less than this, then the chart
* is drawn at the minimum height then scaled down to fit.
*
* @return The minimum drawing height.
*/
public int getMinimumDrawHeight() {
return this.minimumDrawHeight;
}
/**
* Returns the maximum drawing height for charts.
*
* If the height available on the panel is greater than this, then the
* chart is drawn at the maximum height then scaled up to fit.
*
* @return The maximum drawing height.
*/
public int getMaximumDrawHeight() {
return this.maximumDrawHeight;
}
/**
* Sets the maximum drawing height for the chart on this panel.
*
* At the time the chart is drawn on the panel, if the available height is
* greater than this amount, the chart will be drawn using the maximum
* height then scaled up to fit the available space.
*
* @param height The height.
*/
public void setMaximumDrawHeight(int height) {
this.maximumDrawHeight = height;
}
/**
* Returns the popup menu.
*
* @return the popup menu.
*/
public JPopupMenu getPopupMenu() {
return this.popup;
}
/**
* Sets the popup menu for the panel.
*
* @param popup the new popup menu.
*/
public void setPopupMenu(JPopupMenu popup) {
this.popup = popup;
}
/**
* Returns the chart rendering info from the most recent chart redraw.
*
* @return the chart rendering info.
*/
public ChartRenderingInfo getChartRenderingInfo() {
return this.info;
}
/**
* A flag that controls mouse-based zooming.
*
* @param flag true enables zooming and rectangle fill on zoom.
*/
public void setMouseZoomable(boolean flag) {
setMouseZoomable(flag, true);
}
/**
* Controls mouse zooming and how the zoom rectangle is displayed
*
* @param flag true if zooming enabled
* @param fillRectangle true if zoom rectangle is filled,
* false if rectangle is shown as outline only.
*/
public void setMouseZoomable(boolean flag, boolean fillRectangle) {
setHorizontalZoom(flag);
setVerticalZoom(flag);
setFillZoomRectangle(fillRectangle);
}
/**
* A flag that controls mouse-based zooming on the horizontal axis.
*
* @param flag true enables zooming on HorizontalValuePlots.
*/
public void setHorizontalZoom(boolean flag) {
Plot plot = this.chart.getPlot();
ValueAxis axis = getHorizontalValueAxis(plot);
this.horizontalZoom = flag && (axis != null);
}
/**
* A flag that controls how the zoom rectangle is drawn.
*
* @param flag true instructs to fill the rectangle on
* zoom, otherwise it will be outlined.
*/
public void setFillZoomRectangle(boolean flag) {
this.fillZoomRectangle = flag;
}
/**
* A flag that controls mouse-based zooming on the vertical axis.
*
* @param flag true enables zooming on VerticalValuePlots.
*/
public void setVerticalZoom(boolean flag) {
Plot plot = this.chart.getPlot();
ValueAxis axis = getVerticalValueAxis(plot);
this.verticalZoom = flag && (axis != null);
}
/**
* A flag that controls trace lines on the horizontal axis.
*
* @param flag true enables trace lines for the mouse
* pointer on the horizontal axis.
*/
public void setHorizontalAxisTrace(boolean flag) {
this.horizontalAxisTrace = flag;
}
/**
* A flag that controls trace lines on the vertical axis.
*
* @param flag true enables trace lines for the mouse
* pointer on the vertical axis.
*/
public void setVerticalAxisTrace(boolean flag) {
this.verticalAxisTrace = flag;
}
/**
* Returns true if file extensions should be enforced, and false
* otherwise.
*
* @return The flag.
*/
public boolean isEnforceFileExtensions() {
return this.enforceFileExtensions;
}
/**
* Sets a flag that controls whether or not file extensions are enforced.
*
* @param enforce the new flag value.
*/
public void setEnforceFileExtensions(boolean enforce) {
this.enforceFileExtensions = enforce;
}
/**
* Switches chart tooltip generation on or off.
*
* @param flag the flag.
*/
public void setDisplayToolTips(boolean flag) {
if (flag) {
ToolTipManager.sharedInstance().registerComponent(this);
}
else {
ToolTipManager.sharedInstance().unregisterComponent(this);
}
}
/**
* Returns a string for the tooltip.
*
* @param e the mouse event.
*
* @return a tool tip or null if no tooltip is available.
*/
public String getToolTipText(MouseEvent e) {
String result = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
Insets insets = getInsets();
ChartEntity entity = entities.getEntity((int) ((e.getX() - insets.left) / scaleX),
(int) ((e.getY() - insets.top) / scaleY));
if (entity != null) {
result = entity.getToolTipText();
}
}
}
return result;
}
/**
* Translates a Java2D point on the chart to a screen location.
*
* @param java2DPoint the Java2D point.
*
* @return the screen location.
*/
public Point translateJava2DToScreen(Point2D java2DPoint) {
Insets insets = getInsets();
int x = (int) (java2DPoint.getX() * this.scaleX + insets.left);
int y = (int) (java2DPoint.getY() * this.scaleY + insets.top);
return new Point(x, y);
}
/**
* Translates a screen location to a Java2D point.
*
* @param screenPoint the screen location.
*
* @return the Java2D coordinates.
*/
public Point2D translateScreenToJava2D(Point screenPoint) {
Insets insets = getInsets();
double x = (screenPoint.getX() - insets.left) / this.scaleX;
double y = (screenPoint.getY() - insets.top) / this.scaleY;
return new Point2D.Double(x, y);
}
/**
* Returns the chart entity at a given point.
*
* This method will return null if there is (a) no entity at the given point, or
* (b) no entity collection has been generated.
*
* @param viewX the x-coordinate.
* @param viewY the y-coordinate.
*
* @return the chart entity (possibly null).
*/
public ChartEntity getEntityForPoint(int viewX, int viewY) {
ChartEntity result = null;
if (this.info != null) {
Insets insets = getInsets();
double x = (viewX - insets.left) / scaleX;
double y = (viewY - insets.top) / scaleY;
EntityCollection entities = this.info.getEntityCollection();
result = entities != null ? entities.getEntity(x, y) : null;
}
return result;
}
/**
* Sets the refresh buffer flag.
*
* @param flag true indicate, that the buffer should be refreshed.
*/
public void setRefreshBuffer(boolean flag) {
this.refreshBuffer = flag;
}
/** Working storage for available panel area after deducting insets. */
private Rectangle2D available = new Rectangle2D.Double();
/** Working storage for the chart area. */
private Rectangle2D chartArea = new Rectangle2D.Double();
/**
* Paints the component by drawing the chart to fill the entire component,
* but allowing for the insets (which will be non-zero if a border has been
* set for this component). To increase performance (at the expense of
* memory), an off-screen buffer image can be used.
*
* @param g the graphics device for drawing on.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// first determine the size of the chart rendering area...
Dimension size = getSize();
Insets insets = getInsets();
available.setRect(insets.left, insets.top,
size.getWidth() - insets.left - insets.right,
size.getHeight() - insets.top - insets.bottom);
// work out if scaling is required...
boolean scale = false;
double drawWidth = available.getWidth();
double drawHeight = available.getHeight();
this.scaleX = 1.0;
this.scaleY = 1.0;
if (drawWidth < this.minimumDrawWidth) {
scaleX = drawWidth / minimumDrawWidth;
drawWidth = minimumDrawWidth;
scale = true;
}
else if (drawWidth > this.maximumDrawWidth) {
scaleX = drawWidth / maximumDrawWidth;
drawWidth = maximumDrawWidth;
scale = true;
}
if (drawHeight < this.minimumDrawHeight) {
scaleY = drawHeight / minimumDrawHeight;
drawHeight = minimumDrawHeight;
scale = true;
}
else if (drawHeight > this.maximumDrawHeight) {
scaleY = drawHeight / maximumDrawHeight;
drawHeight = maximumDrawHeight;
scale = true;
}
chartArea.setRect(0.0, 0.0, drawWidth, drawHeight);
// are we using the chart buffer?
if (useBuffer) {
// do we need to resize the buffer?
if ((chartBuffer == null) || (chartBufferWidth != available.getWidth())
|| (chartBufferHeight != available.getHeight())) {
chartBufferWidth = (int) available.getWidth();
chartBufferHeight = (int) available.getHeight();
chartBuffer = createImage(chartBufferWidth, chartBufferHeight);
refreshBuffer = true;
}
// do we need to redraw the buffer?
if (refreshBuffer) {
Rectangle2D bufferArea =
new Rectangle2D.Double(0, 0, chartBufferWidth, chartBufferHeight);
Graphics2D bufferG2 = (Graphics2D) chartBuffer.getGraphics();
if (scale) {
AffineTransform saved = bufferG2.getTransform();
AffineTransform st = AffineTransform.getScaleInstance(scaleX, scaleY);
bufferG2.transform(st);
chart.draw(bufferG2, chartArea, this.info);
bufferG2.setTransform(saved);
}
else {
chart.draw(bufferG2, bufferArea, this.info);
}
refreshBuffer = false;
}
// zap the buffer onto the panel...
g2.drawImage(chartBuffer, insets.left, insets.right, this);
}
// or redrawing the chart every time...
else {
AffineTransform saved = g2.getTransform();
g2.translate(insets.left, insets.right);
if (scale) {
AffineTransform st = AffineTransform.getScaleInstance(scaleX, scaleY);
g2.transform(st);
}
chart.draw(g2, chartArea, this.info);
g2.setTransform(saved);
}
this.verticalTraceLine = null;
this.horizontalTraceLine = null;
}
/**
* Receives notification of changes to the chart, and redraws the chart.
*
* @param event details of the chart change event.
*/
public void chartChanged(ChartChangeEvent event) {
this.refreshBuffer = true;
repaint();
}
/**
* Receives notification of a chart progress event.
*
* @param event the event.
*/
public void chartProgress(ChartProgressEvent event) {
// does nothing - override if necessary
}
/**
* Handles action events generated by the popup menu.
*
* @param event the event.
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals(PROPERTIES_ACTION_COMMAND)) {
attemptEditChartProperties();
}
else if (command.equals(SAVE_ACTION_COMMAND)) {
try {
doSaveAs();
}
catch (IOException e) {
System.err.println("ChartPanel.doSaveAs: i/o exception = " + e.getMessage());
}
}
else if (command.equals(PRINT_ACTION_COMMAND)) {
createChartPrintJob();
}
else if (command.equals(ZOOM_IN_BOTH_ACTION_COMMAND)) {
zoomInBoth(this.zoomPoint.getX(), this.zoomPoint.getY());
}
else if (command.equals(ZOOM_IN_HORIZONTAL_ACTION_COMMAND)) {
zoomInHorizontal(this.zoomPoint.getX());
}
else if (command.equals(ZOOM_IN_VERTICAL_ACTION_COMMAND)) {
zoomInVertical(this.zoomPoint.getY());
}
else if (command.equals(ZOOM_OUT_BOTH_ACTION_COMMAND)) {
zoomOutBoth(this.zoomPoint.getX(), this.zoomPoint.getY());
}
else if (command.equals(ZOOM_OUT_HORIZONTAL_ACTION_COMMAND)) {
zoomOutHorizontal(this.zoomPoint.getX());
}
else if (command.equals(ZOOM_OUT_VERTICAL_ACTION_COMMAND)) {
zoomOutVertical(this.zoomPoint.getY());
}
else if (command.equals(AUTO_RANGE_BOTH_ACTION_COMMAND)) {
autoRangeBoth();
}
else if (command.equals(AUTO_RANGE_HORIZONTAL_ACTION_COMMAND)) {
autoRangeHorizontal();
}
else if (command.equals(AUTO_RANGE_VERTICAL_ACTION_COMMAND)) {
autoRangeVertical();
}
}
/**
* Handles a 'mouse entered' event.
*
* This method does nothing, but is required for implementation of the MouseListener
* interface.
*
* @param e the mouse event.
*/
public void mouseEntered(MouseEvent e) {
// do nothing
}
/**
* Handles a 'mouse exited' event.
*
* This method does nothing, but is required for implementation of the MouseListener
* interface.
*
* @param e the mouse event.
*/
public void mouseExited(MouseEvent e) {
// do nothing
}
/**
* Handles a 'mouse pressed' event.
*
* This event is the popup trigger on Unix/Linux. For Windows, the popup
* trigger is the 'mouse released' event.
*
* @param e The mouse event.
*/
public void mousePressed(MouseEvent e) {
if (zoomRectangle == null) {
this.zoomPoint = RefineryUtilities.getPointInRectangle(e.getX(), e.getY(),
getScaledDataArea());
// check for popup trigger...
if (e.isPopupTrigger()) {
if (popup != null) {
displayPopupMenu(e.getX(), e.getY());
}
}
}
}
/**
* 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 (zoomRectangle != null) {
if (Math.abs(e.getX() - zoomPoint.getX()) >= MINIMUM_DRAG_ZOOM_SIZE) {
if (e.getX() < zoomPoint.getX() || e.getY() < zoomPoint.getY()) {
autoRangeBoth();
}
else {
double x, y, w, h;
Rectangle2D scaledDataArea = getScaledDataArea();
//for a mouseReleased event, (horizontalZoom || verticalZoom)
//will be true, so we can just test for either being false;
//otherwise both are true
if (!verticalZoom) {
x = zoomPoint.getX();
y = scaledDataArea.getMinY();
w = Math.min(zoomRectangle.getWidth(),
scaledDataArea.getMaxX() - zoomPoint.getX());
h = scaledDataArea.getHeight();
}
else if (!horizontalZoom) {
x = scaledDataArea.getMinX();
y = zoomPoint.getY();
w = scaledDataArea.getWidth();
h = Math.min(zoomRectangle.getHeight(),
scaledDataArea.getMaxY() - zoomPoint.getY());
}
else {
x = zoomPoint.getX();
y = zoomPoint.getY();
w = Math.min(zoomRectangle.getWidth(),
scaledDataArea.getMaxX() - zoomPoint.getX());
h = Math.min(zoomRectangle.getHeight(),
scaledDataArea.getMaxY() - zoomPoint.getY());
}
Rectangle2D zoomArea = new Rectangle2D.Double(x, y, w, h);
zoom(zoomArea);
}
this.zoomPoint = null;
this.zoomRectangle = null;
}
else {
Graphics2D g2 = (Graphics2D) getGraphics();
g2.setXORMode(java.awt.Color.gray);
if (fillZoomRectangle) {
g2.fill(zoomRectangle);
}
else {
g2.draw(zoomRectangle);
}
g2.dispose();
this.zoomRectangle = null;
}
}
else if (e.isPopupTrigger()) {
if (popup != null) {
displayPopupMenu(e.getX(), e.getY());
}
}
}
/**
* Receives notification of mouse clicks on the panel. These are
* translated and passed on to any registered chart mouse click listeners.
*
* @param event Information about the mouse event.
*/
public void mouseClicked(MouseEvent event) {
Insets insets = getInsets();
int x = (int) ((event.getX() - insets.left) / scaleX);
int y = (int) ((event.getY() - insets.top) / scaleY);
// old 'handle click' code...
chart.handleClick(x, y, this.info);
// new entity code...
if (this.chartMouseListeners.isEmpty()) {
return;
}
ChartEntity entity = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
entity = entities.getEntity(x, y);
}
}
ChartMouseEvent chartEvent = new ChartMouseEvent(getChart(), event, entity);
Iterator iterator = chartMouseListeners.iterator();
while (iterator.hasNext()) {
ChartMouseListener listener = (ChartMouseListener) iterator.next();
listener.chartMouseClicked(chartEvent);
}
}
/**
* Implementation of the MouseMotionListener's method
*
* @param e the event.
*/
public void mouseMoved(MouseEvent e) {
if (this.horizontalAxisTrace) {
drawHorizontalAxisTrace(e.getX());
}
if (this.verticalAxisTrace) {
drawVerticalAxisTrace(e.getY());
}
if (this.chartMouseListeners.isEmpty()) {
return;
}
Insets insets = getInsets();
int x = (int) ((e.getX() - insets.left) / scaleX);
int y = (int) ((e.getY() - insets.top) / scaleY);
ChartEntity entity = null;
if (this.info != null) {
EntityCollection entities = this.info.getEntityCollection();
if (entities != null) {
entity = entities.getEntity(x, y);
}
}
ChartMouseEvent event = new ChartMouseEvent(getChart(), e, entity);
Iterator iterator = chartMouseListeners.iterator();
while (iterator.hasNext()) {
ChartMouseListener listener = (ChartMouseListener) iterator.next();
listener.chartMouseMoved(event);
}
}
/**
* Handles a 'mouse dragged' event.
*
* @param e the mouse event.
*/
public void mouseDragged(MouseEvent e) {
// if the popup menu has already been triggered, then ignore dragging...
if (popup != null && popup.isShowing()) {
return;
}
Graphics2D g2 = (Graphics2D) getGraphics();
// use XOR to erase the previous zoom rectangle (if any)...
g2.setXORMode(java.awt.Color.gray);
if (zoomRectangle != null) {
if (fillZoomRectangle) {
g2.fill(zoomRectangle);
}
else {
g2.draw(zoomRectangle);
}
}
Rectangle2D scaledDataArea = getScaledDataArea();
if (this.horizontalZoom && this.verticalZoom) {
// 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());
zoomRectangle = new Rectangle2D.Double(zoomPoint.getX(), zoomPoint.getY(),
xmax - zoomPoint.getX(),
ymax - zoomPoint.getY());
}
else if (this.horizontalZoom) {
double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
zoomRectangle = new Rectangle2D.Double(zoomPoint.getX(), scaledDataArea.getMinY(),
xmax - zoomPoint.getX(),
scaledDataArea.getHeight());
}
else if (this.verticalZoom) {
double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
zoomRectangle = new Rectangle2D.Double(scaledDataArea.getMinX(), zoomPoint.getY(),
scaledDataArea.getWidth(),
ymax - zoomPoint.getY());
}
if (zoomRectangle != null) {
// use XOR to draw the new zoom rectangle...
if (fillZoomRectangle) {
g2.fill(zoomRectangle);
}
else {
g2.draw(zoomRectangle);
}
}
g2.dispose();
}
/**
* Zooms in on an anchor point (measured in Java2D coordinates).
*
* @param x The x value.
* @param y The y value.
*/
public void zoomInBoth(double x, double y) {
zoomInHorizontal(x);
zoomInVertical(y);
}
/**
* Returns a reference to the 'horizontal' value axis, if there is one.
*
* @param plot the plot.
*
* @return The axis.
*/
private ValueAxis getHorizontalValueAxis(Plot plot) {
if (plot == null) {
return null;
}
ValueAxis axis = null;
if (plot instanceof CategoryPlot) {
CategoryPlot cp = (CategoryPlot) plot;
if (cp.getOrientation() == PlotOrientation.HORIZONTAL) {
axis = cp.getRangeAxis();
}
}
if (plot instanceof XYPlot) {
XYPlot xyp = (XYPlot) plot;
if (xyp.getOrientation() == PlotOrientation.HORIZONTAL) {
axis = xyp.getRangeAxis();
}
else if (xyp.getOrientation() == PlotOrientation.VERTICAL) {
axis = xyp.getDomainAxis();
}
}
return axis;
}
/**
* Returns a reference to the 'vertical' value axis, if there is one.
*
* @param plot the plot.
*
* @return The axis.
*/
private ValueAxis getVerticalValueAxis(Plot plot) {
if (plot == null) {
return null;
}
ValueAxis axis = null;
if (plot instanceof CategoryPlot) {
CategoryPlot cp = (CategoryPlot) plot;
if (cp.getOrientation() == PlotOrientation.VERTICAL) {
axis = cp.getRangeAxis();
}
}
if (plot instanceof XYPlot) {
XYPlot xyp = (XYPlot) plot;
if (xyp.getOrientation() == PlotOrientation.HORIZONTAL) {
axis = xyp.getDomainAxis();
}
else if (xyp.getOrientation() == PlotOrientation.VERTICAL) {
axis = xyp.getRangeAxis();
}
}
return axis;
}
/**
* Decreases the range on the horizontal axis, centered about a Java2D
* x coordinate.
*
* The range on the x axis is halved.
*
* @param x The x coordinate in Java2D space.
*/
public void zoomInHorizontal(double x) {
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomHorizontalAxes(0.5);
}
}
/**
* Decreases the range on the vertical axis, centered about a Java2D
* y coordinate.
*
* The range on the y axis is halved.
*
* @param y The y coordinate in Java2D space.
*/
public void zoomInVertical(double y) {
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomVerticalAxes(0.5);
}
}
/**
* Zooms out on an anchor point (measured in Java2D coordinates).
*
* @param x The x value.
* @param y The y value.
*/
public void zoomOutBoth(double x, double y) {
zoomOutHorizontal(x);
zoomOutVertical(y);
}
/**
* Increases the range on the horizontal axis, centered about a Java2D
* x coordinate.
*
* The range on the x axis is doubled.
*
* @param x The x coordinate in Java2D space.
*/
public void zoomOutHorizontal(double x) {
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomHorizontalAxes(2.0);
}
}
/**
* Increases the range on the vertical axis, centered about a Java2D y coordinate.
*
* The range on the y axis is doubled.
*
* @param y the y coordinate in Java2D space.
*/
public void zoomOutVertical(double y) {
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomVerticalAxes(2.0);
}
}
/**
* Zooms in on a selected region.
*
* @param selection the selected region.
*/
public void zoom(Rectangle2D selection) {
double hLower = 0.0;
double hUpper = 0.0;
double vLower = 0.0;
double vUpper = 0.0;
if ((selection.getHeight() > 0) && (selection.getWidth() > 0)) {
Rectangle2D scaledDataArea = getScaledDataArea();
hLower = (selection.getMinX() - scaledDataArea.getMinX()) / scaledDataArea.getWidth();
hUpper = (selection.getMaxX() - scaledDataArea.getMinX()) / scaledDataArea.getWidth();
vLower = (scaledDataArea.getMaxY() - selection.getMaxY()) / scaledDataArea.getHeight();
vUpper = (scaledDataArea.getMaxY() - selection.getMinY()) / scaledDataArea.getHeight();
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomHorizontalAxes(hLower, hUpper);
plot.zoomVerticalAxes(vLower, vUpper);
}
}
}
/**
* Restores the auto-range calculation on both axes.
*/
public void autoRangeBoth() {
autoRangeHorizontal();
autoRangeVertical();
}
/**
* Restores the auto-range calculation on the horizontal axis.
*/
public void autoRangeHorizontal() {
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomHorizontalAxes(0.0);
}
}
/**
* Restores the auto-range calculation on the vertical axis.
*/
public void autoRangeVertical() {
Plot p = chart.getPlot();
if (p instanceof ValueAxisPlot) {
ValueAxisPlot plot = (ValueAxisPlot) p;
plot.zoomVerticalAxes(0.0);
}
}
/**
* Returns the data area for the chart (the area inside the axes) with the
* current scaling applied.
*
* @return the scaled data area.
*/
public Rectangle2D getScaledDataArea() {
Rectangle2D dataArea = this.info.getDataArea();
Insets insets = getInsets();
double x = dataArea.getX() * scaleX + insets.left;
double y = dataArea.getY() * scaleY + insets.top;
double w = dataArea.getWidth() * scaleX;
double h = dataArea.getHeight() * scaleY;
return new Rectangle2D.Double(x, y, w, h);
}
/**
* Draws a vertical line used to trace the mouse position to the horizontal axis.
*
* @param x the x-coordinate of the trace line.
*/
private void drawHorizontalAxisTrace(int x) {
Graphics2D g2 = (Graphics2D) getGraphics();
Rectangle2D dataArea = getScaledDataArea();
g2.setXORMode(java.awt.Color.orange);
if (((int) dataArea.getMinX() < x) && (x < (int) dataArea.getMaxX())) {
if (verticalTraceLine != null) {
g2.draw(verticalTraceLine);
verticalTraceLine.setLine(x, (int) dataArea.getMinY(),
x, (int) dataArea.getMaxY());
}
else {
verticalTraceLine = new Line2D.Float(x, (int) dataArea.getMinY(),
x, (int) dataArea.getMaxY());
}
g2.draw(verticalTraceLine);
}
}
/**
* Draws a horizontal line used to trace the mouse position to the vertical axis.
*
* @param y the y-coordinate of the trace line.
*/
private void drawVerticalAxisTrace(int y) {
Graphics2D g2 = (Graphics2D) getGraphics();
Rectangle2D dataArea = getScaledDataArea();
g2.setXORMode(java.awt.Color.orange);
if (((int) dataArea.getMinY() < y) && (y < (int) dataArea.getMaxY())) {
if (horizontalTraceLine != null) {
g2.draw(horizontalTraceLine);
horizontalTraceLine.setLine((int) dataArea.getMinX(), y,
(int) dataArea.getMaxX(), y);
}
else {
horizontalTraceLine = new Line2D.Float((int) dataArea.getMinX(), y,
(int) dataArea.getMaxX(), y);
}
g2.draw(horizontalTraceLine);
}
}
/**
* Displays a dialog that allows the user to edit the properties for the
* current chart.
*/
private void attemptEditChartProperties() {
ChartPropertyEditPanel panel = new ChartPropertyEditPanel(chart);
int result =
JOptionPane.showConfirmDialog(this, panel,
localizationResources.getString("Chart_Properties"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
panel.updateChartProperties(chart);
}
}
/**
* Opens a file chooser and gives the user an opportunity to save the chart
* in PNG format.
*
* @throws IOException if there is an I/O error.
*/
public void doSaveAs() throws IOException {
JFileChooser fileChooser = new JFileChooser();
ExtensionFileFilter filter =
new ExtensionFileFilter(localizationResources.getString("PNG_Image_Files"), ".png");
fileChooser.addChoosableFileFilter(filter);
fileChooser.addChoosableFileFilter(new ExtensionFileFilter("All files", ""));
int option = fileChooser.showSaveDialog(this);
if (option == JFileChooser.APPROVE_OPTION) {
String filename = fileChooser.getSelectedFile().getPath();
if (isEnforceFileExtensions()) {
if (!filename.endsWith(".png")) {
filename = filename + ".png";
}
}
ChartUtilities.saveChartAsPNG(new File(filename), this.chart, getWidth(), getHeight());
}
}
/**
* Creates a print job for the chart.
*/
public void createChartPrintJob() {
PrinterJob job = PrinterJob.getPrinterJob();
PageFormat pf = job.defaultPage();
PageFormat pf2 = job.pageDialog(pf);
if (pf2 != pf) {
job.setPrintable(this, pf2);
if (job.printDialog()) {
try {
job.print();
}
catch (PrinterException e) {
JOptionPane.showMessageDialog(this, e);
}
}
}
}
/**
* 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 0, nothing gets print.
*
* @return the result of printing.
*/
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();
chart.draw(g2, new Rectangle2D.Double(x, y, w, h), null);
return PAGE_EXISTS;
}
/**
* Adds a listener to the list of objects listening for chart mouse events.
*
* @param listener the listener.
*/
public void addChartMouseListener(ChartMouseListener listener) {
this.chartMouseListeners.add(listener);
}
/**
* Removes a listener from the list of objects listening for chart mouse events.
*
* @param listener the listener.
*/
public void removeChartMouseListener(ChartMouseListener listener) {
this.chartMouseListeners.remove(listener);
}
/**
* Creates a popup menu for the panel.
*
* @param properties include a menu item for the chart property editor.
* @param save include a menu item for saving the chart.
* @param print include a menu item for printing the chart.
* @param zoom include menu items for zooming.
*
* @return The popup menu.
*/
protected JPopupMenu createPopupMenu(boolean properties, boolean save, boolean print,
boolean zoom) {
JPopupMenu result = new JPopupMenu("Chart:");
boolean separator = false;
if (properties) {
JMenuItem propertiesItem =
new JMenuItem(localizationResources.getString("Properties..."));
propertiesItem.setActionCommand(PROPERTIES_ACTION_COMMAND);
propertiesItem.addActionListener(this);
result.add(propertiesItem);
separator = true;
}
if (save) {
if (separator) {
result.addSeparator();
separator = false;
}
JMenuItem saveItem = new JMenuItem(localizationResources.getString("Save_as..."));
saveItem.setActionCommand(SAVE_ACTION_COMMAND);
saveItem.addActionListener(this);
result.add(saveItem);
separator = true;
}
if (print) {
if (separator) {
result.addSeparator();
separator = false;
}
JMenuItem printItem = new JMenuItem(localizationResources.getString("Print..."));
printItem.setActionCommand(PRINT_ACTION_COMMAND);
printItem.addActionListener(this);
result.add(printItem);
separator = true;
}
if (zoom) {
if (separator) {
result.addSeparator();
separator = false;
}
JMenu zoomInMenu = new JMenu(localizationResources.getString("Zoom_In"));
zoomInBothMenuItem = new JMenuItem(localizationResources.getString("All_Axes"));
zoomInBothMenuItem.setActionCommand(ZOOM_IN_BOTH_ACTION_COMMAND);
zoomInBothMenuItem.addActionListener(this);
zoomInMenu.add(zoomInBothMenuItem);
zoomInMenu.addSeparator();
zoomInHorizontalMenuItem =
new JMenuItem(localizationResources.getString("Horizontal_Axis"));
zoomInHorizontalMenuItem.setActionCommand(ZOOM_IN_HORIZONTAL_ACTION_COMMAND);
zoomInHorizontalMenuItem.addActionListener(this);
zoomInMenu.add(zoomInHorizontalMenuItem);
zoomInVerticalMenuItem =
new JMenuItem(localizationResources.getString("Vertical_Axis"));
zoomInVerticalMenuItem.setActionCommand(ZOOM_IN_VERTICAL_ACTION_COMMAND);
zoomInVerticalMenuItem.addActionListener(this);
zoomInMenu.add(zoomInVerticalMenuItem);
result.add(zoomInMenu);
JMenu zoomOutMenu = new JMenu(localizationResources.getString("Zoom_Out"));
zoomOutBothMenuItem = new JMenuItem(localizationResources.getString("All_Axes"));
zoomOutBothMenuItem.setActionCommand(ZOOM_OUT_BOTH_ACTION_COMMAND);
zoomOutBothMenuItem.addActionListener(this);
zoomOutMenu.add(zoomOutBothMenuItem);
zoomOutMenu.addSeparator();
zoomOutHorizontalMenuItem =
new JMenuItem(localizationResources.getString("Horizontal_Axis"));
zoomOutHorizontalMenuItem.setActionCommand(ZOOM_OUT_HORIZONTAL_ACTION_COMMAND);
zoomOutHorizontalMenuItem.addActionListener(this);
zoomOutMenu.add(zoomOutHorizontalMenuItem);
zoomOutVerticalMenuItem =
new JMenuItem(localizationResources.getString("Vertical_Axis"));
zoomOutVerticalMenuItem.setActionCommand(ZOOM_OUT_VERTICAL_ACTION_COMMAND);
zoomOutVerticalMenuItem.addActionListener(this);
zoomOutMenu.add(zoomOutVerticalMenuItem);
result.add(zoomOutMenu);
JMenu autoRangeMenu = new JMenu(localizationResources.getString("Auto_Range"));
autoRangeBothMenuItem = new JMenuItem(localizationResources.getString("All_Axes"));
autoRangeBothMenuItem.setActionCommand(AUTO_RANGE_BOTH_ACTION_COMMAND);
autoRangeBothMenuItem.addActionListener(this);
autoRangeMenu.add(autoRangeBothMenuItem);
autoRangeMenu.addSeparator();
autoRangeHorizontalMenuItem =
new JMenuItem(localizationResources.getString("Horizontal_Axis"));
autoRangeHorizontalMenuItem.setActionCommand(AUTO_RANGE_HORIZONTAL_ACTION_COMMAND);
autoRangeHorizontalMenuItem.addActionListener(this);
autoRangeMenu.add(autoRangeHorizontalMenuItem);
autoRangeVerticalMenuItem =
new JMenuItem(localizationResources.getString("Vertical_Axis"));
autoRangeVerticalMenuItem.setActionCommand(AUTO_RANGE_VERTICAL_ACTION_COMMAND);
autoRangeVerticalMenuItem.addActionListener(this);
autoRangeMenu.add(autoRangeVerticalMenuItem);
result.addSeparator();
result.add(autoRangeMenu);
}
return result;
}
/**
* The idea is to modify the zooming options depending on the type of chart being displayed by
* the panel. This code is incomplete.
*
* @param x horizontal position of the popup.
* @param y vertical position of the popup.
*/
protected void displayPopupMenu(int x, int y) {
if (popup != null) {
// go through each zoom menu item and decide whether or not to enable it...
Plot plot = this.chart.getPlot();
ValueAxis horizontalAxis = getHorizontalValueAxis(plot);
boolean isHorizontal = (horizontalAxis != null);
ValueAxis verticalAxis = getVerticalValueAxis(plot);
boolean isVertical = (verticalAxis != null);
if (this.zoomInHorizontalMenuItem != null) {
this.zoomInHorizontalMenuItem.setEnabled(isHorizontal);
}
if (this.zoomOutHorizontalMenuItem != null) {
this.zoomOutHorizontalMenuItem.setEnabled(isHorizontal);
}
if (this.autoRangeHorizontalMenuItem != null) {
this.autoRangeHorizontalMenuItem.setEnabled(isHorizontal);
}
if (this.zoomInVerticalMenuItem != null) {
this.zoomInVerticalMenuItem.setEnabled(isVertical);
}
if (this.zoomOutVerticalMenuItem != null) {
this.zoomOutVerticalMenuItem.setEnabled(isVertical);
}
if (this.autoRangeVerticalMenuItem != null) {
this.autoRangeVerticalMenuItem.setEnabled(isVertical);
}
if (this.zoomInBothMenuItem != null) {
this.zoomInBothMenuItem.setEnabled(isHorizontal & isVertical);
}
if (this.zoomOutBothMenuItem != null) {
this.zoomOutBothMenuItem.setEnabled(isHorizontal & isVertical);
}
if (this.autoRangeBothMenuItem != null) {
this.autoRangeBothMenuItem.setEnabled(isHorizontal & isVertical);
}
popup.show(this, x, y);
}
}
}