Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extRemoteSensing / src / org / gvsig / remotesensing / scatterplot / chart / ScatterPlotDiagram.java @ 17394

History | View | Annotate | Download (79.2 KB)

1
package org.gvsig.remotesensing.scatterplot.chart;
2

    
3
import java.awt.AWTEvent;
4
import java.awt.Color;
5
import java.awt.Dimension;
6
import java.awt.Graphics;
7
import java.awt.Graphics2D;
8
import java.awt.Image;
9
import java.awt.Insets;
10
import java.awt.Point;
11
import java.awt.Shape;
12
import java.awt.event.ActionEvent;
13
import java.awt.event.ActionListener;
14
import java.awt.event.MouseEvent;
15
import java.awt.event.MouseListener;
16
import java.awt.event.MouseMotionListener;
17
import java.awt.geom.AffineTransform;
18
import java.awt.geom.Line2D;
19
import java.awt.geom.Point2D;
20
import java.awt.geom.Rectangle2D;
21
import java.awt.print.PageFormat;
22
import java.awt.print.Printable;
23
import java.awt.print.PrinterException;
24
import java.awt.print.PrinterJob;
25
import java.io.File;
26
import java.io.IOException;
27
import java.io.Serializable;
28
import java.util.EventListener;
29
import java.util.Iterator;
30
import java.util.ResourceBundle;
31

    
32
import javax.swing.JFileChooser;
33
import javax.swing.JMenu;
34
import javax.swing.JMenuItem;
35
import javax.swing.JOptionPane;
36
import javax.swing.JPanel;
37
import javax.swing.JPopupMenu;
38
import javax.swing.SwingUtilities;
39
import javax.swing.ToolTipManager;
40
import javax.swing.event.EventListenerList;
41

    
42
import org.jfree.chart.ChartMouseEvent;
43
import org.jfree.chart.ChartMouseListener;
44
import org.jfree.chart.ChartRenderingInfo;
45
import org.jfree.chart.ChartUtilities;
46
import org.jfree.chart.JFreeChart;
47
import org.jfree.chart.entity.ChartEntity;
48
import org.jfree.chart.entity.EntityCollection;
49
import org.jfree.chart.event.ChartChangeEvent;
50
import org.jfree.chart.event.ChartChangeListener;
51
import org.jfree.chart.event.ChartProgressEvent;
52
import org.jfree.chart.event.ChartProgressListener;
53
import org.jfree.chart.plot.Plot;
54
import org.jfree.chart.plot.PlotOrientation;
55
import org.jfree.chart.plot.PlotRenderingInfo;
56
import org.jfree.chart.plot.Zoomable;
57
import org.jfree.data.Range;
58
import org.jfree.data.general.DatasetGroup;
59
import org.jfree.ui.ExtensionFileFilter;
60

    
61
import com.iver.andami.PluginServices;
62

    
63

    
64
public class ScatterPlotDiagram extends JPanel implements ChartChangeListener,
65
        ChartProgressListener, ActionListener, MouseListener, 
