KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > experimental > chart > swt > ChartComposite


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * -------------------
28  * ChartComposite.java
29  * -------------------
30  * (C) Copyright 2006, by Henry Proudhon and Contributors.
31  *
32  * Original Author: Henry Proudhon (henry.proudhon AT insa-lyon.fr);
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * Changes
36  * -------
37  * 19-Jun-2006 : New class (HP);
38  * 06-Nov-2006 : Added accessor methods for zoomInFactor and zoomOutFactor (DG);
39  *
40  */

41
42 package org.jfree.experimental.chart.swt;
43
44 import java.awt.Graphics JavaDoc;
45 import java.awt.Point JavaDoc;
46 import java.awt.geom.Point2D JavaDoc;
47 import java.awt.geom.Rectangle2D JavaDoc;
48 import java.awt.print.PageFormat JavaDoc;
49 import java.awt.print.Printable JavaDoc;
50 import java.awt.print.PrinterException JavaDoc;
51 import java.awt.print.PrinterJob JavaDoc;
52 import java.io.File JavaDoc;
53 import java.io.IOException JavaDoc;
54 import java.util.ResourceBundle JavaDoc;
55
56 import javax.swing.event.EventListenerList JavaDoc;
57
58 import org.eclipse.swt.SWT;
59 import org.eclipse.swt.events.PaintEvent;
60 import org.eclipse.swt.events.PaintListener;
61 import org.eclipse.swt.events.SelectionEvent;
62 import org.eclipse.swt.events.SelectionListener;
63 import org.eclipse.swt.graphics.GC;
64 import org.eclipse.swt.graphics.Rectangle;
65 import org.eclipse.swt.layout.FillLayout;
66 import org.eclipse.swt.widgets.Canvas;
67 import org.eclipse.swt.widgets.Composite;
68 import org.eclipse.swt.widgets.Event;
69 import org.eclipse.swt.widgets.FileDialog;
70 import org.eclipse.swt.widgets.Listener;
71 import org.eclipse.swt.widgets.Menu;
72 import org.eclipse.swt.widgets.MenuItem;
73 import org.eclipse.swt.widgets.MessageBox;
74 import org.eclipse.swt.widgets.Tracker;
75 import org.jfree.chart.ChartMouseEvent;
76 import org.jfree.chart.ChartMouseListener;
77 import org.jfree.chart.ChartRenderingInfo;
78 import org.jfree.chart.ChartUtilities;
79 import org.jfree.chart.JFreeChart;
80 import org.jfree.chart.entity.ChartEntity;
81 import org.jfree.chart.entity.EntityCollection;
82 import org.jfree.chart.event.ChartChangeEvent;
83 import org.jfree.chart.event.ChartChangeListener;
84 import org.jfree.chart.event.ChartProgressEvent;
85 import org.jfree.chart.event.ChartProgressListener;
86 import org.jfree.chart.plot.Plot;
87 import org.jfree.chart.plot.PlotOrientation;
88 import org.jfree.chart.plot.PlotRenderingInfo;
89 import org.jfree.chart.plot.ValueAxisPlot;
90 import org.jfree.chart.plot.Zoomable;
91 import org.jfree.experimental.chart.swt.editor.SWTChartEditor;
92 import org.jfree.experimental.swt.SWTGraphics2D;
93
94 /**
95  * Notes:
96  * the tooltip support have been removed for now.
97  * It may be possible to add it using the
98  * org.eclipse.swt.events.MouseTrackListener interface.
99  * @author Henry Proudhon
100  *
101  */

