KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > plot > ContourPlot


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this library; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
24  * in the United States and other countries.]
25  *
26  * ----------------
27  * ContourPlot.java
28  * ----------------
29  * (C) Copyright 2002-2005, by David M. O'Donnell and Contributors.
30  *
31  * Original Author: David M. O'Donnell;
32  * Contributor(s): David Gilbert (for Object Refinery Limited);
33  * Arnaud Lelievre;
34  * Nicolas Brodu;
35  *
36  * $Id: ContourPlot.java,v 1.16 2005/05/19 14:03:41 mungady Exp $
37  *
38  * Changes
39  * -------
40  * 26-Nov-2002 : Version 1 contributed by David M. O'Donnell (DG);
41  * 14-Jan-2003 : Added crosshair attributes (DG);
42  * 23-Jan-2003 : Removed two constructors (DG);
43  * 21-Mar-2003 : Bug fix 701744 (DG);
44  * 26-Mar-2003 : Implemented Serializable (DG);
45  * 09-Jul-2003 : Changed ColorBar from extending axis classes to enclosing
46  * them (DG);
47  * 05-Aug-2003 : Applied changes in bug report 780298 (DG);
48  * 08-Sep-2003 : Added internationalization via use of properties
49  * resourceBundle (RFE 690236) (AL);
50  * 11-Sep-2003 : Cloning support (NB);
51  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
52  * 17-Jan-2004 : Removed references to DefaultContourDataset class, replaced
53  * with ContourDataset interface (with changes to the interface).
54  * See bug 741048 (DG);
55  * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
56  * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG);
57  * 06-Oct-2004 : Updated for changes in DatasetUtilities class (DG);
58  * 11-Nov-2004 : Renamed zoom methods to match ValueAxisPlot interface (DG);
59  * 25-Nov-2004 : Small update to clone() implementation (DG);
60  * 11-Jan-2005 : Removed deprecated code in preparation for 1.0.0 release (DG);
61  * 05-May-2005 : Updated draw() method parameters (DG);
62  *
63  */

64
65 package org.jfree.chart.plot;
66
67 import java.awt.AlphaComposite JavaDoc;
68 import java.awt.Composite JavaDoc;
69 import java.awt.Graphics2D JavaDoc;
70 import java.awt.Paint JavaDoc;
71 import java.awt.RenderingHints JavaDoc;
72 import java.awt.Shape JavaDoc;
73 import java.awt.Stroke JavaDoc;
74 import java.awt.geom.Ellipse2D JavaDoc;
75 import java.awt.geom.GeneralPath JavaDoc;
76 import java.awt.geom.Line2D JavaDoc;
77 import java.awt.geom.Point2D JavaDoc;
78 import java.awt.geom.Rectangle2D JavaDoc;
79 import java.awt.geom.RectangularShape JavaDoc;
80 import java.beans.PropertyChangeEvent JavaDoc;
81 import java.beans.PropertyChangeListener JavaDoc;
82 import java.io.Serializable JavaDoc;
83 import java.util.Iterator JavaDoc;
84 import java.util.List JavaDoc;
85 import java.util.ResourceBundle JavaDoc;
86
87 import org.jfree.chart.ClipPath;
88 import org.jfree.chart.annotations.XYAnnotation;
89 import org.jfree.chart.axis.AxisSpace;
90 import org.jfree.chart.axis.ColorBar;
91 import org.jfree.chart.axis.NumberAxis;
92 import org.jfree.chart.axis.ValueAxis;
93 import org.jfree.chart.entity.ContourEntity;
94 import org.jfree.chart.entity.EntityCollection;
95 import org.jfree.chart.event.AxisChangeEvent;
96 import org.jfree.chart.event.PlotChangeEvent;
97 import org.jfree.chart.labels.ContourToolTipGenerator;
98 import org.jfree.chart.labels.StandardContourToolTipGenerator;
99 import org.jfree.chart.urls.XYURLGenerator;
100 import org.jfree.data.Range;
101 import org.jfree.data.contour.ContourDataset;
102 import org.jfree.data.general.DatasetChangeEvent;
103 import org.jfree.data.general.DatasetUtilities;
104 import org.jfree.ui.RectangleEdge;
105 import org.jfree.ui.RectangleInsets;
106 import org.jfree.util.ObjectUtilities;
107
108 /**
109  * A class for creating shaded contours.
110  *
111  * @author David M. O'Donnell
112  */