66
        MouseMotionListener, Printable, Serializable {
67

    
68
    /** For serialization. */
69
    private static final long serialVersionUID = 6046366297214274674L;
70
    
71
    /** Default setting for buffer usage. */
72
    public static final boolean DEFAULT_BUFFER_USED = false;
73

    
74
    /** The default panel width. */
75
    public static final int DEFAULT_WIDTH = 680;
76

    
77
    /** The default panel height. */
78
    public static final int DEFAULT_HEIGHT = 420;
79

    
80
    /** The default limit below which chart scaling kicks in. */
81
    public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 300;
82

    
83
    /** The default limit below which chart scaling kicks in. */
84
    public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 200;
85

    
86
    /** The default limit below which chart scaling kicks in. */
87
    public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 800;
88

    
89
    /** The default limit below which chart scaling kicks in. */
90
    public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 600;
91

    
92
    /** The minimum size required to perform a zoom on a rectangle */
93
    public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
94

    
95
    /** Properties action command. */
96
    public static final String PROPERTIES_COMMAND = "PROPERTIES";
97

    
98
    /** Save action command. */
99
    public static final String SAVE_COMMAND = "SAVE";
100

    
101
    /** Print action command. */
102
    public static final String PRINT_COMMAND = "PRINT";
103

    
104
    /** Zoom in (both axes) action command. */
105
    public static final String ZOOM_IN_BOTH_COMMAND = "ZOOM_IN_BOTH";
106

    
107
    /** Zoom in (domain axis only) action command. */
108
    public static final String ZOOM_IN_DOMAIN_COMMAND = "ZOOM_IN_DOMAIN";
109

    
110
    /** Zoom in (range axis only) action command. */
111
    public static final String ZOOM_IN_RANGE_COMMAND = "ZOOM_IN_RANGE";
112

    
113
    /** Zoom out (both axes) action command. */
114
    public static final String ZOOM_OUT_BOTH_COMMAND = "ZOOM_OUT_BOTH";
115

    
116
    /** Zoom out (domain axis only) action command. */
117
    public static final String ZOOM_OUT_DOMAIN_COMMAND = "ZOOM_DOMAIN_BOTH";
118

    
119
    /** Zoom out (range axis only) action command. */
120
    public static final String ZOOM_OUT_RANGE_COMMAND = "ZOOM_RANGE_BOTH";
121

    
122
    /** Zoom reset (both axes) action command. */
123
    public static final String ZOOM_RESET_BOTH_COMMAND = "ZOOM_RESET_BOTH";
124

    
125
    /** Zoom reset (domain axis only) action command. */
126
    public static final String ZOOM_RESET_DOMAIN_COMMAND = "ZOOM_RESET_DOMAIN";
127

    
128
    /** Zoom reset (range axis only) action command. */
129
    public static final String ZOOM_RESET_RANGE_COMMAND = "ZOOM_RESET_RANGE";
130
    
131
    
132
    /** Definicion de nueva Roi **/
133
    public static final String NEW_CLASS_COMMAND ="NEW_CLASS";
134
    
135
    
136
    /** Borrado de las Rois sobre el grafico **/
137
    public static final String CLEAR_CHART ="CLEAR_CHART";
138
    
139
 
140
    
141
    /**Contador de Rois definidas para el diagrama*/
142
    int contador= 0;
143
    
144
    
145

    
146
    /** The chart that is displayed in the panel. */
147
    private JFreeChart chart;
148

    
149
    /** Storage for registered (chart) mouse listeners. */
150
    private EventListenerList chartMouseListeners;
151

    
152
    /** A flag that controls whether or not the off-screen buffer is used. */
153
    private boolean useBuffer;
154

    
155
    /** A flag that indicates that the buffer should be refreshed. */
156
    private boolean refreshBuffer;
157

    
158
    /** A buffer for the rendered chart. */
159
    private Image chartBuffer;
160

    
161
    /** The height of the chart buffer. */
162
    private int chartBufferHeight;
163

    
164
    /** The width of the chart buffer. */
165
    private int chartBufferWidth;
166

    
167
    /** 
168
     * The minimum width for drawing a chart (uses scaling for smaller widths). 
169
     */
170
    private int minimumDrawWidth;
171

    
172
    /** 
173
     * The minimum height for drawing a chart (uses scaling for smaller 
174
     * heights). 
175
     */
176
    private int minimumDrawHeight;
177

    
178
    /** 
179
     * The maximum width for drawing a chart (uses scaling for bigger 
180
     * widths). 
181
     */
182
    private int maximumDrawWidth;
183

    
184
    /** 
185
     * The maximum height for drawing a chart (uses scaling for bigger 
186
     * heights). 
187
     */
188
    private int maximumDrawHeight;
189

    
190
    /** The popup menu for the frame. */
191
    private JPopupMenu popup;
192

    
193
    /** The drawing info collected the last time the chart was drawn. */
194
    private ChartRenderingInfo info;
195
    
196
    /** The chart anchor point. */
197
    private Point2D anchor;
198

    
199
    /** The scale factor used to draw the chart. */
200
    private double scaleX;
201

    
202
    /** The scale factor used to draw the chart. */
203
    private double scaleY;
204

    
205
    /** The plot orientation. */
206
    private PlotOrientation orientation = PlotOrientation.VERTICAL;
207
    
208
    /** A flag that controls whether or not domain zooming is enabled. */
209
    private boolean domainZoomable = false;
210

    
211
    /** A flag that controls whether or not range zooming is enabled. */
212
    private boolean rangeZoomable = false;
213

    
214
    /** 
215
     * The zoom rectangle starting point (selected by the user with a mouse 
216
     * click).  This is a point on the screen, not the chart (which may have
217
     * been scaled up or down to fit the panel).  
218
     */
219
    private Point zoomPoint = null;
220

    
221
    /** The zoom rectangle (selected by the user with the mouse). */
222
    private transient Rectangle2D zoomRectangle = null;
223

    
224
    /** Controls if the zoom rectangle is drawn as an outline or filled. */
225
    private boolean fillZoomRectangle = true;
226

    
227
    /** The minimum distance required to drag the mouse to trigger a zoom. */
228
    private int zoomTriggerDistance;
229
    
230
    /** A flag that controls whether or not horizontal tracing is enabled. */
231
    private boolean horizontalAxisTrace = false;
232

    
233
    /** A flag that controls whether or not vertical tracing is enabled. */
234
    private boolean verticalAxisTrace =false;
235

    
236
    /** A vertical trace line. */
237
    private transient Line2D verticalTraceLine;
238

    
239
    /** A horizontal trace line. */
240
    private transient Line2D horizontalTraceLine;
241

    
242
    /** Menu item for zooming in on a chart (both axes). */
243
    private JMenuItem zoomInBothMenuItem;
244

    
245
    /** Menu item for zooming in on a chart (domain axis). */
246
    private JMenuItem zoomInDomainMenuItem;
247

    
248
    /** Menu item for zooming in on a chart (range axis). */
249
    private JMenuItem zoomInRangeMenuItem;
250

    
251
    /** Menu item for zooming out on a chart. */
252
    private JMenuItem zoomOutBothMenuItem;
253

    
254
    /** Menu item for zooming out on a chart (domain axis). */
255
    private JMenuItem zoomOutDomainMenuItem;
256

    
257
    /** Menu item for zooming out on a chart (range axis). */
258
    private JMenuItem zoomOutRangeMenuItem;
259

    
260
    /** Menu item for resetting the zoom (both axes). */
261
    private JMenuItem zoomResetBothMenuItem;
262

    
263
    /** Menu item for resetting the zoom (domain axis only). */
264
    private JMenuItem zoomResetDomainMenuItem;
265

    
266
    /** Menu item for resetting the zoom (range axis only). */
267
    private JMenuItem zoomResetRangeMenuItem;
268

    
269
    /**
270
     * The default directory for saving charts to file.
271
     * 
272
     * @since 1.0.7
273
     */
274
    private File defaultDirectoryForSaveAs;
275
    
276
    /** A flag that controls whether or not file extensions are enforced. */
277
    private boolean enforceFileExtensions;
278

    
279
    /** A flag that indicates if original tooltip delays are changed. */
280
    private boolean ownToolTipDelaysActive;  
281
    
282
    /** Original initial tooltip delay of ToolTipManager.sharedInstance(). */
283
    private int originalToolTipInitialDelay;
284

    
285
    /** Original reshow tooltip delay of ToolTipManager.sharedInstance(). */
286
    private int originalToolTipReshowDelay;  
287

    
288
    /** Original dismiss tooltip delay of ToolTipManager.sharedInstance(). */
289
    private int originalToolTipDismissDelay;
290

    
291
    /** Own initial tooltip delay to be used in this chart panel. */
292
    private int ownToolTipInitialDelay;
293
    
294
    /** Own reshow tooltip delay to be used in this chart panel. */
295
    private int ownToolTipReshowDelay;  
296

    
297
    /** Own dismiss tooltip delay to be used in this chart panel. */
298
    private int ownToolTipDismissDelay;    
299

    
300
    /** The factor used to zoom in on an axis range. */
301
    private double zoomInFactor = 0.5;
302
    
303
    /** The factor used to zoom out on an axis range. */
304
    private double zoomOutFactor = 2.0;
305
    
306
    /**
307
     * A flag that controls whether zoom operations are centred on the
308
     * current anchor point, or the centre point of the relevant axis.
309
     *
310
     * @since 1.0.7
311
     */
312
    private boolean zoomAroundAnchor;
313
    
314
    /** The resourceBundle for the localization. */
315
    protected static ResourceBundle localizationResources 
316
            = ResourceBundle.getBundle("org.jfree.chart.LocalizationBundle");
317

    
318
    
319
    
320
    private ROIChart activeROI= new ROIChart(Color.GREEN,"ROICHARt1");
321
    private ROIChartList roiList= new ROIChartList();
322
    Graphics2D g2= null;
323
    
324
    
325
    /**
326
     * Constructs a panel that displays the specified chart.
327
     *
328
     * @param chart  the chart.
329
     */
330
    public ScatterPlotDiagram(JFreeChart chart) {
331

    
332
        this(
333
            chart,
334
            DEFAULT_WIDTH,
335
            DEFAULT_HEIGHT,
336
            DEFAULT_MINIMUM_DRAW_WIDTH,
337
            DEFAULT_MINIMUM_DRAW_HEIGHT,
338
            DEFAULT_MAXIMUM_DRAW_WIDTH,
339
            DEFAULT_MAXIMUM_DRAW_HEIGHT,
340
            DEFAULT_BUFFER_USED,
341
            true,  // properties
342
            true,  // save
343
            true,  // print
344
            true,  // zoom
345
            true   // tooltips
346
        );
347

    
348
    }
349

    
350
   
351

    
352
    /**
353
     * Constructs a JFreeChart panel.
354
     *
355
     * @param chart  the chart.
356
     * @param width  the preferred width of the panel.
357
     * @param height  the preferred height of the panel.
358
     * @param minimumDrawWidth  the minimum drawing width.
359
     * @param minimumDrawHeight  the minimum drawing height.
360
     * @param maximumDrawWidth  the maximum drawing width.
361
     * @param maximumDrawHeight  the maximum drawing height.
362
     * @param useBuffer  a flag that indicates whether to use the off-screen
363
     *                   buffer to improve performance (at the expense of 
364
     *                   memory).
365
     * @param properties  a flag indicating whether or not the chart property
366
     *                    editor should be available via the popup menu.
367
     * @param save  a flag indicating whether or not save options should be
368
     *              available via the popup menu.
369
     * @param print  a flag indicating whether or not the print option
370
     *               should be available via the popup menu.
371
     * @param zoom  a flag indicating whether or not zoom options should be 
372
     *              added to the popup menu.
373
     * @param tooltips  a flag indicating whether or not tooltips should be 
374
     *                  enabled for the chart.
375
     */
376
    public ScatterPlotDiagram(JFreeChart chart,
377
                      int width,
378
                      int height,
379
                      int minimumDrawWidth,
380
                      int minimumDrawHeight,
381
                      int maximumDrawWidth,
382
                      int maximumDrawHeight,
383
                      boolean useBuffer,
384
                      boolean properties,
385
                      boolean save,
386
                      boolean print,
387
                      boolean zoom,
388
                      boolean tooltips) {
389

    
390
        this.setChart(chart);
391
        this.chartMouseListeners = new EventListenerList();
392
        this.info = new ChartRenderingInfo();
393
        setPreferredSize(new Dimension(width, height));
394
        this.useBuffer = useBuffer;
395
        this.refreshBuffer = false;
396
        this.minimumDrawWidth = minimumDrawWidth;
397
        this.minimumDrawHeight = minimumDrawHeight;
398
        this.maximumDrawWidth = maximumDrawWidth;
399
        this.maximumDrawHeight = maximumDrawHeight;
400
        this.zoomTriggerDistance = DEFAULT_ZOOM_TRIGGER_DISTANCE;
401

    
402
        // set up popup menu...
403
        this.popup = null;
404
        if (properties || save || print || zoom) {
405
            this.popup = createPopupMenu(properties, save, print, zoom);
406
        }
407

    
408
        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
409
        enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
410
        setDisplayToolTips(tooltips);
411
        addMouseListener(this);
412
        addMouseMotionListener(this);
413

    
414
        this.defaultDirectoryForSaveAs = null;
415
        this.enforceFileExtensions = true;
416

    
417
        // initialize ChartPanel-specific tool tip delays with
418
        // values the from ToolTipManager.sharedInstance()
419
        ToolTipManager ttm = ToolTipManager.sharedInstance();       
420
        this.ownToolTipInitialDelay = ttm.getInitialDelay();
421
        this.ownToolTipDismissDelay = ttm.getDismissDelay();
422
        this.ownToolTipReshowDelay = ttm.getReshowDelay();
423

    
424
        this.zoomAroundAnchor = false;
425
    }
426

    
427
    /**
428
     * Returns the chart contained in the panel.
429
     *
430
     * @return The chart (possibly <code>null</code>).
431
     */
432
    public JFreeChart getChart() {
433
        return this.chart;
434
    }
435

    
436
    /**
437
     * Sets the chart that is displayed in the panel.
438
     *
439
     * @param chart  the chart (<code>null</code> permitted).
440
     */
441
    public void setChart(JFreeChart chart) {
442

    
443
        // stop listening for changes to the existing chart
444
        if (this.chart != null) {
445
            this.chart.removeChangeListener(this);
446
            this.chart.removeProgressListener(this);
447
        }
448

    
449
        // add the new chart
450
        this.chart = chart;
451
        if (chart != null) {
452
            this.chart.addChangeListener(this);
453
            this.chart.addProgressListener(this);
454
            Plot plot = chart.getPlot();
455
            this.domainZoomable = false;
456
            this.rangeZoomable = false;
457
            if (plot instanceof Zoomable) {
458
                Zoomable z = (Zoomable) plot;
459
                this.domainZoomable = z.isDomainZoomable();
460
                this.rangeZoomable = z.isRangeZoomable();
461
                this.orientation = z.getOrientation();
462
            }
463
        }
464
        else {
465
            this.domainZoomable = false;
466
            this.rangeZoomable = false;
467
        }
468
        if (this.useBuffer) {
469
            this.refreshBuffer = true;
470
        }
471
        repaint();
472

    
473
    }
474

    
475
    /**
476
     * Returns the minimum drawing width for charts.
477
     * <P>
478
     * If the width available on the panel is less than this, then the chart is
479
     * drawn at the minimum width then scaled down to fit.
480
     *
481
     * @return The minimum drawing width.
482
     */
483
    public int getMinimumDrawWidth() {
484
        return this.minimumDrawWidth;
485
    }
486

    
487
    /**
488
     * Sets the minimum drawing width for the chart on this panel.
489
     * <P>
490
     * At the time the chart is drawn on the panel, if the available width is
491
     * less than this amount, the chart will be drawn using the minimum width
492
     * then scaled down to fit the available space.
493
     *
494
     * @param width  The width.
495
     */
496
    public void setMinimumDrawWidth(int width) {
497
        this.minimumDrawWidth = width;
498
    }
499

    
500
    /**
501
     * Returns the maximum drawing width for charts.
502
     * <P>
503
     * If the width available on the panel is greater than this, then the chart
504
     * is drawn at the maximum width then scaled up to fit.
505
     *
506
     * @return The maximum drawing width.
507
     */
508
    public int getMaximumDrawWidth() {
509
        return this.maximumDrawWidth;
510
    }
511

    
512
    /**
513
     * Sets the maximum drawing width for the chart on this panel.
514
     * <P>
515
     * At the time the chart is drawn on the panel, if the available width is
516
     * greater than this amount, the chart will be drawn using the maximum
517
     * width then scaled up to fit the available space.
518
     *
519
     * @param width  The width.
520
     */
521
    public void setMaximumDrawWidth(int width) {
522
        this.maximumDrawWidth = width;
523
    }
524

    
525
    /**
526
     * Returns the minimum drawing height for charts.
527
     * <P>
528
     * If the height available on the panel is less than this, then the chart
529
     * is drawn at the minimum height then scaled down to fit.
530
     *
531
     * @return The minimum drawing height.
532
     */
533
    public int getMinimumDrawHeight() {
534
        return this.minimumDrawHeight;
535
    }
536

    
537
    /**
538
     * Sets the minimum drawing height for the chart on this panel.
539
     * <P>
540
     * At the time the chart is drawn on the panel, if the available height is
541
     * less than this amount, the chart will be drawn using the minimum height
542
     * then scaled down to fit the available space.
543
     *
544
     * @param height  The height.
545
     */
546
    public void setMinimumDrawHeight(int height) {
547
        this.minimumDrawHeight = height;
548
    }
549

    
550
    /**
551
     * Returns the maximum drawing height for charts.
552
     * <P>
553
     * If the height available on the panel is greater than this, then the
554
     * chart is drawn at the maximum height then scaled up to fit.
555
     *
556
     * @return The maximum drawing height.
557
     */
558
    public int getMaximumDrawHeight() {
559
        return this.maximumDrawHeight;
560
    }
561

    
562
    /**
563
     * Sets the maximum drawing height for the chart on this panel.
564
     * <P>
565
     * At the time the chart is drawn on the panel, if the available height is
566
     * greater than this amount, the chart will be drawn using the maximum
567
     * height then scaled up to fit the available space.
568
     *
569
     * @param height  The height.
570
     */
571
    public void setMaximumDrawHeight(int height) {
572
        this.maximumDrawHeight = height;
573
    }
574

    
575
    /**
576
     * Returns the X scale factor for the chart.  This will be 1.0 if no 
577
     * scaling has been used.
578
     * 
579
     * @return The scale factor.
580
     */
581
    public double getScaleX() {
582
        return this.scaleX;
583
    }
584
    
585
    /**
586
     * Returns the Y scale factory for the chart.  This will be 1.0 if no 
587
     * scaling has been used.
588
     * 
589
     * @return The scale factor.
590
     */
591
    public double getScaleY() {
592
        return this.scaleY;
593
    }
594
    
595
    /**
596
     * Returns the anchor point.
597
     * 
598
     * @return The anchor point (possibly <code>null</code>).
599
     */
600
    public Point2D getAnchor() {
601
        return this.anchor;   
602
    }
603
    
604
    /**
605
     * Sets the anchor point.  This method is provided for the use of 
606
     * subclasses, not end users.
607
     * 
608
     * @param anchor  the anchor point (<code>null</code> permitted).
609
     */
610
    protected void setAnchor(Point2D anchor) {
611
        this.anchor = anchor;   
612
    }
613
    
614
    /**
615
     * Returns the popup menu.
616
     *
617
     * @return The popup menu.
618
     */
619
    public JPopupMenu getPopupMenu() {
620
        return this.popup;
621
    }
622

    
623
    /**
624
     * Sets the popup menu for the panel.
625
     *
626
     * @param popup  the popup menu (<code>null</code> permitted).
627
     */
628
    public void setPopupMenu(JPopupMenu popup) {
629
        this.popup = popup;
630
    }
631

    
632
    /**
633
     * Returns the chart rendering info from the most recent chart redraw.
634
     *
635
     * @return The chart rendering info.
636
     */
637
    public ChartRenderingInfo getChartRenderingInfo() {
638
        return this.info;
639
    }
640

    
641
    /**
642
     * A convenience method that switches on mouse-based zooming.
643
     *
644
     * @param flag  <code>true</code> enables zooming and rectangle fill on 
645
     *              zoom.
646
     */
647
    public void setMouseZoomable(boolean flag) {
648
        setMouseZoomable(flag, true);
649
    }
650

    
651
    /**
652
     * A convenience method that switches on mouse-based zooming.
653
     *
654
     * @param flag  <code>true</code> if zooming enabled
655
     * @param fillRectangle  <code>true</code> if zoom rectangle is filled,
656
     *                       false if rectangle is shown as outline only.
657
     */
658
    public void setMouseZoomable(boolean flag, boolean fillRectangle) {
659
        setDomainZoomable(flag);
660
        setRangeZoomable(flag);
661
        setFillZoomRectangle(fillRectangle);
662
    }
663

    
664
    /**
665
     * Returns the flag that determines whether or not zooming is enabled for 
666
     * the domain axis.
667
     * 
668
     * @return A boolean.
669
     */
670
    public boolean isDomainZoomable() {
671
        return this.domainZoomable;
672
    }
673
    
674
    /**
675
     * Sets the flag that controls whether or not zooming is enable for the 
676
     * domain axis.  A check is made to ensure that the current plot supports
677
     * zooming for the domain values.
678
     *
679
     * @param flag  <code>true</code> enables zooming if possible.
680
     */
681
    public void setDomainZoomable(boolean flag) {
682
        if (flag) {
683
            Plot plot = this.chart.getPlot();
684
            if (plot instanceof Zoomable) {
685
                Zoomable z = (Zoomable) plot;
686
                this.domainZoomable = flag && (z.isDomainZoomable());  
687
            }
688
        }
689
        else {
690
            this.domainZoomable = false;
691
        }
692
    }
693

    
694
    /**
695
     * Returns the flag that determines whether or not zooming is enabled for 
696
     * the range axis.
697
     * 
698
     * @return A boolean.
699
     */
700
    public boolean isRangeZoomable() {
701
        return this.rangeZoomable;
702
    }
703
    
704
    /**
705
     * A flag that controls mouse-based zooming on the vertical axis.
706
     *
707
     * @param flag  <code>true</code> enables zooming.
708
     */
709
    public void setRangeZoomable(boolean flag) {
710
        if (flag) {
711
            Plot plot = this.chart.getPlot();
712
            if (plot instanceof Zoomable) {
713
                Zoomable z = (Zoomable) plot;
714
                this.rangeZoomable = flag && (z.isRangeZoomable());  
715
            }
716
        }
717
        else {
718
            this.rangeZoomable = false;
719
        }
720
    }
721

    
722
    /**
723
     * Returns the flag that controls whether or not the zoom rectangle is
724
     * filled when drawn.
725
     * 
726
     * @return A boolean.
727
     */
728
    public boolean getFillZoomRectangle() {
729
        return this.fillZoomRectangle;
730
    }
731
    
732
    /**
733
     * A flag that controls how the zoom rectangle is drawn.
734
     *
735
     * @param flag  <code>true</code> instructs to fill the rectangle on
736
     *              zoom, otherwise it will be outlined.
737
     */
738
    public void setFillZoomRectangle(boolean flag) {
739
        this.fillZoomRectangle = flag;
740
    }
741

    
742
    /**
743
     * Returns the zoom trigger distance.  This controls how far the mouse must
744
     * move before a zoom action is triggered.
745
     * 
746
     * @return The distance (in Java2D units).
747
     */
748
    public int getZoomTriggerDistance() {
749
        return this.zoomTriggerDistance;
750
    }
751
    
752
    /**
753
     * Sets the zoom trigger distance.  This controls how far the mouse must 
754
     * move before a zoom action is triggered.
755
     * 
756
     * @param distance  the distance (in Java2D units).
757
     */
758
    public void setZoomTriggerDistance(int distance) {
759
        this.zoomTriggerDistance = distance;
760
    }
761
    
762
    /**
763
     * Returns the flag that controls whether or not a horizontal axis trace
764
     * line is drawn over the plot area at the current mouse location.
765
     * 
766
     * @return A boolean.
767
     */
768
    public boolean getHorizontalAxisTrace() {
769
        return this.horizontalAxisTrace;    
770
    }
771
    
772
    /**
773
     * A flag that controls trace lines on the horizontal axis.
774
     *
775
     * @param flag  <code>true</code> enables trace lines for the mouse
776
     *      pointer on the horizontal axis.
777
     */
778
    public void setHorizontalAxisTrace(boolean flag) {
779
        this.horizontalAxisTrace = flag;
780
    }
781
    
782
    /**
783
     * Returns the horizontal trace line.
784
     * 
785
     * @return The horizontal trace line (possibly <code>null</code>).
786
     */
787
    protected Line2D getHorizontalTraceLine() {
788
        return this.horizontalTraceLine;   
789
    }
790
    
791
    /**
792
     * Sets the horizontal trace line.
793
     * 
794
     * @param line  the line (<code>null</code> permitted).
795
     */
796
    protected void setHorizontalTraceLine(Line2D line) {
797
        this.horizontalTraceLine = line;   
798
    }
799

    
800
    /**
801
     * Returns the flag that controls whether or not a vertical axis trace
802
     * line is drawn over the plot area at the current mouse location.
803
     * 
804
     * @return A boolean.
805
     */
806
    public boolean getVerticalAxisTrace() {
807
        return this.verticalAxisTrace;    
808
    }
809
    
810
    /**
811
     * A flag that controls trace lines on the vertical axis.
812
     *
813
     * @param flag  <code>true</code> enables trace lines for the mouse
814
     *              pointer on the vertical axis.
815
     */
816
    public void setVerticalAxisTrace(boolean flag) {
817
        this.verticalAxisTrace = flag;
818
    }
819

    
820
    /**
821
     * Returns the vertical trace line.
822
     * 
823
     * @return The vertical trace line (possibly <code>null</code>).
824
     */
825
    protected Line2D getVerticalTraceLine() {
826
        return this.verticalTraceLine;   
827
    }
828
    
829
    /**
830
     * Sets the vertical trace line.
831
     * 
832
     * @param line  the line (<code>null</code> permitted).
833
     */
834
    protected void setVerticalTraceLine(Line2D line) {
835
        this.verticalTraceLine = line;   
836
    }
837
    
838
    /**
839
     * Returns the default directory for the "save as" option.
840
     * 
841
     * @return The default directory (possibly <code>null</code>).
842
     * 
843
     * @since 1.0.7
844
     */
845
    public File getDefaultDirectoryForSaveAs() {
846
        return this.defaultDirectoryForSaveAs;
847
    }
848

    
849
    /**
850
     * Sets the default directory for the "save as" option.  If you set this
851
     * to <code>null</code>, the user's default directory will be used.
852
     * 
853
     * @param directory  the directory (<code>null</code> permitted).
854
     * 
855
     * @since 1.0.7
856
     */
857
    public void setDefaultDirectoryForSaveAs(File directory) {
858
        if (directory != null) {
859
            if (!directory.isDirectory()) {
860
                throw new IllegalArgumentException(
861
                        "The 'directory' argument is not a directory.");
862
            }
863
        }
864
        this.defaultDirectoryForSaveAs = directory;
865
    }
866
    
867
    /**
868
     * Returns <code>true</code> if file extensions should be enforced, and 
869
     * <code>false</code> otherwise.
870
     *
871
     * @return The flag.
872
     * 
873
     * @see #setEnforceFileExtensions(boolean)
874
     */
875
    public boolean isEnforceFileExtensions() {
876
        return this.enforceFileExtensions;
877
    }
878

    
879
    /**
880
     * Sets a flag that controls whether or not file extensions are enforced.
881
     *
882
     * @param enforce  the new flag value.
883
     * 
884
     * @see #isEnforceFileExtensions()
885
     */
886
    public void setEnforceFileExtensions(boolean enforce) {
887
        this.enforceFileExtensions = enforce;
888
    }
889
    
890
    /**
891
     * Returns the flag that controls whether or not zoom operations are 
892
     * centered around the current anchor point.
893
     * 
894
     * @return A boolean.
895
     * 
896
     * @since 1.0.7
897
     * 
898
     * @see #setZoomAroundAnchor(boolean)
899
     */
900
    public boolean getZoomAroundAnchor() {
901
        return this.zoomAroundAnchor;
902
    }
903
    
904
    /**
905
     * Sets the flag that controls whether or not zoom operations are
906
     * centered around the current anchor point.
907
     * 
908
     * @param zoomAroundAnchor  the new flag value.
909
     * 
910
     * @since 1.0.7
911
     * 
912
     * @see #getZoomAroundAnchor()
913
     */
914
    public void setZoomAroundAnchor(boolean zoomAroundAnchor) {
915
        this.zoomAroundAnchor = zoomAroundAnchor;
916
    }
917

    
918
    /**
919
     * Switches the display of tooltips for the panel on or off.  Note that 
920
     * tooltips can only be displayed if the chart has been configured to
921
     * generate tooltip items.
922
     *
923
     * @param flag  <code>true</code> to enable tooltips, <code>false</code> to
924
     *              disable tooltips.
925
     */
926
    public void setDisplayToolTips(boolean flag) {
927
        if (flag) {
928
            ToolTipManager.sharedInstance().registerComponent(this);
929
        }
930
        else {
931
            ToolTipManager.sharedInstance().unregisterComponent(this);
932
        }
933
    }
934

    
935
    /**
936
     * Returns a string for the tooltip.
937
     *
938
     * @param e  the mouse event.
939
     *
940
     * @return A tool tip or <code>null</code> if no tooltip is available.
941
     */
942
    public String getToolTipText(MouseEvent e) {
943

    
944
        String result = null;
945
        if (this.info != null) {
946
            EntityCollection entities = this.info.getEntityCollection();
947
            if (entities != null) {
948
                Insets insets = getInsets();
949
                ChartEntity entity = entities.getEntity(
950
                        (int) ((e.getX() - insets.left) / this.scaleX),
951
                        (int) ((e.getY() - insets.top) / this.scaleY));
952
                if (entity != null) {
953
                    result = entity.getToolTipText();
954
                }
955
            }
956
        }
957
        return result;
958

    
959
    }
960

    
961
    /**
962
     * Translates a Java2D point on the chart to a screen location.
963
     *
964
     * @param java2DPoint  the Java2D point.
965
     *
966
     * @return The screen location.
967
     */
968
    public Point translateJava2DToScreen(Point2D java2DPoint) {
969
        Insets insets = getInsets();
970
        int x = (int) (java2DPoint.getX() * this.scaleX + insets.left);
971
        int y = (int) (java2DPoint.getY() * this.scaleY + insets.top);
972
        return new Point(x, y);
973
    }
974

    
975
    /**
976
     * Translates a panel (component) location to a Java2D point.
977
     *
978
     * @param screenPoint  the screen location (<code>null</code> not 
979
     *                     permitted).
980
     *
981
     * @return The Java2D coordinates.
982
     */
983
    public Point2D translateScreenToJava2D(Point screenPoint) {
984
        Insets insets = getInsets();
985
        double x = (screenPoint.getX() - insets.left) / this.scaleX;
986
        double y = (screenPoint.getY() - insets.top) / this.scaleY;
987
        return new Point2D.Double(x, y);
988
    }
989

    
990
    /**
991
     * Applies any scaling that is in effect for the chart drawing to the
992
     * given rectangle.
993
     *  
994
     * @param rect  the rectangle.
995
     * 
996
     * @return A new scaled rectangle.
997
     */
998
    public Rectangle2D scale(Rectangle2D rect) {
999
        Insets insets = getInsets();
1000
        double x = rect.getX() * getScaleX() + insets.left;
1001
        double y = rect.getY() * this.getScaleY() + insets.top;
1002
        double w = rect.getWidth() * this.getScaleX();
1003
        double h = rect.getHeight() * this.getScaleY();
1004
        return new Rectangle2D.Double(x, y, w, h);
1005
    }
1006

    
1007
    /**
1008
     * Returns the chart entity at a given point.
1009
     * <P>
1010
     * This method will return null if there is (a) no entity at the given 
1011
     * point, or (b) no entity collection has been generated.
1012
     *
1013
     * @param viewX  the x-coordinate.
1014
     * @param viewY  the y-coordinate.
1015
     *
1016
     * @return The chart entity (possibly <code>null</code>).
1017
     */
1018
    public ChartEntity getEntityForPoint(int viewX, int viewY) {
1019

    
1020
        ChartEntity result = null;
1021
        if (this.info != null) {
1022
            Insets insets = getInsets();
1023
            double x = (viewX - insets.left) / this.scaleX;
1024
            double y = (viewY - insets.top) / this.scaleY;
1025
            EntityCollection entities = this.info.getEntityCollection();
1026
            result = entities != null ? entities.getEntity(x, y) : null; 
1027
        }
1028
        return result;
1029

    
1030
    }
1031

    
1032
    /**
1033
     * Returns the flag that controls whether or not the offscreen buffer
1034
     * needs to be refreshed.
1035
     * 
1036
     * @return A boolean.
1037
     */
1038
    public boolean getRefreshBuffer() {
1039
        return this.refreshBuffer;
1040
    }
1041
    
1042
    /**
1043
     * Sets the refresh buffer flag.  This flag is used to avoid unnecessary
1044
     * redrawing of the chart when the offscreen image buffer is used.
1045
     *
1046
     * @param flag  <code>true</code> indicates that the buffer should be 
1047
     *              refreshed.
1048
     */
1049
    public void setRefreshBuffer(boolean flag) {
1050
        this.refreshBuffer = flag;
1051
    }
1052

    
1053
    /**
1054
     * Paints the component by drawing the chart to fill the entire component,
1055
     * but allowing for the insets (which will be non-zero if a border has been
1056
     * set for this component).  To increase performance (at the expense of
1057
     * memory), an off-screen buffer image can be used.
1058
     *
1059
     * @param g  the graphics device for drawing on.
1060
     */
1061
    public void paintComponent(Graphics g) {
1062
        super.paintComponent(g);
1063
        if (this.chart == null) {
1064
            return;
1065
        }
1066
        Graphics2D g2 = (Graphics2D) g.create();
1067

    
1068
        // first determine the size of the chart rendering area...
1069
        Dimension size = getSize();
1070
        Insets insets = getInsets();
1071
        Rectangle2D available = new Rectangle2D.Double(insets.left, insets.top,
1072
                size.getWidth() - insets.left - insets.right,
1073
                size.getHeight() - insets.top - insets.bottom);
1074

    
1075
        // work out if scaling is required...
1076
        boolean scale = false;
1077
        double drawWidth = available.getWidth();
1078
        double drawHeight = available.getHeight();
1079
        this.scaleX = 1.0;
1080
        this.scaleY = 1.0;
1081

    
1082
        if (drawWidth < this.minimumDrawWidth) {
1083
            this.scaleX = drawWidth / this.minimumDrawWidth;
1084
            drawWidth = this.minimumDrawWidth;
1085
            scale = true;
1086
        }
1087
        else if (drawWidth > this.maximumDrawWidth) {
1088
            this.scaleX = drawWidth / this.maximumDrawWidth;
1089
            drawWidth = this.maximumDrawWidth;
1090
            scale = true;
1091
        }
1092

    
1093
        if (drawHeight < this.minimumDrawHeight) {
1094
            this.scaleY = drawHeight / this.minimumDrawHeight;
1095
            drawHeight = this.minimumDrawHeight;
1096
            scale = true;
1097
        }
1098
        else if (drawHeight > this.maximumDrawHeight) {
1099
            this.scaleY = drawHeight / this.maximumDrawHeight;
1100
            drawHeight = this.maximumDrawHeight;
1101
            scale = true;
1102
        }
1103

    
1104
        Rectangle2D chartArea = new Rectangle2D.Double(0.0, 0.0, drawWidth, 
1105
                drawHeight);
1106

    
1107
        // are we using the chart buffer?
1108
        if (this.useBuffer) {
1109

    
1110
            // if buffer is being refreshed, it needs clearing unless it is
1111
            // new - use the following flag to track this...
1112
            boolean clearBuffer = true;
1113
            
1114
            // do we need to resize the buffer?
1115
            if ((this.chartBuffer == null) 
1116
                    || (this.chartBufferWidth != available.getWidth())
1117
                    || (this.chartBufferHeight != available.getHeight())) {
1118
                this.chartBufferWidth = (int) available.getWidth();
1119
                this.chartBufferHeight = (int) available.getHeight();
1120
                this.chartBuffer = createImage(this.chartBufferWidth, 
1121
                        this.chartBufferHeight);
1122
//                GraphicsConfiguration gc = g2.getDeviceConfiguration();
1123
//                this.chartBuffer = gc.createCompatibleImage(
1124
//                        this.chartBufferWidth, this.chartBufferHeight, 
1125
//                        Transparency.TRANSLUCENT);
1126
                this.refreshBuffer = true;
1127
                clearBuffer = false;  // buffer is new, no clearing required
1128
            }
1129

    
1130
            // do we need to redraw the buffer?
1131
            if (this.refreshBuffer) {
1132

    
1133
                this.refreshBuffer = false; // clear the flag
1134

    
1135
                Rectangle2D bufferArea = new Rectangle2D.Double(
1136
                        0, 0, this.chartBufferWidth, this.chartBufferHeight);
1137

    
1138
                Graphics2D bufferG2 = (Graphics2D) 
1139
                        this.chartBuffer.getGraphics();
1140
                if (clearBuffer) {
1141
                    bufferG2.clearRect(0, 0, this.chartBufferWidth, 
1142
                            this.chartBufferHeight);
1143
                }
1144
                if (scale) {
1145
                    AffineTransform saved = bufferG2.getTransform();
1146
                    AffineTransform st = AffineTransform.getScaleInstance(
1147
                            this.scaleX, this.scaleY);
1148
                    bufferG2.transform(st);
1149
                    this.chart.draw(bufferG2, chartArea, this.anchor, 
1150
                            this.info);
1151
                    bufferG2.setTransform(saved);
1152
                }
1153
                else {
1154
                    this.chart.draw(bufferG2, bufferArea, this.anchor, 
1155
                            this.info);
1156
                }
1157

    
1158
            }
1159

    
1160
            // zap the buffer onto the panel...
1161
            g2.drawImage(this.chartBuffer, insets.left, insets.top, this);
1162
            g2.draw((Shape)activeROI.shapeList.get(1));
1163
          // Dibujar las rois que se encuentren activas
1164
        
1165
        }
1166

    
1167
        // or redrawing the chart every time...
1168
        else {
1169

    
1170
            AffineTransform saved = g2.getTransform();
1171
            g2.translate(insets.left, insets.top);
1172
            if (scale) {
1173
                AffineTransform st = AffineTransform.getScaleInstance(
1174
                        this.scaleX, this.scaleY);
1175
                g2.transform(st);
1176
            }
1177
            this.chart.draw(g2, chartArea, this.anchor, this.info);
1178
            g2.drawImage(this.chartBuffer, insets.left, insets.top, this);
1179
         
1180
            // Se pintan las Roi activa
1181
            drawsROIs(g2);
1182
            g2.setTransform(saved);
1183

    
1184
        }
1185
        
1186
        // Redraw the zoom rectangle (if present)
1187
        drawZoomRectangle(g2);
1188
        
1189
        g2.dispose();
1190

    
1191
        this.anchor = null;
1192
        this.verticalTraceLine = null;
1193
        this.horizontalTraceLine = null;
1194

    
1195
    }
1196

    
1197
  
1198
        /**
1199
     * Receives notification of changes to the chart, and redraws the chart.
1200
     *
1201
     * @param event  details of the chart change event.
1202
     */
1203
    public void chartChanged(ChartChangeEvent event) {
1204
        this.refreshBuffer = true;
1205
        Plot plot = this.chart.getPlot();
1206
        if (plot instanceof Zoomable) {
1207
            Zoomable z = (Zoomable) plot;
1208
            this.orientation = z.getOrientation();
1209
        }
1210
        repaint();
1211
    }
1212

    
1213
    /**
1214
     * Receives notification of a chart progress event.
1215
     *
1216
     * @param event  the event.
1217
     */
1218
    public void chartProgress(ChartProgressEvent event) {
1219
        // does nothing - override if necessary
1220
    }
1221

    
1222
    /**
1223
     * Handles action events generated by the popup menu.
1224
     *
1225
     * @param event  the event.
1226
     */
1227
    public void actionPerformed(ActionEvent event) {
1228

    
1229
        String command = event.getActionCommand();
1230

    
1231
        // many of the zoom methods need a screen location - all we have is 
1232
        // the zoomPoint, but it might be null.  Here we grab the x and y
1233
        // coordinates, or use defaults...
1234
        double screenX = -1.0;
1235
        double screenY = -1.0;
1236
        if (this.zoomPoint != null) {
1237
            screenX = this.zoomPoint.getX();
1238
            screenY = this.zoomPoint.getY();
1239
        }
1240
        
1241
        if (command.equals(SAVE_COMMAND)) {
1242
            try {
1243
                doSaveAs();
1244
            }
1245
            catch (IOException e) {
1246
                e.printStackTrace();
1247
            }
1248
        }
1249
        else if (command.equals(PRINT_COMMAND)) {
1250
            createChartPrintJob();
1251
        }
1252
        else if (command.equals(ZOOM_IN_BOTH_COMMAND)) {
1253
            zoomInBoth(screenX, screenY);
1254
        }
1255
        else if (command.equals(ZOOM_IN_DOMAIN_COMMAND)) {
1256
            zoomInDomain(screenX, screenY);
1257
        }
1258
        else if (command.equals(ZOOM_IN_RANGE_COMMAND)) {
1259
            zoomInRange(screenX, screenY);
1260
        }
1261
        else if (command.equals(ZOOM_OUT_BOTH_COMMAND)) {
1262
            zoomOutBoth(screenX, screenY);
1263
        }
1264
        else if (command.equals(ZOOM_OUT_DOMAIN_COMMAND)) {
1265
            zoomOutDomain(screenX, screenY);
1266
        }
1267
        else if (command.equals(ZOOM_OUT_RANGE_COMMAND)) {
1268
            zoomOutRange(screenX, screenY);
1269
        }
1270
        else if (command.equals(ZOOM_RESET_BOTH_COMMAND)) {
1271
            restoreAutoBounds();
1272
        }
1273
        else if (command.equals(ZOOM_RESET_DOMAIN_COMMAND)) {
1274
            restoreAutoDomainBounds();
1275
        }
1276
        else if (command.equals(ZOOM_RESET_RANGE_COMMAND)) {
1277
            restoreAutoRangeBounds();
1278
        }
1279
        else if (command.equals(NEW_CLASS_COMMAND)) {
1280
            // Definicion de nueba clase
1281
        //        if (activeROI!=null)
1282
                roiList.add(activeROI);
1283
                // se genera una nueva ROI
1284
                activeROI= new ROIChart(new Color((float)Math.random(),(float)Math.random(),(float)Math.random()), "ROIChart"+contador);
1285
                
1286
        }
1287

    
1288
        // Acciones para el borrado de la visualizacion de las rois
1289
        else if (command.equals(CLEAR_CHART)) {
1290
            // Definicion de nueba clase
1291
        
1292
                
1293
                
1294
        }
1295

    
1296
    }
1297

    
1298
    /**
1299
     * Handles a 'mouse entered' event. This method changes the tooltip delays
1300
     * of ToolTipManager.sharedInstance() to the possibly different values set 
1301
     * for this chart panel. 
1302
     *
1303
     * @param e  the mouse event.
1304
     */
1305
    public void mouseEntered(MouseEvent e) {
1306
        if (!this.ownToolTipDelaysActive) {
1307
            ToolTipManager ttm = ToolTipManager.sharedInstance();
1308
            
1309
            this.originalToolTipInitialDelay = ttm.getInitialDelay();
1310
            ttm.setInitialDelay(this.ownToolTipInitialDelay);
1311
    
1312
            this.originalToolTipReshowDelay = ttm.getReshowDelay();
1313
            ttm.setReshowDelay(this.ownToolTipReshowDelay);
1314
            
1315
            this.originalToolTipDismissDelay = ttm.getDismissDelay();
1316
            ttm.setDismissDelay(this.ownToolTipDismissDelay);
1317
    
1318
            this.ownToolTipDelaysActive = true;
1319
        }
1320
    }
1321

    
1322
    /**
1323
     * Handles a 'mouse exited' event. This method resets the tooltip delays of
1324
     * ToolTipManager.sharedInstance() to their
1325
     * original values in effect before mouseEntered()
1326
     *
1327
     * @param e  the mouse event.
1328
     */
1329
    public void mouseExited(MouseEvent e) {
1330
        if (this.ownToolTipDelaysActive) {
1331
            // restore original tooltip dealys 
1332
            ToolTipManager ttm = ToolTipManager.sharedInstance();       
1333
            ttm.setInitialDelay(this.originalToolTipInitialDelay);
1334
            ttm.setReshowDelay(this.originalToolTipReshowDelay);
1335
            ttm.setDismissDelay(this.originalToolTipDismissDelay);
1336
            this.ownToolTipDelaysActive = false;
1337
        }
1338
    }
1339

    
1340
    /**
1341
     * Handles a 'mouse pressed' event.
1342
     * <P>
1343
     * This event is the popup trigger on Unix/Linux.  For Windows, the popup
1344
     * trigger is the 'mouse released' event.
1345
     *
1346
     * @param e  The mouse event.
1347
     */
1348
    public void mousePressed(MouseEvent e) {
1349
        if (this.zoomRectangle == null) {
1350
            Rectangle2D screenDataArea = getScreenDataArea(e.getX(), e.getY());
1351
            if (screenDataArea != null) {
1352
                this.zoomPoint = getPointInRectangle(e.getX(), e.getY(), 
1353
                        screenDataArea);
1354
            }
1355
            else {
1356
                this.zoomPoint = null;
1357
            }
1358
            if (e.isPopupTrigger()) {
1359
                if (this.popup != null) {
1360
                    displayPopupMenu(e.getX(), e.getY());
1361
                }
1362
            }
1363
        }
1364
    }
1365
    
1366
    /**
1367
     * Returns a point based on (x, y) but constrained to be within the bounds
1368
     * of the given rectangle.  This method could be moved to JCommon.
1369
     * 
1370
     * @param x  the x-coordinate.
1371
     * @param y  the y-coordinate.
1372
     * @param area  the rectangle (<code>null</code> not permitted).
1373
     * 
1374
     * @return A point within the rectangle.
1375
     */
1376
    private Point getPointInRectangle(int x, int y, Rectangle2D area) {
1377
        x = (int) Math.max(Math.ceil(area.getMinX()), Math.min(x, 
1378
                Math.floor(area.getMaxX())));   
1379
        y = (int) Math.max(Math.ceil(area.getMinY()), Math.min(y, 
1380
                Math.floor(area.getMaxY())));
1381
        return new Point(x, y);
1382
    }
1383

    
1384
    /**
1385
     * Handles a 'mouse dragged' event.
1386
     *
1387
     * @param e  the mouse event.
1388
     */
1389
    public void mouseDragged(MouseEvent e) {
1390

    
1391
        // if the popup menu has already been triggered, then ignore dragging...
1392
        if (this.popup != null && this.popup.isShowing()) {
1393
            return;
1394
        }
1395
        // if no initial zoom point was set, ignore dragging...
1396
        if (this.zoomPoint == null) {
1397
            return;
1398
        }
1399
        Graphics2D g2 = (Graphics2D) getGraphics();
1400

    
1401
        // Erase the previous zoom rectangle (if any)...
1402
        drawZoomRectangle(g2);
1403

    
1404
        boolean hZoom = false;
1405
        boolean vZoom = false;
1406
        if (this.orientation == PlotOrientation.HORIZONTAL) {
1407
            hZoom = this.rangeZoomable;
1408
            vZoom = this.domainZoomable;
1409
        }
1410
        else {
1411
            hZoom = this.domainZoomable;              
1412
            vZoom = this.rangeZoomable;
1413
        }
1414
        Rectangle2D scaledDataArea = getScreenDataArea(
1415
                (int) this.zoomPoint.getX(), (int) this.zoomPoint.getY());
1416
        if (hZoom && vZoom) {
1417
            // selected rectangle shouldn't extend outside the data area...
1418
            double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
1419
            double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
1420
            this.zoomRectangle = new Rectangle2D.Double(
1421
                    this.zoomPoint.getX(), this.zoomPoint.getY(),
1422
                    xmax - this.zoomPoint.getX(), ymax - this.zoomPoint.getY());
1423
        }
1424
        else if (hZoom) {
1425
            double xmax = Math.min(e.getX(), scaledDataArea.getMaxX());
1426
            this.zoomRectangle = new Rectangle2D.Double(
1427
                    this.zoomPoint.getX(), scaledDataArea.getMinY(),
1428
                    xmax - this.zoomPoint.getX(), scaledDataArea.getHeight());
1429
        }
1430
        else if (vZoom) {
1431
            double ymax = Math.min(e.getY(), scaledDataArea.getMaxY());
1432
            this.zoomRectangle = new Rectangle2D.Double(
1433
                    scaledDataArea.getMinX(), this.zoomPoint.getY(),
1434
                    scaledDataArea.getWidth(), ymax - this.zoomPoint.getY());
1435
        }
1436

    
1437
        // Draw the new zoom rectangle...
1438
        drawZoomRectangle(g2);
1439
        
1440
        g2.dispose();
1441

    
1442
    }
1443

    
1444
    /**
1445
     * Handles a 'mouse released' event.  On Windows, we need to check if this 
1446
     * is a popup trigger, but only if we haven't already been tracking a zoom
1447
     * rectangle.
1448
     *
1449
     * @param e  information about the event.
1450
     */
1451
    public void mouseReleased(MouseEvent e) {
1452

    
1453
        if (this.zoomRectangle != null) {
1454
            boolean hZoom = false;
1455
            boolean vZoom = false;
1456
            if (this.orientation == PlotOrientation.HORIZONTAL) {
1457
                hZoom = this.rangeZoomable;
1458
                vZoom = this.domainZoomable;
1459
            }
1460
            else {
1461
                hZoom = this.domainZoomable;              
1462
                vZoom = this.rangeZoomable;
1463
            }
1464
            
1465
            boolean zoomTrigger1 = hZoom && Math.abs(e.getX() 
1466
                - this.zoomPoint.getX()) >= this.zoomTriggerDistance;
1467
            boolean zoomTrigger2 = vZoom && Math.abs(e.getY() 
1468
                - this.zoomPoint.getY()) >= this.zoomTriggerDistance;
1469
            if (zoomTrigger1 || zoomTrigger2) {
1470
                if ((hZoom && (e.getX() < this.zoomPoint.getX())) 
1471
                    || (vZoom && (e.getY() < this.zoomPoint.getY()))) {
1472
                    restoreAutoBounds();
1473
                }
1474
                else {
1475
                    double x, y, w, h;
1476
                    Rectangle2D screenDataArea = getScreenDataArea(
1477
                            (int) this.zoomPoint.getX(), 
1478
                            (int) this.zoomPoint.getY());
1479
                    // for mouseReleased event, (horizontalZoom || verticalZoom)
1480
                    // will be true, so we can just test for either being false;
1481
                    // otherwise both are true
1482
                    if (!vZoom) {
1483
                        x = this.zoomPoint.getX();
1484
                        y = screenDataArea.getMinY();
1485
                        w = Math.min(this.zoomRectangle.getWidth(),
1486
                                screenDataArea.getMaxX() 
1487
                                - this.zoomPoint.getX());
1488
                        h = screenDataArea.getHeight();
1489
                    }
1490
                    else if (!hZoom) {
1491
                        x = screenDataArea.getMinX();
1492
                        y = this.zoomPoint.getY();
1493
                        w = screenDataArea.getWidth();
1494
                        h = Math.min(this.zoomRectangle.getHeight(),
1495
                                screenDataArea.getMaxY() 
1496
                                - this.zoomPoint.getY());
1497
                    }
1498
                    else {
1499
                        x = this.zoomPoint.getX();
1500
                        y = this.zoomPoint.getY();
1501
                        w = Math.min(this.zoomRectangle.getWidth(),
1502
                                screenDataArea.getMaxX() 
1503
                                - this.zoomPoint.getX());
1504
                        h = Math.min(this.zoomRectangle.getHeight(),
1505
                                screenDataArea.getMaxY() 
1506
                                - this.zoomPoint.getY());
1507
                    }
1508
                    if (activeROI!= null)
1509
                    {
1510
                            Rectangle2D rectangleArea = new Rectangle2D.Double(x, y, w, h);
1511
                            g2 = (Graphics2D)getGraphics();
1512
                            g2.setPaint(activeROI.getColor());
1513
           
1514
                            g2.draw(rectangleArea);
1515
                            activeROI.add(rectangleArea, getRange(rectangleArea));
1516
           
1517
                            Range r[]=getRange(rectangleArea);
1518
                            System.out.print("\n"+r[0]);
1519
                            System.out.print("\n");
1520
                            System.out.print(r[1]);
1521
                    }
1522
                  
1523
                }
1524
                this.zoomPoint = null;
1525
                this.zoomRectangle = null;
1526
            }
1527
            else {
1528
                // Erase the zoom rectangle
1529
                Graphics2D g2 = (Graphics2D) getGraphics();
1530
                drawZoomRectangle(g2);
1531
                g2.dispose();
1532
                this.zoomPoint = null;
1533
                this.zoomRectangle = null;
1534
            }
1535

    
1536
        }
1537

    
1538
        else if (e.isPopupTrigger()) {
1539
            if (this.popup != null) {
1540
                displayPopupMenu(e.getX(), e.getY());
1541
            }
1542
        }
1543

    
1544
    }
1545
    
1546
    
1547
   
1548
    /**
1549
     * Receives notification of mouse clicks on the panel. These are
1550
     * translated and passed on to any registered chart mouse click listeners.
1551
     *
1552
     * @param event  Information about the mouse event.
1553
     */
1554
    public void mouseClicked(MouseEvent event) {
1555

    
1556
        Insets insets = getInsets();
1557
        int x = (int) ((event.getX() - insets.left) / this.scaleX);
1558
        int y = (int) ((event.getY() - insets.top) / this.scaleY);
1559

    
1560
        this.anchor = new Point2D.Double(x, y);
1561
        if (this.chart == null) {
1562
            return;
1563
        }
1564
        this.chart.setNotify(true);  // force a redraw 
1565
        // new entity code...
1566
        Object[] listeners = this.chartMouseListeners.getListeners(
1567
                ChartMouseListener.class);
1568
        if (listeners.length == 0) {
1569
            return;
1570
        }
1571

    
1572
        ChartEntity entity = null;
1573
        if (this.info != null) {
1574
            EntityCollection entities = this.info.getEntityCollection();
1575
            if (entities != null) {
1576
                entity = entities.getEntity(x, y);
1577
            }
1578
        }
1579
        ChartMouseEvent chartEvent = new ChartMouseEvent(getChart(), event, 
1580
                entity);
1581
        for (int i = listeners.length - 1; i >= 0; i -= 1) {
1582
            ((ChartMouseListener) listeners[i]).chartMouseClicked(chartEvent);
1583
        }
1584

    
1585
    }
1586

    
1587
    /**
1588
     * Implementation of the MouseMotionListener's method.
1589
     *
1590
     * @param e  the event.
1591
     */
1592
    public void mouseMoved(MouseEvent e) {
1593
      
1594
    /*        g2 = (Graphics2D) getGraphics();
1595
        if (this.horizontalAxisTrace) {
1596
            drawHorizontalAxisTrace(g2, e.getX());
1597
        }
1598
        if (this.verticalAxisTrace) {
1599
            drawVerticalAxisTrace(g2, e.getY());
1600
        }
1601
        g2.dispose();
1602
        
1603
        Object[] listeners = this.chartMouseListeners.getListeners(
1604
                ChartMouseListener.class);
1605
        if (listeners.length == 0) {
1606
            return;
1607
        }
1608
        Insets insets = getInsets();
1609
        int x = (int) ((e.getX() - insets.left) / this.scaleX);
1610
        int y = (int) ((e.getY() - insets.top) / this.scaleY);
1611

1612
        ChartEntity entity = null;
1613
        if (this.info != null) {
1614
            EntityCollection entities = this.info.getEntityCollection();
1615
            if (entities != null) {
1616
                entity = entities.getEntity(x, y);
1617
            }
1618
        }
1619
        
1620
        // we can only generate events if the panel's chart is not null
1621
        // (see bug report 1556951)
1622
        if (this.chart != null) {
1623
            ChartMouseEvent event = new ChartMouseEvent(getChart(), e, entity);
1624
            for (int i = listeners.length - 1; i >= 0; i -= 1) {
1625
                ((ChartMouseListener) listeners[i]).chartMouseMoved(event);
1626
            }
1627
        }*/
1628

    
1629
    }
1630

    
1631
    /**
1632
     * Zooms in on an anchor point (specified in screen coordinate space).
1633
     *
1634
     * @param x  the x value (in screen coordinates).
1635
     * @param y  the y value (in screen coordinates).
1636
     */
1637
    public void zoomInBoth(double x, double y) {
1638
        zoomInDomain(x, y);
1639
        zoomInRange(x, y);
1640
    }
1641

    
1642
    /**
1643
     * Decreases the length of the domain axis, centered about the given
1644
     * coordinate on the screen.  The length of the domain axis is reduced
1645
     * by the value of {@link #getZoomInFactor()}.
1646
     *
1647
     * @param x  the x coordinate (in screen coordinates).
1648
     * @param y  the y-coordinate (in screen coordinates).
1649
     */
1650
    public void zoomInDomain(double x, double y) {
1651
       
1652
    }
1653

    
1654
    /**
1655
     * Decreases the length of the range axis, centered about the given
1656
     * coordinate on the screen.  The length of the range axis is reduced by
1657
     * the value of {@link #getZoomInFactor()}.
1658
     *
1659
     * @param x  the x-coordinate (in screen coordinates).
1660
     * @param y  the y coordinate (in screen coordinates).
1661
     */
1662
    public void zoomInRange(double x, double y) {
1663
       
1664
    }
1665

    
1666
    /**
1667
     * Zooms out on an anchor point (specified in screen coordinate space).
1668
     *
1669
     * @param x  the x value (in screen coordinates).
1670
     * @param y  the y value (in screen coordinates).
1671
     */
1672
    public void zoomOutBoth(double x, double y) {
1673
        zoomOutDomain(x, y);
1674
        zoomOutRange(x, y);
1675
    }
1676

    
1677
    /**
1678
     * Increases the length of the domain axis, centered about the given
1679
     * coordinate on the screen.  The length of the domain axis is increased
1680
     * by the value of {@link #getZoomOutFactor()}.
1681
     *
1682
     * @param x  the x coordinate (in screen coordinates).
1683
     * @param y  the y-coordinate (in screen coordinates).
1684
     */
1685
    public void zoomOutDomain(double x, double y) {
1686
      
1687
    }
1688

    
1689
    /**
1690
     * Increases the length the range axis, centered about the given
1691
     * coordinate on the screen.  The length of the range axis is increased
1692
     * by the value of {@link #getZoomOutFactor()}.
1693
     *
1694
     * @param x  the x coordinate (in screen coordinates).
1695
     * @param y  the y-coordinate (in screen coordinates).
1696
     */
1697
    public void zoomOutRange(double x, double y) {
1698
       
1699
    }
1700

    
1701
    /**
1702
     * Zooms in on a selected region.
1703
     *
1704
     * @param selection  the selected region.
1705
     */
1706
    public Range[] getRange(Rectangle2D selection) {
1707

    
1708
            Range[] rangos= new Range[2];
1709
            
1710
        // get the origin of the zoom selection in the Java2D space used for
1711
        // drawing the chart (that is, before any scaling to fit the panel)
1712
        Point2D selectOrigin = translateScreenToJava2D(new Point(
1713
                (int) Math.ceil(selection.getX()), 
1714
                (int) Math.ceil(selection.getY())));
1715
        PlotRenderingInfo plotInfo = this.info.getPlotInfo();
1716
        Rectangle2D scaledDataArea = getScreenDataArea(
1717
                (int) selection.getCenterX(), (int) selection.getCenterY());
1718
        if ((selection.getHeight() > 0) && (selection.getWidth() > 0)) {
1719

    
1720
            double hLower = (selection.getMinX() - scaledDataArea.getMinX()) 
1721
                / scaledDataArea.getWidth();
1722
            double hUpper = (selection.getMaxX() - scaledDataArea.getMinX()) 
1723
                / scaledDataArea.getWidth();
1724
            double vLower = (scaledDataArea.getMaxY() - selection.getMaxY()) 
1725
                / scaledDataArea.getHeight();
1726
            double vUpper = (scaledDataArea.getMaxY() - selection.getMinY()) 
1727
                / scaledDataArea.getHeight();
1728

    
1729
            Plot p = this.chart.getPlot();
1730
            if (p instanceof ScatterPlotChart) {
1731
              ScatterPlotChart z = (ScatterPlotChart) p;
1732
                if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
1733
                   rangos[0]= z.getRangeX(vLower, vUpper, plotInfo, selectOrigin);
1734
                    rangos[1]=z.getRangeY(hLower, hUpper, plotInfo, selectOrigin);
1735
                }
1736
                else {
1737
                        // devolver las coordenadas del rectangulo.
1738
                        rangos[0]=z.getRangeX(hLower, hUpper, plotInfo, selectOrigin);
1739
                        rangos[1]=z.getRangeY(vLower, vUpper, plotInfo, selectOrigin);
1740
                }
1741
            }
1742

    
1743
        }
1744

    
1745
        return rangos;
1746
    }