102 public class ChartComposite extends Composite implements ChartChangeListener,
103                                                          ChartProgressListener,
104                                                          SelectionListener,
105                                                          Printable JavaDoc
106 {
107     /** Default setting for buffer usage. */
108     public static final boolean DEFAULT_BUFFER_USED = false;
109
110     /** The default panel width. */
111     public static final int DEFAULT_WIDTH = 680;
112
113     /** The default panel height. */
114     public static final int DEFAULT_HEIGHT = 420;
115
116     /** The default limit below which chart scaling kicks in. */
117     public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 300;
118
119     /** The default limit below which chart scaling kicks in. */
120     public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 200;
121
122     /** The default limit below which chart scaling kicks in. */
123     public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 1000;
124
125     /** The default limit below which chart scaling kicks in. */
126     public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 1000;
127
128     /** The minimum size required to perform a zoom on a rectangle */
129     public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
130
131     /** Properties action command. */
132     public static final String JavaDoc PROPERTIES_COMMAND = "PROPERTIES";
133
134     /** Save action command. */
135     public static final String JavaDoc SAVE_COMMAND = "SAVE";
136
137     /** Print action command. */
138     public static final String JavaDoc PRINT_COMMAND = "PRINT";
139
140     /** Zoom in (both axes) action command. */
141     public static final String JavaDoc ZOOM_IN_BOTH_COMMAND = "ZOOM_IN_BOTH";
142
143     /** Zoom in (domain axis only) action command. */
144     public static final String JavaDoc ZOOM_IN_DOMAIN_COMMAND = "ZOOM_IN_DOMAIN";
145
146     /** Zoom in (range axis only) action command. */
147     public static final String JavaDoc ZOOM_IN_RANGE_COMMAND = "ZOOM_IN_RANGE";
148
149     /** Zoom out (both axes) action command. */
150     public static final String JavaDoc ZOOM_OUT_BOTH_COMMAND = "ZOOM_OUT_BOTH";
151
152     /** Zoom out (domain axis only) action command. */
153     public static final String JavaDoc ZOOM_OUT_DOMAIN_COMMAND = "ZOOM_DOMAIN_BOTH";
154
155     /** Zoom out (range axis only) action command. */
156     public static final String JavaDoc ZOOM_OUT_RANGE_COMMAND = "ZOOM_RANGE_BOTH";
157
158     /** Zoom reset (both axes) action command. */
159     public static final String JavaDoc ZOOM_RESET_BOTH_COMMAND = "ZOOM_RESET_BOTH";
160
161     /** Zoom reset (domain axis only) action command. */
162     public static final String JavaDoc ZOOM_RESET_DOMAIN_COMMAND = "ZOOM_RESET_DOMAIN";
163
164     /** Zoom reset (range axis only) action command. */
165     public static final String JavaDoc ZOOM_RESET_RANGE_COMMAND = "ZOOM_RESET_RANGE";
166
167     /** The chart that is displayed in the panel. */
168     public JFreeChart chart;
169
170     /** The canvas to display the chart */
171     private Canvas canvas;
172     
173     /** Storage for registered (chart) mouse listeners. */
174     private EventListenerList JavaDoc chartMouseListeners;
175
176     /** A flag that controls whether or not the off-screen buffer is used. */
177     private boolean useBuffer;
178
179     /** A flag that indicates that the buffer should be refreshed. */
180     private boolean refreshBuffer;
181
182     /** A buffer for the rendered chart. */
183     private org.eclipse.swt.graphics.Image chartBuffer;
184
185     /** The height of the chart buffer. */
186     private int chartBufferHeight;
187
188     /** The width of the chart buffer. */
189     private int chartBufferWidth;
190
191     /**
192      * The minimum width for drawing a chart (uses scaling for smaller widths).
193      */

194     private int minimumDrawWidth;
195
196     /**
197      * The minimum height for drawing a chart (uses scaling for smaller
198      * heights).
199      */

200     private int minimumDrawHeight;
201
202     /**
203      * The maximum width for drawing a chart (uses scaling for bigger
204      * widths).
205      */

206     private int maximumDrawWidth;
207
208     /**
209      * The maximum height for drawing a chart (uses scaling for bigger
210      * heights).
211      */

212     private int maximumDrawHeight;
213
214     /** The popup menu for the frame. */
215     private Menu popup;
216
217     /** The drawing info collected the last time the chart was drawn. */
218     private ChartRenderingInfo info;
219     
220     /** The chart anchor point. */
221     private Point2D JavaDoc anchor;
222
223     /** The scale factor used to draw the chart. */
224     private double scaleX;
225
226     /** The scale factor used to draw the chart. */
227     private double scaleY;
228
229     /** The plot orientation. */
230     private PlotOrientation orientation = PlotOrientation.VERTICAL;
231     
232     /** A flag that controls whether or not domain zooming is enabled. */
233     private boolean domainZoomable = false;
234
235     /** A flag that controls whether or not range zooming is enabled. */
236     private boolean rangeZoomable = false;
237
238     /**
239      * The zoom rectangle starting point (selected by the user with a mouse
240      * click). This is a point on the screen, not the chart (which may have
241      * been scaled up or down to fit the panel).
242      */

243     private Point JavaDoc zoomPoint = null;
244
245     /** The zoom rectangle (selected by the user with the mouse). */
246     private transient Rectangle2D JavaDoc zoomRectangle = null;
247
248     /** Controls if the zoom rectangle is drawn as an outline or filled. */
249     //TODO private boolean fillZoomRectangle = false;
250

251     /** The minimum distance required to drag the mouse to trigger a zoom. */
252     private int zoomTriggerDistance;
253     
254     /** A flag that controls whether or not horizontal tracing is enabled. */
255     //TODO private boolean horizontalAxisTrace = true;
256

257     /** A flag that controls whether or not vertical tracing is enabled. */
258     //TODO private boolean verticalAxisTrace = true;
259

260     /** A vertical trace line. */
261     //private transient int verticalTraceLineX;
262

263     /** A horizontal trace line. */
264     //private transient int horizontalTraceLineY;
265

266     /** Menu item for zooming in on a chart (both axes). */
267     private MenuItem zoomInBothMenuItem;
268
269     /** Menu item for zooming in on a chart (domain axis). */
270     private MenuItem zoomInDomainMenuItem;
271
272     /** Menu item for zooming in on a chart (range axis). */
273     private MenuItem zoomInRangeMenuItem;
274
275     /** Menu item for zooming out on a chart. */
276     private MenuItem zoomOutBothMenuItem;
277
278     /** Menu item for zooming out on a chart (domain axis). */
279     private MenuItem zoomOutDomainMenuItem;
280
281     /** Menu item for zooming out on a chart (range axis). */
282     private MenuItem zoomOutRangeMenuItem;
283
284     /** Menu item for resetting the zoom (both axes). */
285     private MenuItem zoomResetBothMenuItem;
286
287     /** Menu item for resetting the zoom (domain axis only). */
288     private MenuItem zoomResetDomainMenuItem;
289
290     /** Menu item for resetting the zoom (range axis only). */
291     private MenuItem zoomResetRangeMenuItem;
292
293     /** A flag that controls whether or not file extensions are enforced. */
294     private boolean enforceFileExtensions;
295
296     /** The factor used to zoom in on an axis range. */
297     private double zoomInFactor = 0.5;
298     
299     /** The factor used to zoom out on an axis range. */
300     private double zoomOutFactor = 2.0;
301     
302     /** The resourceBundle for the localization. */
303     protected static ResourceBundle JavaDoc localizationResources
304         = ResourceBundle.getBundle("org.jfree.chart.LocalizationBundle");
305
306     /**
307      * Create a new chart composite with a default FillLayout.
308      * This way, when drawn, the chart will fill all the space.
309      * @param comp The parent.
310      * @param style The style of the composite.
311      */

312     public ChartComposite(Composite comp, int style) {
313         this(comp,
314                 style,
315                 null,
316                 DEFAULT_WIDTH,
317                 DEFAULT_HEIGHT,
318                 DEFAULT_MINIMUM_DRAW_WIDTH,
319                 DEFAULT_MINIMUM_DRAW_HEIGHT,
320                 DEFAULT_MAXIMUM_DRAW_WIDTH,
321                 DEFAULT_MAXIMUM_DRAW_HEIGHT,
322                 DEFAULT_BUFFER_USED,
323                 true, // properties
324
true, // save
325
true, // print
326
true, // zoom
327
true // tooltips
328
);
329     }
330
331     /**
332      * Constructs a panel that displays the specified chart.
333      *
334      * @param comp The parent.
335      * @param style The style of the composite.
336      * @param chart the chart.
337      */

338     public ChartComposite(Composite comp, int style, JFreeChart chart) {
339         this(
340                 comp,
341                 style,
342                 chart,
343                 DEFAULT_WIDTH,
344                 DEFAULT_HEIGHT,
345                 DEFAULT_MINIMUM_DRAW_WIDTH,
346                 DEFAULT_MINIMUM_DRAW_HEIGHT,
347                 DEFAULT_MAXIMUM_DRAW_WIDTH,
348                 DEFAULT_MAXIMUM_DRAW_HEIGHT,
349                 DEFAULT_BUFFER_USED,
350                 true, // properties
351
true, // save
352
true, // print
353
true, // zoom
354
true // tooltips
355
);
356     }
357
358     /**
359      * Constructs a panel containing a chart.
360      *
361      * @param comp The parent.
362      * @param style The style of the composite.
363      * @param chart the chart.
364      * @param useBuffer a flag controlling whether or not an off-screen buffer
365      * is used.
366      */

367     public ChartComposite(Composite comp, int style, JFreeChart chart,
368             boolean useBuffer) {
369         
370         this(comp, style, chart,
371                 DEFAULT_WIDTH,
372                 DEFAULT_HEIGHT,
373                 DEFAULT_MINIMUM_DRAW_WIDTH,
374                 DEFAULT_MINIMUM_DRAW_HEIGHT,
375                 DEFAULT_MAXIMUM_DRAW_WIDTH,
376                 DEFAULT_MAXIMUM_DRAW_HEIGHT,
377                 useBuffer,
378                 true, // properties
379
true, // save
380
true, // print
381
true, // zoom
382
true // tooltips
383
);
384     }
385     
386     /**
387      * Constructs a JFreeChart panel.
388      *
389      * @param comp The parent.
390      * @param style The style of the composite.
391      * @param chart the chart.
392      * @param properties a flag indicating whether or not the chart property
393      * editor should be available via the popup menu.
394      * @param save a flag indicating whether or not save options should be
395      * available via the popup menu.
396      * @param print a flag indicating whether or not the print option
397      * should be available via the popup menu.
398      * @param zoom a flag indicating whether or not zoom options should
399      * be added to the popup menu.
400      * @param tooltips a flag indicating whether or not tooltips should be
401      * enabled for the chart.
402      */

403     public ChartComposite(
404             Composite comp,
405             int style,
406             JFreeChart chart,
407             boolean properties,
408             boolean save,
409             boolean print,
410             boolean zoom,
411             boolean tooltips) {
412         this(
413                 comp,
414                 style,
415                 chart,
416                 DEFAULT_WIDTH,
417                 DEFAULT_HEIGHT,
418                 DEFAULT_MINIMUM_DRAW_WIDTH,
419                 DEFAULT_MINIMUM_DRAW_HEIGHT,
420                 DEFAULT_MAXIMUM_DRAW_WIDTH,
421                 DEFAULT_MAXIMUM_DRAW_HEIGHT,
422                 DEFAULT_BUFFER_USED,
423                 properties,
424                 save,
425                 print,
426                 zoom,
427                 tooltips
428                 );
429     }
430
431     /**
432      * Constructs a JFreeChart panel.
433      *
434      * @param comp The parent.
435      * @param style The style of the composite.
436      * @param jfreechart the chart.
437      * @param width the preferred width of the panel.
438      * @param height the preferred height of the panel.
439      * @param minimumDrawW the minimum drawing width.
440      * @param minimumDrawH the minimum drawing height.
441      * @param maximumDrawW the maximum drawing width.
442      * @param maximumDrawH the maximum drawing height.
443      * @param usingBuffer a flag that indicates whether to use the off-screen
444      * buffer to improve performance (at the expense of
445      * memory).
446      * @param properties a flag indicating whether or not the chart property
447      * editor should be available via the popup menu.
448      * @param save a flag indicating whether or not save options should be
449      * available via the popup menu.
450      * @param print a flag indicating whether or not the print option
451      * should be available via the popup menu.
452      * @param zoom a flag indicating whether or not zoom options should be
453      * added to the popup menu.
454      * @param tooltips a flag indicating whether or not tooltips should be
455      * enabled for the chart.
456      */

457     public ChartComposite(Composite comp,
458             int style,
459             JFreeChart jfreechart,
460             int width,
461             int height,
462             int minimumDrawW,
463             int minimumDrawH,
464             int maximumDrawW,
465             int maximumDrawH,
466             boolean usingBuffer,
467             boolean properties,
468             boolean save,
469             boolean print,
470             boolean zoom,
471             boolean tooltips) {
472         super(comp, style);
473         this.chart = jfreechart;
474         this.setLayout(new FillLayout());
475         this.info = new ChartRenderingInfo();
476         this.useBuffer = usingBuffer;
477         this.refreshBuffer = false;
478         this.minimumDrawWidth = minimumDrawW;
479         this.minimumDrawHeight = minimumDrawH;
480         this.maximumDrawWidth = maximumDrawW;
481         this.maximumDrawHeight = maximumDrawH;
482         this.zoomTriggerDistance = DEFAULT_ZOOM_TRIGGER_DISTANCE;
483         canvas = new Canvas(this, SWT.NO_BACKGROUND);
484         canvas.addPaintListener(new PaintListener() {
485             public void paintControl(PaintEvent e) {
486                 //System.out.println( "detected paint event" );
487
SWTGraphics2D sg2 = new SWTGraphics2D(e.gc);
488                 
489                 // first determine the size of the chart rendering area...
490
// no insets for SWT, try getClientArea
491
//System.out.println( canvas.getClientArea() );
492
Rectangle available = getBounds();
493
494                 // work out if scaling is required...
495
boolean scale = false;
496                 int drawWidth = available.width;
497                 int drawHeight = available.height;
498                 if ( drawWidth == 0.0 || drawHeight == 0.0 ) return;
499                 scaleX = 1.0;
500                 scaleY = 1.0;
501                 if (drawWidth < minimumDrawWidth) {
502                     scaleX = (double) drawWidth / minimumDrawWidth;
503                     drawWidth = minimumDrawWidth;
504                     scale = true;
505                 }
506                 else if (drawWidth > maximumDrawWidth) {
507                     scaleX = (double) drawWidth / maximumDrawWidth;
508                     drawWidth = maximumDrawWidth;
509                     scale = true;
510                 }
511                 if ( drawHeight < minimumDrawHeight ) {
512                     scaleY = ( double ) drawHeight / minimumDrawHeight;
513                     drawHeight = minimumDrawHeight;
514                     scale = true;
515                 }
516                 else if (drawHeight > maximumDrawHeight) {
517                     scaleY = (double) drawHeight / maximumDrawHeight;
518                     drawHeight = maximumDrawHeight;
519                     scale = true;
520                 }
521                 // are we using the chart buffer?
522
if (useBuffer) {
523                     //SwtGraphics2D sg2 = new SwtGraphics2D( e.gc );
524
chartBuffer = (org.eclipse.swt.graphics.Image)
525                             canvas.getData("double-buffer-image");
526                     // do we need to fill the buffer?
527
if ( chartBuffer == null
528                       || chartBufferWidth != available.width
529                       || chartBufferHeight != available.height ) {
530                         chartBufferWidth = available.width;
531                         chartBufferHeight = available.height;
532                         if (chartBuffer != null) {
533                             chartBuffer.dispose();
534                         }
535                         chartBuffer = new org.eclipse.swt.graphics.Image(
536                                   getDisplay(), chartBufferWidth,
537                                   chartBufferHeight);
538                         refreshBuffer = true;
539                     }
540
541                     // do we need to redraw the buffer?
542
if (refreshBuffer) {
543                         if (scale) {
544                             sg2.scale(scaleX, scaleY);
545                         }
546                         // Performs the actual drawing here ...
547
GC gci = new GC(chartBuffer);
548                         SWTGraphics2D sg2d = new SWTGraphics2D(gci);
549                         chart.draw(sg2d, new Rectangle2D.Double JavaDoc(0, 0,
550                                 chartBufferWidth, chartBufferHeight), info);
551                         canvas.setData("double-buffer-image", chartBuffer);
552                         gci.dispose();
553                         refreshBuffer = false;
554                     }
555                     
556                     // zap the buffer onto the canvas...
557
sg2.drawImage(chartBuffer, 0, 0);
558                 }
559                 // or redrawing the chart every time...
560
else
561                 {
562                     chart.draw(sg2, new Rectangle2D.Double JavaDoc(0, 0,
563                         getBounds().width, getBounds().height), info);
564                     //FIXME cross hair does not work properly because a
565
// complete redraw is forced
566
//if (verticalAxisTrace) drawVerticalAxisTrace(
567
// verticalTraceLineX, sg2);
568
//if (horizontalAxisTrace) drawHorizontalAxisTrace(
569
// horizontalTraceLineY, sg2);
570
}
571             }
572         } );
573         this.chartMouseListeners = new EventListenerList JavaDoc();
574         if (chart != null) {
575             chart.addChangeListener(this);
576             Plot plot = chart.getPlot();
577             this.domainZoomable = false;
578             this.rangeZoomable = false;
579             if (plot instanceof Zoomable) {
580                 Zoomable z = (Zoomable) plot;
581                 this.domainZoomable = z.isDomainZoomable();
582                 this.rangeZoomable = z.isRangeZoomable();
583                 this.orientation = z.getOrientation();
584             }
585         }
586
587         // set up popup menu...
588
this.popup = null;
589         if (properties || save || print || zoom)
590             this.popup = createPopupMenu(properties, save, print, zoom);
591
592         Listener listener = new Listener() {
593             public void handleEvent (Event event) {
594                 switch (event.type) {
595                     case SWT.MouseDown:
596                         zoomPoint = new Point JavaDoc(event.x, event.y);
597                         Rectangle insets = getClientArea();
598                         int x = (int) ((event.x - insets.x) / scaleX);
599                         int y = (int) ((event.y - insets.y) / scaleY);
600
601                         anchor = new Point2D.Double JavaDoc(x, y);
602                         chart.setNotify(true); // force a redraw
603
// new entity code...
604
Object JavaDoc[] listeners = chartMouseListeners.getListeners(
605                                 ChartMouseListener.class);
606                         if (listeners.length == 0) {
607                             return;
608                         }
609
610                         ChartEntity entity = null;
611                         if (info != null)
612                         {
613                             EntityCollection entities
614                                     = info.getEntityCollection();
615                             if (entities != null) {
616                                 entity = entities.getEntity(x, y);
617                             }
618                         }
619                         ChartMouseEvent chartEvent = new ChartMouseEvent(
620                                 getChart(), null, entity);
621                         for (int i = listeners.length - 1; i >= 0; i -= 1) {
622                             ((ChartMouseListener)
623                                     listeners[i]).chartMouseClicked(chartEvent);
624                         }
625                         break;
626                     case SWT.MouseMove:
627                         // handle axis trace
628
/* the cross hair has been disbled for now.
629                          * To work properly, it would require a class
630                          * similar to the SWT Tracker (used to handle
631                          * the zoom box).
632                         if ( horizontalAxisTrace || verticalAxisTrace )
633                         {
634                             horizontalTraceLineY = event.y;
635                             verticalTraceLineX = event.x;
636                             canvas.redraw();
637                         }
638                         */

639                         // handle zoom box
640
if (zoomPoint == null) {
641                             return;
642                         }
643                         Tracker tracker = new Tracker(canvas, SWT.RESIZE);
644                         Rectangle rect = new Rectangle(zoomPoint.x,
645                                 zoomPoint.y, zoomPoint.x - event.x, zoomPoint.y
646                                 - event.y);
647                         tracker.setRectangles(new Rectangle [] {rect});
648                         tracker.open();
649                         Rectangle trect = tracker.getRectangles()[0];
650                         // handle zoom
651
boolean hZoom = false;
652                         boolean vZoom = false;
653                         if (orientation == PlotOrientation.HORIZONTAL) {
654                             hZoom = rangeZoomable;
655                             vZoom = domainZoomable;
656                         }
657                         else {
658                             hZoom = domainZoomable;
659                             vZoom = rangeZoomable;
660                         }
661                         Rectangle2D JavaDoc scaledDataArea = getScreenDataArea(
662                             zoomPoint.x, zoomPoint.y);
663                         if (hZoom && vZoom)
664                         {
665                             // selected rectangle shouldn't extend outside the
666
// data area...
667
//double wmax = Math.min(w,
668
// scaledDataArea.getMaxX() - zoomPoint.x);
669
//double hmax = Math.min(h,
670
// scaledDataArea.getMaxY() - zoomPoint.y);
671
zoomRectangle = new Rectangle2D.Double JavaDoc(trect.x,
672                                     trect.y, trect.width, trect.height);
673                             Rectangle2D.intersect(zoomRectangle,
674                                     scaledDataArea, zoomRectangle);
675                         }
676                         else if (hZoom)
677                         {
678                             zoomRectangle = new Rectangle2D.Double JavaDoc(
679                                     trect.x, scaledDataArea.getMinY(),
680                                     trect.width, scaledDataArea.getHeight());
681                             Rectangle2D.intersect(zoomRectangle, scaledDataArea,
682                                     zoomRectangle);
683                         }
684                         else if (vZoom)
685                         {
686                             zoomRectangle = new Rectangle2D.Double JavaDoc(
687                                     scaledDataArea.getMinX(), trect.y,
688                                     scaledDataArea.getWidth(), trect.height);
689                             Rectangle2D.intersect(zoomRectangle,
690                                     scaledDataArea, zoomRectangle);
691                         }
692                         // no break here cause we want to catch mouse up event
693
case SWT.MouseUp:
694                         if (zoomRectangle == null) {
695                             Rectangle2D JavaDoc screenDataArea
696                                     = getScreenDataArea(event.x, event.y);
697                             if (screenDataArea != null) {
698                                 zoomPoint = getPointInRectangle(
699                                         event.x, event.y, screenDataArea);
700                             }
701                             if (popup != null && event.button == 3) {
702                                 displayPopupMenu(
703                                         canvas.getShell().getLocation().x
704                                         + canvas.getParent().getLocation().x
705                                         + canvas.getLocation().x + event.x,
706                                         canvas.getShell().getLocation().y
707                                         + canvas.getParent().getLocation().y
708                                         + canvas.getLocation().y + event.y);
709                             }
710                         }
711                         else
712                         {
713                             hZoom = false;
714                             vZoom = false;
715                             if (orientation == PlotOrientation.HORIZONTAL) {
716                                 hZoom = rangeZoomable;
717                                 vZoom = domainZoomable;
718                             }
719                             else {
720                                 hZoom = domainZoomable;
721                                 vZoom = rangeZoomable;
722                             }
723                             boolean zoomTrigger1 = hZoom
724                                     && zoomRectangle.getWidth()
725                                     >= zoomTriggerDistance;
726                             boolean zoomTrigger2 = vZoom
727                                     && zoomRectangle.getHeight()
728                                     >= zoomTriggerDistance;
729                             if (zoomTrigger1 || zoomTrigger2) {
730                                 // if the box has been drawn backwards, restore the auto bounds
731
if ((hZoom && (zoomRectangle.getX()
732                                         < zoomPoint.x))
733                                         || (vZoom && (zoomRectangle.getY()
734                                                 < zoomPoint.y)))
735                                     restoreAutoBounds();
736                                 else zoom(zoomRectangle);
737                                 canvas.redraw();
738                             }
739                         }
740                         zoomPoint = null;
741                         zoomRectangle = null;
742                         break;
743                 }
744             }
745         };
746         canvas.addListener(SWT.MouseDown, listener);
747         canvas.addListener(SWT.MouseMove, listener);
748         canvas.addListener(SWT.MouseUp, listener);
749         
750         this.enforceFileExtensions = true;
751     }
752     
753     /**
754      * Returns the X scale factor for the chart. This will be 1.0 if no
755      * scaling has been used.
756      *
757      * @return The scale factor.
758      */

759     public double getScaleX() {
760         return this.scaleX;
761     }
762     
763     /**
764      * Returns the Y scale factory for the chart. This will be 1.0 if no
765      * scaling has been used.
766      *
767      * @return The scale factor.
768      */

769     public double getScaleY() {
770         return this.scaleY;
771     }
772     
773     /**
774      * Returns the anchor point.
775      *
776      * @return The anchor point (possibly <code>null</code>).
777      */

778     public Point2D JavaDoc getAnchor() {
779         return this.anchor;
780     }
781     
782     /**
783      * Sets the anchor point. This method is provided for the use of
784      * subclasses, not end users.
785      *
786      * @param anchor the anchor point (<code>null</code> permitted).
787      */

788     protected void setAnchor(Point2D JavaDoc anchor) {
789         this.anchor = anchor;
790     }
791
792     /**
793      * Returns the chart contained in the panel.
794      *
795      * @return The chart (possibly <code>null</code>).
796      */

797     public JFreeChart getChart() {
798         return this.chart;
799     }
800
801     /**
802      * Sets the chart that is displayed in the panel.
803      *
804      * @param chart the chart (<code>null</code> permitted).
805      */

806     public void setChart(JFreeChart chart) {
807         // stop listening for changes to the existing chart
808
if (this.chart != null) {
809             this.chart.removeChangeListener(this);
810             this.chart.removeProgressListener(this);
811         }
812
813         // add the new chart
814
this.chart = chart;
815         if (chart != null) {
816             this.chart.addChangeListener(this);
817             this.chart.addProgressListener(this);
818             Plot plot = chart.getPlot();
819             this.domainZoomable = false;
820             this.rangeZoomable = false;
821             if (plot instanceof Zoomable) {
822                 Zoomable z = (Zoomable) plot;
823                 this.domainZoomable = z.isDomainZoomable();
824                 this.rangeZoomable = z.isRangeZoomable();
825                 this.orientation = z.getOrientation();
826             }
827         }
828         else {
829             this.domainZoomable = false;
830             this.rangeZoomable = false;
831         }
832         if (this.useBuffer) {
833             this.refreshBuffer = true;
834         }
835         redraw();
836     }
837
838     /**
839      * Returns the zoom in factor.
840      *
841      * @return The zoom in factor.
842      *
843      * @see #setZoomInFactor(double)
844      */

845     public double getZoomInFactor() {
846         return this.zoomInFactor;
847     }
848     
849     /**
850      * Sets the zoom in factor.
851      *
852      * @param factor the factor.
853      *
854      * @see #getZoomInFactor()
855      */

856     public void setZoomInFactor(double factor) {
857         this.zoomInFactor = factor;
858     }
859     
860     /**
861      * Returns the zoom out factor.
862      *
863      * @return The zoom out factor.
864      *
865      * @see #setZoomOutFactor(double)
866      */

867     public double getZoomOutFactor() {
868         return this.zoomOutFactor;
869     }
870     
871     /**
872      * Sets the zoom out factor.
873      *
874      * @param factor the factor.
875      *
876      * @see #getZoomOutFactor()
877      */

878     public void setZoomOutFactor(double factor) {
879         this.zoomOutFactor = factor;
880     }
881     
882     /**
883      * Displays a dialog that allows the user to edit the properties for the
884      * current chart.
885      */

886     private void attemptEditChartProperties()
887     {
888         SWTChartEditor editor = new SWTChartEditor(canvas.getDisplay(), this.chart);
889             //ChartEditorManager.getChartEditor( canvas.getDisplay(), this.chart );
890
editor.open();
891     }
892
893     /**
894      * Returns <code>true</code> if file extensions should be enforced, and
895      * <code>false</code> otherwise.
896      *
897      * @return The flag.
898      */

899     public boolean isEnforceFileExtensions() {
900         return this.enforceFileExtensions;
901     }
902
903     /**
904      * Sets a flag that controls whether or not file extensions are enforced.
905      *
906      * @param enforce the new flag value.
907      */

908     public void setEnforceFileExtensions(boolean enforce) {
909         this.enforceFileExtensions = enforce;
910     }
911
912     /**
913      * Opens a file chooser and gives the user an opportunity to save the chart
914      * in PNG format.
915      *
916      * @throws IOException if there is an I/O error.
917      */

918     public void doSaveAs() throws IOException JavaDoc {
919         FileDialog fileDialog = new FileDialog(canvas.getShell(), SWT.SAVE);
920         String JavaDoc[] extensions = { "*.png" };
921         fileDialog.setFilterExtensions(extensions);
922         String JavaDoc filename = fileDialog.open();
923         if (filename != null) {
924             if (isEnforceFileExtensions()) {
925                 if (!filename.endsWith(".png")) {
926                     filename = filename + ".png";
927                 }
928             }
929             //TODO replace getSize by getBounds ?
930
ChartUtilities.saveChartAsPNG(new File JavaDoc(filename), this.chart,
931                     canvas.getSize().x, canvas.getSize().y);
932         }
933     }
934
935     /**
936      * Returns a point based on (x, y) but constrained to be within the bounds
937      * of the given rectangle. This method could be moved to JCommon.
938      *
939      * @param x the x-coordinate.
940      * @param y the y-coordinate.
941      * @param area the rectangle (<code>null</code> not permitted).
942      *
943      * @return A point within the rectangle.
944      */

945     private Point JavaDoc getPointInRectangle(int x, int y, Rectangle2D JavaDoc area) {
946         x = (int) Math.max(Math.ceil(area.getMinX()), Math.min(x,
947                 Math.floor(area.getMaxX())));
948         y = (int) Math.max(Math.ceil(area.getMinY()), Math.min(y,
949                 Math.floor(area.getMaxY())));
950         return new Point JavaDoc(x, y);
951     }
952
953     /**
954      * Zooms in on an anchor point (specified in screen coordinate space).
955      *
956      * @param x the x value (in screen coordinates).
957      * @param y the y value (in screen coordinates).
958      */

959     public void zoomInBoth(double x, double y) {
960         zoomInDomain(x, y);
961         zoomInRange(x, y);
962     }
963
964     /**
965      * Decreases the length of the domain axis, centered about the given
966      * coordinate on the screen. The length of the domain axis is reduced
967      * by the value of {@link #getZoomInFactor()}.
968      *
969      * @param x the x coordinate (in screen coordinates).
970      * @param y the y-coordinate (in screen coordinates).
971      */

972     public void zoomInDomain(double x, double y) {
973         Plot p = this.chart.getPlot();
974         if (p instanceof Zoomable)
975         {
976             Zoomable plot = (Zoomable) p;
977             plot.zoomDomainAxes(this.zoomInFactor, this.info.getPlotInfo(),
978                     translateScreenToJava2D(new Point JavaDoc((int) x, (int) y)));
979         }
980     }
981
982     /**
983      * Decreases the length of the range axis, centered about the given
984      * coordinate on the screen. The length of the range axis is reduced by
985      * the value of {@link #getZoomInFactor()}.
986      *
987      * @param x the x-coordinate (in screen coordinates).
988      * @param y the y coordinate (in screen coordinates).
989      */

990     public void zoomInRange(double x, double y) {
991         Plot p = this.chart.getPlot();
992         if (p instanceof Zoomable) {
993             Zoomable z = (Zoomable) p;
994             z.zoomRangeAxes(this.zoomInFactor, this.info.getPlotInfo(),
995                     translateScreenToJava2D(new Point JavaDoc((int) x, (int) y)));
996         }
997     }
998
999     /**
1000     * Zooms out on an anchor point (specified in screen coordinate space).
1001     *
1002     * @param x the x value (in screen coordinates).
1003     * @param y the y value (in screen coordinates).
1004     */

1005    public void zoomOutBoth(double x, double y) {
1006        zoomOutDomain(x, y);
1007        zoomOutRange(x, y);
1008    }
1009
1010    /**
1011     * Increases the length of the domain axis, centered about the given
1012     * coordinate on the screen. The length of the domain axis is increased
1013     * by the value of {@link #getZoomOutFactor()}.
1014     *
1015     * @param x the x coordinate (in screen coordinates).
1016     * @param y the y-coordinate (in screen coordinates).
1017     */

1018    public void zoomOutDomain(double x, double y) {
1019        Plot p = this.chart.getPlot();
1020        if (p instanceof Zoomable) {
1021            Zoomable z = (Zoomable) p;
1022            z.zoomDomainAxes(this.zoomOutFactor, this.info.getPlotInfo(),
1023                    translateScreenToJava2D(new Point JavaDoc((int) x, (int) y)));
1024        }
1025    }
1026
1027    /**
1028     * Increases the length the range axis, centered about the given
1029     * coordinate on the screen. The length of the range axis is increased
1030     * by the value of {@link #getZoomOutFactor()}.
1031     *
1032     * @param x the x coordinate (in screen coordinates).
1033     * @param y the y-coordinate (in screen coordinates).
1034     */

1035    public void zoomOutRange(double x, double y) {
1036        Plot p = this.chart.getPlot();
1037        if (p instanceof Zoomable) {
1038            Zoomable z = (Zoomable) p;
1039            z.zoomRangeAxes(this.zoomOutFactor, this.info.getPlotInfo(),
1040                    translateScreenToJava2D(new Point JavaDoc((int) x, (int) y)));
1041        }
1042    }
1043
1044    /**
1045     * Zooms in on a selected region.
1046     *
1047     * @param selection the selected region.
1048     */

1049    public void zoom(Rectangle2D JavaDoc selection) {
1050
1051        // get the origin of the zoom selection in the Java2D space used for
1052
// drawing the chart (that is, before any scaling to fit the panel)
1053
Point2D JavaDoc selectOrigin = translateScreenToJava2D(new Point JavaDoc(
1054                (int) Math.ceil(selection.getX()),
1055                (int) Math.ceil(selection.getY())));
1056        PlotRenderingInfo plotInfo = this.info.getPlotInfo();
1057        Rectangle2D JavaDoc scaledDataArea = getScreenDataArea(
1058                (int) selection.getCenterX(), (int) selection.getCenterY());
1059        if ((selection.getHeight() > 0) && (selection.getWidth() > 0)) {
1060
1061            double hLower = (selection.getMinX() - scaledDataArea.getMinX())
1062                / scaledDataArea.getWidth();
1063            double hUpper = (selection.getMaxX() - scaledDataArea.getMinX())
1064                / scaledDataArea.getWidth();
1065            double vLower = (scaledDataArea.getMaxY() - selection.getMaxY())
1066                / scaledDataArea.getHeight();
1067            double vUpper = (scaledDataArea.getMaxY() - selection.getMinY())
1068                / scaledDataArea.getHeight();
1069
1070            Plot p = this.chart.getPlot();
1071            if (p instanceof Zoomable) {
1072                Zoomable z = (Zoomable) p;
1073                if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
1074                    z.zoomDomainAxes(vLower, vUpper, plotInfo, selectOrigin);
1075                    z.zoomRangeAxes(hLower, hUpper, plotInfo, selectOrigin);
1076                }
1077                else {
1078                    z.zoomDomainAxes(hLower, hUpper, plotInfo, selectOrigin);
1079                    z.zoomRangeAxes(vLower, vUpper, plotInfo, selectOrigin);
1080                }
1081            }
1082
1083        }
1084
1085    }
1086
1087    /**
1088     * Receives notification of changes to the chart, and redraws the chart.
1089     *
1090     * @param event details of the chart change event.
1091     */