113 public class ContourPlot extends Plot implements ContourValuePlot,
114                                                  ValueAxisPlot,
115                                                  PropertyChangeListener JavaDoc,
116                                                  Serializable JavaDoc,
117                                                  Cloneable JavaDoc {
118
119     /** For serialization. */
120     private static final long serialVersionUID = 7861072556590502247L;
121     
122     /** The default insets. */
123     protected static final RectangleInsets DEFAULT_INSETS
124         = new RectangleInsets(2.0, 2.0, 100.0, 10.0);
125
126     /** The domain axis (used for the x-values). */
127     private ValueAxis domainAxis;
128
129     /** The range axis (used for the y-values). */
130     private ValueAxis rangeAxis;
131
132     /** The dataset. */
133     private ContourDataset dataset;
134     
135     /** The colorbar axis (used for the z-values). */
136     private ColorBar colorBar = null;
137
138     /** The color bar location. */
139     private RectangleEdge colorBarLocation;
140     
141     /** A flag that controls whether or not a domain crosshair is drawn..*/
142     private boolean domainCrosshairVisible;
143
144     /** The domain crosshair value. */
145     private double domainCrosshairValue;
146
147     /** The pen/brush used to draw the crosshair (if any). */
148     private transient Stroke JavaDoc domainCrosshairStroke;
149
150     /** The color used to draw the crosshair (if any). */
151     private transient Paint JavaDoc domainCrosshairPaint;
152
153     /**
154      * A flag that controls whether or not the crosshair locks onto actual data
155      * points.
156      */

157     private boolean domainCrosshairLockedOnData = true;
158
159     /** A flag that controls whether or not a range crosshair is drawn..*/
160     private boolean rangeCrosshairVisible;
161
162     /** The range crosshair value. */
163     private double rangeCrosshairValue;
164
165     /** The pen/brush used to draw the crosshair (if any). */
166     private transient Stroke JavaDoc rangeCrosshairStroke;
167
168     /** The color used to draw the crosshair (if any). */
169     private transient Paint JavaDoc rangeCrosshairPaint;
170
171     /**
172      * A flag that controls whether or not the crosshair locks onto actual data
173      * points.
174      */

175     private boolean rangeCrosshairLockedOnData = true;
176
177     /** A list of markers (optional) for the domain axis. */
178     private List JavaDoc domainMarkers;
179
180     /** A list of markers (optional) for the range axis. */
181     private List JavaDoc rangeMarkers;
182
183     /** A list of annotations (optional) for the plot. */
184     private List JavaDoc annotations;
185
186     /** The tool tip generator. */
187     private ContourToolTipGenerator toolTipGenerator;
188
189     /** The URL text generator. */
190     private XYURLGenerator urlGenerator;
191
192     /**
193      * Controls whether data are render as filled rectangles or rendered as
194      * points
195      */

196     private boolean renderAsPoints = false;
197
198     /**
199      * Size of points rendered when renderAsPoints = true. Size is relative to
200      * dataArea
201      */

202     private double ptSizePct = 0.05;
203
204     /** Contains the a ClipPath to "trim" the contours. */
205     private transient ClipPath clipPath = null;
206
207     /** Set to Paint to represent missing values. */
208     private transient Paint JavaDoc missingPaint = null;
209
210     /** The resourceBundle for the localization. */
211     protected static ResourceBundle JavaDoc localizationResources =
212         ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
213
214     /**
215      * Constructs a contour plot with the specified axes (other attributes take
216      * default values).
217      *
218      * @param dataset The dataset.
219      * @param domainAxis The domain axis.
220      * @param rangeAxis The range axis.
221      * @param colorBar The z-axis axis.
222     */

223     public ContourPlot(ContourDataset dataset,
224                        ValueAxis domainAxis, ValueAxis rangeAxis,
225                        ColorBar colorBar) {
226
227         super();
228
229         this.dataset = dataset;
230         if (dataset != null) {
231             dataset.addChangeListener(this);
232         }
233         
234         this.domainAxis = domainAxis;
235         if (domainAxis != null) {
236             domainAxis.setPlot(this);
237             domainAxis.addChangeListener(this);
238         }
239
240         this.rangeAxis = rangeAxis;
241         if (rangeAxis != null) {
242             rangeAxis.setPlot(this);
243             rangeAxis.addChangeListener(this);
244         }
245
246         this.colorBar = colorBar;
247         if (colorBar != null) {
248             colorBar.getAxis().setPlot(this);
249             colorBar.getAxis().addChangeListener(this);
250             colorBar.configure(this);
251         }
252         this.colorBarLocation = RectangleEdge.LEFT;
253
254         this.toolTipGenerator = new StandardContourToolTipGenerator();
255
256     }
257
258     /**
259      * Returns the color bar location.
260      *
261      * @return The color bar location.
262      */

263     public RectangleEdge getColorBarLocation() {
264         return this.colorBarLocation;
265     }
266     
267     /**
268      * Sets the color bar location and sends a {@link PlotChangeEvent} to all
269      * registered listeners.
270      *
271      * @param edge the location.
272      */

273     public void setColorBarLocation(RectangleEdge edge) {
274         this.colorBarLocation = edge;
275         notifyListeners(new PlotChangeEvent(this));
276     }
277     
278     /**
279      * Returns the primary dataset for the plot.
280      *
281      * @return The primary dataset (possibly <code>null</code>).
282      */

283     public ContourDataset getDataset() {
284         return this.dataset;
285     }
286     
287     /**
288      * Sets the dataset for the plot, replacing the existing dataset if there
289      * is one.
290      *
291      * @param dataset the dataset (<code>null</code> permitted).
292      */

293     public void setDataset(ContourDataset dataset) {
294         
295         // if there is an existing dataset, remove the plot from the list of
296
// change listeners...
297
ContourDataset existing = this.dataset;
298         if (existing != null) {
299             existing.removeChangeListener(this);
300         }
301
302         // set the new dataset, and register the chart as a change listener...
303
this.dataset = dataset;
304         if (dataset != null) {
305             setDatasetGroup(dataset.getGroup());
306             dataset.addChangeListener(this);
307         }
308
309         // send a dataset change event to self...
310
DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
311         datasetChanged(event);
312         
313     }
314
315     /**
316      * Returns the domain axis for the plot.
317      *
318      * @return The domain axis.
319      */

320     public ValueAxis getDomainAxis() {
321
322         ValueAxis result = this.domainAxis;
323
324         return result;
325
326     }
327
328     /**
329      * Sets the domain axis for the plot (this must be compatible with the plot
330      * type or an exception is thrown).
331      *
332      * @param axis The new axis.
333      */

334     public void setDomainAxis(ValueAxis axis) {
335
336         if (isCompatibleDomainAxis(axis)) {
337
338             if (axis != null) {
339                 axis.setPlot(this);
340                 axis.addChangeListener(this);
341             }
342
343             // plot is likely registered as a listener with the existing axis...
344
if (this.domainAxis != null) {
345                 this.domainAxis.removeChangeListener(this);
346             }
347
348             this.domainAxis = axis;
349             notifyListeners(new PlotChangeEvent(this));
350
351         }
352
353     }
354
355     /**
356      * Returns the range axis for the plot.
357      *
358      * @return The range axis.
359      */

360     public ValueAxis getRangeAxis() {
361
362         ValueAxis result = this.rangeAxis;
363
364         return result;
365
366     }
367
368     /**
369      * Sets the range axis for the plot.
370      * <P>
371      * An exception is thrown if the new axis and the plot are not mutually
372      * compatible.
373      *
374      * @param axis The new axis (null permitted).
375      */

376     public void setRangeAxis(ValueAxis axis) {
377
378         if (axis != null) {
379             axis.setPlot(this);
380             axis.addChangeListener(this);
381         }
382
383         // plot is likely registered as a listener with the existing axis...
384
if (this.rangeAxis != null) {
385             this.rangeAxis.removeChangeListener(this);
386         }
387
388         this.rangeAxis = axis;
389         notifyListeners(new PlotChangeEvent(this));
390
391     }
392
393     /**
394      * Sets the colorbar for the plot.
395      *
396      * @param axis The new axis (null permitted).
397      */

398     public void setColorBarAxis(ColorBar axis) {
399
400         this.colorBar = axis;
401         notifyListeners(new PlotChangeEvent(this));
402
403     }
404
405     /**
406      * Adds a marker for the domain axis.
407      * <P>
408      * Typically a marker will be drawn by the renderer as a line perpendicular
409      * to the range axis, however this is entirely up to the renderer.
410      *
411      * @param marker the marker.
412      */

413     public void addDomainMarker(Marker marker) {
414
415         if (this.domainMarkers == null) {
416             this.domainMarkers = new java.util.ArrayList JavaDoc();
417         }
418         this.domainMarkers.add(marker);
419         notifyListeners(new PlotChangeEvent(this));
420
421     }
422
423     /**
424      * Clears all the domain markers.
425      */

426     public void clearDomainMarkers() {
427         if (this.domainMarkers != null) {
428             this.domainMarkers.clear();
429             notifyListeners(new PlotChangeEvent(this));
430         }
431     }
432
433     /**
434      * Adds a marker for the range axis.
435      * <P>
436      * Typically a marker will be drawn by the renderer as a line perpendicular
437      * to the range axis, however this is entirely up to the renderer.
438      *
439      * @param marker The marker.
440      */

441     public void addRangeMarker(Marker marker) {
442
443         if (this.rangeMarkers == null) {
444             this.rangeMarkers = new java.util.ArrayList JavaDoc();
445         }
446         this.rangeMarkers.add(marker);
447         notifyListeners(new PlotChangeEvent(this));
448
449     }
450
451     /**
452      * Clears all the range markers.
453      */

454     public void clearRangeMarkers() {
455         if (this.rangeMarkers != null) {
456             this.rangeMarkers.clear();
457             notifyListeners(new PlotChangeEvent(this));
458         }
459     }
460
461     /**
462      * Adds an annotation to the plot.
463      *
464      * @param annotation the annotation.
465      */

466     public void addAnnotation(XYAnnotation annotation) {
467
468         if (this.annotations == null) {
469             this.annotations = new java.util.ArrayList JavaDoc();
470         }
471         this.annotations.add(annotation);
472         notifyListeners(new PlotChangeEvent(this));
473
474     }
475
476     /**
477      * Clears all the annotations.
478      */

479     public void clearAnnotations() {
480         if (this.annotations != null) {
481             this.annotations.clear();
482             notifyListeners(new PlotChangeEvent(this));
483         }
484     }
485
486     /**
487      * Checks the compatibility of a domain axis, returning true if the axis is
488      * compatible with the plot, and false otherwise.
489      *
490      * @param axis The proposed axis.
491      *
492      * @return <code>true</code> if the axis is compatible with the plot.
493      */

494     public boolean isCompatibleDomainAxis(ValueAxis axis) {
495
496         return true;
497
498     }
499
500     /**
501      * Draws the plot on a Java 2D graphics device (such as the screen or a
502      * printer).
503      * <P>
504      * The optional <code>info</code> argument collects information about the
505      * rendering of the plot (dimensions, tooltip information etc). Just pass
506      * in <code>null</code> if you do not need this information.
507      *
508      * @param g2 the graphics device.
509      * @param area the area within which the plot (including axis labels)
510      * should be drawn.
511      * @param anchor the anchor point (<code>null</code> permitted).
512      * @param parentState the state from the parent plot, if there is one.
513      * @param info collects chart drawing information (<code>null</code>
514      * permitted).
515      */

516     public void draw(Graphics2D JavaDoc g2, Rectangle2D JavaDoc area, Point2D JavaDoc anchor,
517                      PlotState parentState,
518                      PlotRenderingInfo info) {
519
520         // if the plot area is too small, just return...
521
boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
522         boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
523         if (b1 || b2) {
524             return;
525         }
526
527         // record the plot area...
528
if (info != null) {
529             info.setPlotArea(area);
530         }
531
532         // adjust the drawing area for plot insets (if any)...
533
RectangleInsets insets = getInsets();
534         insets.trim(area);
535
536         AxisSpace space = new AxisSpace();
537         
538         space = this.domainAxis.reserveSpace(
539             g2, this, area, RectangleEdge.BOTTOM, space
540         );
541         space = this.rangeAxis.reserveSpace(
542             g2, this, area, RectangleEdge.LEFT, space
543         );
544
545         Rectangle2D JavaDoc estimatedDataArea = space.shrink(area, null);
546         
547         AxisSpace space2 = new AxisSpace();
548         space2 = this.colorBar.reserveSpace(
549             g2, this, area, estimatedDataArea, this.colorBarLocation,
550             space2
551         );
552         Rectangle2D JavaDoc adjustedPlotArea = space2.shrink(area, null);
553         
554         Rectangle2D JavaDoc dataArea = space.shrink(adjustedPlotArea, null);
555
556         Rectangle2D JavaDoc colorBarArea = space2.reserved(
557             area, this.colorBarLocation
558         );
559
560         // additional dataArea modifications
561
if (getDataAreaRatio() != 0.0) { //check whether modification is
562
double ratio = getDataAreaRatio();
563             Rectangle2D JavaDoc tmpDataArea = (Rectangle2D JavaDoc) dataArea.clone();
564             double h = tmpDataArea.getHeight();
565             double w = tmpDataArea.getWidth();
566
567             if (ratio > 0) { // ratio represents pixels
568
if (w * ratio <= h) {
569                     h = ratio * w;
570                 }
571                 else {
572                     w = h / ratio;
573                 }
574             }
575             else { // ratio represents axis units
576
ratio *= -1.0;
577                 double xLength = getDomainAxis().getRange().getLength();
578                 double yLength = getRangeAxis().getRange().getLength();
579                 double unitRatio = yLength / xLength;
580
581                 ratio = unitRatio * ratio;
582
583                 if (w * ratio <= h) {
584                     h = ratio * w;
585                 }
586                 else {
587                     w = h / ratio;
588                 }
589             }
590
591             dataArea.setRect(
592                 tmpDataArea.getX() + tmpDataArea.getWidth() / 2 - w / 2,
593                 tmpDataArea.getY(), w, h
594             );
595         }
596
597         if (info != null) {
598             info.setDataArea(dataArea);
599         }
600
601         CrosshairState crosshairState = new CrosshairState();
602         crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY);
603
604         // draw the plot background...
605
drawBackground(g2, dataArea);
606
607         double cursor = dataArea.getMaxY();
608         if (this.domainAxis != null) {
609             this.domainAxis.draw(
610                 g2, cursor, adjustedPlotArea, dataArea, RectangleEdge.BOTTOM,
611                 info
612             );
613         }
614
615         if (this.rangeAxis != null) {
616             cursor = dataArea.getMinX();
617             this.rangeAxis.draw(
618                 g2, cursor, adjustedPlotArea, dataArea, RectangleEdge.LEFT, info
619             );
620         }
621
622         if (this.colorBar != null) {
623             cursor = 0.0;
624             cursor = this.colorBar.draw(
625                 g2, cursor, adjustedPlotArea, dataArea, colorBarArea,
626                 this.colorBarLocation
627             );
628         }
629         Shape JavaDoc originalClip = g2.getClip();
630         Composite JavaDoc originalComposite = g2.getComposite();
631
632         g2.clip(dataArea);
633         g2.setComposite(AlphaComposite.getInstance(
634             AlphaComposite.SRC_OVER, getForegroundAlpha())
635         );
636         render(g2, dataArea, info, crosshairState);
637
638         if (this.domainMarkers != null) {
639             Iterator JavaDoc iterator = this.domainMarkers.iterator();
640             while (iterator.hasNext()) {
641                 Marker marker = (Marker) iterator.next();
642                 drawDomainMarker(g2, this, getDomainAxis(), marker, dataArea);
643             }
644         }
645
646         if (this.rangeMarkers != null) {
647             Iterator JavaDoc iterator = this.rangeMarkers.iterator();
648             while (iterator.hasNext()) {
649                 Marker marker = (Marker) iterator.next();
650                 drawRangeMarker(g2, this, getRangeAxis(), marker, dataArea);
651             }
652         }
653
654 // TO DO: these annotations only work with XYPlot, see if it is possible to
655
// make ContourPlot a subclass of XYPlot (DG);
656

657 // // draw the annotations...
658
// if (this.annotations != null) {
659
// Iterator iterator = this.annotations.iterator();
660
// while (iterator.hasNext()) {
661
// Annotation annotation = (Annotation) iterator.next();
662
// if (annotation instanceof XYAnnotation) {
663
// XYAnnotation xya = (XYAnnotation) annotation;
664
// // get the annotation to draw itself...
665
// xya.draw(g2, this, dataArea, getDomainAxis(),
666
// getRangeAxis());
667
// }
668
// }
669
// }
670

671         g2.setClip(originalClip);
672         g2.setComposite(originalComposite);
673         drawOutline(g2, dataArea);
674
675     }
676
677     /**
678      * Draws a representation of the data within the dataArea region, using the
679      * current renderer.
680      * <P>
681      * The <code>info</code> and <code>crosshairState</code> arguments may be
682      * <code>null</code>.
683      *
684      * @param g2 the graphics device.
685      * @param dataArea the region in which the data is to be drawn.
686      * @param info an optional object for collection dimension information.
687      * @param crosshairState an optional object for collecting crosshair info.
688      */