1747

    
1748
    /**
1749
     * Restores the auto-range calculation on both axes.
1750
     */
1751
    public void restoreAutoBounds() {
1752
        restoreAutoDomainBounds();
1753
        restoreAutoRangeBounds();
1754
    }
1755

    
1756
    /**
1757
     * Restores the auto-range calculation on the domain axis.
1758
     */
1759
    public void restoreAutoDomainBounds() {
1760
        Plot p = this.chart.getPlot();
1761
        if (p instanceof Zoomable) {
1762
            Zoomable z = (Zoomable) p;
1763
            // we need to guard against this.zoomPoint being null
1764
            Point zp = (this.zoomPoint != null ? this.zoomPoint : new Point());
1765
            z.zoomDomainAxes(0.0, this.info.getPlotInfo(), zp);
1766
        }
1767
    }
1768

    
1769
    /**
1770
     * Restores the auto-range calculation on the range axis.
1771
     */
1772
    public void restoreAutoRangeBounds() {
1773
        Plot p = this.chart.getPlot();
1774
        if (p instanceof Zoomable) {
1775
            Zoomable z = (Zoomable) p;
1776
            // we need to guard against this.zoomPoint being null
1777
            Point zp = (this.zoomPoint != null ? this.zoomPoint : new Point());
1778
            z.zoomRangeAxes(0.0, this.info.getPlotInfo(), zp);
1779
        }
1780
    }