1092    public void chartChanged(ChartChangeEvent event) {
1093        this.refreshBuffer = true;
1094        Plot plot = chart.getPlot();
1095        if (plot instanceof Zoomable)
1096        {
1097            Zoomable z = (Zoomable) plot;
1098            this.orientation = z.getOrientation();
1099        }
1100        this.redraw();
1101    }
1102
1103    /**
1104     * Forces a redraw of the canvas by invoking a new PaintEvent.
1105     */

1106    public void forceRedraw() {
1107        Event ev = new Event();
1108        ev.gc = new GC(canvas);
1109        ev.x = 0;
1110        ev.y = 0;
1111        ev.width = canvas.getBounds().width;
1112        ev.height = canvas.getBounds().height;
1113        ev.count = 0;
1114        canvas.notifyListeners(SWT.Paint, ev);
1115    }
1116    
1117    /**
1118     * Receives notification of a chart progress event.
1119     *
1120     * @param event the event.
1121     */

1122    public void chartProgress(ChartProgressEvent event) {
1123        // does nothing - override if necessary
1124
}
1125
1126    /**
1127     * Restores the auto-range calculation on both axes.
1128     */

1129    public void restoreAutoBounds() {
1130        restoreAutoDomainBounds();
1131        restoreAutoRangeBounds();
1132    }
1133
1134    /**
1135     * Restores the auto-range calculation on the domain axis.
1136     */