689     public void render(Graphics2D JavaDoc g2, Rectangle2D JavaDoc dataArea,
690                        PlotRenderingInfo info, CrosshairState crosshairState) {
691
692         // now get the data and plot it (the visual representation will depend
693
// on the renderer that has been set)...
694
ContourDataset data = getDataset();
695         if (data != null) {
696
697             ColorBar zAxis = getColorBar();
698
699             if (this.clipPath != null) {
700                 GeneralPath JavaDoc clipper = getClipPath().draw(
701                     g2, dataArea, this.domainAxis, this.rangeAxis
702                 );
703                 if (this.clipPath.isClip()) {
704                     g2.clip(clipper);
705                 }
706             }
707
708             if (this.renderAsPoints) {
709                 pointRenderer(g2, dataArea, info, this,
710                         this.domainAxis, this.rangeAxis, zAxis,
711                               data, crosshairState);
712             }
713             else {
714                 contourRenderer(g2, dataArea, info, this,
715                         this.domainAxis, this.rangeAxis, zAxis,
716                                 data, crosshairState);
717             }
718
719             // draw vertical crosshair if required...
720
setDomainCrosshairValue(crosshairState.getCrosshairX(), false);
721             if (isDomainCrosshairVisible()) {
722                 drawVerticalLine(g2, dataArea,
723                                  getDomainCrosshairValue(),
724                                  getDomainCrosshairStroke(),
725                                  getDomainCrosshairPaint());
726             }
727
728             // draw horizontal crosshair if required...
729
setRangeCrosshairValue(crosshairState.getCrosshairY(), false);
730             if (isRangeCrosshairVisible()) {
731                 drawHorizontalLine(g2, dataArea,
732                                    getRangeCrosshairValue(),
733                                    getRangeCrosshairStroke(),
734                                    getRangeCrosshairPaint());
735             }
736
737         }
738         else if (this.clipPath != null) {
739             getClipPath().draw(g2, dataArea, this.domainAxis, this.rangeAxis);
740         }
741
742     }
743
744     /**
745      * Fills the plot.
746      *
747      * @param g2 the graphics device.
748      * @param dataArea the area within which the data is being drawn.
749      * @param info collects information about the drawing.
750      * @param plot the plot (can be used to obtain standard color
751      * information etc).
752      * @param horizontalAxis the domain (horizontal) axis.
753      * @param verticalAxis the range (vertical) axis.
754      * @param colorBar the color bar axis.
755      * @param data the dataset.
756      * @param crosshairState information about crosshairs on a plot.
757      */

