KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > xy > AbstractXYItemRenderer


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------------------
28  * AbstractXYItemRenderer.java
29  * ---------------------------
30  * (C) Copyright 2002-2006, by Object Refinery Limited and Contributors.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): Richard Atkinson;
34  * Focus Computer Services Limited;
35  * Tim Bardzil;
36  * Sergei Ivanov;
37  *
38  * $Id: AbstractXYItemRenderer.java,v 1.26.2.8 2006/10/24 15:39:20 mungady Exp $
39  *
40  * Changes:
41  * --------
42  * 15-Mar-2002 : Version 1 (DG);
43  * 09-Apr-2002 : Added a getToolTipGenerator() method reflecting the change in
44  * the XYItemRenderer interface (DG);
45  * 05-Aug-2002 : Added a urlGenerator member variable to support HTML image
46  * maps (RA);
47  * 20-Aug-2002 : Added property change events for the tooltip and URL
48  * generators (DG);
49  * 22-Aug-2002 : Moved property change support into AbstractRenderer class (DG);
50  * 23-Sep-2002 : Fixed errors reported by Checkstyle tool (DG);
51  * 18-Nov-2002 : Added methods for drawing grid lines (DG);
52  * 17-Jan-2003 : Moved plot classes into a separate package (DG);
53  * 25-Mar-2003 : Implemented Serializable (DG);
54  * 01-May-2003 : Modified initialise() return type and drawItem() method
55  * signature (DG);
56  * 15-May-2003 : Modified to take into account the plot orientation (DG);
57  * 21-May-2003 : Added labels to markers (DG);
58  * 05-Jun-2003 : Added domain and range grid bands (sponsored by Focus Computer
59  * Services Ltd) (DG);
60  * 27-Jul-2003 : Added getRangeType() to support stacked XY area charts (RA);
61  * 31-Jul-2003 : Deprecated all but the default constructor (DG);
62  * 13-Aug-2003 : Implemented Cloneable (DG);
63  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
64  * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG);
65  * 05-Nov-2003 : Fixed marker rendering bug (833623) (DG);
66  * 11-Feb-2004 : Updated labelling for markers (DG);
67  * 25-Feb-2004 : Added updateCrosshairValues() method. Moved deprecated code
68  * to bottom of source file (DG);
69  * 16-Apr-2004 : Added support for IntervalMarker in drawRangeMarker() method
70  * - thanks to Tim Bardzil (DG);
71  * 05-May-2004 : Fixed bug (948310) where interval markers extend beyond axis
72  * range (DG);
73  * 03-Jun-2004 : Fixed more bugs in drawing interval markers (DG);
74  * 26-Aug-2004 : Added the addEntity() method (DG);
75  * 29-Sep-2004 : Added annotation support (with layers) (DG);
76  * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities -->
77  * TextUtilities (DG);
78  * 06-Oct-2004 : Added findDomainBounds() method and renamed
79  * getRangeExtent() --> findRangeBounds() (DG);
80  * 07-Jan-2005 : Removed deprecated code (DG);
81  * 27-Jan-2005 : Modified getLegendItem() to omit hidden series (DG);
82  * 24-Feb-2005 : Added getLegendItems() method (DG);
83  * 08-Mar-2005 : Fixed positioning of marker labels (DG);
84  * 20-Apr-2005 : Renamed XYLabelGenerator --> XYItemLabelGenerator and
85  * added generators for legend labels, tooltips and URLs (DG);
86  * 01-Jun-2005 : Handle one dimension of the marker label adjustment
87  * automatically (DG);
88  * ------------- JFREECHART 1.0.x ---------------------------------------------
89  * 20-Jul-2006 : Set dataset and series indices in LegendItem (DG);
90  * 24-Oct-2006 : Respect alpha setting in markers (see patch 1567843 by Sergei
91  * Ivanov) (DG);
92  * 24-Oct-2006 : Added code to draw outlines for interval markers (DG);
93  *
94  */

95
96 package org.jfree.chart.renderer.xy;
97
98 import java.awt.AlphaComposite JavaDoc;
99 import java.awt.Composite JavaDoc;
100 import java.awt.Font JavaDoc;
101 import java.awt.GradientPaint JavaDoc;
102 import java.awt.Graphics2D JavaDoc;
103 import java.awt.Paint JavaDoc;
104 import java.awt.Shape JavaDoc;
105 import java.awt.Stroke JavaDoc;
106 import java.awt.geom.Ellipse2D JavaDoc;
107 import java.awt.geom.Line2D JavaDoc;
108 import java.awt.geom.Point2D JavaDoc;
109 import java.awt.geom.Rectangle2D JavaDoc;
110 import java.io.Serializable JavaDoc;
111 import java.util.Iterator JavaDoc;
112 import java.util.List JavaDoc;
113
114 import org.jfree.chart.LegendItem;
115 import org.jfree.chart.LegendItemCollection;
116 import org.jfree.chart.annotations.XYAnnotation;
117 import org.jfree.chart.axis.ValueAxis;
118 import org.jfree.chart.entity.EntityCollection;
119 import org.jfree.chart.entity.XYItemEntity;
120 import org.jfree.chart.event.RendererChangeEvent;
121 import org.jfree.chart.labels.ItemLabelPosition;
122 import org.jfree.chart.labels.StandardXYSeriesLabelGenerator;
123 import org.jfree.chart.labels.XYItemLabelGenerator;
124 import org.jfree.chart.labels.XYSeriesLabelGenerator;
125 import org.jfree.chart.labels.XYToolTipGenerator;
126 import org.jfree.chart.plot.CrosshairState;
127 import org.jfree.chart.plot.DrawingSupplier;
128 import org.jfree.chart.plot.IntervalMarker;
129 import org.jfree.chart.plot.Marker;
130 import org.jfree.chart.plot.Plot;
131 import org.jfree.chart.plot.PlotOrientation;
132 import org.jfree.chart.plot.PlotRenderingInfo;
133 import org.jfree.chart.plot.ValueMarker;
134 import org.jfree.chart.plot.XYPlot;
135 import org.jfree.chart.renderer.AbstractRenderer;
136 import org.jfree.chart.urls.XYURLGenerator;
137 import org.jfree.data.Range;
138 import org.jfree.data.general.DatasetUtilities;
139 import org.jfree.data.xy.XYDataset;
140 import org.jfree.text.TextUtilities;
141 import org.jfree.ui.GradientPaintTransformer;
142 import org.jfree.ui.Layer;
143 import org.jfree.ui.LengthAdjustmentType;
144 import org.jfree.ui.RectangleAnchor;
145 import org.jfree.ui.RectangleInsets;
146 import org.jfree.util.ObjectList;
147 import org.jfree.util.ObjectUtilities;
148 import org.jfree.util.PublicCloneable;
149
150 /**
151  * A base class that can be used to create new {@link XYItemRenderer}
152  * implementations.
153  */