1137    public void restoreAutoDomainBounds() {
1138        Plot p = this.chart.getPlot();
1139        if (p instanceof Zoomable)
1140        {
1141            Zoomable z = (Zoomable) p;
1142            z.zoomDomainAxes(0.0, this.info.getPlotInfo(), this.zoomPoint);
1143        }
1144    }
1145
1146    /**
1147     * Restores the auto-range calculation on the range axis.
1148     */

1149    public void restoreAutoRangeBounds() {
1150        Plot p = this.chart.getPlot();
1151        if (p instanceof ValueAxisPlot)
1152        {
1153            Zoomable z = (Zoomable) p;
1154            z.zoomRangeAxes(0.0, this.info.getPlotInfo(), this.zoomPoint);
1155        }
1156    }
1157
1158    /**
1159     * Applies any scaling that is in effect for the chart drawing to the
1160     * given rectangle.
1161     *
1162     * @param rect the rectangle.
1163     *
1164     * @return A new scaled rectangle.
1165     */

1166    public Rectangle2D JavaDoc scale(Rectangle2D JavaDoc rect) {
1167        Rectangle insets = this.getClientArea();
1168        double x = rect.getX() * getScaleX() + insets.x;
1169        double y = rect.getY() * this.getScaleY() + insets.y;
1170        double w = rect.getWidth() * this.getScaleX();
1171        double h = rect.getHeight() * this.getScaleY();
1172        return new Rectangle2D.Double JavaDoc(x, y, w, h);
1173    }
1174
1175    /**
1176     * Returns the data area for the chart (the area inside the axes) with the
1177     * current scaling applied (that is, the area as it appears on screen).
1178     *
1179     * @return The scaled data area.
1180     */