758     public void contourRenderer(Graphics2D JavaDoc g2,
759                                 Rectangle2D JavaDoc dataArea,
760                                 PlotRenderingInfo info,
761                                 ContourPlot plot,
762                                 ValueAxis horizontalAxis,
763                                 ValueAxis verticalAxis,
764                                 ColorBar colorBar,
765                                 ContourDataset data,
766                                 CrosshairState crosshairState) {
767
768         // setup for collecting optional entity info...
769
Rectangle2D.Double JavaDoc entityArea = null;
770         EntityCollection entities = null;
771         if (info != null) {
772             entities = info.getOwner().getEntityCollection();
773         }
774
775         Rectangle2D.Double JavaDoc rect = null;
776         rect = new Rectangle2D.Double JavaDoc();
777
778         //turn off anti-aliasing when filling rectangles
779
Object JavaDoc antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
780         g2.setRenderingHint(
781             RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF
782         );
783
784         // get the data points
785
Number JavaDoc[] xNumber = data.getXValues();
786         Number JavaDoc[] yNumber = data.getYValues();
787         Number JavaDoc[] zNumber = data.getZValues();
788
789         double[] x = new double[xNumber.length];
790         double[] y = new double[yNumber.length];
791
792         for (int i = 0; i < x.length; i++) {
793             x[i] = xNumber[i].doubleValue();
794             y[i] = yNumber[i].doubleValue();
795         }
796
797         int[] xIndex = data.indexX();
798         int[] indexX = data.getXIndices();
799         boolean vertInverted = ((NumberAxis) verticalAxis).isInverted();
800         boolean horizInverted = false;
801         if (horizontalAxis instanceof NumberAxis) {
802             horizInverted = ((NumberAxis) horizontalAxis).isInverted();
803         }
804         double transX = 0.0;
805         double transXm1 = 0.0;
806         double transXp1 = 0.0;
807         double transDXm1 = 0.0;
808         double transDXp1 = 0.0;
809         double transDX = 0.0;
810         double transY = 0.0;
811         double transYm1 = 0.0;
812         double transYp1 = 0.0;
813         double transDYm1 = 0.0;
814         double transDYp1 = 0.0;
815         double transDY = 0.0;
816         int iMax = xIndex[xIndex.length - 1];
817         for (int k = 0; k < x.length; k++) {
818             int i = xIndex[k];
819             if (indexX[i] == k) { // this is a new column
820
if (i == 0) {
821                     transX = horizontalAxis.valueToJava2D(
822                         x[k], dataArea, RectangleEdge.BOTTOM
823                     );
824                     transXm1 = transX;
825                     transXp1 = horizontalAxis.valueToJava2D(
826                         x[indexX[i + 1]], dataArea, RectangleEdge.BOTTOM
827                     );
828                     transDXm1 = Math.abs(0.5 * (transX - transXm1));
829                     transDXp1 = Math.abs(0.5 * (transX - transXp1));
830                 }
831                 else if (i == iMax) {
832                     transX = horizontalAxis.valueToJava2D(
833                         x[k], dataArea, RectangleEdge.BOTTOM
834                     );
835                     transXm1 = horizontalAxis.valueToJava2D(
836                         x[indexX[i - 1]], dataArea, RectangleEdge.BOTTOM
837                     );
838                     transXp1 = transX;
839                     transDXm1 = Math.abs(0.5 * (transX - transXm1));
840                     transDXp1 = Math.abs(0.5 * (transX - transXp1));
841                 }
842                 else {
843                     transX = horizontalAxis.valueToJava2D(
844                         x[k], dataArea, RectangleEdge.BOTTOM
845                     );
846                     transXp1 = horizontalAxis.valueToJava2D(
847                         x[indexX[i + 1]], dataArea, RectangleEdge.BOTTOM
848                     );
849                     transDXm1 = transDXp1;
850                     transDXp1 = Math.abs(0.5 * (transX - transXp1));
851                 }
852
853                 if (horizInverted) {
854                     transX -= transDXp1;
855                 }
856                 else {
857                     transX -= transDXm1;
858                 }
859
860                 transDX = transDXm1 + transDXp1;
861
862                 transY = verticalAxis.valueToJava2D(
863                     y[k], dataArea, RectangleEdge.LEFT
864                 );
865                 transYm1 = transY;
866                 if (k + 1 == y.length) {
867                     continue;
868                 }
869                 transYp1 = verticalAxis.valueToJava2D(
870                     y[k + 1], dataArea, RectangleEdge.LEFT
871                 );
872                 transDYm1 = Math.abs(0.5 * (transY - transYm1));
873                 transDYp1 = Math.abs(0.5 * (transY - transYp1));
874             }
875             else if ((i < indexX.length - 1
876                      && indexX[i + 1] - 1 == k) || k == x.length - 1) {
877                 // end of column
878
transY = verticalAxis.valueToJava2D(
879                     y[k], dataArea, RectangleEdge.LEFT
880                 );
881                 transYm1 = verticalAxis.valueToJava2D(
882                     y[k - 1], dataArea, RectangleEdge.LEFT
883                 );
884                 transYp1 = transY;
885                 transDYm1 = Math.abs(0.5 * (transY - transYm1));
886                 transDYp1 = Math.abs(0.5 * (transY - transYp1));
887             }
888             else {
889                 transY = verticalAxis.valueToJava2D(
890                     y[k], dataArea, RectangleEdge.LEFT
891                 );
892                 transYp1 = verticalAxis.valueToJava2D(
893                     y[k + 1], dataArea, RectangleEdge.LEFT
894                 );
895                 transDYm1 = transDYp1;
896                 transDYp1 = Math.abs(0.5 * (transY - transYp1));
897             }
898             if (vertInverted) {
899                 transY -= transDYm1;
900             }
901             else {
902                 transY -= transDYp1;
903             }
904
905             transDY = transDYm1 + transDYp1;
906
907             rect.setRect(transX, transY, transDX, transDY);
908             if (zNumber[k] != null) {
909                 g2.setPaint(colorBar.getPaint(zNumber[k].doubleValue()));
910                 g2.fill(rect);
911             }
912             else if (this.missingPaint != null) {
913                 g2.setPaint(this.missingPaint);
914                 g2.fill(rect);
915             }
916
917             entityArea = rect;
918
919             // add an entity for the item...
920
if (entities != null) {
921                 String JavaDoc tip = "";
922                 if (getToolTipGenerator() != null) {
923                     tip = this.toolTipGenerator.generateToolTip(data, k);
924                 }
925 // Shape s = g2.getClip();
926
// if (s.contains(rect) || s.intersects(rect)) {
927
String JavaDoc url = null;
928                 // if (getURLGenerator() != null) { //dmo: look at this later
929
// url = getURLGenerator().generateURL(data, series, item);
930
// }
931
// Unlike XYItemRenderer, we need to clone entityArea since it
932
// reused.
933
ContourEntity entity = new ContourEntity(
934                     (Rectangle2D.Double JavaDoc) entityArea.clone(), tip, url
935                 );
936                 entity.setIndex(k);
937                 entities.add(entity);
938 // }
939
}
940
941             // do we need to update the crosshair values?
942
if (plot.isDomainCrosshairLockedOnData()) {
943                 if (plot.isRangeCrosshairLockedOnData()) {
944                     // both axes
945
crosshairState.updateCrosshairPoint(
946                         x[k], y[k], transX, transY, PlotOrientation.VERTICAL
947                     );
948                 }
949                 else {
950                     // just the horizontal axis...
951
crosshairState.updateCrosshairX(transX);
952                 }
953             }
954             else {
955                 if (plot.isRangeCrosshairLockedOnData()) {
956                     // just the vertical axis...
957
crosshairState.updateCrosshairY(transY);
958                 }
959             }
960         }
961
962         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
963
964         return;
965
966     }
967
968     /**
969      * Draws the visual representation of a single data item.
970      *
971      * @param g2 the graphics device.
972      * @param dataArea the area within which the data is being drawn.
973      * @param info collects information about the drawing.
974      * @param plot the plot (can be used to obtain standard color
975      * information etc).
976      * @param domainAxis the domain (horizontal) axis.
977      * @param rangeAxis the range (vertical) axis.
978      * @param colorBar the color bar axis.
979      * @param data the dataset.
980      * @param crosshairState information about crosshairs on a plot.
981      */