154 public abstract class AbstractXYItemRenderer extends AbstractRenderer
155                                              implements XYItemRenderer,
156                                                         Cloneable JavaDoc,
157                                                         Serializable JavaDoc {
158
159     /** For serialization. */
160     private static final long serialVersionUID = 8019124836026607990L;
161     
162     /** The plot. */
163     private XYPlot plot;
164     
165     /** The item label generator for ALL series. */
166     private XYItemLabelGenerator itemLabelGenerator;
167
168     /** A list of item label generators (one per series). */
169     private ObjectList itemLabelGeneratorList;
170
171     /** The base item label generator. */
172     private XYItemLabelGenerator baseItemLabelGenerator;
173
174     /** The tool tip generator for ALL series. */
175     private XYToolTipGenerator toolTipGenerator;
176
177     /** A list of tool tip generators (one per series). */
178     private ObjectList toolTipGeneratorList;
179
180     /** The base tool tip generator. */
181     private XYToolTipGenerator baseToolTipGenerator;
182
183     /** The URL text generator. */
184     private XYURLGenerator urlGenerator;
185     
186     /**
187      * Annotations to be drawn in the background layer ('underneath' the data
188      * items).
189      */

190     private List JavaDoc backgroundAnnotations;
191     
192     /**
193      * Annotations to be drawn in the foreground layer ('on top' of the data
194      * items).
195      */

196     private List JavaDoc foregroundAnnotations;
197     
198     private int defaultEntityRadius;
199     
200     private XYSeriesLabelGenerator legendItemLabelGenerator;
201     
202     private XYSeriesLabelGenerator legendItemToolTipGenerator;
203     
204     private XYSeriesLabelGenerator legendItemURLGenerator;
205
206     /**
207      * Creates a renderer where the tooltip generator and the URL generator are
208      * both <code>null</code>.
209      */

210     protected AbstractXYItemRenderer() {
211         this.itemLabelGenerator = null;
212         this.itemLabelGeneratorList = new ObjectList();
213         this.toolTipGenerator = null;
214         this.toolTipGeneratorList = new ObjectList();
215         this.urlGenerator = null;
216         this.backgroundAnnotations = new java.util.ArrayList JavaDoc();
217         this.foregroundAnnotations = new java.util.ArrayList JavaDoc();
218         this.defaultEntityRadius = 3;
219         this.legendItemLabelGenerator
220             = new StandardXYSeriesLabelGenerator("{0}");
221     }
222
223     /**
224      * Returns the number of passes through the data that the renderer requires
225      * in order to draw the chart. Most charts will require a single pass, but
226      * some require two passes.
227      *
228      * @return The pass count.
229      */

230     public int getPassCount() {
231         return 1;
232     }
233
234     /**
235      * Returns the plot that the renderer is assigned to.
236      *
237      * @return The plot.
238      */

239     public XYPlot getPlot() {
240         return this.plot;
241     }
242
243     /**
244      * Sets the plot that the renderer is assigned to.
245      *
246      * @param plot the plot.
247      */

248     public void setPlot(XYPlot plot) {
249         this.plot = plot;
250     }
251
252     /**
253      * Initialises the renderer and returns a state object that should be
254      * passed to all subsequent calls to the drawItem() method.
255      * <P>
256      * This method will be called before the first item is rendered, giving the
257      * renderer an opportunity to initialise any state information it wants to
258      * maintain. The renderer can do nothing if it chooses.
259      *
260      * @param g2 the graphics device.
261      * @param dataArea the area inside the axes.
262      * @param plot the plot.
263      * @param data the data.
264      * @param info an optional info collection object to return data back to
265      * the caller.
266      *
267      * @return The renderer state (never <code>null</code>).
268      */

269     public XYItemRendererState initialise(Graphics2D JavaDoc g2,
270                                           Rectangle2D JavaDoc dataArea,
271                                           XYPlot plot,
272                                           XYDataset data,
273                                           PlotRenderingInfo info) {
274
275         XYItemRendererState state = new XYItemRendererState(info);
276         return state;
277
278     }
279
280     // ITEM LABEL GENERATOR
281

282     /**
283      * Returns the label generator for a data item. This implementation simply
284      * passes control to the {@link #getSeriesItemLabelGenerator(int)} method.
285      * If, for some reason, you want a different generator for individual
286      * items, you can override this method.
287      *
288      * @param row the row index (zero based).
289      * @param column the column index (zero based).
290      *
291      * @return The generator (possibly <code>null</code>).
292      */

293     public XYItemLabelGenerator getItemLabelGenerator(int row, int column) {
294         return getSeriesItemLabelGenerator(row);
295     }
296
297     /**
298      * Returns the item label generator for a series.
299      *
300      * @param series the series index (zero based).
301      *
302      * @return The generator (possibly <code>null</code>).
303      */

304     public XYItemLabelGenerator getSeriesItemLabelGenerator(int series) {
305
306         // return the generator for ALL series, if there is one...
307
if (this.itemLabelGenerator != null) {
308             return this.itemLabelGenerator;
309         }
310
311         // otherwise look up the generator table
312
XYItemLabelGenerator generator
313             = (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series);
314         if (generator == null) {
315             generator = this.baseItemLabelGenerator;
316         }
317         return generator;
318
319     }
320
321     /**
322      * Sets the item label generator for ALL series and sends a
323      * {@link RendererChangeEvent} to all registered listeners.
324      *
325      * @param generator the generator (<code>null</code> permitted).
326      */

327     public void setItemLabelGenerator(XYItemLabelGenerator generator) {
328         this.itemLabelGenerator = generator;
329         notifyListeners(new RendererChangeEvent(this));
330     }
331
332     /**
333      * Sets the item label generator for a series and sends a
334      * {@link RendererChangeEvent} to all registered listeners.
335      *
336      * @param series the series index (zero based).
337      * @param generator the generator (<code>null</code> permitted).
338      */

339     public void setSeriesItemLabelGenerator(int series,
340                                             XYItemLabelGenerator generator) {
341         this.itemLabelGeneratorList.set(series, generator);
342         notifyListeners(new RendererChangeEvent(this));
343     }
344
345     /**
346      * Returns the base item label generator.
347      *
348      * @return The generator (possibly <code>null</code>).
349      */

350     public XYItemLabelGenerator getBaseItemLabelGenerator() {
351         return this.baseItemLabelGenerator;
352     }
353
354     /**
355      * Sets the base item label generator and sends a
356      * {@link RendererChangeEvent} to all registered listeners.
357      *
358      * @param generator the generator (<code>null</code> permitted).
359      */

360     public void setBaseItemLabelGenerator(XYItemLabelGenerator generator) {
361         this.baseItemLabelGenerator = generator;
362         notifyListeners(new RendererChangeEvent(this));
363     }
364
365     // TOOL TIP GENERATOR
366

367     /**
368      * Returns the tool tip generator for a data item. This implementation
369      * simply passes control to the getSeriesToolTipGenerator() method. If,
370      * for some reason, you want a different generator for individual items,
371      * you can override this method.
372      *
373      * @param row the row index (zero based).
374      * @param column the column index (zero based).
375      *
376      * @return The generator (possibly <code>null</code>).
377      */

378     public XYToolTipGenerator getToolTipGenerator(int row, int column) {
379         return getSeriesToolTipGenerator(row);
380     }
381
382     /**
383      * Returns the tool tip generator for a series.
384      *
385      * @param series the series index (zero based).
386      *
387      * @return The generator (possibly <code>null</code>).
388      */

389     public XYToolTipGenerator getSeriesToolTipGenerator(int series) {
390
391         // return the generator for ALL series, if there is one...
392
if (this.toolTipGenerator != null) {
393             return this.toolTipGenerator;
394         }
395
396         // otherwise look up the generator table
397
XYToolTipGenerator generator
398             = (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
399         if (generator == null) {
400             generator = this.baseToolTipGenerator;
401         }
402         return generator;
403
404     }
405
406     /**
407      * Sets the tool tip generator for ALL series and sends a
408      * {@link RendererChangeEvent} to all registered listeners.
409      *
410      * @param generator the generator (<code>null</code> permitted).
411      */

412     public void setToolTipGenerator(XYToolTipGenerator generator) {
413         this.toolTipGenerator = generator;
414         notifyListeners(new RendererChangeEvent(this));
415     }
416
417     /**
418      * Sets the tool tip generator for a series and sends a
419      * {@link RendererChangeEvent} to all registered listeners.
420      *
421      * @param series the series index (zero based).
422      * @param generator the generator (<code>null</code> permitted).
423      */

424     public void setSeriesToolTipGenerator(int series,
425                                           XYToolTipGenerator generator) {
426         this.toolTipGeneratorList.set(series, generator);
427         notifyListeners(new RendererChangeEvent(this));
428     }
429
430     /**
431      * Returns the base tool tip generator.
432      *
433      * @return The generator (possibly <code>null</code>).
434      */

435     public XYToolTipGenerator getBaseToolTipGenerator() {
436         return this.baseToolTipGenerator;
437     }
438
439     /**
440      * Sets the base tool tip generator and sends a {@link RendererChangeEvent}
441      * to all registered listeners.
442      *
443      * @param generator the generator (<code>null</code> permitted).
444      */

445     public void setBaseToolTipGenerator(XYToolTipGenerator generator) {
446         this.baseToolTipGenerator = generator;
447         notifyListeners(new RendererChangeEvent(this));
448     }
449
450     // URL GENERATOR
451

452     /**
453      * Returns the URL generator for HTML image maps.
454      *
455      * @return The URL generator (possibly <code>null</code>).
456      */

457     public XYURLGenerator getURLGenerator() {
458         return this.urlGenerator;
459     }
460
461     /**
462      * Sets the URL generator for HTML image maps.
463      *
464      * @param urlGenerator the URL generator (<code>null</code> permitted).
465      */

466     public void setURLGenerator(XYURLGenerator urlGenerator) {
467         this.urlGenerator = urlGenerator;
468         notifyListeners(new RendererChangeEvent(this));
469     }
470
471     /**
472      * Adds an annotation and sends a {@link RendererChangeEvent} to all
473      * registered listeners. The annotation is added to the foreground
474      * layer.
475      *
476      * @param annotation the annotation (<code>null</code> not permitted).
477      */

478     public void addAnnotation(XYAnnotation annotation) {
479         // defer argument checking
480
addAnnotation(annotation, Layer.FOREGROUND);
481     }
482     
483     /**
484      * Adds an annotation to the specified layer.
485      *
486      * @param annotation the annotation (<code>null</code> not permitted).
487      * @param layer the layer (<code>null</code> not permitted).
488      */

489     public void addAnnotation(XYAnnotation annotation, Layer layer) {
490         if (annotation == null) {
491             throw new IllegalArgumentException JavaDoc("Null 'annotation' argument.");
492         }
493         if (layer.equals(Layer.FOREGROUND)) {
494             this.foregroundAnnotations.add(annotation);
495             notifyListeners(new RendererChangeEvent(this));
496         }
497         else if (layer.equals(Layer.BACKGROUND)) {
498             this.backgroundAnnotations.add(annotation);
499             notifyListeners(new RendererChangeEvent(this));
500         }
501         else {
502             // should never get here
503
throw new RuntimeException JavaDoc("Unknown layer.");
504         }
505     }
506     /**
507      * Removes the specified annotation and sends a {@link RendererChangeEvent}
508      * to all registered listeners.
509      *
510      * @param annotation the annotation to remove (<code>null</code> not
511      * permitted).
512      *
513      * @return A boolean to indicate whether or not the annotation was
514      * successfully removed.
515      */

516     public boolean removeAnnotation(XYAnnotation annotation) {
517         boolean removed = this.foregroundAnnotations.remove(annotation);
518         removed = removed & this.backgroundAnnotations.remove(annotation);
519         notifyListeners(new RendererChangeEvent(this));
520         return removed;
521     }
522     
523     /**
524      * Removes all annotations and sends a {@link RendererChangeEvent}
525      * to all registered listeners.
526      */

527     public void removeAnnotations() {
528         this.foregroundAnnotations.clear();
529         this.backgroundAnnotations.clear();
530         notifyListeners(new RendererChangeEvent(this));
531     }
532     
533     /**
534      * Returns the radius of the circle used for the default entity area
535      * when no area is specified.
536      *
537      * @return A radius.
538      */

539     public int getDefaultEntityRadius() {
540         return this.defaultEntityRadius;
541     }
542     
543     /**
544      * Sets the radius of the circle used for the default entity area
545      * when no area is specified.
546      *
547      * @param radius the radius.
548      */

549     public void setDefaultEntityRadius(int radius) {
550         this.defaultEntityRadius = radius;
551     }
552     
553     /**
554      * Returns the legend item label generator.
555      *
556      * @return The label generator (never <code>null</code>).
557      */

558     public XYSeriesLabelGenerator getLegendItemLabelGenerator() {
559         return this.legendItemLabelGenerator;
560     }
561     
562     /**
563      * Sets the legend item label generator.
564      *
565      * @param generator the generator (<code>null</code> not permitted).
566      */

567     public void setLegendItemLabelGenerator(XYSeriesLabelGenerator generator) {
568         if (generator == null) {
569             throw new IllegalArgumentException JavaDoc("Null 'generator' argument.");
570         }
571         this.legendItemLabelGenerator = generator;
572     }
573     
574     /**
575      * Returns the legend item tool tip generator.
576      *
577      * @return The tool tip generator (possibly <code>null</code>).
578      */

579     public XYSeriesLabelGenerator getLegendItemToolTipGenerator() {
580         return this.legendItemToolTipGenerator;
581     }
582     
583     /**
584      * Sets the legend item tool tip generator.
585      *
586      * @param generator the generator (<code>null</code> permitted).
587      */

588     public void setLegendItemToolTipGenerator(XYSeriesLabelGenerator generator)
589     {
590         this.legendItemToolTipGenerator = generator;
591     }
592     
593     /**
594      * Returns the legend item URL generator.
595      *
596      * @return The URL generator (possibly <code>null</code>).
597      */

598     public XYSeriesLabelGenerator getLegendItemURLGenerator() {
599         return this.legendItemURLGenerator;
600     }
601     
602     /**
603      * Sets the legend item URL generator.
604      *
605      * @param generator the generator (<code>null</code> permitted).
606      */

607     public void setLegendItemURLGenerator(XYSeriesLabelGenerator generator)
608     {
609         this.legendItemURLGenerator = generator;
610     }
611     
612     /**
613      * Returns the lower and upper bounds (range) of the x-values in the
614      * specified dataset.
615      *
616      * @param dataset the dataset (<code>null</code> permitted).
617      *
618      * @return The range (<code>null</code> if the dataset is <code>null</code>
619      * or empty).
620      */

621     public Range findDomainBounds(XYDataset dataset) {
622         if (dataset != null) {
623             return DatasetUtilities.findDomainBounds(dataset, false);
624         }
625         else {
626             return null;
627         }
628     }
629
630     /**
631      * Returns the range of values the renderer requires to display all the
632      * items from the specified dataset.
633      *
634      * @param dataset the dataset (<code>null</code> permitted).
635      *
636      * @return The range (<code>null</code> if the dataset is <code>null</code>
637      * or empty).
638      */

639     public Range findRangeBounds(XYDataset dataset) {
640         if (dataset != null) {
641             return DatasetUtilities.findRangeBounds(dataset, false);
642         }
643         else {
644             return null;
645         }
646     }
647
648     /**
649      * Returns a (possibly empty) collection of legend items for the series
650      * that this renderer is responsible for drawing.
651      *
652      * @return The legend item collection (never <code>null</code>).
653      */

654     public LegendItemCollection getLegendItems() {
655         if (this.plot == null) {
656             return new LegendItemCollection();
657         }
658         LegendItemCollection result = new LegendItemCollection();
659         int index = this.plot.getIndexOf(this);
660         XYDataset dataset = this.plot.getDataset(index);
661         if (dataset != null) {
662             int seriesCount = dataset.getSeriesCount();
663             for (int i = 0; i < seriesCount; i++) {
664                 if (isSeriesVisibleInLegend(i)) {
665                     LegendItem item = getLegendItem(index, i);
666                     if (item != null) {
667                         result.add(item);
668                     }
669                 }
670             }
671    
672         }
673         return result;
674     }
675
676     /**
677      * Returns a default legend item for the specified series. Subclasses
678      * should override this method to generate customised items.
679      *
680      * @param datasetIndex the dataset index (zero-based).
681      * @param series the series index (zero-based).
682      *
683      * @return A legend item for the series.
684      */

685     public LegendItem getLegendItem(int datasetIndex, int series) {
686         LegendItem result = null;
687         XYPlot xyplot = getPlot();
688         if (xyplot != null) {
689             XYDataset dataset = xyplot.getDataset(datasetIndex);
690             if (dataset != null) {
691                 String JavaDoc label = this.legendItemLabelGenerator.generateLabel(
692                         dataset, series);
693                 String JavaDoc description = label;
694                 String JavaDoc toolTipText = null;
695                 if (getLegendItemToolTipGenerator() != null) {
696                     toolTipText = getLegendItemToolTipGenerator().generateLabel(
697                             dataset, series);
698                 }
699                 String JavaDoc urlText = null;
700                 if (getLegendItemURLGenerator() != null) {
701                     urlText = getLegendItemURLGenerator().generateLabel(
702                             dataset, series);
703                 }
704                 Shape JavaDoc shape = getSeriesShape(series);
705                 Paint JavaDoc paint = getSeriesPaint(series);
706                 Paint JavaDoc outlinePaint = getSeriesOutlinePaint(series);
707                 Stroke JavaDoc outlineStroke = getSeriesOutlineStroke(series);
708                 result = new LegendItem(label, description, toolTipText,
709                         urlText, shape, paint, outlineStroke, outlinePaint);
710                 result.setSeriesIndex(series);
711                 result.setDatasetIndex(datasetIndex);
712             }
713         }
714         return result;
715     }
716
717     /**
718      * Fills a band between two values on the axis. This can be used to color
719      * bands between the grid lines.
720      *
721      * @param g2 the graphics device.
722      * @param plot the plot.
723      * @param axis the domain axis.
724      * @param dataArea the data area.
725      * @param start the start value.
726      * @param end the end value.
727      */

728     public void fillDomainGridBand(Graphics2D JavaDoc g2,
729                                    XYPlot plot,
730                                    ValueAxis axis,
731                                    Rectangle2D JavaDoc dataArea,
732                                    double start, double end) {
733
734         double x1 = axis.valueToJava2D(start, dataArea,
735                 plot.getDomainAxisEdge());
736         double x2 = axis.valueToJava2D(end, dataArea,
737                 plot.getDomainAxisEdge());
738         // TODO: need to change the next line to take account of plot
739
// orientation...
740
Rectangle2D JavaDoc band = new Rectangle2D.Double JavaDoc(x1, dataArea.getMinY(),
741                 x2 - x1, dataArea.getMaxY() - dataArea.getMinY());
742         Paint JavaDoc paint = plot.getDomainTickBandPaint();
743
744         if (paint != null) {
745             g2.setPaint(paint);
746             g2.fill(band);
747         }
748
749     }
750
751     /**
752      * Fills a band between two values on the range axis. This can be used to
753      * color bands between the grid lines.
754      *
755      * @param g2 the graphics device.
756      * @param plot the plot.
757      * @param axis the range axis.
758      * @param dataArea the data area.
759      * @param start the start value.
760      * @param end the end value.
761      */

762     public void fillRangeGridBand(Graphics2D JavaDoc g2,
763                                   XYPlot plot,
764                                   ValueAxis axis,
765                                   Rectangle2D JavaDoc dataArea,
766                                   double start, double end) {
767
768         double y1 = axis.valueToJava2D(start, dataArea,
769                 plot.getRangeAxisEdge());
770         double y2 = axis.valueToJava2D(end, dataArea, plot.getRangeAxisEdge());
771         // TODO: need to change the next line to take account of the plot
772
// orientation
773
Rectangle2D JavaDoc band = new Rectangle2D.Double JavaDoc(dataArea.getMinX(), y2,
774                 dataArea.getWidth(), y1 - y2);
775         Paint JavaDoc paint = plot.getRangeTickBandPaint();
776
777         if (paint != null) {
778             g2.setPaint(paint);
779             g2.fill(band);
780         }
781
782     }
783
784     /**
785      * Draws a grid line against the range axis.
786      *
787      * @param g2 the graphics device.
788      * @param plot the plot.
789      * @param axis the value axis.
790      * @param dataArea the area for plotting data (not yet adjusted for any
791      * 3D effect).
792      * @param value the value at which the grid line should be drawn.
793      */

794     public void drawDomainGridLine(Graphics2D JavaDoc g2,
795                                    XYPlot plot,
796                                    ValueAxis axis,
797                                    Rectangle2D JavaDoc dataArea,
798                                    double value) {
799
800         Range range = axis.getRange();
801         if (!range.contains(value)) {
802             return;
803         }
804
805         PlotOrientation orientation = plot.getOrientation();
806         double v = axis.valueToJava2D(value, dataArea,
807                 plot.getDomainAxisEdge());
808         Line2D JavaDoc line = null;
809         if (orientation == PlotOrientation.HORIZONTAL) {
810             line = new Line2D.Double JavaDoc(dataArea.getMinX(), v,
811                     dataArea.getMaxX(), v);
812         }
813         else if (orientation == PlotOrientation.VERTICAL) {
814             line = new Line2D.Double JavaDoc(v, dataArea.getMinY(), v,
815                     dataArea.getMaxY());
816         }
817
818         Paint JavaDoc paint = plot.getDomainGridlinePaint();
819         Stroke JavaDoc stroke = plot.getDomainGridlineStroke();
820         g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
821         g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
822         g2.draw(line);
823
824     }
825
826     /**
827      * Draws a line perpendicular to the range axis.
828      *
829      * @param g2 the graphics device.
830      * @param plot the plot.
831      * @param axis the value axis.
832      * @param dataArea the area for plotting data (not yet adjusted for any 3D
833      * effect).
834      * @param value the value at which the grid line should be drawn.
835      * @param paint the paint.
836      * @param stroke the stroke.
837      */

838     public void drawRangeLine(Graphics2D JavaDoc g2,
839                               XYPlot plot,
840                               ValueAxis axis,
841                               Rectangle2D JavaDoc dataArea,
842                               double value,
843                               Paint JavaDoc paint,
844                               Stroke JavaDoc stroke) {
845
846         Range range = axis.getRange();
847         if (!range.contains(value)) {
848             return;
849         }
850
851         PlotOrientation orientation = plot.getOrientation();
852         Line2D JavaDoc line = null;
853         double v = axis.valueToJava2D(value, dataArea, plot.getRangeAxisEdge());
854         if (orientation == PlotOrientation.HORIZONTAL) {
855             line = new Line2D.Double JavaDoc(v, dataArea.getMinY(), v,
856                     dataArea.getMaxY());
857         }
858         else if (orientation == PlotOrientation.VERTICAL) {
859             line = new Line2D.Double JavaDoc(dataArea.getMinX(), v,
860                     dataArea.getMaxX(), v);
861         }
862         
863         g2.setPaint(paint);
864         g2.setStroke(stroke);
865         g2.draw(line);
866
867     }
868
869     /**
870      * Draws a vertical line on the chart to represent a 'range marker'.
871      *
872      * @param g2 the graphics device.
873      * @param plot the plot.
874      * @param domainAxis the domain axis.
875      * @param marker the marker line.
876      * @param dataArea the axis data area.
877      */

878     public void drawDomainMarker(Graphics2D JavaDoc g2,
879                                  XYPlot plot,
880                                  ValueAxis domainAxis,
881                                  Marker marker,
882                                  Rectangle2D JavaDoc dataArea) {
883
884         if (marker instanceof ValueMarker) {
885             ValueMarker vm = (ValueMarker) marker;
886             double value = vm.getValue();
887             Range range = domainAxis.getRange();
888             if (!range.contains(value)) {
889                 return;
890             }
891
892             double v = domainAxis.valueToJava2D(value, dataArea,
893                     plot.getDomainAxisEdge());
894
895             PlotOrientation orientation = plot.getOrientation();
896             Line2D JavaDoc line = null;
897             if (orientation == PlotOrientation.HORIZONTAL) {
898                 line = new Line2D.Double JavaDoc(dataArea.getMinX(), v,
899                         dataArea.getMaxX(), v);
900             }
901             else if (orientation == PlotOrientation.VERTICAL) {
902                 line = new Line2D.Double JavaDoc(v, dataArea.getMinY(), v,
903                         dataArea.getMaxY());
904             }
905
906             final Composite JavaDoc originalComposite = g2.getComposite();
907             g2.setComposite(AlphaComposite.getInstance(
908                     AlphaComposite.SRC_OVER, marker.getAlpha()));
909             g2.setPaint(marker.getPaint());
910             g2.setStroke(marker.getStroke());
911             g2.draw(line);
912
913             String JavaDoc label = marker.getLabel();
914             RectangleAnchor anchor = marker.getLabelAnchor();
915             if (label != null) {
916                 Font JavaDoc labelFont = marker.getLabelFont();
917                 g2.setFont(labelFont);
918                 g2.setPaint(marker.getLabelPaint());
919                 Point2D JavaDoc coordinates = calculateDomainMarkerTextAnchorPoint(
920                         g2, orientation, dataArea, line.getBounds2D(),
921                         marker.getLabelOffset(),
922                         LengthAdjustmentType.EXPAND, anchor);
923                 TextUtilities.drawAlignedString(label, g2,
924                         (float) coordinates.getX(), (float) coordinates.getY(),
925                         marker.getLabelTextAnchor());
926             }
927             g2.setComposite(originalComposite);
928         }
929         else if (marker instanceof IntervalMarker) {
930             IntervalMarker im = (IntervalMarker) marker;
931             double start = im.getStartValue();
932             double end = im.getEndValue();
933             Range range = domainAxis.getRange();
934             if (!(range.intersects(start, end))) {
935                 return;
936             }
937
938             double start2d = domainAxis.valueToJava2D(start, dataArea,
939                     plot.getDomainAxisEdge());
940             double end2d = domainAxis.valueToJava2D(end, dataArea,
941                     plot.getDomainAxisEdge());
942
943             PlotOrientation orientation = plot.getOrientation();
944             Rectangle2D JavaDoc rect = null;
945             if (orientation == PlotOrientation.HORIZONTAL) {
946                 rect = new Rectangle2D.Double JavaDoc(dataArea.getMinX(),
947                         Math.min(start2d, end2d), dataArea.getWidth(),
948                         Math.abs(end2d - start2d));
949             }
950             else if (orientation == PlotOrientation.VERTICAL) {
951                 rect = new Rectangle2D.Double JavaDoc(Math.min(start2d, end2d),
952                         dataArea.getMinY(), Math.abs(end2d - start2d),
953                         dataArea.getHeight());
954             }
955
956             final Composite JavaDoc originalComposite = g2.getComposite();
957             g2.setComposite(AlphaComposite.getInstance(
958                     AlphaComposite.SRC_OVER, marker.getAlpha()));
959             Paint JavaDoc p = marker.getPaint();
960             if (p instanceof GradientPaint JavaDoc) {
961                 GradientPaint JavaDoc gp = (GradientPaint JavaDoc) p;
962                 GradientPaintTransformer t = im.getGradientPaintTransformer();
963                 if (t != null) {
964                     gp = t.transform(gp, rect);
965                 }
966                 g2.setPaint(gp);
967             }
968             else {
969                 g2.setPaint(p);
970             }
971             g2.fill(rect);
972             
973             // now draw the outlines, if visible...
974
if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) {
975                 double x0 = rect.getMinX();
976                 double x1 = rect.getMaxX();
977                 double y0 = rect.getMinY();
978                 double y1 = rect.getMaxY();
979                 if (orientation == PlotOrientation.VERTICAL) {
980                     Line2D JavaDoc line = new Line2D.Double JavaDoc(x0, y0, x0, y1);
981                     g2.setPaint(im.getOutlinePaint());
982                     g2.setStroke(im.getOutlineStroke());
983                     g2.draw(line);
984                     line.setLine(x1, y0, x1, y1);
985                     g2.draw(line);
986                 }
987                 else { // PlotOrientation.HORIZONTAL
988
Line2D JavaDoc line = new Line2D.Double JavaDoc(x0, y0, x1, y0);
989                     g2.setPaint(im.getOutlinePaint());
990                     g2.setStroke(im.getOutlineStroke());
991                     g2.draw(line);
992                     line.setLine(x0, y1, x1, y1);
993                     g2.draw(line);
994                 }
995             }
996
997             String JavaDoc label = marker.getLabel();
998             RectangleAnchor anchor = marker.getLabelAnchor();
999             if (label != null) {
1000                Font JavaDoc labelFont = marker.getLabelFont();
1001                g2.setFont(labelFont);
1002                g2.setPaint(marker.getLabelPaint());
1003                Point2D JavaDoc coordinates = calculateDomainMarkerTextAnchorPoint(
1004                        g2, orientation, dataArea, rect,
1005                        marker.getLabelOffset(), marker.getLabelOffsetType(),
1006                        anchor);
1007                TextUtilities.drawAlignedString(label, g2,
1008                        (float) coordinates.getX(), (float) coordinates.getY(),
1009                        marker.getLabelTextAnchor());
1010            }
1011            g2.setComposite(originalComposite);
1012
1013        }
1014
1015    }
1016
1017    /**
1018     * Calculates the (x, y) coordinates for drawing a marker label.
1019     *
1020     * @param g2 the graphics device.
1021     * @param orientation the plot orientation.
1022     * @param dataArea the data area.
1023     * @param markerArea the rectangle surrounding the marker area.
1024     * @param markerOffset the marker label offset.
1025     * @param labelOffsetType the label offset type.
1026     * @param anchor the label anchor.
1027     *
1028     * @return The coordinates for drawing the marker label.
1029     */

1030    protected Point2D JavaDoc calculateDomainMarkerTextAnchorPoint(Graphics2D JavaDoc g2,
1031            PlotOrientation orientation,
1032            Rectangle2D JavaDoc dataArea,
1033            Rectangle2D JavaDoc markerArea,
1034            RectangleInsets markerOffset,
1035            LengthAdjustmentType labelOffsetType,
1036            RectangleAnchor anchor) {
1037
1038        Rectangle2D JavaDoc anchorRect = null;
1039        if (orientation == PlotOrientation.HORIZONTAL) {
1040            anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1041                    LengthAdjustmentType.CONTRACT, labelOffsetType);
1042        }
1043        else if (orientation == PlotOrientation.VERTICAL) {
1044            anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1045                    labelOffsetType, LengthAdjustmentType.CONTRACT);
1046        }
1047        return RectangleAnchor.coordinates(anchorRect, anchor);
1048
1049    }
1050
1051    /**
1052     * Draws a horizontal line across the chart to represent a 'range marker'.
1053     *
1054     * @param g2 the graphics device.
1055     * @param plot the plot.
1056     * @param rangeAxis the range axis.
1057     * @param marker the marker line.
1058     * @param dataArea the axis data area.
1059     */