1181    public Rectangle2D JavaDoc getScreenDataArea() {
1182        Rectangle2D JavaDoc dataArea = this.info.getPlotInfo().getDataArea();
1183        Rectangle clientArea = this.getClientArea();
1184        int x = (int) (dataArea.getX() * this.scaleX + clientArea.x);
1185        int y = (int) (dataArea.getY() * this.scaleY + clientArea.y);
1186        int w = (int) (dataArea.getWidth() * this.scaleX);
1187        int h = (int) (dataArea.getHeight() * this.scaleY);
1188        return new Rectangle2D.Double JavaDoc(x, y, w, h);
1189    }
1190    
1191    /**
1192     * Returns the data area (the area inside the axes) for the plot or subplot,
1193     * with the current scaling applied.
1194     *
1195     * @param x the x-coordinate (for subplot selection).
1196     * @param y the y-coordinate (for subplot selection).
1197     *
1198     * @return The scaled data area.
1199     */

1200    public Rectangle2D JavaDoc getScreenDataArea(int x, int y) {
1201        PlotRenderingInfo plotInfo = this.info.getPlotInfo();
1202        Rectangle2D JavaDoc result;
1203        if (plotInfo.getSubplotCount() == 0)
1204            result = getScreenDataArea();
1205        else {
1206            // get the origin of the zoom selection in the Java2D space used for
1207
// drawing the chart (that is, before any scaling to fit the panel)
1208
Point2D JavaDoc selectOrigin = translateScreenToJava2D(new Point JavaDoc(x, y));
1209            int subplotIndex = plotInfo.getSubplotIndex(selectOrigin);
1210            if (subplotIndex == -1) {
1211                return null;
1212            }
1213            result = scale(plotInfo.getSubplotInfo(subplotIndex).getDataArea());
1214        }
1215        return result;
1216    }
1217
1218    /**
1219     * Translates a Java2D point on the chart to a screen location.
1220     *
1221     * @param java2DPoint the Java2D point.
1222     *
1223     * @return The screen location.
1224     */