982     public void pointRenderer(Graphics2D JavaDoc g2,
983                               Rectangle2D JavaDoc dataArea,
984                               PlotRenderingInfo info,
985                               ContourPlot plot,
986                               ValueAxis domainAxis,
987                               ValueAxis rangeAxis,
988                               ColorBar colorBar,
989                               ContourDataset data,
990                               CrosshairState crosshairState) {
991
992         // setup for collecting optional entity info...
993
RectangularShape JavaDoc entityArea = null;
994         EntityCollection entities = null;
995         if (info != null) {
996             entities = info.getOwner().getEntityCollection();
997         }
998
999 // Rectangle2D.Double rect = null;
1000
// rect = new Rectangle2D.Double();
1001
RectangularShape JavaDoc rect = new Ellipse2D.Double JavaDoc();
1002
1003
1004        //turn off anti-aliasing when filling rectangles
1005
Object JavaDoc antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
1006        g2.setRenderingHint(
1007            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF
1008        );
1009
1010        // if (tooltips!=null) tooltips.clearToolTips(); // reset collection
1011
// get the data points
1012
Number JavaDoc[] xNumber = data.getXValues();
1013        Number JavaDoc[] yNumber = data.getYValues();
1014        Number JavaDoc[] zNumber = data.getZValues();
1015
1016        double[] x = new double[xNumber.length];
1017        double[] y = new double[yNumber.length];
1018
1019        for (int i = 0; i < x.length; i++) {
1020            x[i] = xNumber[i].doubleValue();
1021            y[i] = yNumber[i].doubleValue();
1022        }
1023
1024        double transX = 0.0;
1025        double transDX = 0.0;
1026        double transY = 0.0;
1027        double transDY = 0.0;
1028        double size = dataArea.getWidth() * this.ptSizePct;
1029        for (int k = 0; k < x.length; k++) {
1030
1031            transX = domainAxis.valueToJava2D(
1032                x[k], dataArea, RectangleEdge.BOTTOM
1033            ) - 0.5 * size;
1034            transY = rangeAxis.valueToJava2D(y[k], dataArea, RectangleEdge.LEFT)
1035                     - 0.5 * size;
1036            transDX = size;
1037            transDY = size;
1038
1039            rect.setFrame(transX, transY, transDX, transDY);
1040
1041            if (zNumber[k] != null) {
1042                g2.setPaint(colorBar.getPaint(zNumber[k].doubleValue()));
1043                g2.fill(rect);
1044            }
1045            else if (this.missingPaint != null) {
1046                g2.setPaint(this.missingPaint);
1047                g2.fill(rect);
1048            }
1049
1050
1051            entityArea = rect;
1052
1053            // add an entity for the item...
1054
if (entities != null) {
1055                String JavaDoc tip = null;
1056                if (getToolTipGenerator() != null) {
1057                    tip = this.toolTipGenerator.generateToolTip(data, k);
1058                }
1059                String JavaDoc url = null;
1060                // if (getURLGenerator() != null) { //dmo: look at this later
1061
// url = getURLGenerator().generateURL(data, series, item);
1062
// }
1063
// Unlike XYItemRenderer, we need to clone entityArea since it
1064
// reused.
1065
ContourEntity entity = new ContourEntity(
1066                    (RectangularShape JavaDoc) entityArea.clone(), tip, url
1067                );
1068                entity.setIndex(k);
1069                entities.add(entity);
1070            }
1071
1072            // do we need to update the crosshair values?
1073
if (plot.isDomainCrosshairLockedOnData()) {
1074                if (plot.isRangeCrosshairLockedOnData()) {
1075                    // both axes
1076
crosshairState.updateCrosshairPoint(
1077                        x[k], y[k], transX, transY, PlotOrientation.VERTICAL
1078                    );
1079                }
1080                else {
1081                    // just the horizontal axis...
1082
crosshairState.updateCrosshairX(transX);
1083                }
1084            }
1085            else {
1086                if (plot.isRangeCrosshairLockedOnData()) {
1087                    // just the vertical axis...
1088
crosshairState.updateCrosshairY(transY);
1089                }
1090            }
1091        }
1092
1093
1094        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
1095
1096        return;
1097
1098    }
1099
1100    /**
1101     * Utility method for drawing a crosshair on the chart (if required).
1102     *
1103     * @param g2 The graphics device.
1104     * @param dataArea The data area.
1105     * @param value The coordinate, where to draw the line.
1106     * @param stroke The stroke to use.
1107     * @param paint The paint to use.
1108     */

1109    protected void drawVerticalLine(Graphics2D JavaDoc g2, Rectangle2D JavaDoc dataArea,
1110                                    double value, Stroke JavaDoc stroke, Paint JavaDoc paint) {
1111
1112        double xx = getDomainAxis().valueToJava2D(
1113            value, dataArea, RectangleEdge.BOTTOM
1114        );
1115        Line2D JavaDoc line = new Line2D.Double JavaDoc(
1116            xx, dataArea.getMinY(), xx, dataArea.getMaxY()
1117        );
1118        g2.setStroke(stroke);
1119        g2.setPaint(paint);
1120        g2.draw(line);
1121
1122    }
1123
1124    /**
1125     * Utility method for drawing a crosshair on the chart (if required).
1126     *
1127     * @param g2 The graphics device.
1128     * @param dataArea The data area.
1129     * @param value The coordinate, where to draw the line.
1130     * @param stroke The stroke to use.
1131     * @param paint The paint to use.
1132     */

