Source Code Cross Referenced for ChartPanel.java in  » Chart » jfreechart » org » jfree » chart » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Chart » jfreechart » org.jfree.chart 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ===========================================================
0002:         * JFreeChart : a free chart library for the Java(tm) platform
0003:         * ===========================================================
0004:         *
0005:         * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
0006:         *
0007:         * Project Info:  http://www.jfree.org/jfreechart/index.html
0008:         *
0009:         * This library is free software; you can redistribute it and/or modify it 
0010:         * under the terms of the GNU Lesser General Public License as published by 
0011:         * the Free Software Foundation; either version 2.1 of the License, or 
0012:         * (at your option) any later version.
0013:         *
0014:         * This library is distributed in the hope that it will be useful, but 
0015:         * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
0016:         * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
0017:         * License for more details.
0018:         *
0019:         * You should have received a copy of the GNU Lesser General Public
0020:         * License along with this library; if not, write to the Free Software
0021:         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
0022:         * USA.  
0023:         *
0024:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
0025:         * in the United States and other countries.]
0026:         *
0027:         * ---------------
0028:         * ChartPanel.java
0029:         * ---------------
0030:         * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
0031:         *
0032:         * Original Author:  David Gilbert (for Object Refinery Limited);
0033:         * Contributor(s):   Andrzej Porebski;
0034:         *                   Soren Caspersen;
0035:         *                   Jonathan Nash;
0036:         *                   Hans-Jurgen Greiner;
0037:         *                   Andreas Schneider;
0038:         *                   Daniel van Enckevort;
0039:         *                   David M O'Donnell;
0040:         *                   Arnaud Lelievre;
0041:         *                   Matthias Rose;
0042:         *                   Onno vd Akker;
0043:         *                   Sergei Ivanov;
0044:         *
0045:         * $Id: ChartPanel.java,v 1.20.2.15 2007/06/06 15:08:23 mungady Exp $
0046:         *
0047:         * Changes (from 28-Jun-2001)
0048:         * --------------------------
0049:         * 28-Jun-2001 : Integrated buffering code contributed by S???ren 
0050:         *               Caspersen (DG);
0051:         * 18-Sep-2001 : Updated header and fixed DOS encoding problem (DG);
0052:         * 22-Nov-2001 : Added scaling to improve display of charts in small sizes (DG);
0053:         * 26-Nov-2001 : Added property editing, saving and printing (DG);
0054:         * 11-Dec-2001 : Transferred saveChartAsPNG method to new ChartUtilities 
0055:         *               class (DG);
0056:         * 13-Dec-2001 : Added tooltips (DG);
0057:         * 16-Jan-2002 : Added an optional crosshair, based on the implementation by 
0058:         *               Jonathan Nash. Renamed the tooltips class (DG);
0059:         * 23-Jan-2002 : Implemented zooming based on code by Hans-Jurgen Greiner (DG);
0060:         * 05-Feb-2002 : Improved tooltips setup.  Renamed method attemptSaveAs() 
0061:         *               --> doSaveAs() and made it public rather than private (DG);
0062:         * 28-Mar-2002 : Added a new constructor (DG);
0063:         * 09-Apr-2002 : Changed initialisation of tooltip generation, as suggested by 
0064:         *               Hans-Jurgen Greiner (DG);
0065:         * 27-May-2002 : New interactive zooming methods based on code by Hans-Jurgen 
0066:         *               Greiner. Renamed JFreeChartPanel --> ChartPanel, moved 
0067:         *               constants to ChartPanelConstants interface (DG);
0068:         * 31-May-2002 : Fixed a bug with interactive zooming and added a way to 
0069:         *               control if the zoom rectangle is filled in or drawn as an 
0070:         *               outline. A mouse drag gesture towards the top left now causes 
0071:         *               an autoRangeBoth() and is a way to undo zooms (AS);
0072:         * 11-Jun-2002 : Reinstated handleClick method call in mouseClicked() to get 
0073:         *               crosshairs working again (DG);
0074:         * 13-Jun-2002 : Added check for null popup menu in mouseDragged method (DG);
0075:         * 18-Jun-2002 : Added get/set methods for minimum and maximum chart 
0076:         *               dimensions (DG);
0077:         * 25-Jun-2002 : Removed redundant code (DG);
0078:         * 27-Aug-2002 : Added get/set methods for popup menu (DG);
0079:         * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
0080:         * 22-Oct-2002 : Added translation methods for screen <--> Java2D, contributed
0081:         *               by Daniel van Enckevort (DG);
0082:         * 05-Nov-2002 : Added a chart reference to the ChartMouseEvent class (DG);
0083:         * 22-Nov-2002 : Added test in zoom method for inverted axes, supplied by 
0084:         *               David M O'Donnell (DG);
0085:         * 14-Jan-2003 : Implemented ChartProgressListener interface (DG);
0086:         * 14-Feb-2003 : Removed deprecated setGenerateTooltips method (DG);
0087:         * 12-Mar-2003 : Added option to enforce filename extension (see bug id 
0088:         *               643173) (DG);
0089:         * 08-Sep-2003 : Added internationalization via use of properties 
0090:         *               resourceBundle (RFE 690236) (AL);
0091:         * 18-Sep-2003 : Added getScaleX() and getScaleY() methods (protected) as 
0092:         *               requested by Irv Thomae (DG);
0093:         * 12-Nov-2003 : Added zooming support for the FastScatterPlot class (DG);
0094:         * 24-Nov-2003 : Minor Javadoc updates (DG);
0095:         * 04-Dec-2003 : Added anchor point for crosshair calculation (DG);
0096:         * 17-Jan-2004 : Added new methods to set tooltip delays to be used in this 
0097:         *               chart panel. Refer to patch 877565 (MR);
0098:         * 02-Feb-2004 : Fixed bug in zooming trigger and added zoomTriggerDistance 
0099:         *               attribute (DG);
0100:         * 08-Apr-2004 : Changed getScaleX() and getScaleY() from protected to 
0101:         *               public (DG);
0102:         * 15-Apr-2004 : Added zoomOutFactor and zoomInFactor (DG);
0103:         * 21-Apr-2004 : Fixed zooming bug in mouseReleased() method (DG);
0104:         * 13-Jul-2004 : Added check for null chart (DG);
0105:         * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG); 
0106:         * 11-Nov-2004 : Moved constants back in from ChartPanelConstants (DG);
0107:         * 12-Nov-2004 : Modified zooming mechanism to support zooming within 
0108:         *               subplots (DG);
0109:         * 26-Jan-2005 : Fixed mouse zooming for horizontal category plots (DG);
0110:         * 11-Apr-2005 : Added getFillZoomRectangle() method, renamed 
0111:         *               setHorizontalZoom() --> setDomainZoomable(), 
0112:         *               setVerticalZoom() --> setRangeZoomable(), added 
0113:         *               isDomainZoomable() and isRangeZoomable(), added 
0114:         *               getHorizontalAxisTrace() and getVerticalAxisTrace(),
0115:         *               renamed autoRangeBoth() --> restoreAutoBounds(),
0116:         *               autoRangeHorizontal() --> restoreAutoDomainBounds(),
0117:         *               autoRangeVertical() --> restoreAutoRangeBounds() (DG);
0118:         * 12-Apr-2005 : Removed working areas, added getAnchorPoint() method,
0119:         *               added protected accessors for tracelines (DG);
0120:         * 18-Apr-2005 : Made constants final (DG);
0121:         * 26-Apr-2005 : Removed LOGGER (DG);
0122:         * 01-Jun-2005 : Fixed zooming for combined plots - see bug report 
0123:         *               1212039, fix thanks to Onno vd Akker (DG);
0124:         * 25-Nov-2005 : Reworked event listener mechanism (DG);
0125:         * ------------- JFREECHART 1.0.x ---------------------------------------------
0126:         * 01-Aug-2006 : Fixed minor bug in restoreAutoRangeBounds() (DG);
0127:         * 04-Sep-2006 : Renamed attemptEditChartProperties() --> 
0128:         *               doEditChartProperties() and made public (DG);
0129:         * 13-Sep-2006 : Don't generate ChartMouseEvents if the panel's chart is null
0130:         *               (fixes bug 1556951) (DG);
0131:         * 05-Mar-2007 : Applied patch 1672561 by Sergei Ivanov, to fix zoom rectangle
0132:         *               drawing for dynamic charts (DG);
0133:         * 17-Apr-2007 : Fix NullPointerExceptions in zooming for combined plots (DG);
0134:         * 24-May-2007 : When the look-and-feel changes, update the popup menu if there 
0135:         *               is one (DG);
0136:         * 06-Jun-2007 : Fixed coordinates for drawing buffer image (DG);
0137:         *               
0138:         */
0139:
0140:        package org.jfree.chart;
0141:
0142:        import java.awt.AWTEvent;
0143:        import java.awt.Color;
0144:        import java.awt.Dimension;
0145:        import java.awt.Graphics;
0146:        import java.awt.Graphics2D;
0147:        import java.awt.Image;
0148:        import java.awt.Insets;
0149:        import java.awt.Point;
0150:        import java.awt.event.ActionEvent;
0151:        import java.awt.event.ActionListener;
0152:        import java.awt.event.MouseEvent;
0153:        import java.awt.event.MouseListener;
0154:        import java.awt.event.MouseMotionListener;
0155:        import java.awt.geom.AffineTransform;
0156:        import java.awt.geom.Line2D;
0157:        import java.awt.geom.Point2D;
0158:        import java.awt.geom.Rectangle2D;
0159:        import java.awt.print.PageFormat;
0160:        import java.awt.print.Printable;
0161:        import java.awt.print.PrinterException;
0162:        import java.awt.print.PrinterJob;
0163:        import java.io.File;
0164:        import java.io.IOException;
0165:        import java.io.Serializable;
0166:        import java.util.EventListener;
0167:        import java.util.ResourceBundle;
0168:
0169:        import javax.swing.JFileChooser;
0170:        import javax.swing.JMenu;
0171:        import javax.swing.JMenuItem;
0172:        import javax.swing.JOptionPane;
0173:        import javax.swing.JPanel;
0174:        import javax.swing.JPopupMenu;
0175:        import javax.swing.SwingUtilities;
0176:        import javax.swing.ToolTipManager;
0177:        import javax.swing.event.EventListenerList;
0178:
0179:        import org.jfree.chart.editor.ChartEditor;
0180:        import org.jfree.chart.editor.ChartEditorManager;
0181:        import org.jfree.chart.entity.ChartEntity;
0182:        import org.jfree.chart.entity.EntityCollection;
0183:        import org.jfree.chart.event.ChartChangeEvent;
0184:        import org.jfree.chart.event.ChartChangeListener;
0185:        import org.jfree.chart.event.ChartProgressEvent;
0186:        import org.jfree.chart.event.ChartProgressListener;
0187:        import org.jfree.chart.plot.Plot;
0188:        import org.jfree.chart.plot.PlotOrientation;
0189:        import org.jfree.chart.plot.PlotRenderingInfo;
0190:        import org.jfree.chart.plot.Zoomable;
0191:        import org.jfree.ui.ExtensionFileFilter;
0192:
0193:        /**
0194:         * A Swing GUI component for displaying a {@link JFreeChart} object.
0195:         * <P>
0196:         * The panel registers with the chart to receive notification of changes to any
0197:         * component of the chart.  The chart is redrawn automatically whenever this 
0198:         * notification is received.
0199:         */
0200:        public class ChartPanel extends JPanel implements  ChartChangeListener,
0201:                ChartProgressListener, ActionListener, MouseListener,
0202:                MouseMotionListener, Printable, Serializable {
0203:
0204:            /** For serialization. */
0205:            private static final long serialVersionUID = 6046366297214274674L;
0206:
0207:            /** Default setting for buffer usage. */
0208:            public static final boolean DEFAULT_BUFFER_USED = false;
0209:
0210:            /** The default panel width. */
0211:            public static final int DEFAULT_WIDTH = 680;
0212:
0213:            /** The default panel height. */
0214:            public static final int DEFAULT_HEIGHT = 420;
0215:
0216:            /** The default limit below which chart scaling kicks in. */
0217:            public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 300;
0218:
0219:            /** The default limit below which chart scaling kicks in. */
0220:            public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 200;
0221:
0222:            /** The default limit below which chart scaling kicks in. */
0223:            public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 800;
0224:
0225:            /** The default limit below which chart scaling kicks in. */
0226:            public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 600;
0227:
0228:            /** The minimum size required to perform a zoom on a rectangle */
0229:            public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
0230:
0231:            /** Properties action command. */
0232:            public static final String PROPERTIES_COMMAND = "PROPERTIES";
0233:
0234:            /** Save action command. */
0235:            public static final String SAVE_COMMAND = "SAVE";
0236:
0237:            /** Print action command. */
0238:            public static final String PRINT_COMMAND = "PRINT";
0239:
0240:            /** Zoom in (both axes) action command. */
0241:            public static final String ZOOM_IN_BOTH_COMMAND = "ZOOM_IN_BOTH";
0242:
0243:            /** Zoom in (domain axis only) action command. */
0244:            public static final String ZOOM_IN_DOMAIN_COMMAND = "ZOOM_IN_DOMAIN";
0245:
0246:            /** Zoom in (range axis only) action command. */
0247:            public static final String ZOOM_IN_RANGE_COMMAND = "ZOOM_IN_RANGE";
0248:
0249:            /** Zoom out (both axes) action command. */
0250:            public static final String ZOOM_OUT_BOTH_COMMAND = "ZOOM_OUT_BOTH";
0251:
0252:            /** Zoom out (domain axis only) action command. */
0253:            public static final String ZOOM_OUT_DOMAIN_COMMAND = "ZOOM_DOMAIN_BOTH";
0254:
0255:            /** Zoom out (range axis only) action command. */
0256:            public static final String ZOOM_OUT_RANGE_COMMAND = "ZOOM_RANGE_BOTH";
0257:
0258:            /** Zoom reset (both axes) action command. */
0259:            public static final String ZOOM_RESET_BOTH_COMMAND = "ZOOM_RESET_BOTH";
0260:
0261:            /** Zoom reset (domain axis only) action command. */
0262:            public static final String ZOOM_RESET_DOMAIN_COMMAND = "ZOOM_RESET_DOMAIN";
0263:
0264:            /** Zoom reset (range axis only) action command. */
0265:            public static final String ZOOM_RESET_RANGE_COMMAND = "ZOOM_RESET_RANGE";
0266:
0267:            /** The chart that is displayed in the panel. */
0268:            private JFreeChart chart;
0269:
0270:            /** Storage for registered (chart) mouse listeners. */
0271:            private EventListenerList chartMouseListeners;
0272:
0273:            /** A flag that controls whether or not the off-screen buffer is used. */
0274:            private boolean useBuffer;
0275:
0276:            /** A flag that indicates that the buffer should be refreshed. */
0277:            private boolean refreshBuffer;
0278:
0279:            /** A buffer for the rendered chart. */
0280:            private Image chartBuffer;
0281:
0282:            /** The height of the chart buffer. */
0283:            private int chartBufferHeight;
0284:
0285:            /** The width of the chart buffer. */
0286:            private int chartBufferWidth;
0287:
0288:            /** 
0289:             * The minimum width for drawing a chart (uses scaling for smaller widths). 
0290:             */
0291:            private int minimumDrawWidth;
0292:
0293:            /** 
0294:             * The minimum height for drawing a chart (uses scaling for smaller 
0295:             * heights). 
0296:             */
0297:            private int minimumDrawHeight;
0298:
0299:            /** 
0300:             * The maximum width for drawing a chart (uses scaling for bigger 
0301:             * widths). 
0302:             */
0303:            private int maximumDrawWidth;
0304:
0305:            /** 
0306:             * The maximum height for drawing a chart (uses scaling for bigger 
0307:             * heights). 
0308:             */
0309:            private int maximumDrawHeight;
0310:
0311:            /** The popup menu for the frame. */
0312:            private JPopupMenu popup;
0313:
0314:            /** The drawing info collected the last time the chart was drawn. */
0315:            private ChartRenderingInfo info;
0316:
0317:            /** The chart anchor point. */
0318:            private Point2D anchor;
0319:
0320:            /** The scale factor used to draw the chart. */
0321:            private double scaleX;
0322:
0323:            /** The scale factor used to draw the chart. */
0324:            private double scaleY;
0325:
0326:            /** The plot orientation. */
0327:            private PlotOrientation orientation = PlotOrientation.VERTICAL;
0328:
0329:            /** A flag that controls whether or not domain zooming is enabled. */
0330:            private boolean domainZoomable = false;
0331:
0332:            /** A flag that controls whether or not range zooming is enabled. */
0333:            private boolean rangeZoomable = false;
0334:
0335:            /** 
0336:             * The zoom rectangle starting point (selected by the user with a mouse 
0337:             * click).  This is a point on the screen, not the chart (which may have
0338:             * been scaled up or down to fit the panel).  
0339:             */
0340:            private Point zoomPoint = null;
0341:
0342:            /** The zoom rectangle (selected by the user with the mouse). */
0343:            private transient Rectangle2D zoomRectangle = null;
0344:
0345:            /** Controls if the zoom rectangle is drawn as an outline or filled. */
0346:            private boolean fillZoomRectangle = false;
0347:
0348:            /** The minimum distance required to drag the mouse to trigger a zoom. */
0349:            private int zoomTriggerDistance;
0350:
0351:            /** A flag that controls whether or not horizontal tracing is enabled. */
0352:            private boolean horizontalAxisTrace = false;
0353:
0354:            /** A flag that controls whether or not vertical tracing is enabled. */
0355:            private boolean verticalAxisTrace = false;
0356:
0357:            /** A vertical trace line. */
0358:            private transient Line2D verticalTraceLine;
0359:
0360:            /** A horizontal trace line. */
0361:            private transient Line2D horizontalTraceLine;
0362:
0363:            /** Menu item for zooming in on a chart (both axes). */
0364:            private JMenuItem zoomInBothMenuItem;
0365:
0366:            /** Menu item for zooming in on a chart (domain axis). */
0367:            private JMenuItem zoomInDomainMenuItem;
0368:
0369:            /** Menu item for zooming in on a chart (range axis). */
0370:            private JMenuItem zoomInRangeMenuItem;
0371:
0372:            /** Menu item for zooming out on a chart. */
0373:            private JMenuItem zoomOutBothMenuItem;
0374:
0375:            /** Menu item for zooming out on a chart (domain axis). */
0376:            private JMenuItem zoomOutDomainMenuItem;
0377:
0378:            /** Menu item for zooming out on a chart (range axis). */
0379:            private JMenuItem zoomOutRangeMenuItem;
0380:
0381:            /** Menu item for resetting the zoom (both axes). */
0382:            private JMenuItem zoomResetBothMenuItem;
0383:
0384:            /** Menu item for resetting the zoom (domain axis only). */
0385:            private JMenuItem zoomResetDomainMenuItem;
0386:
0387:            /** Menu item for resetting the zoom (range axis only). */
0388:            private JMenuItem zoomResetRangeMenuItem;
0389:
0390:            /** A flag that controls whether or not file extensions are enforced. */
0391:            private boolean enforceFileExtensions;
0392:
0393:            /** A flag that indicates if original tooltip delays are changed. */
0394:            private boolean ownToolTipDelaysActive;
0395:
0396:            /** Original initial tooltip delay of ToolTipManager.sharedInstance(). */
0397:            private int originalToolTipInitialDelay;
0398:
0399:            /** Original reshow tooltip delay of ToolTipManager.sharedInstance(). */
0400:            private int originalToolTipReshowDelay;
0401:
0402:            /** Original dismiss tooltip delay of ToolTipManager.sharedInstance(). */
0403:            private int originalToolTipDismissDelay;
0404:
0405:            /** Own initial tooltip delay to be used in this chart panel. */
0406:            private int ownToolTipInitialDelay;
0407:
0408:            /** Own reshow tooltip delay to be used in this chart panel. */
0409:            private int ownToolTipReshowDelay;
0410:
0411:            /** Own dismiss tooltip delay to be used in this chart panel. */
0412:            private int ownToolTipDismissDelay;
0413:
0414:            /** The factor used to zoom in on an axis range. */
0415:            private double zoomInFactor = 0.5;
0416:
0417:            /** The factor used to zoom out on an axis range. */
0418:            private double zoomOutFactor = 2.0;
0419:
0420:            /** The resourceBundle for the localization. */
0421:            protected static ResourceBundle localizationResources = ResourceBundle
0422:                    .getBundle("org.jfree.chart.LocalizationBundle");
0423:
0424:            /**
0425:             * Constructs a panel that displays the specified chart.
0426:             *
0427:             * @param chart  the chart.
0428:             */
0429:            public ChartPanel(JFreeChart chart) {
0430:
0431:                this (chart, DEFAULT_WIDTH, DEFAULT_HEIGHT,
0432:                        DEFAULT_MINIMUM_DRAW_WIDTH,
0433:                        DEFAULT_MINIMUM_DRAW_HEIGHT,
0434:                        DEFAULT_MAXIMUM_DRAW_WIDTH,
0435:                        DEFAULT_MAXIMUM_DRAW_HEIGHT, DEFAULT_BUFFER_USED, true, // properties
0436:                        true, // save
0437:                        true, // print
0438:                        true, // zoom
0439:                        true // tooltips
0440:                );
0441:
0442:            }
0443:
0444:            /**
0445:             * Constructs a panel containing a chart.
0446:             *
0447:             * @param chart  the chart.
0448:             * @param useBuffer  a flag controlling whether or not an off-screen buffer
0449:             *                   is used.
0450:             */
0451:            public ChartPanel(JFreeChart chart, boolean useBuffer) {
0452:
0453:                this (chart, DEFAULT_WIDTH, DEFAULT_HEIGHT,
0454:                        DEFAULT_MINIMUM_DRAW_WIDTH,
0455:                        DEFAULT_MINIMUM_DRAW_HEIGHT,
0456:                        DEFAULT_MAXIMUM_DRAW_WIDTH,
0457:                        DEFAULT_MAXIMUM_DRAW_HEIGHT, useBuffer, true, // properties
0458:                        true, // save
0459:                        true, // print
0460:                        true, // zoom
0461:                        true // tooltips
0462:                );
0463:
0464:            }
0465:
0466:            /**
0467:             * Constructs a JFreeChart panel.
0468:             *
0469:             * @param chart  the chart.
0470:             * @param properties  a flag indicating whether or not the chart property
0471:             *                    editor should be available via the popup menu.
0472:             * @param save  a flag indicating whether or not save options should be
0473:             *              available via the popup menu.
0474:             * @param print  a flag indicating whether or not the print option
0475:             *               should be available via the popup menu.
0476:             * @param zoom  a flag indicating whether or not zoom options should
0477:             *              be added to the popup menu.
0478:             * @param tooltips  a flag indicating whether or not tooltips should be
0479:             *                  enabled for the chart.
0480:             */
0481:            public ChartPanel(JFreeChart chart, boolean properties,
0482:                    boolean save, boolean print, boolean zoom, boolean tooltips) {
0483:
0484:                this (chart, DEFAULT_WIDTH, DEFAULT_HEIGHT,
0485:                        DEFAULT_MINIMUM_DRAW_WIDTH,
0486:                        DEFAULT_MINIMUM_DRAW_HEIGHT,
0487:                        DEFAULT_MAXIMUM_DRAW_WIDTH,
0488:                        DEFAULT_MAXIMUM_DRAW_HEIGHT, DEFAULT_BUFFER_USED,
0489:                        properties, save, print, zoom, tooltips);
0490:
0491:            }
0492:
0493:            /**
0494:             * Constructs a JFreeChart panel.
0495:             *
0496:             * @param chart  the chart.
0497:             * @param width  the preferred width of the panel.
0498:             * @param height  the preferred height of the panel.
0499:             * @param minimumDrawWidth  the minimum drawing width.
0500:             * @param minimumDrawHeight  the minimum drawing height.
0501:             * @param maximumDrawWidth  the maximum drawing width.
0502:             * @param maximumDrawHeight  the maximum drawing height.
0503:             * @param useBuffer  a flag that indicates whether to use the off-screen
0504:             *                   buffer to improve performance (at the expense of 
0505:             *                   memory).
0506:             * @param properties  a flag indicating whether or not the chart property
0507:             *                    editor should be available via the popup menu.
0508:             * @param save  a flag indicating whether or not save options should be
0509:             *              available via the popup menu.
0510:             * @param print  a flag indicating whether or not the print option
0511:             *               should be available via the popup menu.
0512:             * @param zoom  a flag indicating whether or not zoom options should be 
0513:             *              added to the popup menu.
0514:             * @param tooltips  a flag indicating whether or not tooltips should be 
0515:             *                  enabled for the chart.
0516:             */
0517:            public ChartPanel(JFreeChart chart, int width, int height,
0518:                    int minimumDrawWidth, int minimumDrawHeight,
0519:                    int maximumDrawWidth, int maximumDrawHeight,
0520:                    boolean useBuffer, boolean properties, boolean save,
0521:                    boolean print, boolean zoom, boolean tooltips) {
0522:
0523:                this .setChart(chart);
0524:                this .chartMouseListeners = new EventListenerList();
0525:                this .info = new ChartRenderingInfo();
0526:                setPreferredSize(new Dimension(width, height));
0527:                this .useBuffer = useBuffer;
0528:                this .refreshBuffer = false;
0529:                this .minimumDrawWidth = minimumDrawWidth;
0530:                this .minimumDrawHeight = minimumDrawHeight;
0531:                this .maximumDrawWidth = maximumDrawWidth;
0532:                this .maximumDrawHeight = maximumDrawHeight;
0533:                this .zoomTriggerDistance = DEFAULT_ZOOM_TRIGGER_DISTANCE;
0534:
0535:                // set up popup menu...
0536:                this .popup = null;
0537:                if (properties || save || print || zoom) {
0538:                    this .popup = createPopupMenu(properties, save, print, zoom);
0539:                }
0540:
0541:                enableEvents(AWTEvent.MOUSE_EVENT_MASK);
0542:                enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
0543:                setDisplayToolTips(tooltips);
0544:                addMouseListener(this );
0545:                addMouseMotionListener(this );
0546:
0547:                this .enforceFileExtensions = true;
0548:
0549:                // initialize ChartPanel-specific tool tip delays with
0550:                // values the from ToolTipManager.sharedInstance()
0551:                ToolTipManager ttm = ToolTipManager.sharedInstance();
0552:                this .ownToolTipInitialDelay = ttm.getInitialDelay();
0553:                this .ownToolTipDismissDelay = ttm.getDismissDelay();
0554:                this .ownToolTipReshowDelay = ttm.getReshowDelay();
0555:
0556:            }
0557:
0558:            /**
0559:             * Returns the chart contained in the panel.
0560:             *
0561:             * @return The chart (possibly <code>null</code>).
0562:             */
0563:            public JFreeChart getChart() {
0564:                return this .chart;
0565:            }
0566:
0567:            /**
0568:             * Sets the chart that is displayed in the panel.
0569:             *
0570:             * @param chart  the chart (<code>null</code> permitted).
0571:             */
0572:            public void setChart(JFreeChart chart) {
0573:
0574:                // stop listening for changes to the existing chart
0575:                if (this .chart != null) {
0576:                    this .chart.removeChangeListener(this );
0577:                    this .chart.removeProgressListener(this );
0578:                }
0579:
0580:                // add the new chart
0581:                this .chart = chart;
0582:                if (chart != null) {
0583:                    this .chart.addChangeListener(this );
0584:                    this .chart.addProgressListener(this );
0585:                    Plot plot = chart.getPlot();
0586:                    this .domainZoomable = false;
0587:                    this .rangeZoomable = false;
0588:                    if (plot instanceof  Zoomable) {
0589:                        Zoomable z = (Zoomable) plot;
0590:                        this .domainZoomable = z.isDomainZoomable();
0591:                        this .rangeZoomable = z.isRangeZoomable();
0592:                        this .orientation = z.getOrientation();
0593:                    }
0594:                } else {
0595:                    this .domainZoomable = false;
0596:                    this .rangeZoomable = false;
0597:                }
0598:                if (this .useBuffer) {
0599:                    this .refreshBuffer = true;
0600:                }
0601:                repaint();
0602:
0603:            }
0604:
0605:            /**
0606:             * Returns the minimum drawing width for charts.
0607:             * <P>
0608:             * If the width available on the panel is less than this, then the chart is
0609:             * drawn at the minimum width then scaled down to fit.
0610:             *
0611:             * @return The minimum drawing width.
0612:             */
0613:            public int getMinimumDrawWidth() {
0614:                return this .minimumDrawWidth;
0615:            }
0616:
0617:            /**
0618:             * Sets the minimum drawing width for the chart on this panel.
0619:             * <P>
0620:             * At the time the chart is drawn on the panel, if the available width is
0621:             * less than this amount, the chart will be drawn using the minimum width
0622:             * then scaled down to fit the available space.
0623:             *
0624:             * @param width  The width.
0625:             */
0626:            public void setMinimumDrawWidth(int width) {
0627:                this .minimumDrawWidth = width;
0628:            }
0629:
0630:            /**
0631:             * Returns the maximum drawing width for charts.
0632:             * <P>
0633:             * If the width available on the panel is greater than this, then the chart
0634:             * is drawn at the maximum width then scaled up to fit.
0635:             *
0636:             * @return The maximum drawing width.
0637:             */
0638:            public int getMaximumDrawWidth() {
0639:                return this .maximumDrawWidth;
0640:            }
0641:
0642:            /**
0643:             * Sets the maximum drawing width for the chart on this panel.
0644:             * <P>
0645:             * At the time the chart is drawn on the panel, if the available width is
0646:             * greater than this amount, the chart will be drawn using the maximum
0647:             * width then scaled up to fit the available space.
0648:             *
0649:             * @param width  The width.
0650:             */
0651:            public void setMaximumDrawWidth(int width) {
0652:                this .maximumDrawWidth = width;
0653:            }
0654:
0655:            /**
0656:             * Returns the minimum drawing height for charts.
0657:             * <P>
0658:             * If the height available on the panel is less than this, then the chart
0659:             * is drawn at the minimum height then scaled down to fit.
0660:             *
0661:             * @return The minimum drawing height.
0662:             */
0663:            public int getMinimumDrawHeight() {
0664:                return this .minimumDrawHeight;
0665:            }
0666:
0667:            /**
0668:             * Sets the minimum drawing height for the chart on this panel.
0669:             * <P>
0670:             * At the time the chart is drawn on the panel, if the available height is
0671:             * less than this amount, the chart will be drawn using the minimum height
0672:             * then scaled down to fit the available space.
0673:             *
0674:             * @param height  The height.
0675:             */
0676:            public void setMinimumDrawHeight(int height) {
0677:                this .minimumDrawHeight = height;
0678:            }
0679:
0680:            /**
0681:             * Returns the maximum drawing height for charts.
0682:             * <P>
0683:             * If the height available on the panel is greater than this, then the
0684:             * chart is drawn at the maximum height then scaled up to fit.
0685:             *
0686:             * @return The maximum drawing height.
0687:             */
0688:            public int getMaximumDrawHeight() {
0689:                return this .maximumDrawHeight;
0690:            }
0691:
0692:            /**
0693:             * Sets the maximum drawing height for the chart on this panel.
0694:             * <P>
0695:             * At the time the chart is drawn on the panel, if the available height is
0696:             * greater than this amount, the chart will be drawn using the maximum
0697:             * height then scaled up to fit the available space.
0698:             *
0699:             * @param height  The height.
0700:             */
0701:            public void setMaximumDrawHeight(int height) {
0702:                this .maximumDrawHeight = height;
0703:            }
0704:
0705:            /**
0706:             * Returns the X scale factor for the chart.  This will be 1.0 if no 
0707:             * scaling has been used.
0708:             * 
0709:             * @return The scale factor.
0710:             */
0711:            public double getScaleX() {
0712:                return this .scaleX;
0713:            }
0714:
0715:            /**
0716:             * Returns the Y scale factory for the chart.  This will be 1.0 if no 
0717:             * scaling has been used.
0718:             * 
0719:             * @return The scale factor.
0720:             */
0721:            public double getScaleY() {
0722:                return this .scaleY;
0723:            }
0724:
0725:            /**
0726:             * Returns the anchor point.
0727:             * 
0728:             * @return The anchor point (possibly <code>null</code>).
0729:             */
0730:            public Point2D getAnchor() {
0731:                return this .anchor;
0732:            }
0733:
0734:            /**
0735:             * Sets the anchor point.  This method is provided for the use of 
0736:             * subclasses, not end users.
0737:             * 
0738:             * @param anchor  the anchor point (<code>null</code> permitted).
0739:             */
0740:            protected void setAnchor(Point2D anchor) {
0741:                this .anchor = anchor;
0742:            }
0743:
0744:            /**
0745:             * Returns the popup menu.
0746:             *
0747:             * @return The popup menu.
0748:             */
0749:            public JPopupMenu getPopupMenu() {
0750:                return this .popup;
0751:            }
0752:
0753:            /**
0754:             * Sets the popup menu for the panel.
0755:             *
0756:             * @param popup  the popup menu (<code>null</code> permitted).
0757:             */
0758:            public void setPopupMenu(JPopupMenu popup) {
0759:                this .popup = popup;
0760:            }
0761:
0762:            /**
0763:             * Returns the chart rendering info from the most recent chart redraw.
0764:             *
0765:             * @return The chart rendering info.
0766:             */
0767:            public ChartRenderingInfo getChartRenderingInfo() {
0768:                return this .info;
0769:            }
0770:
0771:            /**
0772:             * A convenience method that switches on mouse-based zooming.
0773:             *
0774:             * @param flag  <code>true</code> enables zooming and rectangle fill on 
0775:             *              zoom.
0776:             */
0777:            public void setMouseZoomable(boolean flag) {
0778:                setMouseZoomable(flag, true);
0779:            }
0780:
0781:            /**
0782:             * A convenience method that switches on mouse-based zooming.
0783:             *
0784:             * @param flag  <code>true</code> if zooming enabled
0785:             * @param fillRectangle  <code>true</code> if zoom rectangle is filled,
0786:             *                       false if rectangle is shown as outline only.
0787:             */
0788:            public void setMouseZoomable(boolean flag, boolean fillRectangle) {
0789:                setDomainZoomable(flag);
0790:                setRangeZoomable(flag);
0791:                setFillZoomRectangle(fillRectangle);
0792:            }
0793:
0794:            /**
0795:             * Returns the flag that determines whether or not zooming is enabled for 
0796:             * the domain axis.
0797:             * 
0798:             * @return A boolean.
0799:             */
0800:            public boolean isDomainZoomable() {
0801:                return this .domainZoomable;
0802:            }
0803:
0804:            /**
0805:             * Sets the flag that controls whether or not zooming is enable for the 
0806:             * domain axis.  A check is made to ensure that the current plot supports
0807:             * zooming for the domain values.
0808:             *
0809:             * @param flag  <code>true</code> enables zooming if possible.
0810:             */
0811:            public void setDomainZoomable(boolean flag) {
0812:                if (flag) {
0813:                    Plot plot = this .chart.getPlot();
0814:                    if (plot instanceof  Zoomable) {
0815:                        Zoomable z = (Zoomable) plot;
0816:                        this .domainZoomable = flag && (z.isDomainZoomable());
0817:                    }
0818:                } else {
0819:                    this .domainZoomable = false;
0820:                }
0821:            }
0822:
0823:            /**
0824:             * Returns the flag that determines whether or not zooming is enabled for 
0825:             * the range axis.
0826:             * 
0827:             * @return A boolean.
0828:             */
0829:            public boolean isRangeZoomable() {
0830:                return this .rangeZoomable;
0831:            }
0832:
0833:            /**
0834:             * A flag that controls mouse-based zooming on the vertical axis.
0835:             *
0836:             * @param flag  <code>true</code> enables zooming.
0837:             */
0838:            public void setRangeZoomable(boolean flag) {
0839:                if (flag) {
0840:                    Plot plot = this .chart.getPlot();
0841:                    if (plot instanceof  Zoomable) {
0842:                        Zoomable z = (Zoomable) plot;
0843:                        this .rangeZoomable = flag && (z.isRangeZoomable());
0844:                    }
0845:                } else {
0846:                    this .rangeZoomable = false;
0847:                }
0848:            }
0849:
0850:            /**
0851:             * Returns the flag that controls whether or not the zoom rectangle is
0852:             * filled when drawn.
0853:             * 
0854:             * @return A boolean.
0855:             */
0856:            public boolean getFillZoomRectangle() {
0857:                return this .fillZoomRectangle;
0858:            }
0859:
0860:            /**
0861:             * A flag that controls how the zoom rectangle is drawn.
0862:             *
0863:             * @param flag  <code>true</code> instructs to fill the rectangle on
0864:             *              zoom, otherwise it will be outlined.
0865:             */
0866:            public void setFillZoomRectangle(boolean flag) {
0867:                this .fillZoomRectangle = flag;
0868:            }
0869:
0870:            /**
0871:             * Returns the zoom trigger distance.  This controls how far the mouse must
0872:             * move before a zoom action is triggered.
0873:             * 
0874:             * @return The distance (in Java2D units).
0875:             */
0876:            public int getZoomTriggerDistance() {
0877:                return this .zoomTriggerDistance;
0878:            }
0879:
0880:            /**
0881:             * Sets the zoom trigger distance.  This controls how far the mouse must 
0882:             * move before a zoom action is triggered.
0883:             * 
0884:             * @param distance  the distance (in Java2D units).
0885:             */
0886:            public void setZoomTriggerDistance(int distance) {
0887:                this .zoomTriggerDistance = distance;
0888:            }
0889:
0890:            /**
0891:             * Returns the flag that controls whether or not a horizontal axis trace
0892:             * line is drawn over the plot area at the current mouse location.
0893:             * 
0894:             * @return A boolean.
0895:             */
0896:            public boolean getHorizontalAxisTrace() {
0897:                return this .horizontalAxisTrace;
0898:            }
0899:
0900:            /**
0901:             * A flag that controls trace lines on the horizontal axis.
0902:             *
0903:             * @param flag  <code>true</code> enables trace lines for the mouse
0904:             *      pointer on the horizontal axis.
0905:             */
0906:            public void setHorizontalAxisTrace(boolean flag) {
0907:                this .horizontalAxisTrace = flag;
0908:            }
0909:
0910:            /**
0911:             * Returns the horizontal trace line.
0912:             * 
0913:             * @return The horizontal trace line (possibly <code>null</code>).
0914:             */
0915:            protected Line2D getHorizontalTraceLine() {
0916:                return this .horizontalTraceLine;
0917:            }
0918:
0919:            /**
0920:             * Sets the horizontal trace line.
0921:             * 
0922:             * @param line  the line (<code>null</code> permitted).
0923:             */
0924:            protected void setHorizontalTraceLine(Line2D line) {
0925:                this .horizontalTraceLine = line;
0926:            }
0927:
0928:            /**
0929:             * Returns the flag that controls whether or not a vertical axis trace
0930:             * line is drawn over the plot area at the current mouse location.
0931:             * 
0932:             * @return A boolean.
0933:             */
0934:            public boolean getVerticalAxisTrace() {
0935:                return this .verticalAxisTrace;
0936:            }
0937:
0938:            /**
0939:             * A flag that controls trace lines on the vertical axis.
0940:             *
0941:             * @param flag  <code>true</code> enables trace lines for the mouse
0942:             *              pointer on the vertical axis.
0943:             */
0944:            public void setVerticalAxisTrace(boolean flag) {
0945:                this .verticalAxisTrace = flag;
0946:            }
0947:
0948:            /**
0949:             * Returns the vertical trace line.
0950:             * 
0951:             * @return The vertical trace line (possibly <code>null</code>).
0952:             */
0953:            protected Line2D getVerticalTraceLine() {
0954:                return this .verticalTraceLine;
0955:            }
0956:
0957:            /**
0958:             * Sets the vertical trace line.
0959:             * 
0960:             * @param line  the line (<code>null</code> permitted).
0961:             */
0962:            protected void setVerticalTraceLine(Line2D line) {
0963:                this .verticalTraceLine = line;
0964:            }
0965:
0966:            /**
0967:             * Returns <code>true</code> if file extensions should be enforced, and 
0968:             * <code>false</code> otherwise.
0969:             *
0970:             * @return The flag.
0971:             */
0972:            public boolean isEnforceFileExtensions() {
0973:                return this .enforceFileExtensions;
0974:            }
0975:
0976:            /**
0977:             * Sets a flag that controls whether or not file extensions are enforced.
0978:             *
0979:             * @param enforce  the new flag value.
0980:             */
0981:            public void setEnforceFileExtensions(boolean enforce) {
0982:                this .enforceFileExtensions = enforce;
0983:            }
0984:
0985:            /**
0986:             * Switches the display of tooltips for the panel on or off.  Note that 
0987:             * tooltips can only be displayed if the chart has been configured to
0988:             * generate tooltip items.
0989:             *
0990:             * @param flag  <code>true</code> to enable tooltips, <code>false</code> to
0991:             *              disable tooltips.
0992:             */
0993:            public void setDisplayToolTips(boolean flag) {
0994:                if (flag) {
0995:                    ToolTipManager.sharedInstance().registerComponent(this );
0996:                } else {
0997:                    ToolTipManager.sharedInstance().unregisterComponent(this );
0998:                }
0999:            }
1000:
1001:            /**
1002:             * Returns a string for the tooltip.
1003:             *
1004:             * @param e  the mouse event.
1005:             *
1006:             * @return A tool tip or <code>null</code> if no tooltip is available.
1007:             */
1008:            public String getToolTipText(MouseEvent e) {
1009:
1010:                String result = null;
1011:                if (this .info != null) {
1012:                    EntityCollection entities = this .info.getEntityCollection();
1013:                    if (entities != null) {
1014:                        Insets insets = getInsets();
1015:                        ChartEntity entity = entities.getEntity((int) ((e
1016:                                .getX() - insets.left) / this .scaleX),
1017:                                (int) ((e.getY() - insets.top) / this .scaleY));
1018:                        if (entity != null) {
1019:                            result = entity.getToolTipText();
1020:                        }
1021:                    }
1022:                }
1023:                return result;
1024:
1025:            }
1026:
1027:            /**
1028:             * Translates a Java2D point on the chart to a screen location.
1029:             *
1030:             * @param java2DPoint  the Java2D point.
1031:             *
1032:             * @return The screen location.
1033:             */
1034:            public Point translateJava2DToScreen(Point2D java2DPoint) {
1035:                Insets insets = getInsets();
1036:                int x = (int) (java2DPoint.getX() * this .scaleX + insets.left);
1037:                int y = (int) (java2DPoint.getY() * this .scaleY + insets.top);
1038:                return new Point(x, y);
1039:            }
1040:
1041:            /**
1042:             * Translates a screen location to a Java2D point.
1043:             *
1044:             * @param screenPoint  the screen location.
1045:             *
1046:             * @return The Java2D coordinates.
1047:             */
1048:            public Point2D translateScreenToJava2D(Point screenPoint) {
1049:                Insets insets = getInsets();
1050:                double x = (screenPoint.getX() - insets.left) / this .scaleX;
1051:                double y = (screenPoint.getY() - insets.top) / this .scaleY;
1052:                return new Point2D.Double(x, y);
1053:            }
1054:
1055:            /**
1056:             * Applies any scaling that is in effect for the chart drawing to the
1057:             * given rectangle.
1058:             *  
1059:             * @param rect  the rectangle.
1060:             * 
1061:             * @return A new scaled rectangle.
1062:             */
1063:            public Rectangle2D scale(Rectangle2D rect) {
1064:                Insets insets = getInsets();
1065:                double x = rect.getX() * getScaleX() + insets.left;
1066:                double y = rect.getY() * this .getScaleY() + insets.top;
1067:                double w = rect.getWidth() * this .getScaleX();
1068:                double h = rect.getHeight() * this .getScaleY();
1069:                return new Rectangle2D.Double(x, y, w, h);
1070:            }
1071:
1072:            /**
1073:             * Returns the chart entity at a given point.
1074:             * <P>
1075:             * This method will return null if there is (a) no entity at the given 
1076:             * point, or (b) no entity collection has been generated.
1077:             *
1078:             * @param viewX  the x-coordinate.
1079:             * @param viewY  the y-coordinate.
1080:             *
1081:             * @return The chart entity (possibly <code>null</code>).
1082:             */
1083:            public ChartEntity getEntityForPoint(int viewX, int viewY) {
1084:
1085:                ChartEntity result = null;
1086:                if (this .info != null) {
1087:                    Insets insets = getInsets();
1088:                    double x = (viewX - insets.left) / this .scaleX;
1089:                    double y = (viewY - insets.top) / this .scaleY;
1090:                    EntityCollection entities = this .info.getEntityCollection();
1091:                    result = entities != null ? entities.getEntity(x, y) : null;
1092:                }
1093:                return result;
1094:
1095:            }
1096:
1097:            /**
1098:             * Returns the flag that controls whether or not the offscreen buffer
1099:             * needs to be refreshed.
1100:             * 
1101:             * @return A boolean.
1102:             */
1103:            public boolean getRefreshBuffer() {
1104:                return this .refreshBuffer;
1105:            }
1106:
1107:            /**
1108:             * Sets the refresh buffer flag.  This flag is used to avoid unnecessary
1109:             * redrawing of the chart when the offscreen image buffer is used.
1110:             *
1111:             * @param flag  <code>true</code> indicates that the buffer should be 
1112:             *              refreshed.
1113:             */
1114:            public void setRefreshBuffer(boolean flag) {
1115:                this .refreshBuffer = flag;
1116:            }
1117:
1118:            /**
1119:             * Paints the component by drawing the chart to fill the entire component,
1120:             * but allowing for the insets (which will be non-zero if a border has been
1121:             * set for this component).  To increase performance (at the expense of
1122:             * memory), an off-screen buffer image can be used.
1123:             *
1124:             * @param g  the graphics device for drawing on.
1125:             */
1126:            public void paintComponent(Graphics g) {
1127:                super .paintComponent(g);
1128:                if (this .chart == null) {
1129:                    return;
1130:                }
1131:                Graphics2D g2 = (Graphics2D) g.create();
1132:
1133:                // first determine the size of the chart rendering area...
1134:                Dimension size = getSize();
1135:                Insets insets = getInsets();
1136:                Rectangle2D available = new Rectangle2D.Double(insets.left,
1137:                        insets.top, size.getWidth() - insets.left
1138:                                - insets.right, size.getHeight() - insets.top
1139:                                - insets.bottom);
1140:
1141:                // work out if scaling is required...
1142:                boolean scale = false;
1143:                double drawWidth = available.getWidth();
1144:                double drawHeight = available.getHeight();
1145:                this .scaleX = 1.0;
1146:                this .scaleY = 1.0;
1147:
1148:                if (drawWidth < this .minimumDrawWidth) {
1149:                    this .scaleX = drawWidth / this .minimumDrawWidth;
1150:                    drawWidth = this .minimumDrawWidth;
1151:                    scale = true;
1152:                } else if (drawWidth > this .maximumDrawWidth) {
1153:                    this .scaleX = drawWidth / this .maximumDrawWidth;
1154:                    drawWidth = this .maximumDrawWidth;
1155:                    scale = true;
1156:                }
1157:
1158:                if (drawHeight < this .minimumDrawHeight) {
1159:                    this .scaleY = drawHeight / this .minimumDrawHeight;
1160:                    drawHeight = this .minimumDrawHeight;
1161:                    scale = true;
1162:                } else if (drawHeight > this .maximumDrawHeight) {
1163:                    this .scaleY = drawHeight / this .maximumDrawHeight;
1164:                    drawHeight = this .maximumDrawHeight;
1165:                    scale = true;
1166:                }
1167:
1168:                Rectangle2D chartArea = new Rectangle2D.Double(0.0, 0.0,
1169:                        drawWidth, drawHeight);
1170:
1171:                // are we using the chart buffer?
1172:                if (this .useBuffer) {
1173:
1174:                    // do we need to resize the buffer?
1175:                    if ((this .chartBuffer == null)
1176:                            || (this .chartBufferWidth != available.getWidth())
1177:                            || (this .chartBufferHeight != available.getHeight())) {
1178:                        this .chartBufferWidth = (int) available.getWidth();
1179:                        this .chartBufferHeight = (int) available.getHeight();
1180:                        this .chartBuffer = createImage(this .chartBufferWidth,
1181:                                this .chartBufferHeight);
1182:                        //                GraphicsConfiguration gc = g2.getDeviceConfiguration();
1183:                        //                this.chartBuffer = gc.createCompatibleImage(
1184:                        //                        this.chartBufferWidth, this.chartBufferHeight, 
1185:                        //                        Transparency.TRANSLUCENT);
1186:                        this .refreshBuffer = true;
1187:                    }
1188:
1189:                    // do we need to redraw the buffer?
1190:                    if (this .refreshBuffer) {
1191:
1192:                        Rectangle2D bufferArea = new Rectangle2D.Double(0, 0,
1193:                                this .chartBufferWidth, this .chartBufferHeight);
1194:
1195:                        Graphics2D bufferG2 = (Graphics2D) this .chartBuffer
1196:                                .getGraphics();
1197:                        if (scale) {
1198:                            AffineTransform saved = bufferG2.getTransform();
1199:                            AffineTransform st = AffineTransform
1200:                                    .getScaleInstance(this .scaleX, this .scaleY);
1201:                            bufferG2.transform(st);
1202:                            this .chart.draw(bufferG2, chartArea, this .anchor,
1203:                                    this .info);
1204:                            bufferG2.setTransform(saved);
1205:                        } else {
1206:                            this .chart.draw(bufferG2, bufferArea, this .anchor,
1207:                                    this .info);
1208:                        }
1209:
1210:                        this .refreshBuffer = false;
1211:
1212:                    }
1213:
1214:                    // zap the buffer onto the panel...
1215:                    g2.drawImage(this .chartBuffer, insets.left, insets.top,
1216:                            this );
1217:
1218:                }
1219:
1220:                // or redrawing the chart every time...
1221:                else {
1222:
1223:                    AffineTransform saved = g2.getTransform();
1224:                    g2.translate(insets.left, insets.top);
1225:                    if (scale) {
1226:                        AffineTransform st = AffineTransform.getScaleInstance(
1227:                                this .scaleX, this .scaleY);
1228:                        g2.transform(st);
1229:                    }
1230:                    this .chart.draw(g2, chartArea, this .anchor, this .info);
1231:                    g2.setTransform(saved);
1232:
1233:                }
1234:
1235:                // Redraw the zoom rectangle (if present)
1236:                drawZoomRectangle(g2);
1237:
1238:                g2.dispose();
1239:
1240:                this .anchor = null;
1241:                this .verticalTraceLine = null;
1242:                this .horizontalTraceLine = null;
1243:
1244:            }
1245:
1246:            /**
1247:             * Receives notification of changes to the chart, and redraws the chart.
1248:             *
1249:             * @param event  details of the chart change event.
1250:             */
1251:            public void chartChanged(ChartChangeEvent event) {
1252:                this .refreshBuffer = true;
1253:                Plot plot = this .chart.getPlot();
1254:                if (plot instanceof  Zoomable) {
1255:                    Zoomable z = (Zoomable) plot;
1256:                    this .orientation = z.getOrientation();
1257:                }
1258:                repaint();
1259:            }
1260:
1261:            /**
1262:             * Receives notification of a chart progress event.
1263:             *
1264:             * @param event  the event.
1265:             */
1266:            public void chartProgress(ChartProgressEvent event) {
1267:                // does nothing - override if necessary
1268:            }
1269:
1270:            /**
1271:             * Handles action events generated by the popup menu.
1272:             *
1273:             * @param event  the event.
1274:             */
1275:            public void actionPerformed(ActionEvent event) {
1276:
1277:                String command = event.getActionCommand();
1278:
1279:                // many of the zoom methods need a screen location - all we have is 
1280:                // the zoomPoint, but it might be null.  Here we grab the x and y
1281:                // coordinates, or use defaults...
1282:                double screenX = -1.0;
1283:                double screenY = -1.0;
1284:                if (this .zoomPoint != null) {
1285:                    screenX = this .zoomPoint.getX();
1286:                    screenY = this .zoomPoint.getY();
1287:                }
1288:
1289:                if (command.equals(PROPERTIES_COMMAND)) {
1290:                    doEditChartProperties();
1291:                } else if (command.equals(SAVE_COMMAND)) {
1292:                    try {
1293:                        doSaveAs();
1294:                    } catch (IOException e) {
1295:                        e.printStackTrace();
1296:                    }
1297:                } else if (command.equals(PRINT_COMMAND)) {
1298:                    createChartPrintJob();
1299:                } else if (command.equals(ZOOM_IN_BOTH_COMMAND)) {
1300:                    zoomInBoth(screenX, screenY);
1301:                } else if (command.equals(ZOOM_IN_DOMAIN_COMMAND)) {
1302:                    zoomInDomain(screenX, screenY);
1303:                } else if (command.equals(ZOOM_IN_RANGE_COMMAND)) {
1304:                    zoomInRange(screenX, screenY);
1305:                } else if (command.equals(ZOOM_OUT_BOTH_COMMAND)) {
1306:                    zoomOutBoth(screenX, screenY);
1307:                } else if (command.equals(ZOOM_OUT_DOMAIN_COMMAND)) {
1308:                    zoomOutDomain(screenX, screenY);
1309:                } else if (command.equals(ZOOM_OUT_RANGE_COMMAND)) {
1310:                    zoomOutRange(screenX, screenY);
1311:                } else if (command.equals(ZOOM_RESET_BOTH_COMMAND)) {
1312:                    restoreAutoBounds();
1313:                } else if (command.equals(ZOOM_RESET_DOMAIN_COMMAND)) {
1314:                    restoreAutoDomainBounds();
1315:                } else if (command.equals(ZOOM_RESET_RANGE_COMMAND)) {
1316:                    restoreAutoRangeBounds();
1317:                }
1318:
1319:            }
1320:
1321:            /**
1322:             * Handles a 'mouse entered' event. This method changes the tooltip delays
1323:             * of ToolTipManager.sharedInstance() to the possibly different values set 
1324:             * for this chart panel. 
1325:             *
1326:             * @param e  the mouse event.
1327:             */
1328:            public void mouseEntered(MouseEvent e) {
1329:                if (!this .ownToolTipDelaysActive) {
1330:                    ToolTipManager ttm = ToolTipManager.sharedInstance();
1331:
1332:                    this .originalToolTipInitialDelay = ttm.getInitialDelay();
1333:                    ttm.setInitialDelay(this .ownToolTipInitialDelay);
1334:
1335:                    this .originalToolTipReshowDelay = ttm.getReshowDelay();
1336:                    ttm.setReshowDelay(this .ownToolTipReshowDelay);
1337:
1338:                    this .originalToolTipDismissDelay = ttm.getDismissDelay();
1339:                    ttm.setDismissDelay(this .ownToolTipDismissDelay);
1340:
1341:                    this .ownToolTipDelaysActive = true;
1342:                }
1343:            }
1344:
1345:            /**
1346:             * Handles a 'mouse exited' event. This method resets the tooltip delays of
1347:             * ToolTipManager.sharedInstance() to their
1348:             * original values in effect before mouseEntered()
1349:             *
1350:             * @param e  the mouse event.
1351:             */
1352:            public void mouseExited(MouseEvent e) {
1353:                if (this .ownToolTipDelaysActive) {
1354:                    // restore original tooltip dealys 
1355:                    ToolTipManager ttm = ToolTipManager.sharedInstance();
1356:                    ttm.setInitialDelay(this .originalToolTipInitialDelay);
1357:                    ttm.setReshowDelay(this .originalToolTipReshowDelay);
1358:                    ttm.setDismissDelay(this .originalToolTipDismissDelay);
1359:                    this .ownToolTipDelaysActive = false;
1360:                }
1361:            }
1362:
1363:            /**
1364:             * Handles a 'mouse pressed' event.
1365:             * <P>
1366:             * This event is the popup trigger on Unix/Linux.  For Windows, the popup
1367:             * trigger is the 'mouse released' event.
1368:             *
1369:             * @param e  The mouse event.
1370:             */
1371:            public void mousePressed(MouseEvent e) {
1372:                if (this .zoomRectangle == null) {
1373:                    Rectangle2D screenDataArea = getScreenDataArea(e.getX(), e
1374:                            .getY());
1375:                    if (screenDataArea != null) {
1376:                        this .zoomPoint = getPointInRectangle(e.getX(),
1377:                                e.getY(), screenDataArea);
1378:                    } else {
1379:                        this .zoomPoint = null;
1380:                    }
1381:                    if (e.isPopupTrigger()) {
1382:                        if (this .popup != null) {
1383:                            displayPopupMenu(e.getX(), e.getY());
1384:                        }
1385:                    }
1386:                }
1387:            }
1388:
1389:            /**
1390:             * Returns a point based on (x, y) but constrained to be within the bounds
1391:             * of the given rectangle.  This method could be moved to JCommon.
1392:             * 
1393:             * @param x  the x-coordinate.
1394:             * @param y  the y-coordinate.
1395:             * @param area  the rectangle (<code>null</code> not permitted).
1396:             * 
1397:             * @return A point within the rectangle.
1398:             */
1399:            private Point getPointInRectangle(int x, int y, Rectangle2D area) {
1400:                x = (int) Math.max(Math.ceil(area.getMinX()), Math.min(x, Math
1401:                        .floor(area.getMaxX())));
1402:                y = (int) Math.max(Math.ceil(area.getMinY()), Math.min(y, Math
1403:                        .floor(area.getMaxY())));
1404:                return new Point(x, y);
1405:            }
1406:
1407:            /**
1408:             * Handles a 'mouse dragged' event.
1409:             *
1410:             * @param e  the mouse event.
1411:             */
1412:            public void mouseDragged(MouseEvent e) {
1413:
1414:                // if the popup menu has already been triggered, then ignore dragging...
1415:                if (this .popup != null && this .popup.isShowing()) {
1416:                    return;
1417:                }
1418:                // if no initial zoom point was set, ignore dragging...
1419:                if (this .zoomPoint == null) {
1420:                    return;
1421:                }
1422:                Graphics2D g2 = (Graphics2D) getGraphics();
1423:
1424:                // Erase the previous zoom rectangle (if any)...
1425:                drawZoomRectangle(g2);
1426:
1427:                boolean hZoom = false;
1428:                boolean vZoom = false;
1429:                if (this .orientation == PlotOrientation.HORIZONTAL) {
1430:                    hZoom = this .rangeZoomable;
1431:                    vZoom = this .domainZoomable;
1432:                } else {
1433:                    hZoom = this .domainZoomable;
1434:                    vZoom = this .rangeZoomable;
1435:                }
1436:                Rectangle2D scaledDataArea = getScreenDataArea(
1437:                        (int) this .zoomPoint.getX(), (int) this .zoomPoint
1438:                                .getY());
1439:                if (hZoom && vZoom) {
1440:                    // selected rectangle shouldn't extend outside the data area...
1441:                    double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
1442:                    double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
1443:                    this .zoomRectangle = new Rectangle2D.Double(this .zoomPoint
1444:                            .getX(), this .zoomPoint.getY(), xmax
1445:                            - this .zoomPoint.getX(), ymax
1446:                            - this .zoomPoint.getY());
1447:                } else if (hZoom) {
1448:                    double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
1449:                    this .zoomRectangle = new Rectangle2D.Double(this .zoomPoint
1450:                            .getX(), scaledDataArea.getMinY(), xmax
1451:                            - this .zoomPoint.getX(), scaledDataArea.getHeight());
1452:                } else if (vZoom) {
1453:                    double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
1454:                    this .zoomRectangle = new Rectangle2D.Double(scaledDataArea
1455:                            .getMinX(), this .zoomPoint.getY(), scaledDataArea
1456:                            .getWidth(), ymax - this .zoomPoint.getY());
1457:                }
1458:
1459:                // Draw the new zoom rectangle...
1460:                drawZoomRectangle(g2);
1461:
1462:                g2.dispose();
1463:
1464:            }
1465:
1466:            /**
1467:             * Handles a 'mouse released' event.  On Windows, we need to check if this 
1468:             * is a popup trigger, but only if we haven't already been tracking a zoom
1469:             * rectangle.
1470:             *
1471:             * @param e  information about the event.
1472:             */
1473:            public void mouseReleased(MouseEvent e) {
1474:
1475:                if (this .zoomRectangle != null) {
1476:                    boolean hZoom = false;
1477:                    boolean vZoom = false;
1478:                    if (this .orientation == PlotOrientation.HORIZONTAL) {
1479:                        hZoom = this .rangeZoomable;
1480:                        vZoom = this .domainZoomable;
1481:                    } else {
1482:                        hZoom = this .domainZoomable;
1483:                        vZoom = this .rangeZoomable;
1484:                    }
1485:
1486:                    boolean zoomTrigger1 = hZoom
1487:                            && Math.abs(e.getX() - this .zoomPoint.getX()) >= this .zoomTriggerDistance;
1488:                    boolean zoomTrigger2 = vZoom
1489:                            && Math.abs(e.getY() - this .zoomPoint.getY()) >= this .zoomTriggerDistance;
1490:                    if (zoomTrigger1 || zoomTrigger2) {
1491:                        if ((hZoom && (e.getX() < this .zoomPoint.getX()))
1492:                                || (vZoom && (e.getY() < this .zoomPoint.getY()))) {
1493:                            restoreAutoBounds();
1494:                        } else {
1495:                            double x, y, w, h;
1496:                            Rectangle2D screenDataArea = getScreenDataArea(
1497:                                    (int) this .zoomPoint.getX(),
1498:                                    (int) this .zoomPoint.getY());
1499:                            // for mouseReleased event, (horizontalZoom || verticalZoom)
1500:                            // will be true, so we can just test for either being false;
1501:                            // otherwise both are true
1502:                            if (!vZoom) {
1503:                                x = this .zoomPoint.getX();
1504:                                y = screenDataArea.getMinY();
1505:                                w = Math.min(this .zoomRectangle.getWidth(),
1506:                                        screenDataArea.getMaxX()
1507:                                                - this .zoomPoint.getX());
1508:                                h = screenDataArea.getHeight();
1509:                            } else if (!hZoom) {
1510:                                x = screenDataArea.getMinX();
1511:                                y = this .zoomPoint.getY();
1512:                                w = screenDataArea.getWidth();
1513:                                h = Math.min(this .zoomRectangle.getHeight(),
1514:                                        screenDataArea.getMaxY()
1515:                                                - this .zoomPoint.getY());
1516:                            } else {
1517:                                x = this .zoomPoint.getX();
1518:                                y = this .zoomPoint.getY();
1519:                                w = Math.min(this .zoomRectangle.getWidth(),
1520:                                        screenDataArea.getMaxX()
1521:                                                - this .zoomPoint.getX());
1522:                                h = Math.min(this .zoomRectangle.getHeight(),
1523:                                        screenDataArea.getMaxY()
1524:                                                - this .zoomPoint.getY());
1525:                            }
1526:                            Rectangle2D zoomArea = new Rectangle2D.Double(x, y,
1527:                                    w, h);
1528:                            zoom(zoomArea);
1529:                        }
1530:                        this .zoomPoint = null;
1531:                        this .zoomRectangle = null;
1532:                    } else {
1533:                        // Erase the zoom rectangle
1534:                        Graphics2D g2 = (Graphics2D) getGraphics();
1535:                        drawZoomRectangle(g2);
1536:                        g2.dispose();
1537:                        this .zoomPoint = null;
1538:                        this .zoomRectangle = null;
1539:                    }
1540:
1541:                }
1542:
1543:                else if (e.isPopupTrigger()) {
1544:                    if (this .popup != null) {
1545:                        displayPopupMenu(e.getX(), e.getY());
1546:                    }
1547:                }
1548:
1549:            }
1550:
1551:            /**
1552:             * Receives notification of mouse clicks on the panel. These are
1553:             * translated and passed on to any registered chart mouse click listeners.
1554:             *
1555:             * @param event  Information about the mouse event.
1556:             */
1557:            public void mouseClicked(MouseEvent event) {
1558:
1559:                Insets insets = getInsets();
1560:                int x = (int) ((event.getX() - insets.left) / this .scaleX);
1561:                int y = (int) ((event.getY() - insets.top) / this .scaleY);
1562:
1563:                this .anchor = new Point2D.Double(x, y);
1564:                if (this .chart == null) {
1565:                    return;
1566:                }
1567:                this .chart.setNotify(true); // force a redraw 
1568:                // new entity code...
1569:                Object[] listeners = this .chartMouseListeners
1570:                        .getListeners(ChartMouseListener.class);
1571:                if (listeners.length == 0) {
1572:                    return;
1573:                }
1574:
1575:                ChartEntity entity = null;
1576:                if (this .info != null) {
1577:                    EntityCollection entities = this .info.getEntityCollection();
1578:                    if (entities != null) {
1579:                        entity = entities.getEntity(x, y);
1580:                    }
1581:                }
1582:                ChartMouseEvent chartEvent = new ChartMouseEvent(getChart(),
1583:                        event, entity);
1584:                for (int i = listeners.length - 1; i >= 0; i -= 1) {
1585:                    ((ChartMouseListener) listeners[i])
1586:                            .chartMouseClicked(chartEvent);
1587:                }
1588:
1589:            }
1590:
1591:            /**
1592:             * Implementation of the MouseMotionListener's method.
1593:             *
1594:             * @param e  the event.
1595:             */
1596:            public void mouseMoved(MouseEvent e) {
1597:                Graphics2D g2 = (Graphics2D) getGraphics();
1598:                if (this .horizontalAxisTrace) {
1599:                    drawHorizontalAxisTrace(g2, e.getX());
1600:                }
1601:                if (this .verticalAxisTrace) {
1602:                    drawVerticalAxisTrace(g2, e.getY());
1603:                }
1604:                g2.dispose();
1605:
1606:                Object[] listeners = this .chartMouseListeners
1607:                        .getListeners(ChartMouseListener.class);
1608:                if (listeners.length == 0) {
1609:                    return;
1610:                }
1611:                Insets insets = getInsets();
1612:                int x = (int) ((e.getX() - insets.left) / this .scaleX);
1613:                int y = (int) ((e.getY() - insets.top) / this .scaleY);
1614:
1615:                ChartEntity entity = null;
1616:                if (this .info != null) {
1617:                    EntityCollection entities = this .info.getEntityCollection();
1618:                    if (entities != null) {
1619:                        entity = entities.getEntity(x, y);
1620:                    }
1621:                }
1622:
1623:                // we can only generate events if the panel's chart is not null
1624:                // (see bug report 1556951)
1625:                if (this .chart != null) {
1626:                    ChartMouseEvent event = new ChartMouseEvent(getChart(), e,
1627:                            entity);
1628:                    for (int i = listeners.length - 1; i >= 0; i -= 1) {
1629:                        ((ChartMouseListener) listeners[i])
1630:                                .chartMouseMoved(event);
1631:                    }
1632:                }
1633:
1634:            }
1635:
1636:            /**
1637:             * Zooms in on an anchor point (specified in screen coordinate space).
1638:             *
1639:             * @param x  the x value (in screen coordinates).
1640:             * @param y  the y value (in screen coordinates).
1641:             */
1642:            public void zoomInBoth(double x, double y) {
1643:                zoomInDomain(x, y);
1644:                zoomInRange(x, y);
1645:            }
1646:
1647:            /**
1648:             * Decreases the length of the domain axis, centered about the given
1649:             * coordinate on the screen.  The length of the domain axis is reduced
1650:             * by the value of {@link #getZoomInFactor()}.
1651:             *
1652:             * @param x  the x coordinate (in screen coordinates).
1653:             * @param y  the y-coordinate (in screen coordinates).
1654:             */
1655:            public void zoomInDomain(double x, double y) {
1656:                Plot p = this .chart.getPlot();
1657:                if (p instanceof  Zoomable) {
1658:                    Zoomable plot = (Zoomable) p;
1659:                    plot.zoomDomainAxes(this .zoomInFactor, this .info
1660:                            .getPlotInfo(), translateScreenToJava2D(new Point(
1661:                            (int) x, (int) y)));
1662:                }
1663:            }
1664:
1665:            /**
1666:             * Decreases the length of the range axis, centered about the given
1667:             * coordinate on the screen.  The length of the range axis is reduced by
1668:             * the value of {@link #getZoomInFactor()}.
1669:             *
1670:             * @param x  the x-coordinate (in screen coordinates).
1671:             * @param y  the y coordinate (in screen coordinates).
1672:             */
1673:            public void zoomInRange(double x, double y) {
1674:                Plot p = this .chart.getPlot();
1675:                if (p instanceof  Zoomable) {
1676:                    Zoomable z = (Zoomable) p;
1677:                    z
1678:                            .zoomRangeAxes(this .zoomInFactor, this .info
1679:                                    .getPlotInfo(),
1680:                                    translateScreenToJava2D(new Point((int) x,
1681:                                            (int) y)));
1682:                }
1683:            }
1684:
1685:            /**
1686:             * Zooms out on an anchor point (specified in screen coordinate space).
1687:             *
1688:             * @param x  the x value (in screen coordinates).
1689:             * @param y  the y value (in screen coordinates).
1690:             */
1691:            public void zoomOutBoth(double x, double y) {
1692:                zoomOutDomain(x, y);
1693:                zoomOutRange(x, y);
1694:            }
1695:
1696:            /**
1697:             * Increases the length of the domain axis, centered about the given
1698:             * coordinate on the screen.  The length of the domain axis is increased
1699:             * by the value of {@link #getZoomOutFactor()}.
1700:             *
1701:             * @param x  the x coordinate (in screen coordinates).
1702:             * @param y  the y-coordinate (in screen coordinates).
1703:             */
1704:            public void zoomOutDomain(double x, double y) {
1705:                Plot p = this .chart.getPlot();
1706:                if (p instanceof  Zoomable) {
1707:                    Zoomable z = (Zoomable) p;
1708:                    z.zoomDomainAxes(this .zoomOutFactor, this .info
1709:                            .getPlotInfo(), translateScreenToJava2D(new Point(
1710:                            (int) x, (int) y)));
1711:                }
1712:            }
1713:
1714:            /**
1715:             * Increases the length the range axis, centered about the given
1716:             * coordinate on the screen.  The length of the range axis is increased
1717:             * by the value of {@link #getZoomOutFactor()}.
1718:             *
1719:             * @param x  the x coordinate (in screen coordinates).
1720:             * @param y  the y-coordinate (in screen coordinates).
1721:             */
1722:            public void zoomOutRange(double x, double y) {
1723:                Plot p = this .chart.getPlot();
1724:                if (p instanceof  Zoomable) {
1725:                    Zoomable z = (Zoomable) p;
1726:                    z
1727:                            .zoomRangeAxes(this .zoomOutFactor, this .info
1728:                                    .getPlotInfo(),
1729:                                    translateScreenToJava2D(new Point((int) x,
1730:                                            (int) y)));
1731:                }
1732:            }
1733:
1734:            /**
1735:             * Zooms in on a selected region.
1736:             *
1737:             * @param selection  the selected region.
1738:             */
1739:            public void zoom(Rectangle2D selection) {
1740:
1741:                // get the origin of the zoom selection in the Java2D space used for
1742:                // drawing the chart (that is, before any scaling to fit the panel)
1743:                Point2D selectOrigin = translateScreenToJava2D(new Point(
1744:                        (int) Math.ceil(selection.getX()), (int) Math
1745:                                .ceil(selection.getY())));
1746:                PlotRenderingInfo plotInfo = this .info.getPlotInfo();
1747:                Rectangle2D scaledDataArea = getScreenDataArea((int) selection
1748:                        .getCenterX(), (int) selection.getCenterY());
1749:                if ((selection.getHeight() > 0) && (selection.getWidth() > 0)) {
1750:
1751:                    double hLower = (selection.getMinX() - scaledDataArea
1752:                            .getMinX())
1753:                            / scaledDataArea.getWidth();
1754:                    double hUpper = (selection.getMaxX() - scaledDataArea
1755:                            .getMinX())
1756:                            / scaledDataArea.getWidth();
1757:                    double vLower = (scaledDataArea.getMaxY() - selection
1758:                            .getMaxY())
1759:                            / scaledDataArea.getHeight();
1760:                    double vUpper = (scaledDataArea.getMaxY() - selection
1761:                            .getMinY())
1762:                            / scaledDataArea.getHeight();
1763:
1764:                    Plot p = this .chart.getPlot();
1765:                    if (p instanceof  Zoomable) {
1766:                        Zoomable z = (Zoomable) p;
1767:                        if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
1768:                            z.zoomDomainAxes(vLower, vUpper, plotInfo,
1769:                                    selectOrigin);
1770:                            z.zoomRangeAxes(hLower, hUpper, plotInfo,
1771:                                    selectOrigin);
1772:                        } else {
1773:                            z.zoomDomainAxes(hLower, hUpper, plotInfo,
1774:                                    selectOrigin);
1775:                            z.zoomRangeAxes(vLower, vUpper, plotInfo,
1776:                                    selectOrigin);
1777:                        }
1778:                    }
1779:
1780:                }
1781:
1782:            }
1783:
1784:            /**
1785:             * Restores the auto-range calculation on both axes.
1786:             */
1787:            public void restoreAutoBounds() {
1788:                restoreAutoDomainBounds();
1789:                restoreAutoRangeBounds();
1790:            }
1791:
1792:            /**
1793:             * Restores the auto-range calculation on the domain axis.
1794:             */
1795:            public void restoreAutoDomainBounds() {
1796:                Plot p = this .chart.getPlot();
1797:                if (p instanceof  Zoomable) {
1798:                    Zoomable z = (Zoomable) p;
1799:                    // we need to guard against this.zoomPoint being null
1800:                    Point zp = (this .zoomPoint != null ? this .zoomPoint
1801:                            : new Point());
1802:                    z.zoomDomainAxes(0.0, this .info.getPlotInfo(), zp);
1803:                }
1804:            }
1805:
1806:            /**
1807:             * Restores the auto-range calculation on the range axis.
1808:             */
1809:            public void restoreAutoRangeBounds() {
1810:                Plot p = this .chart.getPlot();
1811:                if (p instanceof  Zoomable) {
1812:                    Zoomable z = (Zoomable) p;
1813:                    // we need to guard against this.zoomPoint being null
1814:                    Point zp = (this .zoomPoint != null ? this .zoomPoint
1815:                            : new Point());
1816:                    z.zoomRangeAxes(0.0, this .info.getPlotInfo(), zp);
1817:                }
1818:            }
1819:
1820:            /**
1821:             * Returns the data area for the chart (the area inside the axes) with the
1822:             * current scaling applied (that is, the area as it appears on screen).
1823:             *
1824:             * @return The scaled data area.
1825:             */
1826:            public Rectangle2D getScreenDataArea() {
1827:                Rectangle2D dataArea = this .info.getPlotInfo().getDataArea();
1828:                Insets insets = getInsets();
1829:                double x = dataArea.getX() * this .scaleX + insets.left;
1830:                double y = dataArea.getY() * this .scaleY + insets.top;
1831:                double w = dataArea.getWidth() * this .scaleX;
1832:                double h = dataArea.getHeight() * this .scaleY;
1833:                return new Rectangle2D.Double(x, y, w, h);
1834:            }
1835:
1836:            /**
1837:             * Returns the data area (the area inside the axes) for the plot or subplot,
1838:             * with the current scaling applied.
1839:             *
1840:             * @param x  the x-coordinate (for subplot selection).
1841:             * @param y  the y-coordinate (for subplot selection).
1842:             * 
1843:             * @return The scaled data area.
1844:             */
1845:            public Rectangle2D getScreenDataArea(int x, int y) {
1846:                PlotRenderingInfo plotInfo = this .info.getPlotInfo();
1847:                Rectangle2D result;
1848:                if (plotInfo.getSubplotCount() == 0) {
1849:                    result = getScreenDataArea();
1850:                } else {
1851:                    // get the origin of the zoom selection in the Java2D space used for
1852:                    // drawing the chart (that is, before any scaling to fit the panel)
1853:                    Point2D selectOrigin = translateScreenToJava2D(new Point(x,
1854:                            y));
1855:                    int subplotIndex = plotInfo.getSubplotIndex(selectOrigin);
1856:                    if (subplotIndex == -1) {
1857:                        return null;
1858:                    }
1859:                    result = scale(plotInfo.getSubplotInfo(subplotIndex)
1860:                            .getDataArea());
1861:                }
1862:                return result;
1863:            }
1864:
1865:            /**
1866:             * Returns the initial tooltip delay value used inside this chart panel.
1867:             *
1868:             * @return An integer representing the initial delay value, in milliseconds.
1869:             * 
1870:             * @see javax.swing.ToolTipManager#getInitialDelay()
1871:             */
1872:            public int getInitialDelay() {
1873:                return this .ownToolTipInitialDelay;
1874:            }
1875:
1876:            /**
1877:             * Returns the reshow tooltip delay value used inside this chart panel.
1878:             *
1879:             * @return An integer representing the reshow  delay value, in milliseconds.
1880:             * 
1881:             * @see javax.swing.ToolTipManager#getReshowDelay()
1882:             */
1883:            public int getReshowDelay() {
1884:                return this .ownToolTipReshowDelay;
1885:            }
1886:
1887:            /**
1888:             * Returns the dismissal tooltip delay value used inside this chart panel.
1889:             *
1890:             * @return An integer representing the dismissal delay value, in 
1891:             *         milliseconds.
1892:             * 
1893:             * @see javax.swing.ToolTipManager#getDismissDelay()
1894:             */
1895:            public int getDismissDelay() {
1896:                return this .ownToolTipDismissDelay;
1897:            }
1898:
1899:            /**
1900:             * Specifies the initial delay value for this chart panel.
1901:             *
1902:             * @param delay  the number of milliseconds to delay (after the cursor has 
1903:             *               paused) before displaying. 
1904:             * 
1905:             * @see javax.swing.ToolTipManager#setInitialDelay(int)
1906:             */
1907:            public void setInitialDelay(int delay) {
1908:                this .ownToolTipInitialDelay = delay;
1909:            }
1910:
1911:            /**
1912:             * Specifies the amount of time before the user has to wait initialDelay 
1913:             * milliseconds before a tooltip will be shown.
1914:             *
1915:             * @param delay  time in milliseconds
1916:             * 
1917:             * @see javax.swing.ToolTipManager#setReshowDelay(int)
1918:             */
1919:            public void setReshowDelay(int delay) {
1920:                this .ownToolTipReshowDelay = delay;
1921:            }
1922:
1923:            /**
1924:             * Specifies the dismissal delay value for this chart panel.
1925:             *
1926:             * @param delay the number of milliseconds to delay before taking away the 
1927:             *              tooltip
1928:             * 
1929:             * @see javax.swing.ToolTipManager#setDismissDelay(int)
1930:             */
1931:            public void setDismissDelay(int delay) {
1932:                this .ownToolTipDismissDelay = delay;
1933:            }
1934:
1935:            /**
1936:             * Returns the zoom in factor.
1937:             * 
1938:             * @return The zoom in factor.
1939:             * 
1940:             * @see #setZoomInFactor(double)
1941:             */
1942:            public double getZoomInFactor() {
1943:                return this .zoomInFactor;
1944:            }
1945:
1946:            /**
1947:             * Sets the zoom in factor.
1948:             * 
1949:             * @param factor  the factor.
1950:             * 
1951:             * @see #getZoomInFactor()
1952:             */
1953:            public void setZoomInFactor(double factor) {
1954:                this .zoomInFactor = factor;
1955:            }
1956:
1957:            /**
1958:             * Returns the zoom out factor.
1959:             * 
1960:             * @return The zoom out factor.
1961:             * 
1962:             * @see #setZoomOutFactor(double)
1963:             */
1964:            public double getZoomOutFactor() {
1965:                return this .zoomOutFactor;
1966:            }
1967:
1968:            /**
1969:             * Sets the zoom out factor.
1970:             * 
1971:             * @param factor  the factor.
1972:             * 
1973:             * @see #getZoomOutFactor()
1974:             */
1975:            public void setZoomOutFactor(double factor) {
1976:                this .zoomOutFactor = factor;
1977:            }
1978:
1979:            /**
1980:             * Draws zoom rectangle (if present).
1981:             * The drawing is performed in XOR mode, therefore
1982:             * when this method is called twice in a row,
1983:             * the second call will completely restore the state
1984:             * of the canvas.
1985:             * 
1986:             * @param g2 the graphics device. 
1987:             */
1988:            private void drawZoomRectangle(Graphics2D g2) {
1989:                // Set XOR mode to draw the zoom rectangle
1990:                g2.setXORMode(Color.gray);
1991:                if (this .zoomRectangle != null) {
1992:                    if (this .fillZoomRectangle) {
1993:                        g2.fill(this .zoomRectangle);
1994:                    } else {
1995:                        g2.draw(this .zoomRectangle);
1996:                    }
1997:                }
1998:                // Reset to the default 'overwrite' mode
1999:                g2.setPaintMode();
2000:            }
2001:
2002:            /**
2003:             * Draws a vertical line used to trace the mouse position to the horizontal 
2004:             * axis.
2005:             *
2006:             * @param g2 the graphics device.
2007:             * @param x  the x-coordinate of the trace line.
2008:             */
2009:            private void drawHorizontalAxisTrace(Graphics2D g2, int x) {
2010:
2011:                Rectangle2D dataArea = getScreenDataArea();
2012:
2013:                g2.setXORMode(Color.orange);
2014:                if (((int) dataArea.getMinX() < x)
2015:                        && (x < (int) dataArea.getMaxX())) {
2016:
2017:                    if (this .verticalTraceLine != null) {
2018:                        g2.draw(this .verticalTraceLine);
2019:                        this .verticalTraceLine.setLine(x, (int) dataArea
2020:                                .getMinY(), x, (int) dataArea.getMaxY());
2021:                    } else {
2022:                        this .verticalTraceLine = new Line2D.Float(x,
2023:                                (int) dataArea.getMinY(), x, (int) dataArea
2024:                                        .getMaxY());
2025:                    }
2026:                    g2.draw(this .verticalTraceLine);
2027:                }
2028:
2029:                // Reset to the default 'overwrite' mode
2030:                g2.setPaintMode();
2031:            }
2032:
2033:            /**
2034:             * Draws a horizontal line used to trace the mouse position to the vertical
2035:             * axis.
2036:             *
2037:             * @param g2 the graphics device.
2038:             * @param y  the y-coordinate of the trace line.
2039:             */
2040:            private void drawVerticalAxisTrace(Graphics2D g2, int y) {
2041:
2042:                Rectangle2D dataArea = getScreenDataArea();
2043:
2044:                g2.setXORMode(Color.orange);
2045:                if (((int) dataArea.getMinY() < y)
2046:                        && (y < (int) dataArea.getMaxY())) {
2047:
2048:                    if (this .horizontalTraceLine != null) {
2049:                        g2.draw(this .horizontalTraceLine);
2050:                        this .horizontalTraceLine.setLine((int) dataArea
2051:                                .getMinX(), y, (int) dataArea.getMaxX(), y);
2052:                    } else {
2053:                        this .horizontalTraceLine = new Line2D.Float(
2054:                                (int) dataArea.getMinX(), y, (int) dataArea
2055:                                        .getMaxX(), y);
2056:                    }
2057:                    g2.draw(this .horizontalTraceLine);
2058:                }
2059:
2060:                // Reset to the default 'overwrite' mode
2061:                g2.setPaintMode();
2062:            }
2063:
2064:            /**
2065:             * Displays a dialog that allows the user to edit the properties for the
2066:             * current chart.
2067:             * 
2068:             * @since 1.0.3
2069:             */
2070:            public void doEditChartProperties() {
2071:
2072:                ChartEditor editor = ChartEditorManager
2073:                        .getChartEditor(this .chart);
2074:                int result = JOptionPane
2075:                        .showConfirmDialog(this , editor, localizationResources
2076:                                .getString("Chart_Properties"),
2077:                                JOptionPane.OK_CANCEL_OPTION,
2078:                                JOptionPane.PLAIN_MESSAGE);
2079:                if (result == JOptionPane.OK_OPTION) {
2080:                    editor.updateChart(this .chart);
2081:                }
2082:
2083:            }
2084:
2085:            /**
2086:             * Opens a file chooser and gives the user an opportunity to save the chart
2087:             * in PNG format.
2088:             *
2089:             * @throws IOException if there is an I/O error.
2090:             */
2091:            public void doSaveAs() throws IOException {
2092:
2093:                JFileChooser fileChooser = new JFileChooser();
2094:                ExtensionFileFilter filter = new ExtensionFileFilter(
2095:                        localizationResources.getString("PNG_Image_Files"),
2096:                        ".png");
2097:                fileChooser.addChoosableFileFilter(filter);
2098:
2099:                int option = fileChooser.showSaveDialog(this );
2100:                if (option == JFileChooser.APPROVE_OPTION) {
2101:                    String filename = fileChooser.getSelectedFile().getPath();
2102:                    if (isEnforceFileExtensions()) {
2103:                        if (!filename.endsWith(".png")) {
2104:                            filename = filename + ".png";
2105:                        }
2106:                    }
2107:                    ChartUtilities.saveChartAsPNG(new File(filename),
2108:                            this .chart, getWidth(), getHeight());
2109:                }
2110:
2111:            }
2112:
2113:            /**
2114:             * Creates a print job for the chart.
2115:             */
2116:            public void createChartPrintJob() {
2117:
2118:                PrinterJob job = PrinterJob.getPrinterJob();
2119:                PageFormat pf = job.defaultPage();
2120:                PageFormat pf2 = job.pageDialog(pf);
2121:                if (pf2 != pf) {
2122:                    job.setPrintable(this , pf2);
2123:                    if (job.printDialog()) {
2124:                        try {
2125:                            job.print();
2126:                        } catch (PrinterException e) {
2127:                            JOptionPane.showMessageDialog(this , e);
2128:                        }
2129:                    }
2130:                }
2131:
2132:            }
2133:
2134:            /**
2135:             * Prints the chart on a single page.
2136:             *
2137:             * @param g  the graphics context.
2138:             * @param pf  the page format to use.
2139:             * @param pageIndex  the index of the page. If not <code>0</code>, nothing 
2140:             *                   gets print.
2141:             *
2142:             * @return The result of printing.
2143:             */
2144:            public int print(Graphics g, PageFormat pf, int pageIndex) {
2145:
2146:                if (pageIndex != 0) {
2147:                    return NO_SUCH_PAGE;
2148:                }
2149:                Graphics2D g2 = (Graphics2D) g;
2150:                double x = pf.getImageableX();
2151:                double y = pf.getImageableY();
2152:                double w = pf.getImageableWidth();
2153:                double h = pf.getImageableHeight();
2154:                this .chart.draw(g2, new Rectangle2D.Double(x, y, w, h),
2155:                        this .anchor, null);
2156:                return PAGE_EXISTS;
2157:
2158:            }
2159:
2160:            /**
2161:             * Adds a listener to the list of objects listening for chart mouse events.
2162:             *
2163:             * @param listener  the listener (<code>null</code> not permitted).
2164:             */
2165:            public void addChartMouseListener(ChartMouseListener listener) {
2166:                if (listener == null) {
2167:                    throw new IllegalArgumentException(
2168:                            "Null 'listener' argument.");
2169:                }
2170:                this .chartMouseListeners
2171:                        .add(ChartMouseListener.class, listener);
2172:            }
2173:
2174:            /**
2175:             * Removes a listener from the list of objects listening for chart mouse 
2176:             * events.
2177:             *
2178:             * @param listener  the listener.
2179:             */
2180:            public void removeChartMouseListener(ChartMouseListener listener) {
2181:                this .chartMouseListeners.remove(ChartMouseListener.class,
2182:                        listener);
2183:            }
2184:
2185:            /**
2186:             * Returns an array of the listeners of the given type registered with the
2187:             * panel.
2188:             * 
2189:             * @param listenerType  the listener type.
2190:             * 
2191:             * @return An array of listeners.
2192:             */
2193:            public EventListener[] getListeners(Class listenerType) {
2194:                if (listenerType == ChartMouseListener.class) {
2195:                    // fetch listeners from local storage
2196:                    return this .chartMouseListeners.getListeners(listenerType);
2197:                } else {
2198:                    return super .getListeners(listenerType);
2199:                }
2200:            }
2201:
2202:            /**
2203:             * Creates a popup menu for the panel.
2204:             *
2205:             * @param properties  include a menu item for the chart property editor.
2206:             * @param save  include a menu item for saving the chart.
2207:             * @param print  include a menu item for printing the chart.
2208:             * @param zoom  include menu items for zooming.
2209:             *
2210:             * @return The popup menu.
2211:             */
2212:            protected JPopupMenu createPopupMenu(boolean properties,
2213:                    boolean save, boolean print, boolean zoom) {
2214:
2215:                JPopupMenu result = new JPopupMenu("Chart:");
2216:                boolean separator = false;
2217:
2218:                if (properties) {
2219:                    JMenuItem propertiesItem = new JMenuItem(
2220:                            localizationResources.getString("Properties..."));
2221:                    propertiesItem.setActionCommand(PROPERTIES_COMMAND);
2222:                    propertiesItem.addActionListener(this );
2223:                    result.add(propertiesItem);
2224:                    separator = true;
2225:                }
2226:
2227:                if (save) {
2228:                    if (separator) {
2229:                        result.addSeparator();
2230:                        separator = false;
2231:                    }
2232:                    JMenuItem saveItem = new JMenuItem(localizationResources
2233:                            .getString("Save_as..."));
2234:                    saveItem.setActionCommand(SAVE_COMMAND);
2235:                    saveItem.addActionListener(this );
2236:                    result.add(saveItem);
2237:                    separator = true;
2238:                }
2239:
2240:                if (print) {
2241:                    if (separator) {
2242:                        result.addSeparator();
2243:                        separator = false;
2244:                    }
2245:                    JMenuItem printItem = new JMenuItem(localizationResources
2246:                            .getString("Print..."));
2247:                    printItem.setActionCommand(PRINT_COMMAND);
2248:                    printItem.addActionListener(this );
2249:                    result.add(printItem);
2250:                    separator = true;
2251:                }
2252:
2253:                if (zoom) {
2254:                    if (separator) {
2255:                        result.addSeparator();
2256:                        separator = false;
2257:                    }
2258:
2259:                    JMenu zoomInMenu = new JMenu(localizationResources
2260:                            .getString("Zoom_In"));
2261:
2262:                    this .zoomInBothMenuItem = new JMenuItem(
2263:                            localizationResources.getString("All_Axes"));
2264:                    this .zoomInBothMenuItem
2265:                            .setActionCommand(ZOOM_IN_BOTH_COMMAND);
2266:                    this .zoomInBothMenuItem.addActionListener(this );
2267:                    zoomInMenu.add(this .zoomInBothMenuItem);
2268:
2269:                    zoomInMenu.addSeparator();
2270:
2271:                    this .zoomInDomainMenuItem = new JMenuItem(
2272:                            localizationResources.getString("Domain_Axis"));
2273:                    this .zoomInDomainMenuItem
2274:                            .setActionCommand(ZOOM_IN_DOMAIN_COMMAND);
2275:                    this .zoomInDomainMenuItem.addActionListener(this );
2276:                    zoomInMenu.add(this .zoomInDomainMenuItem);
2277:
2278:                    this .zoomInRangeMenuItem = new JMenuItem(
2279:                            localizationResources.getString("Range_Axis"));
2280:                    this .zoomInRangeMenuItem
2281:                            .setActionCommand(ZOOM_IN_RANGE_COMMAND);
2282:                    this .zoomInRangeMenuItem.addActionListener(this );
2283:                    zoomInMenu.add(this .zoomInRangeMenuItem);
2284:
2285:                    result.add(zoomInMenu);
2286:
2287:                    JMenu zoomOutMenu = new JMenu(localizationResources
2288:                            .getString("Zoom_Out"));
2289:
2290:                    this .zoomOutBothMenuItem = new JMenuItem(
2291:                            localizationResources.getString("All_Axes"));
2292:                    this .zoomOutBothMenuItem
2293:                            .setActionCommand(ZOOM_OUT_BOTH_COMMAND);
2294:                    this .zoomOutBothMenuItem.addActionListener(this );
2295:                    zoomOutMenu.add(this .zoomOutBothMenuItem);
2296:
2297:                    zoomOutMenu.addSeparator();
2298:
2299:                    this .zoomOutDomainMenuItem = new JMenuItem(
2300:                            localizationResources.getString("Domain_Axis"));
2301:                    this .zoomOutDomainMenuItem
2302:                            .setActionCommand(ZOOM_OUT_DOMAIN_COMMAND);
2303:                    this .zoomOutDomainMenuItem.addActionListener(this );
2304:                    zoomOutMenu.add(this .zoomOutDomainMenuItem);
2305:
2306:                    this .zoomOutRangeMenuItem = new JMenuItem(
2307:                            localizationResources.getString("Range_Axis"));
2308:                    this .zoomOutRangeMenuItem
2309:                            .setActionCommand(ZOOM_OUT_RANGE_COMMAND);
2310:                    this .zoomOutRangeMenuItem.addActionListener(this );
2311:                    zoomOutMenu.add(this .zoomOutRangeMenuItem);
2312:
2313:                    result.add(zoomOutMenu);
2314:
2315:                    JMenu autoRangeMenu = new JMenu(localizationResources
2316:                            .getString("Auto_Range"));
2317:
2318:                    this .zoomResetBothMenuItem = new JMenuItem(
2319:                            localizationResources.getString("All_Axes"));
2320:                    this .zoomResetBothMenuItem
2321:                            .setActionCommand(ZOOM_RESET_BOTH_COMMAND);
2322:                    this .zoomResetBothMenuItem.addActionListener(this );
2323:                    autoRangeMenu.add(this .zoomResetBothMenuItem);
2324:
2325:                    autoRangeMenu.addSeparator();
2326:                    this .zoomResetDomainMenuItem = new JMenuItem(
2327:                            localizationResources.getString("Domain_Axis"));
2328:                    this .zoomResetDomainMenuItem
2329:                            .setActionCommand(ZOOM_RESET_DOMAIN_COMMAND);
2330:                    this .zoomResetDomainMenuItem.addActionListener(this );
2331:                    autoRangeMenu.add(this .zoomResetDomainMenuItem);
2332:
2333:                    this .zoomResetRangeMenuItem = new JMenuItem(
2334:                            localizationResources.getString("Range_Axis"));
2335:                    this .zoomResetRangeMenuItem
2336:                            .setActionCommand(ZOOM_RESET_RANGE_COMMAND);
2337:                    this .zoomResetRangeMenuItem.addActionListener(this );
2338:                    autoRangeMenu.add(this .zoomResetRangeMenuItem);
2339:
2340:                    result.addSeparator();
2341:                    result.add(autoRangeMenu);
2342:
2343:                }
2344:
2345:                return result;
2346:
2347:            }
2348:
2349:            /**
2350:             * The idea is to modify the zooming options depending on the type of chart 
2351:             * being displayed by the panel.
2352:             *
2353:             * @param x  horizontal position of the popup.
2354:             * @param y  vertical position of the popup.
2355:             */
2356:            protected void displayPopupMenu(int x, int y) {
2357:
2358:                if (this .popup != null) {
2359:
2360:                    // go through each zoom menu item and decide whether or not to 
2361:                    // enable it...
2362:                    Plot plot = this .chart.getPlot();
2363:                    boolean isDomainZoomable = false;
2364:                    boolean isRangeZoomable = false;
2365:                    if (plot instanceof  Zoomable) {
2366:                        Zoomable z = (Zoomable) plot;
2367:                        isDomainZoomable = z.isDomainZoomable();
2368:                        isRangeZoomable = z.isRangeZoomable();
2369:                    }
2370:
2371:                    if (this .zoomInDomainMenuItem != null) {
2372:                        this .zoomInDomainMenuItem.setEnabled(isDomainZoomable);
2373:                    }
2374:                    if (this .zoomOutDomainMenuItem != null) {
2375:                        this .zoomOutDomainMenuItem.setEnabled(isDomainZoomable);
2376:                    }
2377:                    if (this .zoomResetDomainMenuItem != null) {
2378:                        this .zoomResetDomainMenuItem
2379:                                .setEnabled(isDomainZoomable);
2380:                    }
2381:
2382:                    if (this .zoomInRangeMenuItem != null) {
2383:                        this .zoomInRangeMenuItem.setEnabled(isRangeZoomable);
2384:                    }
2385:                    if (this .zoomOutRangeMenuItem != null) {
2386:                        this .zoomOutRangeMenuItem.setEnabled(isRangeZoomable);
2387:                    }
2388:
2389:                    if (this .zoomResetRangeMenuItem != null) {
2390:                        this .zoomResetRangeMenuItem.setEnabled(isRangeZoomable);
2391:                    }
2392:
2393:                    if (this .zoomInBothMenuItem != null) {
2394:                        this .zoomInBothMenuItem.setEnabled(isDomainZoomable
2395:                                && isRangeZoomable);
2396:                    }
2397:                    if (this .zoomOutBothMenuItem != null) {
2398:                        this .zoomOutBothMenuItem.setEnabled(isDomainZoomable
2399:                                && isRangeZoomable);
2400:                    }
2401:                    if (this .zoomResetBothMenuItem != null) {
2402:                        this .zoomResetBothMenuItem.setEnabled(isDomainZoomable
2403:                                && isRangeZoomable);
2404:                    }
2405:
2406:                    this .popup.show(this , x, y);
2407:                }
2408:
2409:            }
2410:
2411:            /* (non-Javadoc)
2412:             * @see javax.swing.JPanel#updateUI()
2413:             */
2414:            public void updateUI() {
2415:                // here we need to update the UI for the popup menu, if the panel
2416:                // has one...
2417:                if (this.popup != null) {
2418:                    SwingUtilities.updateComponentTreeUI(this.popup);
2419:                }
2420:                super.updateUI();
2421:            }
2422:
2423:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.