1225    public Point JavaDoc translateJava2DToScreen(Point2D JavaDoc java2DPoint) {
1226        Rectangle insets = this.getClientArea();
1227        int x = (int) (java2DPoint.getX() * this.scaleX + insets.x);
1228        int y = (int) (java2DPoint.getY() * this.scaleY + insets.y);
1229        return new Point JavaDoc(x, y);
1230    }
1231
1232    /**
1233     * Translates a screen location to a Java SWT point.
1234     *
1235     * @param screenPoint the screen location.
1236     *
1237     * @return The Java2D coordinates.
1238     */

1239    public Point JavaDoc translateScreenToJavaSWT(Point JavaDoc screenPoint) {
1240        Rectangle insets = this.getClientArea();
1241        int x = (int) ((screenPoint.x - insets.x) / this.scaleX);
1242        int y = (int) ((screenPoint.y - insets.y) / this.scaleY);
1243        return new Point JavaDoc(x, y);
1244    }
1245
1246    /**
1247     * Translates a screen location to a Java2D point.
1248     *
1249     * @param screenPoint the screen location.
1250     *
1251     * @return The Java2D coordinates.
1252     */

1253    public Point2D JavaDoc translateScreenToJava2D(Point JavaDoc screenPoint) {
1254        Rectangle insets = this.getClientArea();
1255        int x = (int) ((screenPoint.x - insets.x) / this.scaleX);
1256        int y = (int) ((screenPoint.y - insets.y) / this.scaleY);
1257        return new Point2D.Double JavaDoc(x, y);
1258    }
1259
1260    /**
1261     * The idea is to modify the zooming options depending on the type of chart
1262     * being displayed by the panel.
1263     *
1264     * @param x horizontal position of the popup.
1265     * @param y vertical position of the popup.
1266     */