1133    protected void drawHorizontalLine(Graphics2D JavaDoc g2, Rectangle2D JavaDoc dataArea,
1134                                      double value, Stroke JavaDoc stroke,
1135                                      Paint JavaDoc paint) {
1136
1137        double yy = getRangeAxis().valueToJava2D(
1138            value, dataArea, RectangleEdge.LEFT
1139        );
1140        Line2D JavaDoc line = new Line2D.Double JavaDoc(
1141            dataArea.getMinX(), yy, dataArea.getMaxX(), yy
1142        );
1143        g2.setStroke(stroke);
1144        g2.setPaint(paint);
1145        g2.draw(line);
1146
1147    }
1148
1149    /**
1150     * Handles a 'click' on the plot by updating the anchor values...
1151     *
1152     * @param x x-coordinate, where the click occured.
1153     * @param y y-coordinate, where the click occured.
1154     * @param info An object for collection dimension information.
1155     */

1156    public void handleClick(int x, int y, PlotRenderingInfo info) {
1157
1158/* // set the anchor value for the horizontal axis...
1159        ValueAxis hva = getDomainAxis();
1160        if (hva != null) {
1161            double hvalue = hva.translateJava2DtoValue(
1162                (float) x, info.getDataArea()
1163            );
1164
1165            hva.setAnchorValue(hvalue);
1166            setDomainCrosshairValue(hvalue);
1167        }
1168
1169        // set the anchor value for the vertical axis...
1170        ValueAxis vva = getRangeAxis();
1171        if (vva != null) {
1172            double vvalue = vva.translateJava2DtoValue(
1173                (float) y, info.getDataArea()
1174            );
1175            vva.setAnchorValue(vvalue);
1176            setRangeCrosshairValue(vvalue);
1177        }
1178*/

1179    }
1180
1181    /**
1182     * Zooms the axis ranges by the specified percentage about the anchor point.
1183     *
1184     * @param percent The amount of the zoom.
1185     */

1186    public void zoom(double percent) {
1187
1188        if (percent > 0) {
1189          // double range = this.domainAxis.getRange().getLength();
1190
// double scaledRange = range * percent;
1191
// domainAxis.setAnchoredRange(scaledRange);
1192

1193          // range = this.rangeAxis.getRange().getLength();
1194
// scaledRange = range * percent;
1195
// rangeAxis.setAnchoredRange(scaledRange);
1196
}
1197        else {
1198            getRangeAxis().setAutoRange(true);
1199            getDomainAxis().setAutoRange(true);
1200        }
1201
1202    }
1203
1204    /**
1205     * Returns the plot type as a string.
1206     *
1207     * @return A short string describing the type of plot.
1208     */

1209    public String JavaDoc getPlotType() {
1210        return localizationResources.getString("Contour_Plot");
1211    }
1212
1213    /**
1214     * Returns the range for an axis.
1215     *
1216     * @param axis the axis.
1217     *
1218     * @return The range for an axis.
1219     */

1220    public Range getDataRange(ValueAxis axis) {
1221
1222        if (this.dataset == null) {
1223            return null;
1224        }
1225
1226        Range result = null;
1227
1228        if (axis == getDomainAxis()) {
1229            result = DatasetUtilities.findDomainBounds(this.dataset);
1230        }
1231        else if (axis == getRangeAxis()) {
1232            result = DatasetUtilities.findRangeBounds(this.dataset);
1233        }
1234
1235        return result;
1236
1237    }
1238
1239    /**
1240     * Returns the range for the Contours.
1241     *
1242     * @return The range for the Contours (z-axis).
1243     */

1244    public Range getContourDataRange() {
1245
1246        Range result = null;
1247
1248        ContourDataset data = getDataset();
1249
1250        if (data != null) {
1251            Range h = getDomainAxis().getRange();
1252            Range v = getRangeAxis().getRange();
1253            result = this.visibleRange(data, h, v);
1254        }
1255
1256        return result;
1257    }
1258
1259    /**
1260     * Notifies all registered listeners of a property change.
1261     * <P>
1262     * One source of property change events is the plot's renderer.
1263     *
1264     * @param event Information about the property change.
1265     */

1266    public void propertyChange(PropertyChangeEvent JavaDoc event) {
1267        notifyListeners(new PlotChangeEvent(this));
1268    }
1269
1270    /**
1271     * Receives notification of a change to the plot's dataset.
1272     * <P>
1273     * The chart reacts by passing on a chart change event to all registered
1274     * listeners.
1275     *
1276     * @param event Information about the event (not used here).
1277     */

1278    public void datasetChanged(DatasetChangeEvent event) {
1279        if (this.domainAxis != null) {
1280            this.domainAxis.configure();
1281        }
1282        if (this.rangeAxis != null) {
1283            this.rangeAxis.configure();
1284        }
1285        if (this.colorBar != null) {
1286            this.colorBar.configure(this);
1287        }
1288        super.datasetChanged(event);
1289    }
1290
1291    /**
1292     * Returns the colorbar.
1293     *
1294     * @return The colorbar.
1295     */

1296    public ColorBar getColorBar() {
1297        return this.colorBar;
1298    }
1299
1300    /**
1301     * Returns a flag indicating whether or not the domain crosshair is visible.
1302     *
1303     * @return The flag.
1304     */

1305    public boolean isDomainCrosshairVisible() {
1306        return this.domainCrosshairVisible;
1307    }
1308
1309    /**
1310     * Sets the flag indicating whether or not the domain crosshair is visible.
1311     *
1312     * @param flag the new value of the flag.
1313     */

1314    public void setDomainCrosshairVisible(boolean flag) {
1315
1316        if (this.domainCrosshairVisible != flag) {
1317            this.domainCrosshairVisible = flag;
1318            notifyListeners(new PlotChangeEvent(this));
1319        }
1320
1321    }
1322
1323    /**
1324     * Returns a flag indicating whether or not the crosshair should "lock-on"
1325     * to actual data values.
1326     *
1327     * @return The flag.
1328     */

1329    public boolean isDomainCrosshairLockedOnData() {
1330        return this.domainCrosshairLockedOnData;
1331    }
1332
1333    /**
1334     * Sets the flag indicating whether or not the domain crosshair should
1335     * "lock-on" to actual data values.
1336     *
1337     * @param flag the flag.
1338     */

1339    public void setDomainCrosshairLockedOnData(boolean flag) {
1340        if (this.domainCrosshairLockedOnData != flag) {
1341            this.domainCrosshairLockedOnData = flag;
1342            notifyListeners(new PlotChangeEvent(this));
1343        }
1344    }
1345
1346    /**
1347     * Returns the domain crosshair value.
1348     *
1349     * @return The value.
1350     */

1351    public double getDomainCrosshairValue() {
1352        return this.domainCrosshairValue;
1353    }
1354
1355    /**
1356     * Sets the domain crosshair value.
1357     * <P>
1358     * Registered listeners are notified that the plot has been modified, but
1359     * only if the crosshair is visible.
1360     *
1361     * @param value the new value.
1362     */

1363    public void setDomainCrosshairValue(double value) {
1364
1365        setDomainCrosshairValue(value, true);
1366
1367    }
1368
1369    /**
1370     * Sets the domain crosshair value.
1371     * <P>
1372     * Registered listeners are notified that the axis has been modified, but
1373     * only if the crosshair is visible.
1374     *
1375     * @param value the new value.
1376     * @param notify a flag that controls whether or not listeners are
1377     * notified.
1378     */

1379    public void setDomainCrosshairValue(double value, boolean notify) {
1380
1381        this.domainCrosshairValue = value;
1382        if (isDomainCrosshairVisible() && notify) {
1383            notifyListeners(new PlotChangeEvent(this));
1384        }
1385
1386    }
1387
1388    /**
1389     * Returns the Stroke used to draw the crosshair (if visible).
1390     *
1391     * @return The crosshair stroke.
1392     */

1393    public Stroke JavaDoc getDomainCrosshairStroke() {
1394        return this.domainCrosshairStroke;
1395    }
1396
1397    /**
1398     * Sets the Stroke used to draw the crosshairs (if visible) and notifies
1399     * registered listeners that the axis has been modified.
1400     *
1401     * @param stroke the new crosshair stroke.
1402     */