1060    public void drawRangeMarker(Graphics2D JavaDoc g2,
1061                                XYPlot plot,
1062                                ValueAxis rangeAxis,
1063                                Marker marker,
1064                                Rectangle2D JavaDoc dataArea) {
1065
1066        if (marker instanceof ValueMarker) {
1067            ValueMarker vm = (ValueMarker) marker;
1068            double value = vm.getValue();
1069            Range range = rangeAxis.getRange();
1070            if (!range.contains(value)) {
1071                return;
1072            }
1073
1074            double v = rangeAxis.valueToJava2D(value, dataArea,
1075                    plot.getRangeAxisEdge());
1076            PlotOrientation orientation = plot.getOrientation();
1077            Line2D JavaDoc line = null;
1078            if (orientation == PlotOrientation.HORIZONTAL) {
1079                line = new Line2D.Double JavaDoc(v, dataArea.getMinY(), v,
1080                        dataArea.getMaxY());
1081            }
1082            else if (orientation == PlotOrientation.VERTICAL) {
1083                line = new Line2D.Double JavaDoc(dataArea.getMinX(), v,
1084                        dataArea.getMaxX(), v);
1085            }
1086
1087            final Composite JavaDoc originalComposite = g2.getComposite();
1088            g2.setComposite(AlphaComposite.getInstance(
1089                    AlphaComposite.SRC_OVER, marker.getAlpha()));
1090            g2.setPaint(marker.getPaint());
1091            g2.setStroke(marker.getStroke());
1092            g2.draw(line);
1093
1094            String JavaDoc label = marker.getLabel();
1095            RectangleAnchor anchor = marker.getLabelAnchor();
1096            if (label != null) {
1097                Font JavaDoc labelFont = marker.getLabelFont();
1098                g2.setFont(labelFont);
1099                g2.setPaint(marker.getLabelPaint());
1100                Point2D JavaDoc coordinates = calculateRangeMarkerTextAnchorPoint(
1101                        g2, orientation, dataArea, line.getBounds2D(),
1102                        marker.getLabelOffset(),
1103                        LengthAdjustmentType.EXPAND, anchor);
1104                TextUtilities.drawAlignedString(label, g2,
1105                        (float) coordinates.getX(), (float) coordinates.getY(),
1106                        marker.getLabelTextAnchor());
1107            }
1108            g2.setComposite(originalComposite);
1109        }
1110        else if (marker instanceof IntervalMarker) {
1111            
1112            IntervalMarker im = (IntervalMarker) marker;
1113            double start = im.getStartValue();
1114            double end = im.getEndValue();
1115            Range range = rangeAxis.getRange();
1116            if (!(range.intersects(start, end))) {
1117                return;
1118            }
1119
1120            double start2d = rangeAxis.valueToJava2D(start, dataArea,
1121                    plot.getRangeAxisEdge());
1122            double end2d = rangeAxis.valueToJava2D(end, dataArea,
1123                    plot.getRangeAxisEdge());
1124
1125            PlotOrientation orientation = plot.getOrientation();
1126            Rectangle2D JavaDoc rect = null;
1127            if (orientation == PlotOrientation.HORIZONTAL) {
1128                rect = new Rectangle2D.Double JavaDoc(Math.min(start2d, end2d),
1129                        dataArea.getMinY(), Math.abs(end2d - start2d),
1130                        dataArea.getHeight());
1131            }
1132            else if (orientation == PlotOrientation.VERTICAL) {
1133                rect = new Rectangle2D.Double JavaDoc(dataArea.getMinX(),
1134                        Math.min(start2d, end2d), dataArea.getWidth(),
1135                        Math.abs(end2d - start2d));
1136            }
1137
1138            final Composite JavaDoc originalComposite = g2.getComposite();
1139            g2.setComposite(AlphaComposite.getInstance(
1140                    AlphaComposite.SRC_OVER, marker.getAlpha()));
1141            Paint JavaDoc p = marker.getPaint();
1142            if (p instanceof GradientPaint JavaDoc) {
1143                GradientPaint JavaDoc gp = (GradientPaint JavaDoc) p;
1144                GradientPaintTransformer t = im.getGradientPaintTransformer();
1145                if (t != null) {
1146                    gp = t.transform(gp, rect);
1147                }
1148                g2.setPaint(gp);
1149            }
1150            else {
1151                g2.setPaint(p);
1152            }
1153            g2.fill(rect);
1154            
1155            // now draw the outlines, if visible...
1156
if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) {
1157                double x0 = rect.getMinX();
1158                double x1 = rect.getMaxX();
1159                double y0 = rect.getMinY();
1160                double y1 = rect.getMaxY();
1161                if (orientation == PlotOrientation.VERTICAL) {
1162                    Line2D JavaDoc line = new Line2D.Double JavaDoc(x0, y0, x0, y1);
1163                    g2.setPaint(im.getOutlinePaint());
1164                    g2.setStroke(im.getOutlineStroke());
1165                    g2.draw(line);
1166                    line.setLine(x1, y0, x1, y1);
1167                    g2.draw(line);
1168                }
1169                else { // PlotOrientation.HORIZONTAL
1170
Line2D JavaDoc line = new Line2D.Double JavaDoc(x0, y0, x1, y0);
1171                    g2.setPaint(im.getOutlinePaint());
1172                    g2.setStroke(im.getOutlineStroke());
1173                    g2.draw(line);
1174                    line.setLine(x0, y1, x1, y1);
1175                    g2.draw(line);
1176                }
1177            }
1178            
1179            String JavaDoc label = marker.getLabel();
1180            RectangleAnchor anchor = marker.getLabelAnchor();
1181            if (label != null) {
1182                Font JavaDoc labelFont = marker.getLabelFont();
1183                g2.setFont(labelFont);
1184                g2.setPaint(marker.getLabelPaint());
1185                Point2D JavaDoc coordinates = calculateRangeMarkerTextAnchorPoint(
1186                        g2, orientation, dataArea, rect,
1187                        marker.getLabelOffset(), marker.getLabelOffsetType(),
1188                        anchor);
1189                TextUtilities.drawAlignedString(label, g2,
1190                        (float) coordinates.getX(), (float) coordinates.getY(),
1191                        marker.getLabelTextAnchor());
1192            }
1193            g2.setComposite(originalComposite);
1194        }
1195    }
1196
1197    /**
1198     * Calculates the (x, y) coordinates for drawing a marker label.
1199     *
1200     * @param g2 the graphics device.
1201     * @param orientation the plot orientation.
1202     * @param dataArea the data area.
1203     * @param markerArea the marker area.
1204     * @param markerOffset the marker offset.
1205     * @param anchor the label anchor.
1206     *
1207     * @return The coordinates for drawing the marker label.
1208     */