1781

    
1782
    /**
1783
     * Returns the data area for the chart (the area inside the axes) with the
1784
     * current scaling applied (that is, the area as it appears on screen).
1785
     *
1786
     * @return The scaled data area.
1787
     */
1788
    public Rectangle2D getScreenDataArea() {
1789
        Rectangle2D dataArea = this.info.getPlotInfo().getDataArea();
1790
        Insets insets = getInsets();
1791
        double x = dataArea.getX() * this.scaleX + insets.left;
1792
        double y = dataArea.getY() * this.scaleY + insets.top;
1793
        double w = dataArea.getWidth() * this.scaleX;
1794
        double h = dataArea.getHeight() * this.scaleY;
1795
        return new Rectangle2D.Double(x, y, w, h);
1796
    }
1797
    
1798
    /**
1799
     * Returns the data area (the area inside the axes) for the plot or subplot,
1800
     * with the current scaling applied.
1801
     *
1802
     * @param x  the x-coordinate (for subplot selection).
1803
     * @param y  the y-coordinate (for subplot selection).
1804
     * 
1805
     * @return The scaled data area.
1806
     */
1807
    public Rectangle2D getScreenDataArea(int x, int y) {
1808
        PlotRenderingInfo plotInfo = this.info.getPlotInfo();
1809
        Rectangle2D result;
1810
        if (plotInfo.getSubplotCount() == 0) {
1811
            result = getScreenDataArea();
1812
        } 
1813
        else {
1814
            // get the origin of the zoom selection in the Java2D space used for
1815
            // drawing the chart (that is, before any scaling to fit the panel)
1816
            Point2D selectOrigin = translateScreenToJava2D(new Point(x, y));
1817
            int subplotIndex = plotInfo.getSubplotIndex(selectOrigin);
1818
            if (subplotIndex == -1) {
1819
                return null;
1820
            }
1821
            result = scale(plotInfo.getSubplotInfo(subplotIndex).getDataArea());
1822
        }
1823
        return result;
1824
    }