1403    public void setDomainCrosshairStroke(Stroke JavaDoc stroke) {
1404        this.domainCrosshairStroke = stroke;
1405        notifyListeners(new PlotChangeEvent(this));
1406    }
1407
1408    /**
1409     * Returns the domain crosshair color.
1410     *
1411     * @return The crosshair color.
1412     */

1413    public Paint JavaDoc getDomainCrosshairPaint() {
1414        return this.domainCrosshairPaint;
1415    }
1416
1417    /**
1418     * Sets the Paint used to color the crosshairs (if visible) and notifies
1419     * registered listeners that the axis has been modified.
1420     *
1421     * @param paint the new crosshair paint.
1422     */

1423    public void setDomainCrosshairPaint(Paint JavaDoc paint) {
1424        this.domainCrosshairPaint = paint;
1425        notifyListeners(new PlotChangeEvent(this));
1426    }
1427
1428    /**
1429     * Returns a flag indicating whether or not the range crosshair is visible.
1430     *
1431     * @return The flag.
1432     */

1433    public boolean isRangeCrosshairVisible() {
1434        return this.rangeCrosshairVisible;
1435    }
1436
1437    /**
1438     * Sets the flag indicating whether or not the range crosshair is visible.
1439     *
1440     * @param flag the new value of the flag.
1441     */

1442    public void setRangeCrosshairVisible(boolean flag) {
1443
1444        if (this.rangeCrosshairVisible != flag) {
1445            this.rangeCrosshairVisible = flag;
1446            notifyListeners(new PlotChangeEvent(this));
1447        }
1448
1449    }
1450
1451    /**
1452     * Returns a flag indicating whether or not the crosshair should "lock-on"
1453     * to actual data values.
1454     *
1455     * @return The flag.
1456     */

1457    public boolean isRangeCrosshairLockedOnData() {
1458        return this.rangeCrosshairLockedOnData;
1459    }
1460
1461    /**
1462     * Sets the flag indicating whether or not the range crosshair should
1463     * "lock-on" to actual data values.
1464     *
1465     * @param flag the flag.
1466     */

1467    public void setRangeCrosshairLockedOnData(boolean flag) {
1468
1469        if (this.rangeCrosshairLockedOnData != flag) {
1470            this.rangeCrosshairLockedOnData = flag;
1471            notifyListeners(new PlotChangeEvent(this));
1472        }
1473
1474    }
1475
1476    /**
1477     * Returns the range crosshair value.
1478     *
1479     * @return The value.
1480     */

1481    public double getRangeCrosshairValue() {
1482        return this.rangeCrosshairValue;
1483    }
1484
1485    /**
1486     * Sets the domain crosshair value.
1487     * <P>
1488     * Registered listeners are notified that the plot has been modified, but
1489     * only if the crosshair is visible.
1490     *
1491     * @param value the new value.
1492     */

1493    public void setRangeCrosshairValue(double value) {
1494
1495        setRangeCrosshairValue(value, true);
1496
1497    }
1498
1499    /**
1500     * Sets the range crosshair value.
1501     * <P>
1502     * Registered listeners are notified that the axis has been modified, but
1503     * only if the crosshair is visible.
1504     *
1505     * @param value the new value.
1506     * @param notify a flag that controls whether or not listeners are
1507     * notified.
1508     */

1509    public void setRangeCrosshairValue(double value, boolean notify) {
1510
1511        this.rangeCrosshairValue = value;
1512        if (isRangeCrosshairVisible() && notify) {
1513            notifyListeners(new PlotChangeEvent(this));
1514        }
1515
1516    }
1517
1518    /**
1519     * Returns the Stroke used to draw the crosshair (if visible).
1520     *
1521     * @return The crosshair stroke.
1522     */

1523    public Stroke JavaDoc getRangeCrosshairStroke() {
1524        return this.rangeCrosshairStroke;
1525    }
1526
1527    /**
1528     * Sets the Stroke used to draw the crosshairs (if visible) and notifies
1529     * registered listeners that the axis has been modified.
1530     *
1531     * @param stroke the new crosshair stroke.
1532     */

1533    public void setRangeCrosshairStroke(Stroke JavaDoc stroke) {
1534        this.rangeCrosshairStroke = stroke;
1535        notifyListeners(new PlotChangeEvent(this));
1536    }
1537
1538    /**
1539     * Returns the range crosshair color.
1540     *
1541     * @return The crosshair color.
1542     */

1543    public Paint JavaDoc getRangeCrosshairPaint() {
1544        return this.rangeCrosshairPaint;
1545    }
1546
1547    /**
1548     * Sets the Paint used to color the crosshairs (if visible) and notifies
1549     * registered listeners that the axis has been modified.
1550     *
1551     * @param paint the new crosshair paint.
1552     */

1553    public void setRangeCrosshairPaint(Paint JavaDoc paint) {
1554        this.rangeCrosshairPaint = paint;
1555        notifyListeners(new PlotChangeEvent(this));
1556    }
1557
1558    /**
1559     * Returns the tool tip generator.
1560     *
1561     * @return The tool tip generator (possibly null).
1562     */

1563    public ContourToolTipGenerator getToolTipGenerator() {
1564        return this.toolTipGenerator;
1565    }
1566
1567    /**
1568     * Sets the tool tip generator.
1569     *
1570     * @param generator the tool tip generator (null permitted).
1571     */

1572    public void setToolTipGenerator(ContourToolTipGenerator generator) {
1573
1574        //Object oldValue = this.toolTipGenerator;
1575
this.toolTipGenerator = generator;
1576
1577    }
1578
1579    /**
1580     * Returns the URL generator for HTML image maps.
1581     *
1582     * @return The URL generator (possibly null).
1583     */

1584    public XYURLGenerator getURLGenerator() {
1585        return this.urlGenerator;
1586    }
1587
1588    /**
1589     * Sets the URL generator for HTML image maps.
1590     *
1591     * @param urlGenerator the URL generator (null permitted).
1592     */

1593    public void setURLGenerator(XYURLGenerator urlGenerator) {
1594
1595        //Object oldValue = this.urlGenerator;
1596
this.urlGenerator = urlGenerator;
1597
1598    }
1599
1600    /**
1601     * Draws a vertical line on the chart to represent a 'range marker'.
1602     *
1603     * @param g2 the graphics device.
1604     * @param plot the plot.
1605     * @param domainAxis the domain axis.
1606     * @param marker the marker line.
1607     * @param dataArea the axis data area.
1608     */

1609    public void drawDomainMarker(Graphics2D JavaDoc g2,
1610                                 ContourPlot plot,
1611                                 ValueAxis domainAxis,
1612                                 Marker marker,
1613                                 Rectangle2D JavaDoc dataArea) {
1614
1615        if (marker instanceof ValueMarker) {
1616            ValueMarker vm = (ValueMarker) marker;
1617            double value = vm.getValue();
1618            Range range = domainAxis.getRange();
1619            if (!range.contains(value)) {
1620                return;
1621            }
1622  
1623            double x = domainAxis.valueToJava2D(
1624                value, dataArea, RectangleEdge.BOTTOM
1625            );
1626            Line2D JavaDoc line = new Line2D.Double JavaDoc(
1627                x, dataArea.getMinY(), x, dataArea.getMaxY()
1628            );
1629            Paint JavaDoc paint = marker.getOutlinePaint();
1630            Stroke JavaDoc stroke = marker.getOutlineStroke();
1631            g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
1632            g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
1633            g2.draw(line);
1634        }
1635
1636    }
1637
1638    /**
1639     * Draws a horizontal line across the chart to represent a 'range marker'.
1640     *
1641     * @param g2 the graphics device.
1642     * @param plot the plot.
1643     * @param rangeAxis the range axis.
1644     * @param marker the marker line.
1645     * @param dataArea the axis data area.
1646     */