1209    private Point2D JavaDoc calculateRangeMarkerTextAnchorPoint(Graphics2D JavaDoc g2,
1210                                      PlotOrientation orientation,
1211                                      Rectangle2D JavaDoc dataArea,
1212                                      Rectangle2D JavaDoc markerArea,
1213                                      RectangleInsets markerOffset,
1214                                      LengthAdjustmentType labelOffsetForRange,
1215                                      RectangleAnchor anchor) {
1216
1217        Rectangle2D JavaDoc anchorRect = null;
1218        if (orientation == PlotOrientation.HORIZONTAL) {
1219            anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1220                    labelOffsetForRange, LengthAdjustmentType.CONTRACT);
1221        }
1222        else if (orientation == PlotOrientation.VERTICAL) {
1223            anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1224                    LengthAdjustmentType.CONTRACT, labelOffsetForRange);
1225        }
1226        return RectangleAnchor.coordinates(anchorRect, anchor);
1227
1228    }
1229
1230    /**
1231     * Returns a clone of the renderer.
1232     *
1233     * @return A clone.
1234     *
1235     * @throws CloneNotSupportedException if the renderer does not support
1236     * cloning.
1237     */

1238    protected Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
1239        AbstractXYItemRenderer clone = (AbstractXYItemRenderer) super.clone();
1240        // 'plot' : just retain reference, not a deep copy
1241
if (this.itemLabelGenerator != null
1242                && this.itemLabelGenerator instanceof PublicCloneable) {
1243            PublicCloneable pc = (PublicCloneable) this.itemLabelGenerator;
1244            clone.itemLabelGenerator = (XYItemLabelGenerator) pc.clone();
1245        }
1246        return clone;
1247    }
1248
1249    /**
1250     * Tests this renderer for equality with another object.
1251     *
1252     * @param obj the object.
1253     *
1254     * @return <code>true</code> or <code>false</code>.
1255     */