1267    protected void displayPopupMenu(int x, int y)
1268    {
1269        if (this.popup != null) {
1270            // go through each zoom menu item and decide whether or not to
1271
// enable it...
1272
Plot plot = this.chart.getPlot();
1273            boolean isDomainZoomable = false;
1274            boolean isRangeZoomable = false;
1275            if (plot instanceof Zoomable)
1276            {
1277                Zoomable z = (Zoomable) plot;
1278                isDomainZoomable = z.isDomainZoomable();
1279                isRangeZoomable = z.isRangeZoomable();
1280            }
1281            if (this.zoomInDomainMenuItem != null) {
1282                this.zoomInDomainMenuItem.setEnabled(isDomainZoomable);
1283            }
1284            if (this.zoomOutDomainMenuItem != null) {
1285                this.zoomOutDomainMenuItem.setEnabled(isDomainZoomable);
1286            }
1287            if (this.zoomResetDomainMenuItem != null) {
1288                this.zoomResetDomainMenuItem.setEnabled(isDomainZoomable);
1289            }
1290
1291            if (this.zoomInRangeMenuItem != null) {
1292                this.zoomInRangeMenuItem.setEnabled(isRangeZoomable);
1293            }
1294            if (this.zoomOutRangeMenuItem != null) {
1295                this.zoomOutRangeMenuItem.setEnabled(isRangeZoomable);
1296            }
1297
1298            if (this.zoomResetRangeMenuItem != null) {
1299                this.zoomResetRangeMenuItem.setEnabled(isRangeZoomable);
1300            }
1301
1302            if (this.zoomInBothMenuItem != null) {
1303                this.zoomInBothMenuItem.setEnabled(
1304                    isDomainZoomable & isRangeZoomable
1305                );
1306            }
1307            if (this.zoomOutBothMenuItem != null) {
1308                this.zoomOutBothMenuItem.setEnabled(
1309                    isDomainZoomable & isRangeZoomable
1310                );
1311            }
1312            if (this.zoomResetBothMenuItem != null) {
1313                this.zoomResetBothMenuItem.setEnabled(
1314                    isDomainZoomable & isRangeZoomable
1315                );
1316            }
1317
1318            this.popup.setLocation(x, y);
1319            this.popup.setVisible(true);
1320        }
1321
1322    }
1323
1324    /**
1325     * Creates a print job for the chart.
1326     */

1327    public void createChartPrintJob() {
1328        //FIXME try to replace swing print stuff by swt
1329
PrinterJob JavaDoc job = PrinterJob.getPrinterJob();
1330        PageFormat JavaDoc pf = job.defaultPage();
1331        PageFormat JavaDoc pf2 = job.pageDialog(pf);
1332        if (pf2 != pf) {
1333            job.setPrintable(this, pf2);
1334            if (job.printDialog()) {
1335                try {
1336                    job.print();
1337                }
1338                catch (PrinterException JavaDoc e) {
1339                    MessageBox messageBox = new MessageBox(
1340                            canvas.getShell(), SWT.OK | SWT.ICON_ERROR );
1341                    messageBox.setMessage( e.getMessage() );
1342                    messageBox.open();
1343                }
1344            }
1345        }
1346    }
1347
1348    /**
1349     * Creates a popup menu for the canvas.
1350     *
1351     * @param properties include a menu item for the chart property editor.
1352     * @param save include a menu item for saving the chart.
1353     * @param print include a menu item for printing the chart.
1354     * @param zoom include menu items for zooming.
1355     *
1356     * @return The popup menu.
1357     */

