001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * ---------------
028 * ChartPanel.java
029 * ---------------
030 * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): Andrzej Porebski;
034 * Soren Caspersen;
035 * Jonathan Nash;
036 * Hans-Jurgen Greiner;
037 * Andreas Schneider;
038 * Daniel van Enckevort;
039 * David M O'Donnell;
040 * Arnaud Lelievre;
041 * Matthias Rose;
042 * Onno vd Akker;
043 * Sergei Ivanov;
044 *
045 * $Id: ChartPanel.java,v 1.20.2.15 2007/06/06 15:08:23 mungady Exp $
046 *
047 * Changes (from 28-Jun-2001)
048 * --------------------------
049 * 28-Jun-2001 : Integrated buffering code contributed by S???ren
050 * Caspersen (DG);
051 * 18-Sep-2001 : Updated header and fixed DOS encoding problem (DG);
052 * 22-Nov-2001 : Added scaling to improve display of charts in small sizes (DG);
053 * 26-Nov-2001 : Added property editing, saving and printing (DG);
054 * 11-Dec-2001 : Transferred saveChartAsPNG method to new ChartUtilities
055 * class (DG);
056 * 13-Dec-2001 : Added tooltips (DG);
057 * 16-Jan-2002 : Added an optional crosshair, based on the implementation by
058 * Jonathan Nash. Renamed the tooltips class (DG);
059 * 23-Jan-2002 : Implemented zooming based on code by Hans-Jurgen Greiner (DG);
060 * 05-Feb-2002 : Improved tooltips setup. Renamed method attemptSaveAs()
061 * --> doSaveAs() and made it public rather than private (DG);
062 * 28-Mar-2002 : Added a new constructor (DG);
063 * 09-Apr-2002 : Changed initialisation of tooltip generation, as suggested by
064 * Hans-Jurgen Greiner (DG);
065 * 27-May-2002 : New interactive zooming methods based on code by Hans-Jurgen
066 * Greiner. Renamed JFreeChartPanel --> ChartPanel, moved
067 * constants to ChartPanelConstants interface (DG);
068 * 31-May-2002 : Fixed a bug with interactive zooming and added a way to
069 * control if the zoom rectangle is filled in or drawn as an
070 * outline. A mouse drag gesture towards the top left now causes
071 * an autoRangeBoth() and is a way to undo zooms (AS);
072 * 11-Jun-2002 : Reinstated handleClick method call in mouseClicked() to get
073 * crosshairs working again (DG);
074 * 13-Jun-2002 : Added check for null popup menu in mouseDragged method (DG);
075 * 18-Jun-2002 : Added get/set methods for minimum and maximum chart
076 * dimensions (DG);
077 * 25-Jun-2002 : Removed redundant code (DG);
078 * 27-Aug-2002 : Added get/set methods for popup menu (DG);
079 * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
080 * 22-Oct-2002 : Added translation methods for screen <--> Java2D, contributed
081 * by Daniel van Enckevort (DG);
082 * 05-Nov-2002 : Added a chart reference to the ChartMouseEvent class (DG);
083 * 22-Nov-2002 : Added test in zoom method for inverted axes, supplied by
084 * David M O'Donnell (DG);
085 * 14-Jan-2003 : Implemented ChartProgressListener interface (DG);
086 * 14-Feb-2003 : Removed deprecated setGenerateTooltips method (DG);
087 * 12-Mar-2003 : Added option to enforce filename extension (see bug id
088 * 643173) (DG);
089 * 08-Sep-2003 : Added internationalization via use of properties
090 * resourceBundle (RFE 690236) (AL);
091 * 18-Sep-2003 : Added getScaleX() and getScaleY() methods (protected) as
092 * requested by Irv Thomae (DG);
093 * 12-Nov-2003 : Added zooming support for the FastScatterPlot class (DG);
094 * 24-Nov-2003 : Minor Javadoc updates (DG);
095 * 04-Dec-2003 : Added anchor point for crosshair calculation (DG);
096 * 17-Jan-2004 : Added new methods to set tooltip delays to be used in this
097 * chart panel. Refer to patch 877565 (MR);
098 * 02-Feb-2004 : Fixed bug in zooming trigger and added zoomTriggerDistance
099 * attribute (DG);
100 * 08-Apr-2004 : Changed getScaleX() and getScaleY() from protected to
101 * public (DG);
102 * 15-Apr-2004 : Added zoomOutFactor and zoomInFactor (DG);
103 * 21-Apr-2004 : Fixed zooming bug in mouseReleased() method (DG);
104 * 13-Jul-2004 : Added check for null chart (DG);
105 * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
106 * 11-Nov-2004 : Moved constants back in from ChartPanelConstants (DG);
107 * 12-Nov-2004 : Modified zooming mechanism to support zooming within
108 * subplots (DG);
109 * 26-Jan-2005 : Fixed mouse zooming for horizontal category plots (DG);
110 * 11-Apr-2005 : Added getFillZoomRectangle() method, renamed
111 * setHorizontalZoom() --> setDomainZoomable(),
112 * setVerticalZoom() --> setRangeZoomable(), added
113 * isDomainZoomable() and isRangeZoomable(), added
114 * getHorizontalAxisTrace() and getVerticalAxisTrace(),
115 * renamed autoRangeBoth() --> restoreAutoBounds(),
116 * autoRangeHorizontal() --> restoreAutoDomainBounds(),
117 * autoRangeVertical() --> restoreAutoRangeBounds() (DG);
118 * 12-Apr-2005 : Removed working areas, added getAnchorPoint() method,
119 * added protected accessors for tracelines (DG);
120 * 18-Apr-2005 : Made constants final (DG);
121 * 26-Apr-2005 : Removed LOGGER (DG);
122 * 01-Jun-2005 : Fixed zooming for combined plots - see bug report
123 * 1212039, fix thanks to Onno vd Akker (DG);
124 * 25-Nov-2005 : Reworked event listener mechanism (DG);
125 * ------------- JFREECHART 1.0.x ---------------------------------------------
126 * 01-Aug-2006 : Fixed minor bug in restoreAutoRangeBounds() (DG);
127 * 04-Sep-2006 : Renamed attemptEditChartProperties() -->
128 * doEditChartProperties() and made public (DG);
129 * 13-Sep-2006 : Don't generate ChartMouseEvents if the panel's chart is null
130 * (fixes bug 1556951) (DG);
131 * 05-Mar-2007 : Applied patch 1672561 by Sergei Ivanov, to fix zoom rectangle
132 * drawing for dynamic charts (DG);
133 * 17-Apr-2007 : Fix NullPointerExceptions in zooming for combined plots (DG);
134 * 24-May-2007 : When the look-and-feel changes, update the popup menu if there
135 * is one (DG);
136 * 06-Jun-2007 : Fixed coordinates for drawing buffer image (DG);
137 *
138 */
139
140 package org.jfree.chart;
141
142 import java.awt.AWTEvent;
143 import java.awt.Color;
144 import java.awt.Dimension;
145 import java.awt.Graphics;
146 import java.awt.Graphics2D;
147 import java.awt.Image;
148 import java.awt.Insets;
149 import java.awt.Point;
150 import java.awt.event.ActionEvent;
151 import java.awt.event.ActionListener;
152 import java.awt.event.MouseEvent;
153 import java.awt.event.MouseListener;
154 import java.awt.event.MouseMotionListener;
155 import java.awt.geom.AffineTransform;
156 import java.awt.geom.Line2D;
157 import java.awt.geom.Point2D;
158 import java.awt.geom.Rectangle2D;
159 import java.awt.print.PageFormat;
160 import java.awt.print.Printable;
161 import java.awt.print.PrinterException;
162 import java.awt.print.PrinterJob;
163 import java.io.File;
164 import java.io.IOException;
165 import java.io.Serializable;
166 import java.util.EventListener;
167 import java.util.ResourceBundle;
168
169 import javax.swing.JFileChooser;
170 import javax.swing.JMenu;
171 import javax.swing.JMenuItem;
172 import javax.swing.JOptionPane;
173 import javax.swing.JPanel;
174 import javax.swing.JPopupMenu;
175 import javax.swing.SwingUtilities;
176 import javax.swing.ToolTipManager;
177 import javax.swing.event.EventListenerList;
178
179 import org.jfree.chart.editor.ChartEditor;
180 import org.jfree.chart.editor.ChartEditorManager;
181 import org.jfree.chart.entity.ChartEntity;
182 import org.jfree.chart.entity.EntityCollection;
183 import org.jfree.chart.event.ChartChangeEvent;
184 import org.jfree.chart.event.ChartChangeListener;
185 import org.jfree.chart.event.ChartProgressEvent;
186 import org.jfree.chart.event.ChartProgressListener;
187 import org.jfree.chart.plot.Plot;
188 import org.jfree.chart.plot.PlotOrientation;
189 import org.jfree.chart.plot.PlotRenderingInfo;
190 import org.jfree.chart.plot.Zoomable;
191 import org.jfree.ui.ExtensionFileFilter;
192
193 /**
194 * A Swing GUI component for displaying a {@link JFreeChart} object.
195 * <P>
196 * The panel registers with the chart to receive notification of changes to any
197 * component of the chart. The chart is redrawn automatically whenever this
198 * notification is received.
199 */
200 public class ChartPanel extends JPanel
201 implements ChartChangeListener,
202 ChartProgressListener,
203 ActionListener,
204 MouseListener,
205 MouseMotionListener,
206 Printable,
207 Serializable {
208
209 /** For serialization. */
210 private static final long serialVersionUID = 6046366297214274674L;
211
212 /** Default setting for buffer usage. */
213 public static final boolean DEFAULT_BUFFER_USED = false;
214
215 /** The default panel width. */
216 public static final int DEFAULT_WIDTH = 680;
217
218 /** The default panel height. */
219 public static final int DEFAULT_HEIGHT = 420;
220
221 /** The default limit below which chart scaling kicks in. */
222 public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 300;
223
224 /** The default limit below which chart scaling kicks in. */
225 public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 200;
226
227 /** The default limit below which chart scaling kicks in. */
228 public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 800;
229
230 /** The default limit below which chart scaling kicks in. */
231 public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 600;
232
233 /** The minimum size required to perform a zoom on a rectangle */
234 public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
235
236 /** Properties action command. */
237 public static final String PROPERTIES_COMMAND = "PROPERTIES";
238
239 /** Save action command. */
240 public static final String SAVE_COMMAND = "SAVE";
241
242 /** Print action command. */
243 public static final String PRINT_COMMAND = "PRINT";
244
245 /** Zoom in (both axes) action command. */
246 public static final String ZOOM_IN_BOTH_COMMAND = "ZOOM_IN_BOTH";
247
248 /** Zoom in (domain axis only) action command. */
249 public static final String ZOOM_IN_DOMAIN_COMMAND = "ZOOM_IN_DOMAIN";
250
251 /** Zoom in (range axis only) action command. */
252 public static final String ZOOM_IN_RANGE_COMMAND = "ZOOM_IN_RANGE";
253
254 /** Zoom out (both axes) action command. */
255 public static final String ZOOM_OUT_BOTH_COMMAND = "ZOOM_OUT_BOTH";
256
257 /** Zoom out (domain axis only) action command. */
258 public static final String ZOOM_OUT_DOMAIN_COMMAND = "ZOOM_DOMAIN_BOTH";
259
260 /** Zoom out (range axis only) action command. */
261 public static final String ZOOM_OUT_RANGE_COMMAND = "ZOOM_RANGE_BOTH";
262
263 /** Zoom reset (both axes) action command. */
264 public static final String ZOOM_RESET_BOTH_COMMAND = "ZOOM_RESET_BOTH";
265
266 /** Zoom reset (domain axis only) action command. */
267 public static final String ZOOM_RESET_DOMAIN_COMMAND = "ZOOM_RESET_DOMAIN";
268
269 /** Zoom reset (range axis only) action command. */
270 public static final String ZOOM_RESET_RANGE_COMMAND = "ZOOM_RESET_RANGE";
271
272 /** The chart that is displayed in the panel. */
273 private JFreeChart chart;
274
275 /** Storage for registered (chart) mouse listeners. */
276 private EventListenerList chartMouseListeners;
277
278 /** A flag that controls whether or not the off-screen buffer is used. */
279 private boolean useBuffer;
280
281 /** A flag that indicates that the buffer should be refreshed. */
282 private boolean refreshBuffer;
283
284 /** A buffer for the rendered chart. */
285 private Image chartBuffer;
286
287 /** The height of the chart buffer. */
288 private int chartBufferHeight;
289
290 /** The width of the chart buffer. */
291 private int chartBufferWidth;
292
293 /**
294 * The minimum width for drawing a chart (uses scaling for smaller widths).
295 */
296 private int minimumDrawWidth;
297
298 /**
299 * The minimum height for drawing a chart (uses scaling for smaller
300 * heights).
301 */
302 private int minimumDrawHeight;
303
304 /**
305 * The maximum width for drawing a chart (uses scaling for bigger
306 * widths).
307 */
308 private int maximumDrawWidth;
309
310 /**
311 * The maximum height for drawing a chart (uses scaling for bigger
312 * heights).
313 */
314 private int maximumDrawHeight;
315
316 /** The popup menu for the frame. */
317 private JPopupMenu popup;
318
319 /** The drawing info collected the last time the chart was drawn. */
320 private ChartRenderingInfo info;
321
322 /** The chart anchor point. */
323 private Point2D anchor;
324
325 /** The scale factor used to draw the chart. */
326 private double scaleX;
327
328 /** The scale factor used to draw the chart. */
329 private double scaleY;
330
331 /** The plot orientation. */
332 private PlotOrientation orientation = PlotOrientation.VERTICAL;
333
334 /** A flag that controls whether or not domain zooming is enabled. */
335 private boolean domainZoomable = false;
336
337 /** A flag that controls whether or not range zooming is enabled. */
338 private boolean rangeZoomable = false;
339
340 /**
341 * The zoom rectangle starting point (selected by the user with a mouse
342 * click). This is a point on the screen, not the chart (which may have
343 * been scaled up or down to fit the panel).
344 */
345 private Point zoomPoint = null;
346
347 /** The zoom rectangle (selected by the user with the mouse). */
348 private transient Rectangle2D zoomRectangle = null;
349
350 /** Controls if the zoom rectangle is drawn as an outline or filled. */
351 private boolean fillZoomRectangle = false;
352
353 /** The minimum distance required to drag the mouse to trigger a zoom. */
354 private int zoomTriggerDistance;
355
356 /** A flag that controls whether or not horizontal tracing is enabled. */
357 private boolean horizontalAxisTrace = false;
358
359 /** A flag that controls whether or not vertical tracing is enabled. */
360 private boolean verticalAxisTrace = false;
361
362 /** A vertical trace line. */
363 private transient Line2D verticalTraceLine;
364
365 /** A horizontal trace line. */
366 private transient Line2D horizontalTraceLine;
367
368 /** Menu item for zooming in on a chart (both axes). */
369 private JMenuItem zoomInBothMenuItem;
370
371 /** Menu item for zooming in on a chart (domain axis). */
372 private JMenuItem zoomInDomainMenuItem;
373
374 /** Menu item for zooming in on a chart (range axis). */
375 private JMenuItem zoomInRangeMenuItem;
376
377 /** Menu item for zooming out on a chart. */
378 private JMenuItem zoomOutBothMenuItem;
379
380 /** Menu item for zooming out on a chart (domain axis). */
381 private JMenuItem zoomOutDomainMenuItem;
382
383 /** Menu item for zooming out on a chart (range axis). */
384 private JMenuItem zoomOutRangeMenuItem;
385
386 /** Menu item for resetting the zoom (both axes). */
387 private JMenuItem zoomResetBothMenuItem;
388
389 /** Menu item for resetting the zoom (domain axis only). */
390 private JMenuItem zoomResetDomainMenuItem;
391
392 /** Menu item for resetting the zoom (range axis only). */
393 private JMenuItem zoomResetRangeMenuItem;
394
395 /** A flag that controls whether or not file extensions are enforced. */
396 private boolean enforceFileExtensions;
397
398 /** A flag that indicates if original tooltip delays are changed. */
399 private boolean ownToolTipDelaysActive;
400
401 /** Original initial tooltip delay of ToolTipManager.sharedInstance(). */
402 private int originalToolTipInitialDelay;
403
404 /** Original reshow tooltip delay of ToolTipManager.sharedInstance(). */
405 private int originalToolTipReshowDelay;
406
407 /** Original dismiss tooltip delay of ToolTipManager.sharedInstance(). */
408 private int originalToolTipDismissDelay;
409
410 /** Own initial tooltip delay to be used in this chart panel. */
411 private int ownToolTipInitialDelay;
412
413 /** Own reshow tooltip delay to be used in this chart panel. */
414 private int ownToolTipReshowDelay;
415
416 /** Own dismiss tooltip delay to be used in this chart panel. */
417 private int ownToolTipDismissDelay;
418
419 /** The factor used to zoom in on an axis range. */
420 private double zoomInFactor = 0.5;
421
422 /** The factor used to zoom out on an axis range. */
423 private double zoomOutFactor = 2.0;
424
425 /** The resourceBundle for the localization. */
426 protected static ResourceBundle localizationResources
427 = ResourceBundle.getBundle("org.jfree.chart.LocalizationBundle");
428
429 /**
430 * Constructs a panel that displays the specified chart.
431 *
432 * @param chart the chart.
433 */
434 public ChartPanel(JFreeChart chart) {
435
436 this(
437 chart,
438 DEFAULT_WIDTH,
439 DEFAULT_HEIGHT,
440 DEFAULT_MINIMUM_DRAW_WIDTH,
441 DEFAULT_MINIMUM_DRAW_HEIGHT,
442 DEFAULT_MAXIMUM_DRAW_WIDTH,
443 DEFAULT_MAXIMUM_DRAW_HEIGHT,
444 DEFAULT_BUFFER_USED,
445 true, // properties
446 true, // save
447 true, // print
448 true, // zoom
449 true // tooltips
450 );
451
452 }
453
454 /**
455 * Constructs a panel containing a chart.
456 *
457 * @param chart the chart.
458 * @param useBuffer a flag controlling whether or not an off-screen buffer
459 * is used.
460 */
461 public ChartPanel(JFreeChart chart, boolean useBuffer) {
462
463 this(chart,
464 DEFAULT_WIDTH,
465 DEFAULT_HEIGHT,
466 DEFAULT_MINIMUM_DRAW_WIDTH,
467 DEFAULT_MINIMUM_DRAW_HEIGHT,
468 DEFAULT_MAXIMUM_DRAW_WIDTH,
469 DEFAULT_MAXIMUM_DRAW_HEIGHT,
470 useBuffer,
471 true, // properties
472 true, // save
473 true, // print
474 true, // zoom
475 true // tooltips
476 );
477
478 }
479
480 /**
481 * Constructs a JFreeChart panel.
482 *
483 * @param chart the chart.
484 * @param properties a flag indicating whether or not the chart property
485 * editor should be available via the popup menu.
486 * @param save a flag indicating whether or not save options should be
487 * available via the popup menu.
488 * @param print a flag indicating whether or not the print option
489 * should be available via the popup menu.
490 * @param zoom a flag indicating whether or not zoom options should
491 * be added to the popup menu.
492 * @param tooltips a flag indicating whether or not tooltips should be
493 * enabled for the chart.
494 */
495 public ChartPanel(JFreeChart chart,
496 boolean properties,
497 boolean save,
498 boolean print,
499 boolean zoom,
500 boolean tooltips) {
501
502 this(chart,
503 DEFAULT_WIDTH,
504 DEFAULT_HEIGHT,
505 DEFAULT_MINIMUM_DRAW_WIDTH,
506 DEFAULT_MINIMUM_DRAW_HEIGHT,
507 DEFAULT_MAXIMUM_DRAW_WIDTH,
508 DEFAULT_MAXIMUM_DRAW_HEIGHT,
509 DEFAULT_BUFFER_USED,
510 properties,
511 save,
512 print,
513 zoom,
514 tooltips
515 );
516
517 }
518
519 /**
520 * Constructs a JFreeChart panel.
521 *
522 * @param chart the chart.
523 * @param width the preferred width of the panel.
524 * @param height the preferred height of the panel.
525 * @param minimumDrawWidth the minimum drawing width.
526 * @param minimumDrawHeight the minimum drawing height.
527 * @param maximumDrawWidth the maximum drawing width.
528 * @param maximumDrawHeight the maximum drawing height.
529 * @param useBuffer a flag that indicates whether to use the off-screen
530 * buffer to improve performance (at the expense of
531 * memory).
532 * @param properties a flag indicating whether or not the chart property
533 * editor should be available via the popup menu.
534 * @param save a flag indicating whether or not save options should be
535 * available via the popup menu.
536 * @param print a flag indicating whether or not the print option
537 * should be available via the popup menu.
538 * @param zoom a flag indicating whether or not zoom options should be
539 * added to the popup menu.
540 * @param tooltips a flag indicating whether or not tooltips should be
541 * enabled for the chart.
542 */
543 public ChartPanel(JFreeChart chart,
544 int width,
545 int height,
546 int minimumDrawWidth,
547 int minimumDrawHeight,
548 int maximumDrawWidth,
549 int maximumDrawHeight,
550 boolean useBuffer,
551 boolean properties,
552 boolean save,
553 boolean print,
554 boolean zoom,
555 boolean tooltips) {
556
557 this.setChart(chart);
558 this.chartMouseListeners = new EventListenerList();
559 this.info = new ChartRenderingInfo();
560 setPreferredSize(new Dimension(width, height));
561 this.useBuffer = useBuffer;
562 this.refreshBuffer = false;
563 this.minimumDrawWidth = minimumDrawWidth;
564 this.minimumDrawHeight = minimumDrawHeight;
565 this.maximumDrawWidth = maximumDrawWidth;
566 this.maximumDrawHeight = maximumDrawHeight;
567 this.zoomTriggerDistance = DEFAULT_ZOOM_TRIGGER_DISTANCE;
568
569 // set up popup menu...
570 this.popup = null;
571 if (properties || save || print || zoom) {
572 this.popup = createPopupMenu(properties, save, print, zoom);
573 }
574
575 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
576 enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
577 setDisplayToolTips(tooltips);
578 addMouseListener(this);
579 addMouseMotionListener(this);
580
581 this.enforceFileExtensions = true;
582
583 // initialize ChartPanel-specific tool tip delays with
584 // values the from ToolTipManager.sharedInstance()
585 ToolTipManager ttm = ToolTipManager.sharedInstance();
586 this.ownToolTipInitialDelay = ttm.getInitialDelay();
587 this.ownToolTipDismissDelay = ttm.getDismissDelay();
588 this.ownToolTipReshowDelay = ttm.getReshowDelay();
589
590 }
591
592 /**
593 * Returns the chart contained in the panel.
594 *
595 * @return The chart (possibly <code>null</code>).
596 */
597 public JFreeChart getChart() {
598 return this.chart;
599 }
600
601 /**
602 * Sets the chart that is displayed in the panel.
603 *
604 * @param chart the chart (<code>null</code> permitted).
605 */
606 public void setChart(JFreeChart chart) {
607
608 // stop listening for changes to the existing chart
609 if (this.chart != null) {
610 this.chart.removeChangeListener(this);
611 this.chart.removeProgressListener(this);
612 }
613
614 // add the new chart
615 this.chart = chart;
616 if (chart != null) {
617 this.chart.addChangeListener(this);
618 this.chart.addProgressListener(this);
619 Plot plot = chart.getPlot();
620 this.domainZoomable = false;
621 this.rangeZoomable = false;
622 if (plot instanceof Zoomable) {
623 Zoomable z = (Zoomable) plot;
624 this.domainZoomable = z.isDomainZoomable();
625 this.rangeZoomable = z.isRangeZoomable();
626 this.orientation = z.getOrientation();
627 }
628 }
629 else {
630 this.domainZoomable = false;
631 this.rangeZoomable = false;
632 }
633 if (this.useBuffer) {
634 this.refreshBuffer = true;
635 }
636 repaint();
637
638 }
639
640 /**
641 * Returns the minimum drawing width for charts.
642 * <P>
643 * If the width available on the panel is less than this, then the chart is
644 * drawn at the minimum width then scaled down to fit.
645 *
646 * @return The minimum drawing width.
647 */
648 public int getMinimumDrawWidth() {
649 return this.minimumDrawWidth;
650 }
651
652 /**
653 * Sets the minimum drawing width for the chart on this panel.
654 * <P>
655 * At the time the chart is drawn on the panel, if the available width is
656 * less than this amount, the chart will be drawn using the minimum width
657 * then scaled down to fit the available space.
658 *
659 * @param width The width.
660 */
661 public void setMinimumDrawWidth(int width) {
662 this.minimumDrawWidth = width;
663 }
664
665 /**
666 * Returns the maximum drawing width for charts.
667 * <P>
668 * If the width available on the panel is greater than this, then the chart
669 * is drawn at the maximum width then scaled up to fit.
670 *
671 * @return The maximum drawing width.
672 */
673 public int getMaximumDrawWidth() {
674 return this.maximumDrawWidth;
675 }
676
677 /**
678 * Sets the maximum drawing width for the chart on this panel.
679 * <P>
680 * At the time the chart is drawn on the panel, if the available width is
681 * greater than this amount, the chart will be drawn using the maximum
682 * width then scaled up to fit the available space.
683 *
684 * @param width The width.
685 */
686 public void setMaximumDrawWidth(int width) {
687 this.maximumDrawWidth = width;
688 }
689
690 /**
691 * Returns the minimum drawing height for charts.
692 * <P>
693 * If the height available on the panel is less than this, then the chart
694 * is drawn at the minimum height then scaled down to fit.
695 *
696 * @return The minimum drawing height.
697 */
698 public int getMinimumDrawHeight() {
699 return this.minimumDrawHeight;
700 }
701
702 /**
703 * Sets the minimum drawing height for the chart on this panel.
704 * <P>
705 * At the time the chart is drawn on the panel, if the available height is
706 * less than this amount, the chart will be drawn using the minimum height
707 * then scaled down to fit the available space.
708 *
709 * @param height The height.
710 */
711 public void setMinimumDrawHeight(int height) {
712 this.minimumDrawHeight = height;
713 }
714
715 /**
716 * Returns the maximum drawing height for charts.
717 * <P>
718 * If the height available on the panel is greater than this, then the
719 * chart is drawn at the maximum height then scaled up to fit.
720 *
721 * @return The maximum drawing height.
722 */
723 public int getMaximumDrawHeight() {
724 return this.maximumDrawHeight;
725 }
726
727 /**
728 * Sets the maximum drawing height for the chart on this panel.
729 * <P>
730 * At the time the chart is drawn on the panel, if the available height is
731 * greater than this amount, the chart will be drawn using the maximum
732 * height then scaled up to fit the available space.
733 *
734 * @param height The height.
735 */
736 public void setMaximumDrawHeight(int height) {
737 this.maximumDrawHeight = height;
738 }
739
740 /**
741 * Returns the X scale factor for the chart. This will be 1.0 if no
742 * scaling has been used.
743 *
744 * @return The scale factor.
745 */
746 public double getScaleX() {
747 return this.scaleX;
748 }
749
750 /**
751 * Returns the Y scale factory for the chart. This will be 1.0 if no
752 * scaling has been used.
753 *
754 * @return The scale factor.
755 */
756 public double getScaleY() {
757 return this.scaleY;
758 }
759
760 /**
761 * Returns the anchor point.
762 *
763 * @return The anchor point (possibly <code>null</code>).
764 */
765 public Point2D getAnchor() {
766 return this.anchor;
767 }
768
769 /**
770 * Sets the anchor point. This method is provided for the use of
771 * subclasses, not end users.
772 *
773 * @param anchor the anchor point (<code>null</code> permitted).
774 */
775 protected void setAnchor(Point2D anchor) {
776 this.anchor = anchor;
777 }
778
779 /**
780 * Returns the popup menu.
781 *
782 * @return The popup menu.
783 */
784 public JPopupMenu getPopupMenu() {
785 return this.popup;
786 }
787
788 /**
789 * Sets the popup menu for the panel.
790 *
791 * @param popup the popup menu (<code>null</code> permitted).
792 */
793 public void setPopupMenu(JPopupMenu popup) {
794 this.popup = popup;
795 }
796
797 /**
798 * Returns the chart rendering info from the most recent chart redraw.
799 *
800 * @return The chart rendering info.
801 */
802 public ChartRenderingInfo getChartRenderingInfo() {
803 return this.info;
804 }
805
806 /**
807 * A convenience method that switches on mouse-based zooming.
808 *
809 * @param flag <code>true</code> enables zooming and rectangle fill on
810 * zoom.
811 */
812 public void setMouseZoomable(boolean flag) {
813 setMouseZoomable(flag, true);
814 }
815
816 /**
817 * A convenience method that switches on mouse-based zooming.
818 *
819 * @param flag <code>true</code> if zooming enabled
820 * @param fillRectangle <code>true</code> if zoom rectangle is filled,
821 * false if rectangle is shown as outline only.
822 */
823 public void setMouseZoomable(boolean flag, boolean fillRectangle) {
824 setDomainZoomable(flag);
825 setRangeZoomable(flag);
826 setFillZoomRectangle(fillRectangle);
827 }
828
829 /**
830 * Returns the flag that determines whether or not zooming is enabled for
831 * the domain axis.
832 *
833 * @return A boolean.
834 */
835 public boolean isDomainZoomable() {
836 return this.domainZoomable;
837 }
838
839 /**
840 * Sets the flag that controls whether or not zooming is enable for the
841 * domain axis. A check is made to ensure that the current plot supports
842 * zooming for the domain values.
843 *
844 * @param flag <code>true</code> enables zooming if possible.
845 */
846 public void setDomainZoomable(boolean flag) {
847 if (flag) {
848 Plot plot = this.chart.getPlot();
849 if (plot instanceof Zoomable) {
850 Zoomable z = (Zoomable) plot;
851 this.domainZoomable = flag && (z.isDomainZoomable());
852 }
853 }
854 else {
855 this.domainZoomable = false;
856 }
857 }
858
859 /**
860 * Returns the flag that determines whether or not zooming is enabled for
861 * the range axis.
862 *
863 * @return A boolean.
864 */
865 public boolean isRangeZoomable() {
866 return this.rangeZoomable;
867 }
868
869 /**
870 * A flag that controls mouse-based zooming on the vertical axis.
871 *
872 * @param flag <code>true</code> enables zooming.
873 */
874 public void setRangeZoomable(boolean flag) {
875 if (flag) {
876 Plot plot = this.chart.getPlot();
877 if (plot instanceof Zoomable) {
878 Zoomable z = (Zoomable) plot;
879 this.rangeZoomable = flag && (z.isRangeZoomable());
880 }
881 }
882 else {
883 this.rangeZoomable = false;
884 }
885 }
886
887 /**
888 * Returns the flag that controls whether or not the zoom rectangle is
889 * filled when drawn.
890 *
891 * @return A boolean.
892 */
893 public boolean getFillZoomRectangle() {
894 return this.fillZoomRectangle;
895 }
896
897 /**
898 * A flag that controls how the zoom rectangle is drawn.
899 *
900 * @param flag <code>true</code> instructs to fill the rectangle on
901 * zoom, otherwise it will be outlined.
902 */
903 public void setFillZoomRectangle(boolean flag) {
904 this.fillZoomRectangle = flag;
905 }
906
907 /**
908 * Returns the zoom trigger distance. This controls how far the mouse must
909 * move before a zoom action is triggered.
910 *
911 * @return The distance (in Java2D units).
912 */
913 public int getZoomTriggerDistance() {
914 return this.zoomTriggerDistance;
915 }
916
917 /**
918 * Sets the zoom trigger distance. This controls how far the mouse must
919 * move before a zoom action is triggered.
920 *
921 * @param distance the distance (in Java2D units).
922 */
923 public void setZoomTriggerDistance(int distance) {
924 this.zoomTriggerDistance = distance;
925 }
926
927 /**
928 * Returns the flag that controls whether or not a horizontal axis trace
929 * line is drawn over the plot area at the current mouse location.
930 *
931 * @return A boolean.
932 */
933 public boolean getHorizontalAxisTrace() {
934 return this.horizontalAxisTrace;
935 }
936
937 /**
938 * A flag that controls trace lines on the horizontal axis.
939 *
940 * @param flag <code>true</code> enables trace lines for the mouse
941 * pointer on the horizontal axis.
942 */
943 public void setHorizontalAxisTrace(boolean flag) {
944 this.horizontalAxisTrace = flag;
945 }
946
947 /**
948 * Returns the horizontal trace line.
949 *
950 * @return The horizontal trace line (possibly <code>null</code>).
951 */
952 protected Line2D getHorizontalTraceLine() {
953 return this.horizontalTraceLine;
954 }
955
956 /**
957 * Sets the horizontal trace line.
958 *
959 * @param line the line (<code>null</code> permitted).
960 */
961 protected void setHorizontalTraceLine(Line2D line) {
962 this.horizontalTraceLine = line;
963 }
964
965 /**
966 * Returns the flag that controls whether or not a vertical axis trace
967 * line is drawn over the plot area at the current mouse location.
968 *
969 * @return A boolean.
970 */
971 public boolean getVerticalAxisTrace() {
972 return this.verticalAxisTrace;
973 }
974
975 /**
976 * A flag that controls trace lines on the vertical axis.
977 *
978 * @param flag <code>true</code> enables trace lines for the mouse
979 * pointer on the vertical axis.
980 */
981 public void setVerticalAxisTrace(boolean flag) {
982 this.verticalAxisTrace = flag;
983 }
984
985 /**
986 * Returns the vertical trace line.
987 *
988 * @return The vertical trace line (possibly <code>null</code>).
989 */
990 protected Line2D getVerticalTraceLine() {
991 return this.verticalTraceLine;
992 }
993
994 /**
995 * Sets the vertical trace line.
996 *
997 * @param line the line (<code>null</code> permitted).
998 */
999 protected void setVerticalTraceLine(Line2D line) {
1000 this.verticalTraceLine = line;
1001 }
1002
1003 /**
1004 * Returns <code>true</code> if file extensions should be enforced, and
1005 * <code>false</code> otherwise.
1006 *
1007 * @return The flag.
1008 */
1009 public boolean isEnforceFileExtensions() {
1010 return this.enforceFileExtensions;
1011 }
1012
1013 /**
1014 * Sets a flag that controls whether or not file extensions are enforced.
1015 *
1016 * @param enforce the new flag value.
1017 */
1018 public void setEnforceFileExtensions(boolean enforce) {
1019 this.enforceFileExtensions = enforce;
1020 }
1021
1022 /**
1023 * Switches the display of tooltips for the panel on or off. Note that
1024 * tooltips can only be displayed if the chart has been configured to
1025 * generate tooltip items.
1026 *
1027 * @param flag <code>true</code> to enable tooltips, <code>false</code> to
1028 * disable tooltips.
1029 */
1030 public void setDisplayToolTips(boolean flag) {
1031 if (flag) {
1032 ToolTipManager.sharedInstance().registerComponent(this);
1033 }
1034 else {
1035 ToolTipManager.sharedInstance().unregisterComponent(this);
1036 }
1037 }
1038
1039 /**
1040 * Returns a string for the tooltip.
1041 *
1042 * @param e the mouse event.
1043 *
1044 * @return A tool tip or <code>null</code> if no tooltip is available.
1045 */
1046 public String getToolTipText(MouseEvent e) {
1047
1048 String result = null;
1049 if (this.info != null) {
1050 EntityCollection entities = this.info.getEntityCollection();
1051 if (entities != null) {
1052 Insets insets = getInsets();
1053 ChartEntity entity = entities.getEntity(
1054 (int) ((e.getX() - insets.left) / this.scaleX),
1055 (int) ((e.getY() - insets.top) / this.scaleY));
1056 if (entity != null) {
1057 result = entity.getToolTipText();
1058 }
1059 }
1060 }
1061 return result;
1062
1063 }
1064
1065 /**
1066 * Translates a Java2D point on the chart to a screen location.
1067 *
1068 * @param java2DPoint the Java2D point.
1069 *
1070 * @return The screen location.
1071 */
1072 public Point translateJava2DToScreen(Point2D java2DPoint) {
1073 Insets insets = getInsets();
1074 int x = (int) (java2DPoint.getX() * this.scaleX + insets.left);
1075 int y = (int) (java2DPoint.getY() * this.scaleY + insets.top);
1076 return new Point(x, y);
1077 }
1078
1079 /**
1080 * Translates a screen location to a Java2D point.
1081 *
1082 * @param screenPoint the screen location.
1083 *
1084 * @return The Java2D coordinates.
1085 */
1086 public Point2D translateScreenToJava2D(Point screenPoint) {
1087 Insets insets = getInsets();
1088 double x = (screenPoint.getX() - insets.left) / this.scaleX;
1089 double y = (screenPoint.getY() - insets.top) / this.scaleY;
1090 return new Point2D.Double(x, y);
1091 }
1092
1093 /**
1094 * Applies any scaling that is in effect for the chart drawing to the
1095 * given rectangle.
1096 *
1097 * @param rect the rectangle.
1098 *
1099 * @return A new scaled rectangle.
1100 */
1101 public Rectangle2D scale(Rectangle2D rect) {
1102 Insets insets = getInsets();
1103 double x = rect.getX() * getScaleX() + insets.left;
1104 double y = rect.getY() * this.getScaleY() + insets.top;
1105 double w = rect.getWidth() * this.getScaleX();
1106 double h = rect.getHeight() * this.getScaleY();
1107 return new Rectangle2D.Double(x, y, w, h);
1108 }
1109
1110 /**
1111 * Returns the chart entity at a given point.
1112 * <P>
1113 * This method will return null if there is (a) no entity at the given
1114 * point, or (b) no entity collection has been generated.
1115 *
1116 * @param viewX the x-coordinate.
1117 * @param viewY the y-coordinate.
1118 *
1119 * @return The chart entity (possibly <code>null</code>).
1120 */
1121 public ChartEntity getEntityForPoint(int viewX, int viewY) {
1122
1123 ChartEntity result = null;
1124 if (this.info != null) {
1125 Insets insets = getInsets();
1126 double x = (viewX - insets.left) / this.scaleX;
1127 double y = (viewY - insets.top) / this.scaleY;
1128 EntityCollection entities = this.info.getEntityCollection();
1129 result = entities != null ? entities.getEntity(x, y) : null;
1130 }
1131 return result;
1132
1133 }
1134
1135 /**
1136 * Returns the flag that controls whether or not the offscreen buffer
1137 * needs to be refreshed.
1138 *
1139 * @return A boolean.
1140 */
1141 public boolean getRefreshBuffer() {
1142 return this.refreshBuffer;
1143 }
1144
1145 /**
1146 * Sets the refresh buffer flag. This flag is used to avoid unnecessary
1147 * redrawing of the chart when the offscreen image buffer is used.
1148 *
1149 * @param flag <code>true</code> indicates that the buffer should be
1150 * refreshed.
1151 */
1152 public void setRefreshBuffer(boolean flag) {
1153 this.refreshBuffer = flag;
1154 }
1155
1156 /**
1157 * Paints the component by drawing the chart to fill the entire component,
1158 * but allowing for the insets (which will be non-zero if a border has been
1159 * set for this component). To increase performance (at the expense of
1160 * memory), an off-screen buffer image can be used.
1161 *
1162 * @param g the graphics device for drawing on.
1163 */
1164 public void paintComponent(Graphics g) {
1165 super.paintComponent(g);
1166 if (this.chart == null) {
1167 return;
1168 }
1169 Graphics2D g2 = (Graphics2D) g.create();
1170
1171 // first determine the size of the chart rendering area...
1172 Dimension size = getSize();
1173 Insets insets = getInsets();
1174 Rectangle2D available = new Rectangle2D.Double(insets.left, insets.top,
1175 size.getWidth() - insets.left - insets.right,
1176 size.getHeight() - insets.top - insets.bottom);
1177
1178 // work out if scaling is required...
1179 boolean scale = false;
1180 double drawWidth = available.getWidth();
1181 double drawHeight = available.getHeight();
1182 this.scaleX = 1.0;
1183 this.scaleY = 1.0;
1184
1185 if (drawWidth < this.minimumDrawWidth) {
1186 this.scaleX = drawWidth / this.minimumDrawWidth;
1187 drawWidth = this.minimumDrawWidth;
1188 scale = true;
1189 }
1190 else if (drawWidth > this.maximumDrawWidth) {
1191 this.scaleX = drawWidth / this.maximumDrawWidth;
1192 drawWidth = this.maximumDrawWidth;
1193 scale = true;
1194 }
1195
1196 if (drawHeight < this.minimumDrawHeight) {
1197 this.scaleY = drawHeight / this.minimumDrawHeight;
1198 drawHeight = this.minimumDrawHeight;
1199 scale = true;
1200 }
1201 else if (drawHeight > this.maximumDrawHeight) {
1202 this.scaleY = drawHeight / this.maximumDrawHeight;
1203 drawHeight = this.maximumDrawHeight;
1204 scale = true;
1205 }
1206
1207 Rectangle2D chartArea = new Rectangle2D.Double(0.0, 0.0, drawWidth,
1208 drawHeight);
1209
1210 // are we using the chart buffer?
1211 if (this.useBuffer) {
1212
1213 // do we need to resize the buffer?
1214 if ((this.chartBuffer == null)
1215 || (this.chartBufferWidth != available.getWidth())
1216 || (this.chartBufferHeight != available.getHeight())
1217 ) {
1218 this.chartBufferWidth = (int) available.getWidth();
1219 this.chartBufferHeight = (int) available.getHeight();
1220 this.chartBuffer = createImage(
1221 this.chartBufferWidth, this.chartBufferHeight);
1222 // GraphicsConfiguration gc = g2.getDeviceConfiguration();
1223 // this.chartBuffer = gc.createCompatibleImage(
1224 // this.chartBufferWidth, this.chartBufferHeight,
1225 // Transparency.TRANSLUCENT);
1226 this.refreshBuffer = true;
1227 }
1228
1229 // do we need to redraw the buffer?
1230 if (this.refreshBuffer) {
1231
1232 Rectangle2D bufferArea = new Rectangle2D.Double(
1233 0, 0, this.chartBufferWidth, this.chartBufferHeight);
1234
1235 Graphics2D bufferG2
1236 = (Graphics2D) this.chartBuffer.getGraphics();
1237 if (scale) {
1238 AffineTransform saved = bufferG2.getTransform();
1239 AffineTransform st = AffineTransform.getScaleInstance(
1240 this.scaleX, this.scaleY);
1241 bufferG2.transform(st);
1242 this.chart.draw(bufferG2, chartArea, this.anchor,
1243 this.info);
1244 bufferG2.setTransform(saved);
1245 }
1246 else {
1247 this.chart.draw(bufferG2, bufferArea, this.anchor,
1248 this.info);
1249 }
1250
1251 this.refreshBuffer = false;
1252
1253 }
1254
1255 // zap the buffer onto the panel...
1256 g2.drawImage(this.chartBuffer, insets.left, insets.top, this);
1257
1258 }
1259
1260 // or redrawing the chart every time...
1261 else {
1262
1263 AffineTransform saved = g2.getTransform();
1264 g2.translate(insets.left, insets.top);
1265 if (scale) {
1266 AffineTransform st = AffineTransform.getScaleInstance(
1267 this.scaleX, this.scaleY);
1268 g2.transform(st);
1269 }
1270 this.chart.draw(g2, chartArea, this.anchor, this.info);
1271 g2.setTransform(saved);
1272
1273 }
1274
1275 // Redraw the zoom rectangle (if present)
1276 drawZoomRectangle(g2);
1277
1278 g2.dispose();
1279
1280 this.anchor = null;
1281 this.verticalTraceLine = null;
1282 this.horizontalTraceLine = null;
1283
1284 }
1285
1286 /**
1287 * Receives notification of changes to the chart, and redraws the chart.
1288 *
1289 * @param event details of the chart change event.
1290 */
1291 public void chartChanged(ChartChangeEvent event) {
1292 this.refreshBuffer = true;
1293 Plot plot = this.chart.getPlot();
1294 if (plot instanceof Zoomable) {
1295 Zoomable z = (Zoomable) plot;
1296 this.orientation = z.getOrientation();
1297 }
1298 repaint();
1299 }
1300
1301 /**
1302 * Receives notification of a chart progress event.
1303 *
1304 * @param event the event.
1305 */
1306 public void chartProgress(ChartProgressEvent event) {
1307 // does nothing - override if necessary
1308 }
1309
1310 /**
1311 * Handles action events generated by the popup menu.
1312 *
1313 * @param event the event.
1314 */
1315 public void actionPerformed(ActionEvent event) {
1316
1317 String command = event.getActionCommand();
1318
1319 // many of the zoom methods need a screen location - all we have is
1320 // the zoomPoint, but it might be null. Here we grab the x and y
1321 // coordinates, or use defaults...
1322 double screenX = -1.0;
1323 double screenY = -1.0;
1324 if (this.zoomPoint != null) {
1325 screenX = this.zoomPoint.getX();
1326 screenY = this.zoomPoint.getY();
1327 }
1328
1329 if (command.equals(PROPERTIES_COMMAND)) {
1330 doEditChartProperties();
1331 }
1332 else if (command.equals(SAVE_COMMAND)) {
1333 try {
1334 doSaveAs();
1335 }
1336 catch (IOException e) {
1337 e.printStackTrace();
1338 }
1339 }
1340 else if (command.equals(PRINT_COMMAND)) {
1341 createChartPrintJob();
1342 }
1343 else if (command.equals(ZOOM_IN_BOTH_COMMAND)) {
1344 zoomInBoth(screenX, screenY);
1345 }
1346 else if (command.equals(ZOOM_IN_DOMAIN_COMMAND)) {
1347 zoomInDomain(screenX, screenY);
1348 }
1349 else if (command.equals(ZOOM_IN_RANGE_COMMAND)) {
1350 zoomInRange(screenX, screenY);
1351 }
1352 else if (command.equals(ZOOM_OUT_BOTH_COMMAND)) {
1353 zoomOutBoth(screenX, screenY);
1354 }
1355 else if (command.equals(ZOOM_OUT_DOMAIN_COMMAND)) {
1356 zoomOutDomain(screenX, screenY);
1357 }
1358 else if (command.equals(ZOOM_OUT_RANGE_COMMAND)) {
1359 zoomOutRange(screenX, screenY);
1360 }
1361 else if (command.equals(ZOOM_RESET_BOTH_COMMAND)) {
1362 restoreAutoBounds();
1363 }
1364 else if (command.equals(ZOOM_RESET_DOMAIN_COMMAND)) {
1365 restoreAutoDomainBounds();
1366 }
1367 else if (command.equals(ZOOM_RESET_RANGE_COMMAND)) {
1368 restoreAutoRangeBounds();
1369 }
1370
1371 }
1372
1373 /**
1374 * Handles a 'mouse entered' event. This method changes the tooltip delays
1375 * of ToolTipManager.sharedInstance() to the possibly different values set
1376 * for this chart panel.
1377 *
1378 * @param e the mouse event.
1379 */
1380 public void mouseEntered(MouseEvent e) {
1381 if (!this.ownToolTipDelaysActive) {
1382 ToolTipManager ttm = ToolTipManager.sharedInstance();
1383
1384 this.originalToolTipInitialDelay = ttm.getInitialDelay();
1385 ttm.setInitialDelay(this.ownToolTipInitialDelay);
1386
1387 this.originalToolTipReshowDelay = ttm.getReshowDelay();
1388 ttm.setReshowDelay(this.ownToolTipReshowDelay);
1389
1390 this.originalToolTipDismissDelay = ttm.getDismissDelay();
1391 ttm.setDismissDelay(this.ownToolTipDismissDelay);
1392
1393 this.ownToolTipDelaysActive = true;
1394 }
1395 }
1396
1397 /**
1398 * Handles a 'mouse exited' event. This method resets the tooltip delays of
1399 * ToolTipManager.sharedInstance() to their
1400 * original values in effect before mouseEntered()
1401 *
1402 * @param e the mouse event.
1403 */
1404 public void mouseExited(MouseEvent e) {
1405 if (this.ownToolTipDelaysActive) {
1406 // restore original tooltip dealys
1407 ToolTipManager ttm = ToolTipManager.sharedInstance();
1408 ttm.setInitialDelay(this.originalToolTipInitialDelay);
1409 ttm.setReshowDelay(this.originalToolTipReshowDelay);
1410 ttm.se