1256    public boolean equals(Object JavaDoc obj) {
1257
1258        if (obj == null) {
1259            return false;
1260        }
1261        if (obj == this) {
1262            return true;
1263        }
1264        if (!(obj instanceof AbstractXYItemRenderer)) {
1265            return false;
1266        }
1267        AbstractXYItemRenderer renderer = (AbstractXYItemRenderer) obj;
1268        if (!super.equals(obj)) {
1269            return false;
1270        }
1271        if (!ObjectUtilities.equal(this.itemLabelGenerator,
1272                renderer.itemLabelGenerator)) {
1273            return false;
1274        }
1275        if (!ObjectUtilities.equal(this.urlGenerator, renderer.urlGenerator)) {
1276            return false;
1277        }
1278        return true;
1279    }
1280
1281    /**
1282     * Returns the drawing supplier from the plot.
1283     *
1284     * @return The drawing supplier (possibly <code>null</code>).
1285     */

1286    public DrawingSupplier getDrawingSupplier() {
1287        DrawingSupplier result = null;
1288        XYPlot p = getPlot();
1289        if (p != null) {
1290            result = p.getDrawingSupplier();
1291        }
1292        return result;
1293    }
1294
1295    /**
1296     * Considers the current (x, y) coordinate and updates the crosshair point
1297     * if it meets the criteria (usually means the (x, y) coordinate is the
1298     * closest to the anchor point so far).
1299     *
1300     * @param crosshairState the crosshair state (<code>null</code> permitted,
1301     * but the method does nothing in that case).
1302     * @param x the x-value (in data space).
1303     * @param y the y-value (in data space).
1304     * @param transX the x-value translated to Java2D space.
1305     * @param transY the y-value translated to Java2D space.
1306     * @param orientation the plot orientation (<code>null</code> not
1307     * permitted).
1308     */