1358    protected Menu createPopupMenu(boolean properties, boolean save,
1359            boolean print, boolean zoom) {
1360        
1361        Menu result = new Menu(this);
1362        boolean separator = false;
1363
1364        if ( properties ) {
1365            MenuItem propertiesItem = new MenuItem(result, SWT.PUSH);
1366            propertiesItem.setText(localizationResources.getString(
1367                    "Properties..."));
1368            propertiesItem.setData(PROPERTIES_COMMAND);
1369            propertiesItem.addSelectionListener(this);
1370            separator = true;
1371        }
1372        if (save)
1373        {
1374            if (separator) {
1375                new MenuItem(result, SWT.SEPARATOR);
1376                separator = false;
1377            }
1378            MenuItem saveItem = new MenuItem(result, SWT.NONE);
1379            saveItem.setText(localizationResources.getString("Save_as..."));
1380            saveItem.setData(SAVE_COMMAND);
1381            saveItem.addSelectionListener(this);
1382            separator = true;
1383        }
1384        if (print) {
1385            if (separator) {
1386                new MenuItem(result, SWT.SEPARATOR);
1387                separator = false;
1388            }
1389            MenuItem printItem = new MenuItem(result, SWT.NONE);
1390            printItem.setText(localizationResources.getString("Print..."));
1391            printItem.setData(PRINT_COMMAND);
1392            printItem.addSelectionListener(this);
1393            separator = true;
1394        }
1395        if (zoom) {
1396            if (separator) {
1397                new MenuItem(result, SWT.SEPARATOR);
1398                separator = false;
1399            }
1400
1401            Menu zoomInMenu = new Menu(result);
1402            MenuItem zoomInMenuItem = new MenuItem(result, SWT.CASCADE);
1403            zoomInMenuItem.setText(localizationResources.getString("Zoom_In"));
1404            zoomInMenuItem.setMenu(zoomInMenu);
1405
1406            this.zoomInBothMenuItem = new MenuItem(zoomInMenu, SWT.PUSH);
1407            this.zoomInBothMenuItem.setText(localizationResources.getString(
1408                    "All_Axes"));
1409            this.zoomInBothMenuItem.setData(ZOOM_IN_BOTH_COMMAND);
1410            this.zoomInBothMenuItem.addSelectionListener(this);
1411
1412            new MenuItem(zoomInMenu, SWT.SEPARATOR);
1413
1414            this.zoomInDomainMenuItem = new MenuItem(zoomInMenu, SWT.PUSH);
1415            this.zoomInDomainMenuItem.setText(localizationResources.getString(
1416                    "Domain_Axis" ) );
1417            this.zoomInDomainMenuItem.setData(ZOOM_IN_DOMAIN_COMMAND);
1418            this.zoomInDomainMenuItem.addSelectionListener(this);
1419
1420            this.zoomInRangeMenuItem = new MenuItem(zoomInMenu, SWT.PUSH);
1421            this.zoomInRangeMenuItem.setText(localizationResources.getString(
1422                    "Range_Axis" ) );
1423            this.zoomInRangeMenuItem.setData(ZOOM_IN_RANGE_COMMAND);
1424            this.zoomInRangeMenuItem.addSelectionListener(this);
1425
1426            Menu zoomOutMenu = new Menu( result );
1427            MenuItem zoomOutMenuItem = new MenuItem(result, SWT.CASCADE);
1428            zoomOutMenuItem.setText(localizationResources.getString(
1429                    "Zoom_Out"));
1430            zoomOutMenuItem.setMenu(zoomOutMenu);
1431
1432            this.zoomOutBothMenuItem = new MenuItem(zoomOutMenu, SWT.PUSH);
1433            this.zoomOutBothMenuItem.setText(localizationResources.getString(
1434                    "All_Axes"));
1435            this.zoomOutBothMenuItem.setData(ZOOM_OUT_BOTH_COMMAND);
1436            this.zoomOutBothMenuItem.addSelectionListener(this);
1437            
1438            new MenuItem(zoomOutMenu, SWT.SEPARATOR);
1439
1440            this.zoomOutDomainMenuItem = new MenuItem(zoomOutMenu, SWT.PUSH);
1441            this.zoomOutDomainMenuItem.setText(localizationResources.getString(
1442                    "Domain_Axis"));
1443            this.zoomOutDomainMenuItem.setData(ZOOM_OUT_DOMAIN_COMMAND);
1444            this.zoomOutDomainMenuItem.addSelectionListener( this );
1445
1446            this.zoomOutRangeMenuItem = new MenuItem(zoomOutMenu, SWT.PUSH);
1447            this.zoomOutRangeMenuItem.setText(
1448                    localizationResources.getString("Range_Axis"));
1449            this.zoomOutRangeMenuItem.setData(ZOOM_OUT_RANGE_COMMAND);
1450            this.zoomOutRangeMenuItem.addSelectionListener(this);
1451
1452            Menu autoRangeMenu = new Menu(result);
1453            MenuItem autoRangeMenuItem = new MenuItem(result, SWT.CASCADE);
1454            autoRangeMenuItem.setText(localizationResources.getString(
1455                    "Auto_Range"));
1456            autoRangeMenuItem.setMenu(autoRangeMenu);
1457
1458            this.zoomResetBothMenuItem = new MenuItem(autoRangeMenu, SWT.PUSH);
1459            this.zoomResetBothMenuItem.setText(localizationResources.getString(
1460                    "All_Axes"));
1461            this.zoomResetBothMenuItem.setData(ZOOM_RESET_BOTH_COMMAND);
1462            this.zoomResetBothMenuItem.addSelectionListener(this);
1463            
1464            new MenuItem(autoRangeMenu, SWT.SEPARATOR);
1465
1466            this.zoomResetDomainMenuItem = new MenuItem(autoRangeMenu,
1467                    SWT.PUSH);
1468            this.zoomResetDomainMenuItem.setText(
1469                    localizationResources.getString("Domain_Axis"));
1470            this.zoomResetDomainMenuItem.setData(ZOOM_RESET_DOMAIN_COMMAND);
1471            this.zoomResetDomainMenuItem.addSelectionListener(this);
1472               
1473            this.zoomResetRangeMenuItem = new MenuItem(autoRangeMenu, SWT.PUSH);
1474            this.zoomResetRangeMenuItem.setText(
1475                    localizationResources.getString("Range_Axis"));
1476            this.zoomResetRangeMenuItem.setData(ZOOM_RESET_RANGE_COMMAND);
1477            this.zoomResetRangeMenuItem.addSelectionListener(this);
1478        }
1479        
1480        return result;
1481    }
1482
1483    /**
1484     * Handles action events generated by the popup menu.
1485     *
1486     * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(
1487     * org.eclipse.swt.events.SelectionEvent)
1488     */

1489    public void widgetDefaultSelected(SelectionEvent e) {
1490        // TODO Auto-generated method stub
1491

1492    }
1493
1494    /**
1495     * Handles action events generated by the popup menu.
1496     *
1497     * @see org.eclipse.swt.events.SelectionListener#widgetSelected(
1498     * org.eclipse.swt.events.SelectionEvent)
1499     */

1500    public void widgetSelected(SelectionEvent e) {
1501        String JavaDoc command = (String JavaDoc) ((MenuItem) e.getSource()).getData();
1502        if (command.equals(PROPERTIES_COMMAND)) {
1503            attemptEditChartProperties();
1504        }
1505        else if (command.equals(SAVE_COMMAND)) {
1506            try {
1507                doSaveAs();
1508            }
1509            catch (IOException JavaDoc ex) {
1510                ex.printStackTrace();
1511            }
1512        }
1513        else if (command.equals(PRINT_COMMAND)) {
1514            createChartPrintJob();
1515        }
1516        /* in the next zoomPoint.x and y replace by e.x and y for now.
1517         * this helps to handle the mouse events and besides,
1518         * those values are unused AFAIK. */

1519        else if (command.equals(ZOOM_IN_BOTH_COMMAND)) {
1520            zoomInBoth( e.x, e.y );
1521        }
1522        else if (command.equals(ZOOM_IN_DOMAIN_COMMAND)) {
1523            zoomInDomain( e.x, e.y );
1524        }
1525        else if (command.equals(ZOOM_IN_RANGE_COMMAND)) {
1526            zoomInRange( e.x, e.y );
1527        }
1528        else if (command.equals(ZOOM_OUT_BOTH_COMMAND)) {
1529            zoomOutBoth( e.x, e.y );
1530        }
1531        else if (command.equals(ZOOM_OUT_DOMAIN_COMMAND)) {
1532            zoomOutDomain( e.x, e.y );
1533        }
1534        else if (command.equals(ZOOM_OUT_RANGE_COMMAND)) {
1535            zoomOutRange( e.x, e.y );
1536        }
1537        else if (command.equals(ZOOM_RESET_BOTH_COMMAND)) {
1538            restoreAutoBounds();
1539        }
1540        else if (command.equals(ZOOM_RESET_DOMAIN_COMMAND)) {
1541            restoreAutoDomainBounds();
1542        }
1543        else if (command.equals(ZOOM_RESET_RANGE_COMMAND)) {
1544            restoreAutoRangeBounds();
1545        }
1546        this.forceRedraw();
1547    }
1548
1549    public int print(Graphics JavaDoc graphics, PageFormat JavaDoc pageFormat, int pageIndex)
1550        throws PrinterException JavaDoc {
1551        if (pageIndex != 0) {
1552            return NO_SUCH_PAGE;
1553        }
1554        /*
1555        CairoImage image = new CairoImage(
1556                this.getBounds().width, this.getBounds().height );
1557        Graphics2D g2 = image.createGraphics2D();
1558        double x = pageFormat.getImageableX();
1559        double y = pageFormat.getImageableY();
1560        double w = pageFormat.getImageableWidth();
1561        double h = pageFormat.getImageableHeight();
1562        this.chart.draw(
1563            g2, new Rectangle2D.Double(x, y, w, h), this.anchor, null
1564        );
1565        */

1566        return PAGE_EXISTS;
1567    }
1568    
1569}
1570
Popular Tags