1825
    
1826
    /**
1827
     * Returns the initial tooltip delay value used inside this chart panel.
1828
     *
1829
     * @return An integer representing the initial delay value, in milliseconds.
1830
     * 
1831
     * @see javax.swing.ToolTipManager#getInitialDelay()
1832
     */
1833
    public int getInitialDelay() {
1834
        return this.ownToolTipInitialDelay;
1835
    }
1836
    
1837
    /**
1838
     * Returns the reshow tooltip delay value used inside this chart panel.
1839
     *
1840
     * @return An integer representing the reshow  delay value, in milliseconds.
1841
     * 
1842
     * @see javax.swing.ToolTipManager#getReshowDelay()
1843
     */
1844
    public int getReshowDelay() {
1845
        return this.ownToolTipReshowDelay;  
1846
    }
1847

    
1848
    /**
1849
     * Returns the dismissal tooltip delay value used inside this chart panel.
1850
     *
1851
     * @return An integer representing the dismissal delay value, in 
1852
     *         milliseconds.
1853
     * 
1854
     * @see javax.swing.ToolTipManager#getDismissDelay()
1855
     */
1856
    public int getDismissDelay() {
1857
        return this.ownToolTipDismissDelay; 
1858
    }
1859
    
1860
    /**
1861
     * Specifies the initial delay value for this chart panel.
1862
     *
1863
     * @param delay  the number of milliseconds to delay (after the cursor has 
1864
     *               paused) before displaying. 
1865
     * 
1866
     * @see javax.swing.ToolTipManager#setInitialDelay(int)
1867
     */