1309    protected void updateCrosshairValues(CrosshairState crosshairState,
1310                                         double x, double y, double transX,
1311                                         double transY,
1312                                         PlotOrientation orientation) {
1313
1314        if (orientation == null) {
1315            throw new IllegalArgumentException JavaDoc("Null 'orientation' argument.");
1316        }
1317
1318        if (crosshairState != null) {
1319            // do we need to update the crosshair values?
1320
if (this.plot.isDomainCrosshairLockedOnData()) {
1321                if (this.plot.isRangeCrosshairLockedOnData()) {
1322                    // both axes
1323
crosshairState.updateCrosshairPoint(x, y, transX, transY,
1324                            orientation);
1325                }
1326                else {
1327                    // just the domain axis...
1328
crosshairState.updateCrosshairX(x);
1329                }
1330            }
1331            else {
1332                if (this.plot.isRangeCrosshairLockedOnData()) {
1333                    // just the range axis...
1334
crosshairState.updateCrosshairY(y);
1335                }
1336            }
1337        }
1338
1339    }
1340    
1341    /**
1342     * Draws an item label.
1343     *
1344     * @param g2 the graphics device.
1345     * @param orientation the orientation.
1346     * @param dataset the dataset.
1347     * @param series the series index (zero-based).
1348     * @param item the item index (zero-based).
1349     * @param x the x coordinate (in Java2D space).
1350     * @param y the y coordinate (in Java2D space).
1351     * @param negative indicates a negative value (which affects the item
1352     * label position).
1353     */