1647    public void drawRangeMarker(Graphics2D JavaDoc g2,
1648                                ContourPlot plot,
1649                                ValueAxis rangeAxis,
1650                                Marker marker,
1651                                Rectangle2D JavaDoc dataArea) {
1652
1653        if (marker instanceof ValueMarker) {
1654            ValueMarker vm = (ValueMarker) marker;
1655            double value = vm.getValue();
1656            Range range = rangeAxis.getRange();
1657            if (!range.contains(value)) {
1658                return;
1659            }
1660
1661            double y = rangeAxis.valueToJava2D(
1662                value, dataArea, RectangleEdge.LEFT
1663            );
1664            Line2D JavaDoc line = new Line2D.Double JavaDoc(
1665                dataArea.getMinX(), y, dataArea.getMaxX(), y
1666            );
1667            Paint JavaDoc paint = marker.getOutlinePaint();
1668            Stroke JavaDoc stroke = marker.getOutlineStroke();
1669            g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
1670            g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
1671            g2.draw(line);
1672        }
1673
1674    }
1675
1676    /**
1677     * Returns the clipPath.
1678     * @return ClipPath
1679     */

1680    public ClipPath getClipPath() {
1681        return this.clipPath;
1682    }
1683
1684    /**
1685     * Sets the clipPath.
1686     * @param clipPath The clipPath to set
1687     */

1688    public void setClipPath(ClipPath clipPath) {
1689        this.clipPath = clipPath;
1690    }
1691
1692    /**
1693     * Returns the ptSizePct.
1694     * @return double
1695     */

1696    public double getPtSizePct() {
1697        return this.ptSizePct;
1698    }
1699
1700    /**
1701     * Returns the renderAsPoints.
1702     * @return boolean
1703     */

1704    public boolean isRenderAsPoints() {
1705        return this.renderAsPoints;
1706    }
1707
1708    /**
1709     * Sets the ptSizePct.
1710     * @param ptSizePct The ptSizePct to set
1711     */

1712    public void setPtSizePct(double ptSizePct) {
1713        this.ptSizePct = ptSizePct;
1714    }
1715
1716    /**
1717     * Sets the renderAsPoints.
1718     * @param renderAsPoints The renderAsPoints to set
1719     */

1720    public void setRenderAsPoints(boolean renderAsPoints) {
1721        this.renderAsPoints = renderAsPoints;
1722    }
1723
1724    /**
1725     * Receives notification of a change to one of the plot's axes.
1726     *
1727     * @param event information about the event.
1728     */

1729    public void axisChanged(AxisChangeEvent event) {
1730        Object JavaDoc source = event.getSource();
1731        if (source.equals(this.rangeAxis) || source.equals(this.domainAxis)) {
1732            ColorBar cba = this.colorBar;
1733            if (this.colorBar.getAxis().isAutoRange()) {
1734                cba.getAxis().configure();
1735            }
1736
1737        }
1738        super.axisChanged(event);
1739    }
1740
1741    /**
1742     * Returns the visible z-range.
1743     *
1744     * @param data the dataset.
1745     * @param x the x range.
1746     * @param y the y range.
1747     *
1748     * @return The range.
1749     */

1750    public Range visibleRange(ContourDataset data, Range x, Range y) {
1751        Range range = null;
1752        range = data.getZValueRange(x, y);
1753        return range;
1754    }
1755
1756    /**
1757     * Returns the missingPaint.
1758     * @return Paint
1759     */

1760    public Paint JavaDoc getMissingPaint() {
1761        return this.missingPaint;
1762    }
1763
1764    /**
1765     * Sets the missingPaint.
1766     *
1767     * @param paint the missingPaint to set.
1768     */

1769    public void setMissingPaint(Paint JavaDoc paint) {
1770        this.missingPaint = paint;
1771    }
1772    
1773    /**
1774     * Multiplies the range on the domain axis/axes by the specified factor
1775     * (to be implemented).
1776     *
1777     * @param x the x-coordinate (in Java2D space).
1778     * @param y the y-coordinate (in Java2D space).
1779     * @param factor the zoom factor.
1780     */

1781    public void zoomDomainAxes(double x, double y, double factor) {
1782        // TODO: to be implemented
1783
}
1784    
1785    /**
1786     * Zooms the domain axes (not yet implemented).
1787     *
1788     * @param x the x-coordinate (in Java2D space).
1789     * @param y the y-coordinate (in Java2D space).
1790     * @param lowerPercent the new lower bound.
1791     * @param upperPercent the new upper bound.
1792     */

1793    public void zoomDomainAxes(double x, double y, double lowerPercent,
1794                               double upperPercent) {
1795        // TODO: to be implemented
1796
}
1797    
1798    /**
1799     * Multiplies the range on the range axis/axes by the specified factor.
1800     *
1801     * @param x the x-coordinate (in Java2D space).
1802     * @param y the y-coordinate (in Java2D space).
1803     * @param factor the zoom factor.
1804     */

1805    public void zoomRangeAxes(double x, double y, double factor) {
1806        // TODO: to be implemented
1807
}
1808
1809    /**
1810     * Zooms the range axes (not yet implemented).
1811     *
1812     * @param x the x-coordinate (in Java2D space).
1813     * @param y the y-coordinate (in Java2D space).
1814     * @param lowerPercent the new lower bound.
1815     * @param upperPercent the new upper bound.
1816     */

1817    public void zoomRangeAxes(double x, double y, double lowerPercent,
1818                              double upperPercent) {
1819        // TODO: to be implemented
1820
}
1821
1822    /**
1823     * Returns <code>false</code>.
1824     *
1825     * @return A boolean.
1826     */

1827    public boolean isDomainZoomable() {
1828        return false;
1829    }
1830    
1831    /**
1832     * Returns <code>false</code>.
1833     *
1834     * @return A boolean.
1835     */

1836    public boolean isRangeZoomable() {
1837        return false;
1838    }
1839
1840    /**
1841     * Extends plot cloning to this plot type
1842     * @see org.jfree.chart.plot.Plot#clone()
1843     */

1844    public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
1845        ContourPlot clone = (ContourPlot) super.clone();
1846        
1847        if (this.domainAxis != null) {
1848            clone.domainAxis = (ValueAxis) this.domainAxis.clone();
1849            clone.domainAxis.setPlot(clone);
1850            clone.domainAxis.addChangeListener(clone);
1851        }
1852        if (this.rangeAxis != null) {
1853            clone.rangeAxis = (ValueAxis) this.rangeAxis.clone();
1854            clone.rangeAxis.setPlot(clone);
1855            clone.rangeAxis.addChangeListener(clone);
1856        }
1857
1858        if (clone.dataset != null) {
1859            clone.dataset.addChangeListener(clone);
1860        }
1861    
1862        if (this.colorBar != null) {
1863            clone.colorBar = (ColorBar) this.colorBar.clone();
1864        }
1865
1866        clone.domainMarkers = (List JavaDoc) ObjectUtilities.deepClone(
1867            this.domainMarkers
1868        );
1869        clone.rangeMarkers = (List JavaDoc) ObjectUtilities.deepClone(
1870            this.rangeMarkers
1871        );
1872        clone.annotations = (List JavaDoc) ObjectUtilities.deepClone(this.annotations);
1873
1874        if (this.clipPath != null) {
1875            clone.clipPath = (ClipPath) this.clipPath.clone();
1876        }
1877
1878        return clone;
1879    }
1880
1881}
1882
Popular Tags