1868
    public void setInitialDelay(int delay) {
1869
        this.ownToolTipInitialDelay = delay;
1870
    }
1871
    
1872
    /**
1873
     * Specifies the amount of time before the user has to wait initialDelay 
1874
     * milliseconds before a tooltip will be shown.
1875
     *
1876
     * @param delay  time in milliseconds
1877
     * 
1878
     * @see javax.swing.ToolTipManager#setReshowDelay(int)
1879
     */
1880
    public void setReshowDelay(int delay) {
1881
        this.ownToolTipReshowDelay = delay;  
1882
    }
1883

    
1884
    /**
1885
     * Specifies the dismissal delay value for this chart panel.
1886
     *
1887
     * @param delay the number of milliseconds to delay before taking away the 
1888
     *              tooltip
1889
     * 
1890
     * @see javax.swing.ToolTipManager#setDismissDelay(int)
1891
     */
1892
    public void setDismissDelay(int delay) {
1893
        this.ownToolTipDismissDelay = delay; 
1894
    }
1895
    
1896
    /**
1897
     * Returns the zoom in factor.
1898
     * 
1899
     * @return The zoom in factor.
1900
     * 
1901
     * @see #setZoomInFactor(double)
1902
     */
1903
    public double getZoomInFactor() {
1904
        return this.zoomInFactor;   
1905
    }