1354    protected void drawItemLabel(Graphics2D JavaDoc g2, PlotOrientation orientation,
1355            XYDataset dataset, int series, int item, double x, double y,
1356            boolean negative) {
1357                                     
1358        XYItemLabelGenerator generator = getItemLabelGenerator(series, item);
1359        if (generator != null) {
1360            Font JavaDoc labelFont = getItemLabelFont(series, item);
1361            Paint JavaDoc paint = getItemLabelPaint(series, item);
1362            g2.setFont(labelFont);
1363            g2.setPaint(paint);
1364            String JavaDoc label = generator.generateLabel(dataset, series, item);
1365
1366            // get the label position..
1367
ItemLabelPosition position = null;
1368            if (!negative) {
1369                position = getPositiveItemLabelPosition(series, item);
1370            }
1371            else {
1372                position = getNegativeItemLabelPosition(series, item);
1373            }
1374
1375            // work out the label anchor point...
1376
Point2D JavaDoc anchorPoint = calculateLabelAnchorPoint(
1377                    position.getItemLabelAnchor(), x, y, orientation);
1378            TextUtilities.drawRotatedString(label, g2,
1379                    (float) anchorPoint.getX(), (float) anchorPoint.getY(),
1380                    position.getTextAnchor(), position.getAngle(),
1381                    position.getRotationAnchor());
1382        }
1383
1384    }
1385    
1386    /**
1387     * Draws all the annotations for the specified layer.
1388     *
1389     * @param g2 the graphics device.
1390     * @param dataArea the data area.
1391     * @param domainAxis the domain axis.
1392     * @param rangeAxis the range axis.
1393     * @param layer the layer.
1394     * @param info the plot rendering info.
1395     */