1906
    
1907
    /**
1908
     * Sets the zoom in factor.
1909
     * 
1910
     * @param factor  the factor.
1911
     * 
1912
     * @see #getZoomInFactor()
1913
     */
1914
    public void setZoomInFactor(double factor) {
1915
        this.zoomInFactor = factor;
1916
    }
1917
    
1918
    /**
1919
     * Returns the zoom out factor.
1920
     * 
1921
     * @return The zoom out factor.
1922
     * 
1923
     * @see #setZoomOutFactor(double)
1924
     */
1925
    public double getZoomOutFactor() {
1926
        return this.zoomOutFactor;   
1927
    }
1928
    
1929
    /**
1930
     * Sets the zoom out factor.
1931
     * 
1932
     * @param factor  the factor.
1933
     * 
1934
     * @see #getZoomOutFactor()
1935
     */
1936
    public void setZoomOutFactor(double factor) {
1937
        this.zoomOutFactor = factor;
1938
    }
1939
    
1940
    /**
1941
     * Draws zoom rectangle (if present).
1942
     * The drawing is performed in XOR mode, therefore
1943
     * when this method is called twice in a row,
1944
     * the second call will completely restore the state
1945
     * of the canvas.
1946
     * 
1947
     * @param g2 the graphics device. 
1948
     */
1949
    private void drawZoomRectangle(Graphics2D g2) {
1950
        // Set XOR mode to draw the zoom rectangle
1951
        g2.setXORMode(Color.gray);
1952
        if (this.zoomRectangle != null) {
1953
            if (this.fillZoomRectangle) {
1954
                g2.fill(this.zoomRectangle);
1955
            }
1956
            else {
1957
                g2.draw(this.zoomRectangle);
1958
            }
1959
        }
1960
        // Reset to the default 'overwrite' mode
1961
        g2.setPaintMode();
1962
    }
1963
    
1964
    /**
1965
     * Draws a vertical line used to trace the mouse position to the horizontal 
1966
     * axis.
1967
     *
1968
     * @param g2 the graphics device.
1969
     * @param x  the x-coordinate of the trace line.
1970
     */
1971
    private void drawHorizontalAxisTrace(Graphics2D g2, int x) {
1972

    
1973
        Rectangle2D dataArea = getScreenDataArea();
1974

    
1975
        g2.setXORMode(Color.orange);
1976
        if (((int) dataArea.getMinX() < x) && (x < (int) dataArea.getMaxX())) {
1977

    
1978
            if (this.verticalTraceLine != null) {
1979
                g2.draw(this.verticalTraceLine);
1980
                this.verticalTraceLine.setLine(x, (int) dataArea.getMinY(), x, 
1981
                        (int) dataArea.getMaxY());
1982
            }
1983
            else {
1984
                this.verticalTraceLine = new Line2D.Float(x, 
1985
                        (int) dataArea.getMinY(), x, (int) dataArea.getMaxY());
1986
            }
1987
            g2.draw(this.verticalTraceLine);
1988
        }
1989

    
1990
        // Reset to the default 'overwrite' mode
1991
        g2.setPaintMode();
1992
    }
1993

    
1994
    /**
1995
     * Draws a horizontal line used to trace the mouse position to the vertical
1996
     * axis.
1997
     *
1998
     * @param g2 the graphics device.
1999
     * @param y  the y-coordinate of the trace line.
2000
     */
2001
    private void drawVerticalAxisTrace(Graphics2D g2, int y) {
2002

    
2003
        Rectangle2D dataArea = getScreenDataArea();
2004

    
2005
        g2.setXORMode(Color.orange);
2006
        if (((int) dataArea.getMinY() < y) && (y < (int) dataArea.getMaxY())) {
2007

    
2008
            if (this.horizontalTraceLine != null) {
2009
                g2.draw(this.horizontalTraceLine);
2010
                this.horizontalTraceLine.setLine((int) dataArea.getMinX(), y, 
2011
                        (int) dataArea.getMaxX(), y);
2012
            }
2013
            else {
2014
                this.horizontalTraceLine = new Line2D.Float(
2015
                        (int) dataArea.getMinX(), y, (int) dataArea.getMaxX(), 
2016
                        y);
2017
            }
2018
            g2.draw(this.horizontalTraceLine);
2019
        }
2020

    
2021
        // Reset to the default 'overwrite' mode
2022
        g2.setPaintMode();
2023
    }
2024

    
2025
    /**
2026
     * Displays a dialog that allows the user to edit the properties for the
2027
     * current chart.
2028
     * 
2029
     * @since 1.0.3
2030
     */
2031
    public void doEditChartProperties() {
2032

    
2033
      
2034
               
2035
               
2036
               /*ChartEditorManager.getChartEditor(this.chart);
2037
        int result = JOptionPane.showConfirmDialog(this, editor, 
2038
                localizationResources.getString("Chart_Properties"),
2039
                JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
2040
        if (result == JOptionPane.OK_OPTION) {
2041
            editor.updateChart(this.chart);
2042
        }
2043
*/
2044
    }
2045

    
2046
    /**
2047
     * Opens a file chooser and gives the user an opportunity to save the chart
2048
     * in PNG format.
2049
     *
2050
     * @throws IOException if there is an I/O error.
2051
     */
2052
    public void doSaveAs() throws IOException {
2053

    
2054
        JFileChooser fileChooser = new JFileChooser();
2055
        fileChooser.setCurrentDirectory(this.defaultDirectoryForSaveAs);
2056
        ExtensionFileFilter filter = new ExtensionFileFilter(
2057
                localizationResources.getString("PNG_Image_Files"), ".png");
2058
        fileChooser.addChoosableFileFilter(filter);
2059

    
2060
        int option = fileChooser.showSaveDialog(this);
2061
        if (option == JFileChooser.APPROVE_OPTION) {
2062
            String filename = fileChooser.getSelectedFile().getPath();
2063
            if (isEnforceFileExtensions()) {
2064
                if (!filename.endsWith(".png")) {
2065
                    filename = filename + ".png";
2066
                }
2067
            }
2068
            ChartUtilities.saveChartAsPNG(new File(filename), this.chart, 
2069
                    getWidth(), getHeight());
2070
        }
2071

    
2072
    }
2073

    
2074
    /**
2075
     * Creates a print job for the chart.
2076
     */
2077
    public void createChartPrintJob() {
2078

    
2079
        PrinterJob job = PrinterJob.getPrinterJob();
2080
        PageFormat pf = job.defaultPage();
2081
        PageFormat pf2 = job.pageDialog(pf);
2082
        if (pf2 != pf) {
2083
            job.setPrintable(this, pf2);
2084
            if (job.printDialog()) {
2085
                try {
2086
                    job.print();
2087
                }
2088
                catch (PrinterException e) {
2089
                    JOptionPane.showMessageDialog(this, e);
2090
                }
2091
            }
2092
        }
2093

    
2094
    }
2095

    
2096
    /**
2097
     * Prints the chart on a single page.
2098
     *
2099
     * @param g  the graphics context.
2100
     * @param pf  the page format to use.
2101
     * @param pageIndex  the index of the page. If not <code>0</code>, nothing 
2102
     *                   gets print.
2103
     *
2104
     * @return The result of printing.
2105
     */
2106
    public int print(Graphics g, PageFormat pf, int pageIndex) {
2107

    
2108
        if (pageIndex != 0) {
2109
            return NO_SUCH_PAGE;
2110
        }
2111
        Graphics2D g2 = (Graphics2D) g;
2112
        double x = pf.getImageableX();
2113
        double y = pf.getImageableY();
2114
        double w = pf.getImageableWidth();
2115
        double h = pf.getImageableHeight();
2116
        this.chart.draw(g2, new Rectangle2D.Double(x, y, w, h), this.anchor, 
2117
                null);
2118
        return PAGE_EXISTS;
2119

    
2120
    }
2121

    
2122
    /**
2123
     * Adds a listener to the list of objects listening for chart mouse events.
2124
     *
2125
     * @param listener  the listener (<code>null</code> not permitted).
2126
     */
2127
    public void addChartMouseListener(ChartMouseListener listener) {
2128
        if (listener == null) {
2129
            throw new IllegalArgumentException("Null 'listener' argument.");
2130
        }
2131
        this.chartMouseListeners.add(ChartMouseListener.class, listener);
2132
    }
2133

    
2134
    /**
2135
     * Removes a listener from the list of objects listening for chart mouse 
2136
     * events.
2137
     *
2138
     * @param listener  the listener.
2139
     */
2140
    public void removeChartMouseListener(ChartMouseListener listener) {
2141
        this.chartMouseListeners.remove(ChartMouseListener.class, listener);
2142
    }
2143

    
2144
    /**
2145
     * Returns an array of the listeners of the given type registered with the
2146
     * panel.
2147
     * 
2148
     * @param listenerType  the listener type.
2149
     * 
2150
     * @return An array of listeners.
2151
     */
2152
    public EventListener[] getListeners(Class listenerType) {
2153
        if (listenerType == ChartMouseListener.class) {
2154
            // fetch listeners from local storage
2155
            return this.chartMouseListeners.getListeners(listenerType);
2156
        }
2157
        else {
2158
            return super.getListeners(listenerType);
2159
        }
2160
    }
2161

    
2162
    /**
2163
     * Creates a popup menu for the panel.
2164
     *
2165
     * @param properties  include a menu item for the chart property editor.
2166
     * @param save  include a menu item for saving the chart.
2167
     * @param print  include a menu item for printing the chart.
2168
     * @param zoom  include menu items for zooming.
2169
     *
2170
     * @return The popup menu.
2171
     */
2172
    protected JPopupMenu createPopupMenu(boolean properties, 
2173
                                         boolean save, 
2174
                                         boolean print,
2175
                                         boolean zoom) {
2176

    
2177
        JPopupMenu result = new JPopupMenu("Chart:");
2178
        boolean separator = false;
2179

    
2180
        JMenuItem newClassItem = new JMenuItem( PluginServices.getText(this,"new_class"));
2181
        newClassItem.setActionCommand(NEW_CLASS_COMMAND);
2182
        newClassItem.addActionListener(this);
2183
        result.add(newClassItem);
2184
        separator = true;
2185
        
2186

    
2187
        JMenuItem newClassItem2 = new JMenuItem( PluginServices.getText(this,"clear_chart"));
2188
        newClassItem2.setActionCommand(CLEAR_CHART);
2189
        newClassItem2.addActionListener(this);
2190
        result.add(newClassItem2);
2191
        separator = true;
2192
        
2193
        
2194
        if (properties) {
2195
         
2196
        }
2197

    
2198
        if (save) {
2199
            if (separator) {
2200
                result.addSeparator();
2201
                separator = false;
2202
            }
2203
            JMenuItem saveItem = new JMenuItem(
2204
                    localizationResources.getString("Save_as..."));
2205
            saveItem.setActionCommand(SAVE_COMMAND);
2206
            saveItem.addActionListener(this);
2207
            result.add(saveItem);
2208
            separator = true;
2209
        }
2210

    
2211
        if (print) {
2212
            if (separator) {
2213
                result.addSeparator();
2214
                separator = false;
2215
            }
2216
            JMenuItem printItem = new JMenuItem(
2217
                    localizationResources.getString("Print..."));
2218
            printItem.setActionCommand(PRINT_COMMAND);
2219
            printItem.addActionListener(this);
2220
            result.add(printItem);
2221
            separator = true;
2222
        }
2223

    
2224
        if (zoom) {
2225
            if (separator) {
2226
                result.addSeparator();
2227
                separator = false;
2228
            }
2229

    
2230
            
2231
            
2232
            
2233
            
2234
            JMenu zoomInMenu = new JMenu(
2235
                    localizationResources.getString("Zoom_In"));
2236

    
2237
            this.zoomInBothMenuItem = new JMenuItem(
2238
                    localizationResources.getString("All_Axes"));
2239
            this.zoomInBothMenuItem.setActionCommand(ZOOM_IN_BOTH_COMMAND);
2240
            this.zoomInBothMenuItem.addActionListener(this);
2241
            zoomInMenu.add(this.zoomInBothMenuItem);
2242

    
2243
            zoomInMenu.addSeparator();
2244

    
2245
            this.zoomInDomainMenuItem = new JMenuItem(
2246
                    localizationResources.getString("Domain_Axis"));
2247
            this.zoomInDomainMenuItem.setActionCommand(ZOOM_IN_DOMAIN_COMMAND);
2248
            this.zoomInDomainMenuItem.addActionListener(this);
2249
            zoomInMenu.add(this.zoomInDomainMenuItem);
2250

    
2251
            this.zoomInRangeMenuItem = new JMenuItem(
2252
                    localizationResources.getString("Range_Axis"));
2253
            this.zoomInRangeMenuItem.setActionCommand(ZOOM_IN_RANGE_COMMAND);
2254
            this.zoomInRangeMenuItem.addActionListener(this);
2255
            zoomInMenu.add(this.zoomInRangeMenuItem);
2256

    
2257
            result.add(zoomInMenu);
2258

    
2259
            JMenu zoomOutMenu = new JMenu(
2260
                    localizationResources.getString("Zoom_Out"));
2261

    
2262
            this.zoomOutBothMenuItem = new JMenuItem(
2263
                    localizationResources.getString("All_Axes"));
2264
            this.zoomOutBothMenuItem.setActionCommand(ZOOM_OUT_BOTH_COMMAND);
2265
            this.zoomOutBothMenuItem.addActionListener(this);
2266
            zoomOutMenu.add(this.zoomOutBothMenuItem);
2267

    
2268
            zoomOutMenu.addSeparator();
2269

    
2270
            this.zoomOutDomainMenuItem = new JMenuItem(
2271
                    localizationResources.getString("Domain_Axis"));
2272
            this.zoomOutDomainMenuItem.setActionCommand(
2273
                    ZOOM_OUT_DOMAIN_COMMAND);
2274
            this.zoomOutDomainMenuItem.addActionListener(this);
2275
            zoomOutMenu.add(this.zoomOutDomainMenuItem);
2276

    
2277
            this.zoomOutRangeMenuItem = new JMenuItem(
2278
                    localizationResources.getString("Range_Axis"));
2279
            this.zoomOutRangeMenuItem.setActionCommand(ZOOM_OUT_RANGE_COMMAND);
2280
            this.zoomOutRangeMenuItem.addActionListener(this);
2281
            zoomOutMenu.add(this.zoomOutRangeMenuItem);
2282

    
2283
            result.add(zoomOutMenu);
2284

    
2285
            JMenu autoRangeMenu = new JMenu(
2286
                    localizationResources.getString("Auto_Range"));
2287

    
2288
            this.zoomResetBothMenuItem = new JMenuItem(
2289
                    localizationResources.getString("All_Axes"));
2290
            this.zoomResetBothMenuItem.setActionCommand(
2291
                    ZOOM_RESET_BOTH_COMMAND);
2292
            this.zoomResetBothMenuItem.addActionListener(this);
2293
            autoRangeMenu.add(this.zoomResetBothMenuItem);
2294

    
2295
            autoRangeMenu.addSeparator();
2296
            this.zoomResetDomainMenuItem = new JMenuItem(
2297
                    localizationResources.getString("Domain_Axis"));
2298
            this.zoomResetDomainMenuItem.setActionCommand(
2299
                    ZOOM_RESET_DOMAIN_COMMAND);
2300
            this.zoomResetDomainMenuItem.addActionListener(this);
2301
            autoRangeMenu.add(this.zoomResetDomainMenuItem);
2302

    
2303
            this.zoomResetRangeMenuItem = new JMenuItem(
2304
                    localizationResources.getString("Range_Axis"));
2305
            this.zoomResetRangeMenuItem.setActionCommand(
2306
                    ZOOM_RESET_RANGE_COMMAND);
2307
            this.zoomResetRangeMenuItem.addActionListener(this);
2308
            autoRangeMenu.add(this.zoomResetRangeMenuItem);
2309

    
2310
            result.addSeparator();
2311
            result.add(autoRangeMenu);
2312

    
2313
        }
2314

    
2315
        return result;
2316

    
2317
    }
2318

    
2319
    /**
2320
     * The idea is to modify the zooming options depending on the type of chart 
2321
     * being displayed by the panel.
2322
     *
2323
     * @param x  horizontal position of the popup.
2324
     * @param y  vertical position of the popup.
2325
     */
2326
    protected void displayPopupMenu(int x, int y) {
2327

    
2328
        if (this.popup != null) {
2329

    
2330
            // go through each zoom menu item and decide whether or not to 
2331
            // enable it...
2332
            Plot plot = this.chart.getPlot();
2333
            boolean isDomainZoomable = false;
2334
            boolean isRangeZoomable = false;
2335
            if (plot instanceof Zoomable) {
2336
                Zoomable z = (Zoomable) plot;
2337
                isDomainZoomable = z.isDomainZoomable();
2338
                isRangeZoomable = z.isRangeZoomable();
2339
            }
2340
            
2341
            if (this.zoomInDomainMenuItem != null) {
2342
                this.zoomInDomainMenuItem.setEnabled(isDomainZoomable);
2343
            }
2344
            if (this.zoomOutDomainMenuItem != null) {
2345
                this.zoomOutDomainMenuItem.setEnabled(isDomainZoomable);
2346
            } 
2347
            if (this.zoomResetDomainMenuItem != null) {
2348
                this.zoomResetDomainMenuItem.setEnabled(isDomainZoomable);
2349
            }
2350

    
2351
            if (this.zoomInRangeMenuItem != null) {
2352
                this.zoomInRangeMenuItem.setEnabled(isRangeZoomable);
2353
            }
2354
            if (this.zoomOutRangeMenuItem != null) {
2355
                this.zoomOutRangeMenuItem.setEnabled(isRangeZoomable);
2356
            }
2357

    
2358
            if (this.zoomResetRangeMenuItem != null) {
2359
                this.zoomResetRangeMenuItem.setEnabled(isRangeZoomable);
2360
            }
2361

    
2362
            if (this.zoomInBothMenuItem != null) {
2363
                this.zoomInBothMenuItem.setEnabled(isDomainZoomable 
2364
                        && isRangeZoomable);
2365
            }
2366
            if (this.zoomOutBothMenuItem != null) {
2367
                this.zoomOutBothMenuItem.setEnabled(isDomainZoomable 
2368
                        && isRangeZoomable);
2369
            }
2370
            if (this.zoomResetBothMenuItem != null) {
2371
                this.zoomResetBothMenuItem.setEnabled(isDomainZoomable 
2372
                        && isRangeZoomable);
2373
            }
2374

    
2375
           // updateUI();
2376
            this.popup.show(this, x, y);
2377
           
2378
          
2379
        }
2380

    
2381
    }
2382
    
2383
    
2384
    /* (non-Javadoc)
2385
     * @see javax.swing.JPanel#updateUI()
2386
     */
2387
    public void updateUI() {
2388
        // here we need to update the UI for the popup menu, if the panel
2389
        // has one...
2390
        if (this.popup != null) {
2391
            SwingUtilities.updateComponentTreeUI(this.popup);
2392
        }
2393
        super.updateUI();
2394
      
2395
          
2396
    }
2397
    
2398
    
2399
    // Devuelve la lista de ROIs definidas sobre el grafico.
2400
    public ROIChartList getROIChartList(){
2401
            return roiList;
2402
    }
2403
    
2404
    
2405
    // Borra una ROI del grafico (con todas las geometrias asociadas)
2406
    public void clearROIChart(int index){
2407
            roiList.deleteROI(index);
2408
    }
2409
    
2410
    
2411
    /**Pinta la lista de ROis Visibles sobre el grafico*/
2412
    public void drawsROIs(Graphics2D g2){
2413
            
2414
            Iterator iterator= roiList.getListRois().iterator();
2415
            ROIChart roiDraw=null;
2416
            while(iterator.hasNext()){
2417
                    roiDraw= (ROIChart)iterator.next();
2418
                    if(roiDraw.shapeList.size()>0)
2419
                            g2.setPaint(roiDraw.getColor());
2420
                            for(int i=0; i<roiDraw.shapeList.size(); i++){
2421
                                    g2.draw((Shape)roiDraw.shapeList.get(i));
2422
                 }
2423
            }
2424
    //  g2.setTransform(saved);
2425
            
2426
    }
2427
    
2428
    public void cleanChart(){
2429
            
2430
            
2431
    }
2432
    
2433

    
2434
}
2435