1396    public void drawAnnotations(Graphics2D JavaDoc g2,
1397                                Rectangle2D JavaDoc dataArea,
1398                                ValueAxis domainAxis,
1399                                ValueAxis rangeAxis,
1400                                Layer layer,
1401                                PlotRenderingInfo info) {
1402        
1403        Iterator JavaDoc iterator = null;
1404        if (layer.equals(Layer.FOREGROUND)) {
1405            iterator = this.foregroundAnnotations.iterator();
1406        }
1407        else if (layer.equals(Layer.BACKGROUND)) {
1408            iterator = this.backgroundAnnotations.iterator();
1409        }
1410        else {
1411            // should not get here
1412
throw new RuntimeException JavaDoc("Unknown layer.");
1413        }
1414        while (iterator.hasNext()) {
1415            XYAnnotation annotation = (XYAnnotation) iterator.next();
1416            annotation.draw(g2, this.plot, dataArea, domainAxis, rangeAxis,
1417                    0, info);
1418        }
1419        
1420    }
1421
1422    /**
1423     * Adds an entity to the collection.
1424     *
1425     * @param entities the entity collection being populated.
1426     * @param area the entity area (if <code>null</code> a default will be
1427     * used).
1428     * @param dataset the dataset.
1429     * @param series the series.
1430     * @param item the item.
1431     * @param entityX the entity's center x-coordinate in user space.
1432     * @param entityY the entity's center y-coordinate in user space.
1433     */

1434    protected void addEntity(EntityCollection entities, Shape JavaDoc area,
1435                             XYDataset dataset, int series, int item,
1436                             double entityX, double entityY) {
1437        if (!getItemCreateEntity(series, item)) {
1438            return;
1439        }
1440        if (area == null) {
1441            area = new Ellipse2D.Double JavaDoc(entityX - this.defaultEntityRadius,
1442                    entityY - this.defaultEntityRadius,
1443                    this.defaultEntityRadius * 2, this.defaultEntityRadius * 2);
1444        }
1445        String JavaDoc tip = null;
1446        XYToolTipGenerator generator = getToolTipGenerator(series, item);
1447        if (generator != null) {
1448            tip = generator.generateToolTip(dataset, series, item);
1449        }
1450        String JavaDoc url = null;
1451        if (getURLGenerator() != null) {
1452            url = getURLGenerator().generateURL(dataset, series, item);
1453        }
1454        XYItemEntity entity = new XYItemEntity(area, dataset, series, item,
1455                tip, url);
1456        entities.add(entity);
1457    }
1458
1459}
1460
Popular Tags