1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2013, 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  * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
25  * Other names may be trademarks of their respective owners.]
26  *
27  * ---------------------------
28  * AbstractXYItemRenderer.java
29  * ---------------------------
30  * (C) Copyright 2002-2013, 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  *                   Peter Kolb (patch 2809117);
38  *                   Martin Krauskopf;
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  * 24-Nov-2006 : Fixed cloning for legend item generators (DG);
94  * 06-Feb-2007 : Added new updateCrosshairValues() method that takes into
95  *               account multiple axis plots (see bug 1086307) (DG);
96  * 20-Feb-2007 : Fixed equals() method implementation (DG);
97  * 01-Mar-2007 : Fixed interval marker drawing (patch 1670686 thanks to
98  *               Sergei Ivanov) (DG);
99  * 22-Mar-2007 : Modified the tool tip generator look up (DG);
100  * 23-Mar-2007 : Added drawDomainLine() method (DG);
101  * 20-Apr-2007 : Updated getLegendItem() for renderer change, and deprecated
102  *               itemLabelGenerator and toolTipGenerator override fields (DG);
103  * 18-May-2007 : Set dataset and seriesKey for LegendItem (DG);
104  * 12-Nov-2007 : Fixed domain and range band drawing methods (DG);
105  * 07-Apr-2008 : Minor API doc update (DG);
106  * 14-May-2008 : Updated addEntity() method to take plot orientation into
107  *               account when the incoming area is null (DG);
108  * 02-Jun-2008 : Added isPointInRect() method (DG);
109  * 17-Jun-2008 : Apply legend shape, font and paint attributes (DG);
110  * 09-Mar-2009 : Added getAnnotations() method (DG);
111  * 27-Mar-2009 : Added new findDomainBounds() and findRangeBounds() methods to
112  *               take account of hidden series (DG);
113  * 01-Apr-2009 : Moved defaultEntityRadius up to superclass (DG);
114  * 28-Apr-2009 : Updated getLegendItem() method to observe new
115  *               'treatLegendShapeAsLine' flag (DG);
116  * 24-Jun-2009 : Added support for annotation events - see patch 2809117
117  *               by PK (DG);
118  * 01-Sep-2009 : Bug 2840132 - set renderer index when drawing
119  *               annotations (DG);
120  * 06-Oct-2011 : Add utility methods to work with 1.4 API in GeneralPath (MK)
121  * 03-Jul-2013 : Use ParamChecks (DG);
122  *
123  */
124 
125 package org.jfree.chart.renderer.xy;
126 
127 import java.awt.AlphaComposite;
128 import java.awt.Composite;
129 import java.awt.Font;
130 import java.awt.GradientPaint;
131 import java.awt.Graphics2D;
132 import java.awt.Paint;
133 import java.awt.Shape;
134 import java.awt.Stroke;
135 import java.awt.geom.Ellipse2D;
136 import java.awt.geom.GeneralPath;
137 import java.awt.geom.Line2D;
138 import java.awt.geom.Point2D;
139 import java.awt.geom.Rectangle2D;
140 import java.io.Serializable;
141 import java.util.ArrayList;
142 import java.util.Collection;
143 import java.util.Iterator;
144 import java.util.List;
145 
146 import org.jfree.chart.LegendItem;
147 import org.jfree.chart.LegendItemCollection;
148 import org.jfree.chart.annotations.Annotation;
149 import org.jfree.chart.annotations.XYAnnotation;
150 import org.jfree.chart.axis.ValueAxis;
151 import org.jfree.chart.entity.EntityCollection;
152 import org.jfree.chart.entity.XYItemEntity;
153 import org.jfree.chart.event.AnnotationChangeEvent;
154 import org.jfree.chart.event.AnnotationChangeListener;
155 import org.jfree.chart.event.RendererChangeEvent;
156 import org.jfree.chart.labels.ItemLabelPosition;
157 import org.jfree.chart.labels.StandardXYSeriesLabelGenerator;
158 import org.jfree.chart.labels.XYItemLabelGenerator;
159 import org.jfree.chart.labels.XYSeriesLabelGenerator;
160 import org.jfree.chart.labels.XYToolTipGenerator;
161 import org.jfree.chart.plot.CrosshairState;
162 import org.jfree.chart.plot.DrawingSupplier;
163 import org.jfree.chart.plot.IntervalMarker;
164 import org.jfree.chart.plot.Marker;
165 import org.jfree.chart.plot.Plot;
166 import org.jfree.chart.plot.PlotOrientation;
167 import org.jfree.chart.plot.PlotRenderingInfo;
168 import org.jfree.chart.plot.ValueMarker;
169 import org.jfree.chart.plot.XYPlot;
170 import org.jfree.chart.renderer.AbstractRenderer;
171 import org.jfree.chart.urls.XYURLGenerator;
172 import org.jfree.chart.util.ParamChecks;
173 import org.jfree.data.Range;
174 import org.jfree.data.general.DatasetUtilities;
175 import org.jfree.data.xy.XYDataset;
176 import org.jfree.text.TextUtilities;
177 import org.jfree.ui.GradientPaintTransformer;
178 import org.jfree.ui.Layer;
179 import org.jfree.ui.LengthAdjustmentType;
180 import org.jfree.ui.RectangleAnchor;
181 import org.jfree.ui.RectangleInsets;
182 import org.jfree.util.ObjectList;
183 import org.jfree.util.ObjectUtilities;
184 import org.jfree.util.PublicCloneable;
185 
186 /**
187  * A base class that can be used to create new {@link XYItemRenderer}
188  * implementations.
189  */
190 public abstract class AbstractXYItemRenderer extends AbstractRenderer
191         implements XYItemRenderer, AnnotationChangeListener,
192         Cloneable, Serializable {
193 
194     /** For serialization. */
195     private static final long serialVersionUID = 8019124836026607990L;
196 
197     /** The plot. */
198     private XYPlot plot;
199 
200     /** A list of item label generators (one per series). */
201     private ObjectList itemLabelGeneratorList;
202 
203     /** The base item label generator. */
204     private XYItemLabelGenerator baseItemLabelGenerator;
205 
206     /** A list of tool tip generators (one per series). */
207     private ObjectList toolTipGeneratorList;
208 
209     /** The base tool tip generator. */
210     private XYToolTipGenerator baseToolTipGenerator;
211 
212     /** The URL text generator. */
213     private XYURLGenerator urlGenerator;
214 
215     /**
216      * Annotations to be drawn in the background layer ('underneath' the data
217      * items).
218      */
219     private List backgroundAnnotations;
220 
221     /**
222      * Annotations to be drawn in the foreground layer ('on top' of the data
223      * items).
224      */
225     private List foregroundAnnotations;
226 
227     /** The legend item label generator. */
228     private XYSeriesLabelGenerator legendItemLabelGenerator;
229 
230     /** The legend item tool tip generator. */
231     private XYSeriesLabelGenerator legendItemToolTipGenerator;
232 
233     /** The legend item URL generator. */
234     private XYSeriesLabelGenerator legendItemURLGenerator;
235 
236     /**
237      * Creates a renderer where the tooltip generator and the URL generator are
238      * both <code>null</code>.
239      */
AbstractXYItemRenderer()240     protected AbstractXYItemRenderer() {
241         super();
242         this.itemLabelGenerator = null;
243         this.itemLabelGeneratorList = new ObjectList();
244         this.toolTipGenerator = null;
245         this.toolTipGeneratorList = new ObjectList();
246         this.urlGenerator = null;
247         this.backgroundAnnotations = new java.util.ArrayList();
248         this.foregroundAnnotations = new java.util.ArrayList();
249         this.legendItemLabelGenerator = new StandardXYSeriesLabelGenerator(
250                 "{0}");
251     }
252 
253     /**
254      * Returns the number of passes through the data that the renderer requires
255      * in order to draw the chart.  Most charts will require a single pass, but
256      * some require two passes.
257      *
258      * @return The pass count.
259      */
260     @Override
getPassCount()261     public int getPassCount() {
262         return 1;
263     }
264 
265     /**
266      * Returns the plot that the renderer is assigned to.
267      *
268      * @return The plot (possibly <code>null</code>).
269      */
270     @Override
getPlot()271     public XYPlot getPlot() {
272         return this.plot;
273     }
274 
275     /**
276      * Sets the plot that the renderer is assigned to.
277      *
278      * @param plot  the plot (<code>null</code> permitted).
279      */
280     @Override
setPlot(XYPlot plot)281     public void setPlot(XYPlot plot) {
282         this.plot = plot;
283     }
284 
285     /**
286      * Initialises the renderer and returns a state object that should be
287      * passed to all subsequent calls to the drawItem() method.
288      * <P>
289      * This method will be called before the first item is rendered, giving the
290      * renderer an opportunity to initialise any state information it wants to
291      * maintain.  The renderer can do nothing if it chooses.
292      *
293      * @param g2  the graphics device.
294      * @param dataArea  the area inside the axes.
295      * @param plot  the plot.
296      * @param data  the data.
297      * @param info  an optional info collection object to return data back to
298      *              the caller.
299      *
300      * @return The renderer state (never <code>null</code>).
301      */
302     @Override
initialise(Graphics2D g2, Rectangle2D dataArea, XYPlot plot, XYDataset data, PlotRenderingInfo info)303     public XYItemRendererState initialise(Graphics2D g2, Rectangle2D dataArea,
304             XYPlot plot, XYDataset data, PlotRenderingInfo info) {
305         return new XYItemRendererState(info);
306     }
307 
308     // ITEM LABEL GENERATOR
309 
310     /**
311      * Returns the label generator for a data item.  This implementation simply
312      * passes control to the {@link #getSeriesItemLabelGenerator(int)} method.
313      * If, for some reason, you want a different generator for individual
314      * items, you can override this method.
315      *
316      * @param series  the series index (zero based).
317      * @param item  the item index (zero based).
318      *
319      * @return The generator (possibly <code>null</code>).
320      */
321     @Override
getItemLabelGenerator(int series, int item)322     public XYItemLabelGenerator getItemLabelGenerator(int series, int item) {
323         // return the generator for ALL series, if there is one...
324         if (this.itemLabelGenerator != null) {
325             return this.itemLabelGenerator;
326         }
327 
328         // otherwise look up the generator table
329         XYItemLabelGenerator generator
330             = (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series);
331         if (generator == null) {
332             generator = this.baseItemLabelGenerator;
333         }
334         return generator;
335     }
336 
337     /**
338      * Returns the item label generator for a series.
339      *
340      * @param series  the series index (zero based).
341      *
342      * @return The generator (possibly <code>null</code>).
343      */
344     @Override
getSeriesItemLabelGenerator(int series)345     public XYItemLabelGenerator getSeriesItemLabelGenerator(int series) {
346         return (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series);
347     }
348 
349     /**
350      * Sets the item label generator for a series and sends a
351      * {@link RendererChangeEvent} to all registered listeners.
352      *
353      * @param series  the series index (zero based).
354      * @param generator  the generator (<code>null</code> permitted).
355      */
356     @Override
setSeriesItemLabelGenerator(int series, XYItemLabelGenerator generator)357     public void setSeriesItemLabelGenerator(int series,
358                                             XYItemLabelGenerator generator) {
359         this.itemLabelGeneratorList.set(series, generator);
360         fireChangeEvent();
361     }
362 
363     /**
364      * Returns the base item label generator.
365      *
366      * @return The generator (possibly <code>null</code>).
367      */
368     @Override
getBaseItemLabelGenerator()369     public XYItemLabelGenerator getBaseItemLabelGenerator() {
370         return this.baseItemLabelGenerator;
371     }
372 
373     /**
374      * Sets the base item label generator and sends a
375      * {@link RendererChangeEvent} to all registered listeners.
376      *
377      * @param generator  the generator (<code>null</code> permitted).
378      */
379     @Override
setBaseItemLabelGenerator(XYItemLabelGenerator generator)380     public void setBaseItemLabelGenerator(XYItemLabelGenerator generator) {
381         this.baseItemLabelGenerator = generator;
382         fireChangeEvent();
383     }
384 
385     // TOOL TIP GENERATOR
386 
387     /**
388      * Returns the tool tip generator for a data item.  If, for some reason,
389      * you want a different generator for individual items, you can override
390      * this method.
391      *
392      * @param series  the series index (zero based).
393      * @param item  the item index (zero based).
394      *
395      * @return The generator (possibly <code>null</code>).
396      */
397     @Override
getToolTipGenerator(int series, int item)398     public XYToolTipGenerator getToolTipGenerator(int series, int item) {
399         // return the generator for ALL series, if there is one...
400         if (this.toolTipGenerator != null) {
401             return this.toolTipGenerator;
402         }
403 
404         // otherwise look up the generator table
405         XYToolTipGenerator generator
406                 = (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
407         if (generator == null) {
408             generator = this.baseToolTipGenerator;
409         }
410         return generator;
411     }
412 
413     /**
414      * Returns the tool tip generator for a series.
415      *
416      * @param series  the series index (zero based).
417      *
418      * @return The generator (possibly <code>null</code>).
419      */
420     @Override
getSeriesToolTipGenerator(int series)421     public XYToolTipGenerator getSeriesToolTipGenerator(int series) {
422         return (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
423     }
424 
425     /**
426      * Sets the tool tip generator for a series and sends a
427      * {@link RendererChangeEvent} to all registered listeners.
428      *
429      * @param series  the series index (zero based).
430      * @param generator  the generator (<code>null</code> permitted).
431      */
432     @Override
setSeriesToolTipGenerator(int series, XYToolTipGenerator generator)433     public void setSeriesToolTipGenerator(int series,
434                                           XYToolTipGenerator generator) {
435         this.toolTipGeneratorList.set(series, generator);
436         fireChangeEvent();
437     }
438 
439     /**
440      * Returns the base tool tip generator.
441      *
442      * @return The generator (possibly <code>null</code>).
443      *
444      * @see #setBaseToolTipGenerator(XYToolTipGenerator)
445      */
446     @Override
getBaseToolTipGenerator()447     public XYToolTipGenerator getBaseToolTipGenerator() {
448         return this.baseToolTipGenerator;
449     }
450 
451     /**
452      * Sets the base tool tip generator and sends a {@link RendererChangeEvent}
453      * to all registered listeners.
454      *
455      * @param generator  the generator (<code>null</code> permitted).
456      *
457      * @see #getBaseToolTipGenerator()
458      */
459     @Override
setBaseToolTipGenerator(XYToolTipGenerator generator)460     public void setBaseToolTipGenerator(XYToolTipGenerator generator) {
461         this.baseToolTipGenerator = generator;
462         fireChangeEvent();
463     }
464 
465     // URL GENERATOR
466 
467     /**
468      * Returns the URL generator for HTML image maps.
469      *
470      * @return The URL generator (possibly <code>null</code>).
471      */
472     @Override
getURLGenerator()473     public XYURLGenerator getURLGenerator() {
474         return this.urlGenerator;
475     }
476 
477     /**
478      * Sets the URL generator for HTML image maps and sends a
479      * {@link RendererChangeEvent} to all registered listeners.
480      *
481      * @param urlGenerator  the URL generator (<code>null</code> permitted).
482      */
483     @Override
setURLGenerator(XYURLGenerator urlGenerator)484     public void setURLGenerator(XYURLGenerator urlGenerator) {
485         this.urlGenerator = urlGenerator;
486         fireChangeEvent();
487     }
488 
489     /**
490      * Adds an annotation and sends a {@link RendererChangeEvent} to all
491      * registered listeners.  The annotation is added to the foreground
492      * layer.
493      *
494      * @param annotation  the annotation (<code>null</code> not permitted).
495      */
496     @Override
addAnnotation(XYAnnotation annotation)497     public void addAnnotation(XYAnnotation annotation) {
498         // defer argument checking
499         addAnnotation(annotation, Layer.FOREGROUND);
500     }
501 
502     /**
503      * Adds an annotation to the specified layer and sends a
504      * {@link RendererChangeEvent} to all registered listeners.
505      *
506      * @param annotation  the annotation (<code>null</code> not permitted).
507      * @param layer  the layer (<code>null</code> not permitted).
508      */
509     @Override
addAnnotation(XYAnnotation annotation, Layer layer)510     public void addAnnotation(XYAnnotation annotation, Layer layer) {
511         ParamChecks.nullNotPermitted(annotation, "annotation");
512         if (layer.equals(Layer.FOREGROUND)) {
513             this.foregroundAnnotations.add(annotation);
514             annotation.addChangeListener(this);
515             fireChangeEvent();
516         }
517         else if (layer.equals(Layer.BACKGROUND)) {
518             this.backgroundAnnotations.add(annotation);
519             annotation.addChangeListener(this);
520             fireChangeEvent();
521         }
522         else {
523             // should never get here
524             throw new RuntimeException("Unknown layer.");
525         }
526     }
527     /**
528      * Removes the specified annotation and sends a {@link RendererChangeEvent}
529      * to all registered listeners.
530      *
531      * @param annotation  the annotation to remove (<code>null</code> not
532      *                    permitted).
533      *
534      * @return A boolean to indicate whether or not the annotation was
535      *         successfully removed.
536      */
537     @Override
removeAnnotation(XYAnnotation annotation)538     public boolean removeAnnotation(XYAnnotation annotation) {
539         boolean removed = this.foregroundAnnotations.remove(annotation);
540         removed = removed & this.backgroundAnnotations.remove(annotation);
541         annotation.removeChangeListener(this);
542         fireChangeEvent();
543         return removed;
544     }
545 
546     /**
547      * Removes all annotations and sends a {@link RendererChangeEvent}
548      * to all registered listeners.
549      */
550     @Override
removeAnnotations()551     public void removeAnnotations() {
552         for(int i = 0; i < this.foregroundAnnotations.size(); i++){
553             XYAnnotation annotation
554                     = (XYAnnotation) this.foregroundAnnotations.get(i);
555             annotation.removeChangeListener(this);
556         }
557          for(int i = 0; i < this.backgroundAnnotations.size(); i++){
558             XYAnnotation annotation
559                     = (XYAnnotation) this.backgroundAnnotations.get(i);
560             annotation.removeChangeListener(this);
561         }
562         this.foregroundAnnotations.clear();
563         this.backgroundAnnotations.clear();
564         fireChangeEvent();
565     }
566 
567 
568     /**
569      * Receives notification of a change to an {@link Annotation} added to
570      * this renderer.
571      *
572      * @param event  information about the event (not used here).
573      *
574      * @since 1.0.14
575      */
576     @Override
annotationChanged(AnnotationChangeEvent event)577     public void annotationChanged(AnnotationChangeEvent event) {
578         fireChangeEvent();
579     }
580 
581     /**
582      * Returns a collection of the annotations that are assigned to the
583      * renderer.
584      *
585      * @return A collection of annotations (possibly empty but never
586      *     <code>null</code>).
587      *
588      * @since 1.0.13
589      */
getAnnotations()590     public Collection getAnnotations() {
591         List result = new java.util.ArrayList(this.foregroundAnnotations);
592         result.addAll(this.backgroundAnnotations);
593         return result;
594     }
595 
596     /**
597      * Returns the legend item label generator.
598      *
599      * @return The label generator (never <code>null</code>).
600      *
601      * @see #setLegendItemLabelGenerator(XYSeriesLabelGenerator)
602      */
603     @Override
getLegendItemLabelGenerator()604     public XYSeriesLabelGenerator getLegendItemLabelGenerator() {
605         return this.legendItemLabelGenerator;
606     }
607 
608     /**
609      * Sets the legend item label generator and sends a
610      * {@link RendererChangeEvent} to all registered listeners.
611      *
612      * @param generator  the generator (<code>null</code> not permitted).
613      *
614      * @see #getLegendItemLabelGenerator()
615      */
616     @Override
setLegendItemLabelGenerator(XYSeriesLabelGenerator generator)617     public void setLegendItemLabelGenerator(XYSeriesLabelGenerator generator) {
618         ParamChecks.nullNotPermitted(generator, "generator");
619         this.legendItemLabelGenerator = generator;
620         fireChangeEvent();
621     }
622 
623     /**
624      * Returns the legend item tool tip generator.
625      *
626      * @return The tool tip generator (possibly <code>null</code>).
627      *
628      * @see #setLegendItemToolTipGenerator(XYSeriesLabelGenerator)
629      */
getLegendItemToolTipGenerator()630     public XYSeriesLabelGenerator getLegendItemToolTipGenerator() {
631         return this.legendItemToolTipGenerator;
632     }
633 
634     /**
635      * Sets the legend item tool tip generator and sends a
636      * {@link RendererChangeEvent} to all registered listeners.
637      *
638      * @param generator  the generator (<code>null</code> permitted).
639      *
640      * @see #getLegendItemToolTipGenerator()
641      */
setLegendItemToolTipGenerator( XYSeriesLabelGenerator generator)642     public void setLegendItemToolTipGenerator(
643             XYSeriesLabelGenerator generator) {
644         this.legendItemToolTipGenerator = generator;
645         fireChangeEvent();
646     }
647 
648     /**
649      * Returns the legend item URL generator.
650      *
651      * @return The URL generator (possibly <code>null</code>).
652      *
653      * @see #setLegendItemURLGenerator(XYSeriesLabelGenerator)
654      */
getLegendItemURLGenerator()655     public XYSeriesLabelGenerator getLegendItemURLGenerator() {
656         return this.legendItemURLGenerator;
657     }
658 
659     /**
660      * Sets the legend item URL generator and sends a
661      * {@link RendererChangeEvent} to all registered listeners.
662      *
663      * @param generator  the generator (<code>null</code> permitted).
664      *
665      * @see #getLegendItemURLGenerator()
666      */
setLegendItemURLGenerator(XYSeriesLabelGenerator generator)667     public void setLegendItemURLGenerator(XYSeriesLabelGenerator generator) {
668         this.legendItemURLGenerator = generator;
669         fireChangeEvent();
670     }
671 
672     /**
673      * Returns the lower and upper bounds (range) of the x-values in the
674      * specified dataset.
675      *
676      * @param dataset  the dataset (<code>null</code> permitted).
677      *
678      * @return The range (<code>null</code> if the dataset is <code>null</code>
679      *         or empty).
680      *
681      * @see #findRangeBounds(XYDataset)
682      */
683     @Override
findDomainBounds(XYDataset dataset)684     public Range findDomainBounds(XYDataset dataset) {
685         return findDomainBounds(dataset, false);
686     }
687 
688     /**
689      * Returns the lower and upper bounds (range) of the x-values in the
690      * specified dataset.
691      *
692      * @param dataset  the dataset (<code>null</code> permitted).
693      * @param includeInterval  include the interval (if any) for the dataset?
694      *
695      * @return The range (<code>null</code> if the dataset is <code>null</code>
696      *         or empty).
697      *
698      * @since 1.0.13
699      */
findDomainBounds(XYDataset dataset, boolean includeInterval)700     protected Range findDomainBounds(XYDataset dataset,
701             boolean includeInterval) {
702         if (dataset == null) {
703             return null;
704         }
705         if (getDataBoundsIncludesVisibleSeriesOnly()) {
706             List visibleSeriesKeys = new ArrayList();
707             int seriesCount = dataset.getSeriesCount();
708             for (int s = 0; s < seriesCount; s++) {
709                 if (isSeriesVisible(s)) {
710                     visibleSeriesKeys.add(dataset.getSeriesKey(s));
711                 }
712             }
713             return DatasetUtilities.findDomainBounds(dataset,
714                     visibleSeriesKeys, includeInterval);
715         }
716         return DatasetUtilities.findDomainBounds(dataset, includeInterval);
717     }
718 
719     /**
720      * Returns the range of values the renderer requires to display all the
721      * items from the specified dataset.
722      *
723      * @param dataset  the dataset (<code>null</code> permitted).
724      *
725      * @return The range (<code>null</code> if the dataset is <code>null</code>
726      *         or empty).
727      *
728      * @see #findDomainBounds(XYDataset)
729      */
730     @Override
findRangeBounds(XYDataset dataset)731     public Range findRangeBounds(XYDataset dataset) {
732         return findRangeBounds(dataset, false);
733     }
734 
735     /**
736      * Returns the range of values the renderer requires to display all the
737      * items from the specified dataset.
738      *
739      * @param dataset  the dataset (<code>null</code> permitted).
740      * @param includeInterval  include the interval (if any) for the dataset?
741      *
742      * @return The range (<code>null</code> if the dataset is <code>null</code>
743      *         or empty).
744      *
745      * @since 1.0.13
746      */
findRangeBounds(XYDataset dataset, boolean includeInterval)747     protected Range findRangeBounds(XYDataset dataset,
748             boolean includeInterval) {
749         if (dataset == null) {
750             return null;
751         }
752         if (getDataBoundsIncludesVisibleSeriesOnly()) {
753             List visibleSeriesKeys = new ArrayList();
754             int seriesCount = dataset.getSeriesCount();
755             for (int s = 0; s < seriesCount; s++) {
756                 if (isSeriesVisible(s)) {
757                     visibleSeriesKeys.add(dataset.getSeriesKey(s));
758                 }
759             }
760             // the bounds should be calculated using just the items within
761             // the current range of the x-axis...if there is one
762             Range xRange = null;
763             XYPlot p = getPlot();
764             if (p != null) {
765                 ValueAxis xAxis = null;
766                 int index = p.getIndexOf(this);
767                 if (index >= 0) {
768                     xAxis = this.plot.getDomainAxisForDataset(index);
769                 }
770                 if (xAxis != null) {
771                     xRange = xAxis.getRange();
772                 }
773             }
774             if (xRange == null) {
775                 xRange = new Range(Double.NEGATIVE_INFINITY,
776                         Double.POSITIVE_INFINITY);
777             }
778             return DatasetUtilities.findRangeBounds(dataset,
779                     visibleSeriesKeys, xRange, includeInterval);
780         }
781         return DatasetUtilities.findRangeBounds(dataset, includeInterval);
782     }
783 
784     /**
785      * Returns a (possibly empty) collection of legend items for the series
786      * that this renderer is responsible for drawing.
787      *
788      * @return The legend item collection (never <code>null</code>).
789      */
790     @Override
getLegendItems()791     public LegendItemCollection getLegendItems() {
792         if (this.plot == null) {
793             return new LegendItemCollection();
794         }
795         LegendItemCollection result = new LegendItemCollection();
796         int index = this.plot.getIndexOf(this);
797         XYDataset dataset = this.plot.getDataset(index);
798         if (dataset != null) {
799             int seriesCount = dataset.getSeriesCount();
800             for (int i = 0; i < seriesCount; i++) {
801                 if (isSeriesVisibleInLegend(i)) {
802                     LegendItem item = getLegendItem(index, i);
803                     if (item != null) {
804                         result.add(item);
805                     }
806                 }
807             }
808 
809         }
810         return result;
811     }
812 
813     /**
814      * Returns a default legend item for the specified series.  Subclasses
815      * should override this method to generate customised items.
816      *
817      * @param datasetIndex  the dataset index (zero-based).
818      * @param series  the series index (zero-based).
819      *
820      * @return A legend item for the series.
821      */
822     @Override
getLegendItem(int datasetIndex, int series)823     public LegendItem getLegendItem(int datasetIndex, int series) {
824         XYPlot xyplot = getPlot();
825         if (xyplot == null) {
826             return null;
827         }
828         XYDataset dataset = xyplot.getDataset(datasetIndex);
829         if (dataset == null) {
830             return null;
831         }
832         String label = this.legendItemLabelGenerator.generateLabel(dataset,
833                 series);
834         String description = label;
835         String toolTipText = null;
836         if (getLegendItemToolTipGenerator() != null) {
837             toolTipText = getLegendItemToolTipGenerator().generateLabel(
838                     dataset, series);
839         }
840         String urlText = null;
841         if (getLegendItemURLGenerator() != null) {
842             urlText = getLegendItemURLGenerator().generateLabel(dataset,
843                     series);
844         }
845         Shape shape = lookupLegendShape(series);
846         Paint paint = lookupSeriesPaint(series);
847         LegendItem item = new LegendItem(label, paint);
848         item.setToolTipText(toolTipText);
849         item.setURLText(urlText);
850         item.setLabelFont(lookupLegendTextFont(series));
851         Paint labelPaint = lookupLegendTextPaint(series);
852         if (labelPaint != null) {
853             item.setLabelPaint(labelPaint);
854         }
855         item.setSeriesKey(dataset.getSeriesKey(series));
856         item.setSeriesIndex(series);
857         item.setDataset(dataset);
858         item.setDatasetIndex(datasetIndex);
859 
860         if (getTreatLegendShapeAsLine()) {
861             item.setLineVisible(true);
862             item.setLine(shape);
863             item.setLinePaint(paint);
864             item.setShapeVisible(false);
865         }
866         else {
867             Paint outlinePaint = lookupSeriesOutlinePaint(series);
868             Stroke outlineStroke = lookupSeriesOutlineStroke(series);
869             item.setOutlinePaint(outlinePaint);
870             item.setOutlineStroke(outlineStroke);
871         }
872         return item;
873     }
874 
875     /**
876      * Fills a band between two values on the axis.  This can be used to color
877      * bands between the grid lines.
878      *
879      * @param g2  the graphics device.
880      * @param plot  the plot.
881      * @param axis  the domain axis.
882      * @param dataArea  the data area.
883      * @param start  the start value.
884      * @param end  the end value.
885      */
886     @Override
fillDomainGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double start, double end)887     public void fillDomainGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis,
888             Rectangle2D dataArea, double start, double end) {
889 
890         double x1 = axis.valueToJava2D(start, dataArea,
891                 plot.getDomainAxisEdge());
892         double x2 = axis.valueToJava2D(end, dataArea,
893                 plot.getDomainAxisEdge());
894         Rectangle2D band;
895         if (plot.getOrientation() == PlotOrientation.VERTICAL) {
896             band = new Rectangle2D.Double(Math.min(x1, x2), dataArea.getMinY(),
897                     Math.abs(x2 - x1), dataArea.getWidth());
898         }
899         else {
900             band = new Rectangle2D.Double(dataArea.getMinX(), Math.min(x1, x2),
901                     dataArea.getWidth(), Math.abs(x2 - x1));
902         }
903         Paint paint = plot.getDomainTickBandPaint();
904 
905         if (paint != null) {
906             g2.setPaint(paint);
907             g2.fill(band);
908         }
909 
910     }
911 
912     /**
913      * Fills a band between two values on the range axis.  This can be used to
914      * color bands between the grid lines.
915      *
916      * @param g2  the graphics device.
917      * @param plot  the plot.
918      * @param axis  the range axis.
919      * @param dataArea  the data area.
920      * @param start  the start value.
921      * @param end  the end value.
922      */
923     @Override
fillRangeGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double start, double end)924     public void fillRangeGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis,
925             Rectangle2D dataArea, double start, double end) {
926 
927         double y1 = axis.valueToJava2D(start, dataArea,
928                 plot.getRangeAxisEdge());
929         double y2 = axis.valueToJava2D(end, dataArea, plot.getRangeAxisEdge());
930         Rectangle2D band;
931         if (plot.getOrientation() == PlotOrientation.VERTICAL) {
932             band = new Rectangle2D.Double(dataArea.getMinX(), Math.min(y1, y2),
933                 dataArea.getWidth(), Math.abs(y2 - y1));
934         }
935         else {
936             band = new Rectangle2D.Double(Math.min(y1, y2), dataArea.getMinY(),
937                     Math.abs(y2 - y1), dataArea.getHeight());
938         }
939         Paint paint = plot.getRangeTickBandPaint();
940 
941         if (paint != null) {
942             g2.setPaint(paint);
943             g2.fill(band);
944         }
945 
946     }
947 
948     /**
949      * Draws a grid line against the range axis.
950      *
951      * @param g2  the graphics device.
952      * @param plot  the plot.
953      * @param axis  the value axis.
954      * @param dataArea  the area for plotting data (not yet adjusted for any
955      *                  3D effect).
956      * @param value  the value at which the grid line should be drawn.
957      */
958     @Override
drawDomainGridLine(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double value)959     public void drawDomainGridLine(Graphics2D g2, XYPlot plot, ValueAxis axis,
960             Rectangle2D dataArea, double value) {
961 
962         Range range = axis.getRange();
963         if (!range.contains(value)) {
964             return;
965         }
966 
967         PlotOrientation orientation = plot.getOrientation();
968         double v = axis.valueToJava2D(value, dataArea,
969                 plot.getDomainAxisEdge());
970         Line2D line = null;
971         if (orientation == PlotOrientation.HORIZONTAL) {
972             line = new Line2D.Double(dataArea.getMinX(), v,
973                     dataArea.getMaxX(), v);
974         }
975         else if (orientation == PlotOrientation.VERTICAL) {
976             line = new Line2D.Double(v, dataArea.getMinY(), v,
977                     dataArea.getMaxY());
978         }
979 
980         Paint paint = plot.getDomainGridlinePaint();
981         Stroke stroke = plot.getDomainGridlineStroke();
982         g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
983         g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
984         g2.draw(line);
985 
986     }
987 
988     /**
989      * Draws a line perpendicular to the domain axis.
990      *
991      * @param g2  the graphics device.
992      * @param plot  the plot.
993      * @param axis  the value axis.
994      * @param dataArea  the area for plotting data (not yet adjusted for any 3D
995      *                  effect).
996      * @param value  the value at which the grid line should be drawn.
997      * @param paint  the paint (<code>null</code> not permitted).
998      * @param stroke  the stroke (<code>null</code> not permitted).
999      *
1000      * @since 1.0.5
1001      */
drawDomainLine(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double value, Paint paint, Stroke stroke)1002     public void drawDomainLine(Graphics2D g2, XYPlot plot, ValueAxis axis,
1003             Rectangle2D dataArea, double value, Paint paint, Stroke stroke) {
1004 
1005         Range range = axis.getRange();
1006         if (!range.contains(value)) {
1007             return;
1008         }
1009 
1010         PlotOrientation orientation = plot.getOrientation();
1011         Line2D line = null;
1012         double v = axis.valueToJava2D(value, dataArea,
1013                 plot.getDomainAxisEdge());
1014         if (orientation == PlotOrientation.HORIZONTAL) {
1015             line = new Line2D.Double(dataArea.getMinX(), v, dataArea.getMaxX(),
1016                     v);
1017         }
1018         else if (orientation == PlotOrientation.VERTICAL) {
1019             line = new Line2D.Double(v, dataArea.getMinY(), v,
1020                     dataArea.getMaxY());
1021         }
1022 
1023         g2.setPaint(paint);
1024         g2.setStroke(stroke);
1025         g2.draw(line);
1026 
1027     }
1028 
1029     /**
1030      * Draws a line perpendicular to the range axis.
1031      *
1032      * @param g2  the graphics device.
1033      * @param plot  the plot.
1034      * @param axis  the value axis.
1035      * @param dataArea  the area for plotting data (not yet adjusted for any 3D
1036      *                  effect).
1037      * @param value  the value at which the grid line should be drawn.
1038      * @param paint  the paint.
1039      * @param stroke  the stroke.
1040      */
1041     @Override
drawRangeLine(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double value, Paint paint, Stroke stroke)1042     public void drawRangeLine(Graphics2D g2, XYPlot plot, ValueAxis axis,
1043             Rectangle2D dataArea, double value, Paint paint, Stroke stroke) {
1044 
1045         Range range = axis.getRange();
1046         if (!range.contains(value)) {
1047             return;
1048         }
1049 
1050         PlotOrientation orientation = plot.getOrientation();
1051         Line2D line = null;
1052         double v = axis.valueToJava2D(value, dataArea, plot.getRangeAxisEdge());
1053         if (orientation == PlotOrientation.HORIZONTAL) {
1054             line = new Line2D.Double(v, dataArea.getMinY(), v,
1055                     dataArea.getMaxY());
1056         }
1057         else if (orientation == PlotOrientation.VERTICAL) {
1058             line = new Line2D.Double(dataArea.getMinX(), v,
1059                     dataArea.getMaxX(), v);
1060         }
1061 
1062         g2.setPaint(paint);
1063         g2.setStroke(stroke);
1064         g2.draw(line);
1065 
1066     }
1067 
1068     /**
1069      * Draws a vertical line on the chart to represent a 'range marker'.
1070      *
1071      * @param g2  the graphics device.
1072      * @param plot  the plot.
1073      * @param domainAxis  the domain axis.
1074      * @param marker  the marker line.
1075      * @param dataArea  the axis data area.
1076      */
1077     @Override
drawDomainMarker(Graphics2D g2, XYPlot plot, ValueAxis domainAxis, Marker marker, Rectangle2D dataArea)1078     public void drawDomainMarker(Graphics2D g2, XYPlot plot,
1079             ValueAxis domainAxis, Marker marker, Rectangle2D dataArea) {
1080 
1081         if (marker instanceof ValueMarker) {
1082             ValueMarker vm = (ValueMarker) marker;
1083             double value = vm.getValue();
1084             Range range = domainAxis.getRange();
1085             if (!range.contains(value)) {
1086                 return;
1087             }
1088 
1089             double v = domainAxis.valueToJava2D(value, dataArea,
1090                     plot.getDomainAxisEdge());
1091 
1092             PlotOrientation orientation = plot.getOrientation();
1093             Line2D line = null;
1094             if (orientation == PlotOrientation.HORIZONTAL) {
1095                 line = new Line2D.Double(dataArea.getMinX(), v,
1096                         dataArea.getMaxX(), v);
1097             }
1098             else if (orientation == PlotOrientation.VERTICAL) {
1099                 line = new Line2D.Double(v, dataArea.getMinY(), v,
1100                         dataArea.getMaxY());
1101             } else {
1102                 throw new IllegalStateException();
1103             }
1104 
1105             final Composite originalComposite = g2.getComposite();
1106             g2.setComposite(AlphaComposite.getInstance(
1107                     AlphaComposite.SRC_OVER, marker.getAlpha()));
1108             g2.setPaint(marker.getPaint());
1109             g2.setStroke(marker.getStroke());
1110             g2.draw(line);
1111 
1112             String label = marker.getLabel();
1113             RectangleAnchor anchor = marker.getLabelAnchor();
1114             if (label != null) {
1115                 Font labelFont = marker.getLabelFont();
1116                 g2.setFont(labelFont);
1117                 g2.setPaint(marker.getLabelPaint());
1118                 Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
1119                         g2, orientation, dataArea, line.getBounds2D(),
1120                         marker.getLabelOffset(),
1121                         LengthAdjustmentType.EXPAND, anchor);
1122                 TextUtilities.drawAlignedString(label, g2,
1123                         (float) coordinates.getX(), (float) coordinates.getY(),
1124                         marker.getLabelTextAnchor());
1125             }
1126             g2.setComposite(originalComposite);
1127         }
1128         else if (marker instanceof IntervalMarker) {
1129             IntervalMarker im = (IntervalMarker) marker;
1130             double start = im.getStartValue();
1131             double end = im.getEndValue();
1132             Range range = domainAxis.getRange();
1133             if (!(range.intersects(start, end))) {
1134                 return;
1135             }
1136 
1137             double start2d = domainAxis.valueToJava2D(start, dataArea,
1138                     plot.getDomainAxisEdge());
1139             double end2d = domainAxis.valueToJava2D(end, dataArea,
1140                     plot.getDomainAxisEdge());
1141             double low = Math.min(start2d, end2d);
1142             double high = Math.max(start2d, end2d);
1143 
1144             PlotOrientation orientation = plot.getOrientation();
1145             Rectangle2D rect = null;
1146             if (orientation == PlotOrientation.HORIZONTAL) {
1147                 // clip top and bottom bounds to data area
1148                 low = Math.max(low, dataArea.getMinY());
1149                 high = Math.min(high, dataArea.getMaxY());
1150                 rect = new Rectangle2D.Double(dataArea.getMinX(),
1151                         low, dataArea.getWidth(),
1152                         high - low);
1153             }
1154             else if (orientation == PlotOrientation.VERTICAL) {
1155                 // clip left and right bounds to data area
1156                 low = Math.max(low, dataArea.getMinX());
1157                 high = Math.min(high, dataArea.getMaxX());
1158                 rect = new Rectangle2D.Double(low,
1159                         dataArea.getMinY(), high - low,
1160                         dataArea.getHeight());
1161             }
1162 
1163             final Composite originalComposite = g2.getComposite();
1164             g2.setComposite(AlphaComposite.getInstance(
1165                     AlphaComposite.SRC_OVER, marker.getAlpha()));
1166             Paint p = marker.getPaint();
1167             if (p instanceof GradientPaint) {
1168                 GradientPaint gp = (GradientPaint) p;
1169                 GradientPaintTransformer t = im.getGradientPaintTransformer();
1170                 if (t != null) {
1171                     gp = t.transform(gp, rect);
1172                 }
1173                 g2.setPaint(gp);
1174             }
1175             else {
1176                 g2.setPaint(p);
1177             }
1178             g2.fill(rect);
1179 
1180             // now draw the outlines, if visible...
1181             if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) {
1182                 if (orientation == PlotOrientation.VERTICAL) {
1183                     Line2D line = new Line2D.Double();
1184                     double y0 = dataArea.getMinY();
1185                     double y1 = dataArea.getMaxY();
1186                     g2.setPaint(im.getOutlinePaint());
1187                     g2.setStroke(im.getOutlineStroke());
1188                     if (range.contains(start)) {
1189                         line.setLine(start2d, y0, start2d, y1);
1190                         g2.draw(line);
1191                     }
1192                     if (range.contains(end)) {
1193                         line.setLine(end2d, y0, end2d, y1);
1194                         g2.draw(line);
1195                     }
1196                 }
1197                 else { // PlotOrientation.HORIZONTAL
1198                     Line2D line = new Line2D.Double();
1199                     double x0 = dataArea.getMinX();
1200                     double x1 = dataArea.getMaxX();
1201                     g2.setPaint(im.getOutlinePaint());
1202                     g2.setStroke(im.getOutlineStroke());
1203                     if (range.contains(start)) {
1204                         line.setLine(x0, start2d, x1, start2d);
1205                         g2.draw(line);
1206                     }
1207                     if (range.contains(end)) {
1208                         line.setLine(x0, end2d, x1, end2d);
1209                         g2.draw(line);
1210                     }
1211                 }
1212             }
1213 
1214             String label = marker.getLabel();
1215             RectangleAnchor anchor = marker.getLabelAnchor();
1216             if (label != null) {
1217                 Font labelFont = marker.getLabelFont();
1218                 g2.setFont(labelFont);
1219                 g2.setPaint(marker.getLabelPaint());
1220                 Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
1221                         g2, orientation, dataArea, rect,
1222                         marker.getLabelOffset(), marker.getLabelOffsetType(),
1223                         anchor);
1224                 TextUtilities.drawAlignedString(label, g2,
1225                         (float) coordinates.getX(), (float) coordinates.getY(),
1226                         marker.getLabelTextAnchor());
1227             }
1228             g2.setComposite(originalComposite);
1229 
1230         }
1231 
1232     }
1233 
1234     /**
1235      * Calculates the (x, y) coordinates for drawing a marker label.
1236      *
1237      * @param g2  the graphics device.
1238      * @param orientation  the plot orientation.
1239      * @param dataArea  the data area.
1240      * @param markerArea  the rectangle surrounding the marker area.
1241      * @param markerOffset  the marker label offset.
1242      * @param labelOffsetType  the label offset type.
1243      * @param anchor  the label anchor.
1244      *
1245      * @return The coordinates for drawing the marker label.
1246      */
calculateDomainMarkerTextAnchorPoint(Graphics2D g2, PlotOrientation orientation, Rectangle2D dataArea, Rectangle2D markerArea, RectangleInsets markerOffset, LengthAdjustmentType labelOffsetType, RectangleAnchor anchor)1247     protected Point2D calculateDomainMarkerTextAnchorPoint(Graphics2D g2,
1248             PlotOrientation orientation, Rectangle2D dataArea,
1249             Rectangle2D markerArea, RectangleInsets markerOffset,
1250             LengthAdjustmentType labelOffsetType, RectangleAnchor anchor) {
1251 
1252         Rectangle2D anchorRect = null;
1253         if (orientation == PlotOrientation.HORIZONTAL) {
1254             anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1255                     LengthAdjustmentType.CONTRACT, labelOffsetType);
1256         }
1257         else if (orientation == PlotOrientation.VERTICAL) {
1258             anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1259                     labelOffsetType, LengthAdjustmentType.CONTRACT);
1260         }
1261         return RectangleAnchor.coordinates(anchorRect, anchor);
1262 
1263     }
1264 
1265     /**
1266      * Draws a horizontal line across the chart to represent a 'range marker'.
1267      *
1268      * @param g2  the graphics device.
1269      * @param plot  the plot.
1270      * @param rangeAxis  the range axis.
1271      * @param marker  the marker line.
1272      * @param dataArea  the axis data area.
1273      */
1274     @Override
drawRangeMarker(Graphics2D g2, XYPlot plot, ValueAxis rangeAxis, Marker marker, Rectangle2D dataArea)1275     public void drawRangeMarker(Graphics2D g2, XYPlot plot, ValueAxis rangeAxis,
1276             Marker marker, Rectangle2D dataArea) {
1277 
1278         if (marker instanceof ValueMarker) {
1279             ValueMarker vm = (ValueMarker) marker;
1280             double value = vm.getValue();
1281             Range range = rangeAxis.getRange();
1282             if (!range.contains(value)) {
1283                 return;
1284             }
1285 
1286             double v = rangeAxis.valueToJava2D(value, dataArea,
1287                     plot.getRangeAxisEdge());
1288             PlotOrientation orientation = plot.getOrientation();
1289             Line2D line = null;
1290             if (orientation == PlotOrientation.HORIZONTAL) {
1291                 line = new Line2D.Double(v, dataArea.getMinY(), v,
1292                         dataArea.getMaxY());
1293             }
1294             else if (orientation == PlotOrientation.VERTICAL) {
1295                 line = new Line2D.Double(dataArea.getMinX(), v,
1296                         dataArea.getMaxX(), v);
1297             }
1298             else {
1299                 throw new IllegalStateException("Unknown orientation.");
1300             }
1301 
1302             final Composite originalComposite = g2.getComposite();
1303             g2.setComposite(AlphaComposite.getInstance(
1304                     AlphaComposite.SRC_OVER, marker.getAlpha()));
1305             g2.setPaint(marker.getPaint());
1306             g2.setStroke(marker.getStroke());
1307             g2.draw(line);
1308 
1309             String label = marker.getLabel();
1310             RectangleAnchor anchor = marker.getLabelAnchor();
1311             if (label != null) {
1312                 Font labelFont = marker.getLabelFont();
1313                 g2.setFont(labelFont);
1314                 g2.setPaint(marker.getLabelPaint());
1315                 Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
1316                         g2, orientation, dataArea, line.getBounds2D(),
1317                         marker.getLabelOffset(),
1318                         LengthAdjustmentType.EXPAND, anchor);
1319                 TextUtilities.drawAlignedString(label, g2,
1320                         (float) coordinates.getX(), (float) coordinates.getY(),
1321                         marker.getLabelTextAnchor());
1322             }
1323             g2.setComposite(originalComposite);
1324         }
1325         else if (marker instanceof IntervalMarker) {
1326             IntervalMarker im = (IntervalMarker) marker;
1327             double start = im.getStartValue();
1328             double end = im.getEndValue();
1329             Range range = rangeAxis.getRange();
1330             if (!(range.intersects(start, end))) {
1331                 return;
1332             }
1333 
1334             double start2d = rangeAxis.valueToJava2D(start, dataArea,
1335                     plot.getRangeAxisEdge());
1336             double end2d = rangeAxis.valueToJava2D(end, dataArea,
1337                     plot.getRangeAxisEdge());
1338             double low = Math.min(start2d, end2d);
1339             double high = Math.max(start2d, end2d);
1340 
1341             PlotOrientation orientation = plot.getOrientation();
1342             Rectangle2D rect = null;
1343             if (orientation == PlotOrientation.HORIZONTAL) {
1344                 // clip left and right bounds to data area
1345                 low = Math.max(low, dataArea.getMinX());
1346                 high = Math.min(high, dataArea.getMaxX());
1347                 rect = new Rectangle2D.Double(low,
1348                         dataArea.getMinY(), high - low,
1349                         dataArea.getHeight());
1350             }
1351             else if (orientation == PlotOrientation.VERTICAL) {
1352                 // clip top and bottom bounds to data area
1353                 low = Math.max(low, dataArea.getMinY());
1354                 high = Math.min(high, dataArea.getMaxY());
1355                 rect = new Rectangle2D.Double(dataArea.getMinX(),
1356                         low, dataArea.getWidth(),
1357                         high - low);
1358             }
1359 
1360             final Composite originalComposite = g2.getComposite();
1361             g2.setComposite(AlphaComposite.getInstance(
1362                     AlphaComposite.SRC_OVER, marker.getAlpha()));
1363             Paint p = marker.getPaint();
1364             if (p instanceof GradientPaint) {
1365                 GradientPaint gp = (GradientPaint) p;
1366                 GradientPaintTransformer t = im.getGradientPaintTransformer();
1367                 if (t != null) {
1368                     gp = t.transform(gp, rect);
1369                 }
1370                 g2.setPaint(gp);
1371             }
1372             else {
1373                 g2.setPaint(p);
1374             }
1375             g2.fill(rect);
1376 
1377             // now draw the outlines, if visible...
1378             if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) {
1379                 if (orientation == PlotOrientation.VERTICAL) {
1380                     Line2D line = new Line2D.Double();
1381                     double x0 = dataArea.getMinX();
1382                     double x1 = dataArea.getMaxX();
1383                     g2.setPaint(im.getOutlinePaint());
1384                     g2.setStroke(im.getOutlineStroke());
1385                     if (range.contains(start)) {
1386                         line.setLine(x0, start2d, x1, start2d);
1387                         g2.draw(line);
1388                     }
1389                     if (range.contains(end)) {
1390                         line.setLine(x0, end2d, x1, end2d);
1391                         g2.draw(line);
1392                     }
1393                 }
1394                 else { // PlotOrientation.HORIZONTAL
1395                     Line2D line = new Line2D.Double();
1396                     double y0 = dataArea.getMinY();
1397                     double y1 = dataArea.getMaxY();
1398                     g2.setPaint(im.getOutlinePaint());
1399                     g2.setStroke(im.getOutlineStroke());
1400                     if (range.contains(start)) {
1401                         line.setLine(start2d, y0, start2d, y1);
1402                         g2.draw(line);
1403                     }
1404                     if (range.contains(end)) {
1405                         line.setLine(end2d, y0, end2d, y1);
1406                         g2.draw(line);
1407                     }
1408                 }
1409             }
1410 
1411             String label = marker.getLabel();
1412             RectangleAnchor anchor = marker.getLabelAnchor();
1413             if (label != null) {
1414                 Font labelFont = marker.getLabelFont();
1415                 g2.setFont(labelFont);
1416                 g2.setPaint(marker.getLabelPaint());
1417                 Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
1418                         g2, orientation, dataArea, rect,
1419                         marker.getLabelOffset(), marker.getLabelOffsetType(),
1420                         anchor);
1421                 TextUtilities.drawAlignedString(label, g2,
1422                         (float) coordinates.getX(), (float) coordinates.getY(),
1423                         marker.getLabelTextAnchor());
1424             }
1425             g2.setComposite(originalComposite);
1426         }
1427     }
1428 
1429     /**
1430      * Calculates the (x, y) coordinates for drawing a marker label.
1431      *
1432      * @param g2  the graphics device.
1433      * @param orientation  the plot orientation.
1434      * @param dataArea  the data area.
1435      * @param markerArea  the marker area.
1436      * @param markerOffset  the marker offset.
1437      * @param labelOffsetForRange  ??
1438      * @param anchor  the label anchor.
1439      *
1440      * @return The coordinates for drawing the marker label.
1441      */
calculateRangeMarkerTextAnchorPoint(Graphics2D g2, PlotOrientation orientation, Rectangle2D dataArea, Rectangle2D markerArea, RectangleInsets markerOffset, LengthAdjustmentType labelOffsetForRange, RectangleAnchor anchor)1442     private Point2D calculateRangeMarkerTextAnchorPoint(Graphics2D g2,
1443            PlotOrientation orientation, Rectangle2D dataArea,
1444            Rectangle2D markerArea, RectangleInsets markerOffset,
1445            LengthAdjustmentType labelOffsetForRange, RectangleAnchor anchor) {
1446 
1447         Rectangle2D anchorRect = null;
1448         if (orientation == PlotOrientation.HORIZONTAL) {
1449             anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1450                     labelOffsetForRange, LengthAdjustmentType.CONTRACT);
1451         }
1452         else if (orientation == PlotOrientation.VERTICAL) {
1453             anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1454                     LengthAdjustmentType.CONTRACT, labelOffsetForRange);
1455         }
1456         return RectangleAnchor.coordinates(anchorRect, anchor);
1457 
1458     }
1459 
1460     /**
1461      * Returns a clone of the renderer.
1462      *
1463      * @return A clone.
1464      *
1465      * @throws CloneNotSupportedException if the renderer does not support
1466      *         cloning.
1467      */
1468     @Override
clone()1469     protected Object clone() throws CloneNotSupportedException {
1470         AbstractXYItemRenderer clone = (AbstractXYItemRenderer) super.clone();
1471         // 'plot' : just retain reference, not a deep copy
1472 
1473         if (this.itemLabelGenerator != null
1474                 && this.itemLabelGenerator instanceof PublicCloneable) {
1475             PublicCloneable pc = (PublicCloneable) this.itemLabelGenerator;
1476             clone.itemLabelGenerator = (XYItemLabelGenerator) pc.clone();
1477         }
1478         clone.itemLabelGeneratorList
1479                 = (ObjectList) this.itemLabelGeneratorList.clone();
1480         if (this.baseItemLabelGenerator != null
1481                 && this.baseItemLabelGenerator instanceof PublicCloneable) {
1482             PublicCloneable pc = (PublicCloneable) this.baseItemLabelGenerator;
1483             clone.baseItemLabelGenerator = (XYItemLabelGenerator) pc.clone();
1484         }
1485 
1486         if (this.toolTipGenerator != null
1487                 && this.toolTipGenerator instanceof PublicCloneable) {
1488             PublicCloneable pc = (PublicCloneable) this.toolTipGenerator;
1489             clone.toolTipGenerator = (XYToolTipGenerator) pc.clone();
1490         }
1491         clone.toolTipGeneratorList
1492                 = (ObjectList) this.toolTipGeneratorList.clone();
1493         if (this.baseToolTipGenerator != null
1494                 && this.baseToolTipGenerator instanceof PublicCloneable) {
1495             PublicCloneable pc = (PublicCloneable) this.baseToolTipGenerator;
1496             clone.baseToolTipGenerator = (XYToolTipGenerator) pc.clone();
1497         }
1498 
1499         if (this.legendItemLabelGenerator instanceof PublicCloneable) {
1500             clone.legendItemLabelGenerator = (XYSeriesLabelGenerator)
1501                     ObjectUtilities.clone(this.legendItemLabelGenerator);
1502         }
1503         if (this.legendItemToolTipGenerator instanceof PublicCloneable) {
1504             clone.legendItemToolTipGenerator = (XYSeriesLabelGenerator)
1505                     ObjectUtilities.clone(this.legendItemToolTipGenerator);
1506         }
1507         if (this.legendItemURLGenerator instanceof PublicCloneable) {
1508             clone.legendItemURLGenerator = (XYSeriesLabelGenerator)
1509                     ObjectUtilities.clone(this.legendItemURLGenerator);
1510         }
1511 
1512         clone.foregroundAnnotations = (List) ObjectUtilities.deepClone(
1513                 this.foregroundAnnotations);
1514         clone.backgroundAnnotations = (List) ObjectUtilities.deepClone(
1515                 this.backgroundAnnotations);
1516 
1517         return clone;
1518     }
1519 
1520     /**
1521      * Tests this renderer for equality with another object.
1522      *
1523      * @param obj  the object (<code>null</code> permitted).
1524      *
1525      * @return <code>true</code> or <code>false</code>.
1526      */
1527     @Override
equals(Object obj)1528     public boolean equals(Object obj) {
1529         if (obj == this) {
1530             return true;
1531         }
1532         if (!(obj instanceof AbstractXYItemRenderer)) {
1533             return false;
1534         }
1535         AbstractXYItemRenderer that = (AbstractXYItemRenderer) obj;
1536         if (!ObjectUtilities.equal(this.itemLabelGenerator,
1537                 that.itemLabelGenerator)) {
1538             return false;
1539         }
1540         if (!this.itemLabelGeneratorList.equals(that.itemLabelGeneratorList)) {
1541             return false;
1542         }
1543         if (!ObjectUtilities.equal(this.baseItemLabelGenerator,
1544                 that.baseItemLabelGenerator)) {
1545             return false;
1546         }
1547         if (!ObjectUtilities.equal(this.toolTipGenerator,
1548                 that.toolTipGenerator)) {
1549             return false;
1550         }
1551         if (!this.toolTipGeneratorList.equals(that.toolTipGeneratorList)) {
1552             return false;
1553         }
1554         if (!ObjectUtilities.equal(this.baseToolTipGenerator,
1555                 that.baseToolTipGenerator)) {
1556             return false;
1557         }
1558         if (!ObjectUtilities.equal(this.urlGenerator, that.urlGenerator)) {
1559             return false;
1560         }
1561         if (!this.foregroundAnnotations.equals(that.foregroundAnnotations)) {
1562             return false;
1563         }
1564         if (!this.backgroundAnnotations.equals(that.backgroundAnnotations)) {
1565             return false;
1566         }
1567         if (!ObjectUtilities.equal(this.legendItemLabelGenerator,
1568                 that.legendItemLabelGenerator)) {
1569             return false;
1570         }
1571         if (!ObjectUtilities.equal(this.legendItemToolTipGenerator,
1572                 that.legendItemToolTipGenerator)) {
1573             return false;
1574         }
1575         if (!ObjectUtilities.equal(this.legendItemURLGenerator,
1576                 that.legendItemURLGenerator)) {
1577             return false;
1578         }
1579         return super.equals(obj);
1580     }
1581 
1582     /**
1583      * Returns the drawing supplier from the plot.
1584      *
1585      * @return The drawing supplier (possibly <code>null</code>).
1586      */
1587     @Override
getDrawingSupplier()1588     public DrawingSupplier getDrawingSupplier() {
1589         DrawingSupplier result = null;
1590         XYPlot p = getPlot();
1591         if (p != null) {
1592             result = p.getDrawingSupplier();
1593         }
1594         return result;
1595     }
1596 
1597     /**
1598      * Considers the current (x, y) coordinate and updates the crosshair point
1599      * if it meets the criteria (usually means the (x, y) coordinate is the
1600      * closest to the anchor point so far).
1601      *
1602      * @param crosshairState  the crosshair state (<code>null</code> permitted,
1603      *                        but the method does nothing in that case).
1604      * @param x  the x-value (in data space).
1605      * @param y  the y-value (in data space).
1606      * @param domainAxisIndex  the index of the domain axis for the point.
1607      * @param rangeAxisIndex  the index of the range axis for the point.
1608      * @param transX  the x-value translated to Java2D space.
1609      * @param transY  the y-value translated to Java2D space.
1610      * @param orientation  the plot orientation (<code>null</code> not
1611      *                     permitted).
1612      *
1613      * @since 1.0.4
1614      */
updateCrosshairValues(CrosshairState crosshairState, double x, double y, int domainAxisIndex, int rangeAxisIndex, double transX, double transY, PlotOrientation orientation)1615     protected void updateCrosshairValues(CrosshairState crosshairState,
1616             double x, double y, int domainAxisIndex, int rangeAxisIndex,
1617             double transX, double transY, PlotOrientation orientation) {
1618 
1619         ParamChecks.nullNotPermitted(orientation, "orientation");
1620         if (crosshairState != null) {
1621             // do we need to update the crosshair values?
1622             if (this.plot.isDomainCrosshairLockedOnData()) {
1623                 if (this.plot.isRangeCrosshairLockedOnData()) {
1624                     // both axes
1625                     crosshairState.updateCrosshairPoint(x, y, domainAxisIndex,
1626                             rangeAxisIndex, transX, transY, orientation);
1627                 }
1628                 else {
1629                     // just the domain axis...
1630                     crosshairState.updateCrosshairX(x, domainAxisIndex);
1631                 }
1632             }
1633             else {
1634                 if (this.plot.isRangeCrosshairLockedOnData()) {
1635                     // just the range axis...
1636                     crosshairState.updateCrosshairY(y, rangeAxisIndex);
1637                 }
1638             }
1639         }
1640 
1641     }
1642 
1643     /**
1644      * Draws an item label.
1645      *
1646      * @param g2  the graphics device.
1647      * @param orientation  the orientation.
1648      * @param dataset  the dataset.
1649      * @param series  the series index (zero-based).
1650      * @param item  the item index (zero-based).
1651      * @param x  the x coordinate (in Java2D space).
1652      * @param y  the y coordinate (in Java2D space).
1653      * @param negative  indicates a negative value (which affects the item
1654      *                  label position).
1655      */
drawItemLabel(Graphics2D g2, PlotOrientation orientation, XYDataset dataset, int series, int item, double x, double y, boolean negative)1656     protected void drawItemLabel(Graphics2D g2, PlotOrientation orientation,
1657             XYDataset dataset, int series, int item, double x, double y,
1658             boolean negative) {
1659 
1660         XYItemLabelGenerator generator = getItemLabelGenerator(series, item);
1661         if (generator != null) {
1662             Font labelFont = getItemLabelFont(series, item);
1663             Paint paint = getItemLabelPaint(series, item);
1664             g2.setFont(labelFont);
1665             g2.setPaint(paint);
1666             String label = generator.generateLabel(dataset, series, item);
1667 
1668             // get the label position..
1669             ItemLabelPosition position;
1670             if (!negative) {
1671                 position = getPositiveItemLabelPosition(series, item);
1672             }
1673             else {
1674                 position = getNegativeItemLabelPosition(series, item);
1675             }
1676 
1677             // work out the label anchor point...
1678             Point2D anchorPoint = calculateLabelAnchorPoint(
1679                     position.getItemLabelAnchor(), x, y, orientation);
1680             TextUtilities.drawRotatedString(label, g2,
1681                     (float) anchorPoint.getX(), (float) anchorPoint.getY(),
1682                     position.getTextAnchor(), position.getAngle(),
1683                     position.getRotationAnchor());
1684         }
1685 
1686     }
1687 
1688     /**
1689      * Draws all the annotations for the specified layer.
1690      *
1691      * @param g2  the graphics device.
1692      * @param dataArea  the data area.
1693      * @param domainAxis  the domain axis.
1694      * @param rangeAxis  the range axis.
1695      * @param layer  the layer.
1696      * @param info  the plot rendering info.
1697      */
1698     @Override
drawAnnotations(Graphics2D g2, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, Layer layer, PlotRenderingInfo info)1699     public void drawAnnotations(Graphics2D g2, Rectangle2D dataArea,
1700             ValueAxis domainAxis, ValueAxis rangeAxis, Layer layer,
1701             PlotRenderingInfo info) {
1702 
1703         Iterator iterator = null;
1704         if (layer.equals(Layer.FOREGROUND)) {
1705             iterator = this.foregroundAnnotations.iterator();
1706         }
1707         else if (layer.equals(Layer.BACKGROUND)) {
1708             iterator = this.backgroundAnnotations.iterator();
1709         }
1710         else {
1711             // should not get here
1712             throw new RuntimeException("Unknown layer.");
1713         }
1714         while (iterator.hasNext()) {
1715             XYAnnotation annotation = (XYAnnotation) iterator.next();
1716             int index = this.plot.getIndexOf(this);
1717             annotation.draw(g2, this.plot, dataArea, domainAxis, rangeAxis,
1718                     index, info);
1719         }
1720 
1721     }
1722 
1723     /**
1724      * Adds an entity to the collection.
1725      *
1726      * @param entities  the entity collection being populated.
1727      * @param area  the entity area (if <code>null</code> a default will be
1728      *              used).
1729      * @param dataset  the dataset.
1730      * @param series  the series.
1731      * @param item  the item.
1732      * @param entityX  the entity's center x-coordinate in user space (only
1733      *                 used if <code>area</code> is <code>null</code>).
1734      * @param entityY  the entity's center y-coordinate in user space (only
1735      *                 used if <code>area</code> is <code>null</code>).
1736      */
addEntity(EntityCollection entities, Shape area, XYDataset dataset, int series, int item, double entityX, double entityY)1737     protected void addEntity(EntityCollection entities, Shape area,
1738                              XYDataset dataset, int series, int item,
1739                              double entityX, double entityY) {
1740         if (!getItemCreateEntity(series, item)) {
1741             return;
1742         }
1743         Shape hotspot = area;
1744         if (hotspot == null) {
1745             double r = getDefaultEntityRadius();
1746             double w = r * 2;
1747             if (getPlot().getOrientation() == PlotOrientation.VERTICAL) {
1748                 hotspot = new Ellipse2D.Double(entityX - r, entityY - r, w, w);
1749             }
1750             else {
1751                 hotspot = new Ellipse2D.Double(entityY - r, entityX - r, w, w);
1752             }
1753         }
1754         String tip = null;
1755         XYToolTipGenerator generator = getToolTipGenerator(series, item);
1756         if (generator != null) {
1757             tip = generator.generateToolTip(dataset, series, item);
1758         }
1759         String url = null;
1760         if (getURLGenerator() != null) {
1761             url = getURLGenerator().generateURL(dataset, series, item);
1762         }
1763         XYItemEntity entity = new XYItemEntity(hotspot, dataset, series, item,
1764                 tip, url);
1765         entities.add(entity);
1766     }
1767 
1768     /**
1769      * Returns <code>true</code> if the specified point (x, y) falls within or
1770      * on the boundary of the specified rectangle.
1771      *
1772      * @param rect  the rectangle (<code>null</code> not permitted).
1773      * @param x  the x-coordinate.
1774      * @param y  the y-coordinate.
1775      *
1776      * @return A boolean.
1777      *
1778      * @since 1.0.10
1779      */
isPointInRect(Rectangle2D rect, double x, double y)1780     public static boolean isPointInRect(Rectangle2D rect, double x, double y) {
1781         // TODO: For JFreeChart 1.2.0, this method should go in the
1782         //       ShapeUtilities class
1783         return (x >= rect.getMinX() && x <= rect.getMaxX()
1784                 && y >= rect.getMinY() && y <= rect.getMaxY());
1785     }
1786 
1787     /**
1788      * Utility method delegating to {@link GeneralPath#moveTo} taking double as
1789      * parameters.
1790      *
1791      * @param hotspot  the region under construction (<code>null</code> not
1792      *           permitted);
1793      * @param x  the x coordinate;
1794      * @param y  the y coordinate;
1795      *
1796      * @since 1.0.14
1797      */
moveTo(GeneralPath hotspot, double x, double y)1798     protected static void moveTo(GeneralPath hotspot, double x, double y) {
1799         hotspot.moveTo((float) x, (float) y);
1800     }
1801 
1802     /**
1803      * Utility method delegating to {@link GeneralPath#lineTo} taking double as
1804      * parameters.
1805      *
1806      * @param hotspot  the region under construction (<code>null</code> not
1807      *           permitted);
1808      * @param x  the x coordinate;
1809      * @param y  the y coordinate;
1810      *
1811      * @since 1.0.14
1812      */
lineTo(GeneralPath hotspot, double x, double y)1813     protected static void lineTo(GeneralPath hotspot, double x, double y) {
1814         hotspot.lineTo((float) x, (float) y);
1815     }
1816 
1817     // === DEPRECATED CODE ===
1818 
1819     /**
1820      * The item label generator for ALL series.
1821      *
1822      * @deprecated This field is redundant, use itemLabelGeneratorList and
1823      *     baseItemLabelGenerator instead.  Deprecated as of version 1.0.6.
1824      */
1825     private XYItemLabelGenerator itemLabelGenerator;
1826 
1827     /**
1828      * The tool tip generator for ALL series.
1829      *
1830      * @deprecated This field is redundant, use tooltipGeneratorList and
1831      *     baseToolTipGenerator instead.  Deprecated as of version 1.0.6.
1832      */
1833     private XYToolTipGenerator toolTipGenerator;
1834 
1835     /**
1836      * Returns the item label generator override.
1837      *
1838      * @return The generator (possibly <code>null</code>).
1839      *
1840      * @since 1.0.5
1841      *
1842      * @see #setItemLabelGenerator(XYItemLabelGenerator)
1843      *
1844      * @deprecated As of version 1.0.6, this override setting should not be
1845      *     used.  You can use the base setting instead
1846      *     ({@link #getBaseItemLabelGenerator()}).
1847      */
getItemLabelGenerator()1848     public XYItemLabelGenerator getItemLabelGenerator() {
1849         return this.itemLabelGenerator;
1850     }
1851 
1852     /**
1853      * Sets the item label generator for ALL series and sends a
1854      * {@link RendererChangeEvent} to all registered listeners.
1855      *
1856      * @param generator  the generator (<code>null</code> permitted).
1857      *
1858      * @see #getItemLabelGenerator()
1859      *
1860      * @deprecated As of version 1.0.6, this override setting should not be
1861      *     used.  You can use the base setting instead
1862      *     ({@link #setBaseItemLabelGenerator(XYItemLabelGenerator)}).
1863      */
1864     @Override
setItemLabelGenerator(XYItemLabelGenerator generator)1865     public void setItemLabelGenerator(XYItemLabelGenerator generator) {
1866         this.itemLabelGenerator = generator;
1867         fireChangeEvent();
1868     }
1869 
1870     /**
1871      * Returns the override tool tip generator.
1872      *
1873      * @return The tool tip generator (possible <code>null</code>).
1874      *
1875      * @since 1.0.5
1876      *
1877      * @see #setToolTipGenerator(XYToolTipGenerator)
1878      *
1879      * @deprecated As of version 1.0.6, this override setting should not be
1880      *     used.  You can use the base setting instead
1881      *     ({@link #getBaseToolTipGenerator()}).
1882      */
getToolTipGenerator()1883     public XYToolTipGenerator getToolTipGenerator() {
1884         return this.toolTipGenerator;
1885     }
1886 
1887     /**
1888      * Sets the tool tip generator for ALL series and sends a
1889      * {@link RendererChangeEvent} to all registered listeners.
1890      *
1891      * @param generator  the generator (<code>null</code> permitted).
1892      *
1893      * @see #getToolTipGenerator()
1894      *
1895      * @deprecated As of version 1.0.6, this override setting should not be
1896      *     used.  You can use the base setting instead
1897      *     ({@link #setBaseToolTipGenerator(XYToolTipGenerator)}).
1898      */
1899     @Override
setToolTipGenerator(XYToolTipGenerator generator)1900     public void setToolTipGenerator(XYToolTipGenerator generator) {
1901         this.toolTipGenerator = generator;
1902         fireChangeEvent();
1903     }
1904 
1905     /**
1906      * Considers the current (x, y) coordinate and updates the crosshair point
1907      * if it meets the criteria (usually means the (x, y) coordinate is the
1908      * closest to the anchor point so far).
1909      *
1910      * @param crosshairState  the crosshair state (<code>null</code> permitted,
1911      *                        but the method does nothing in that case).
1912      * @param x  the x-value (in data space).
1913      * @param y  the y-value (in data space).
1914      * @param transX  the x-value translated to Java2D space.
1915      * @param transY  the y-value translated to Java2D space.
1916      * @param orientation  the plot orientation (<code>null</code> not
1917      *                     permitted).
1918      *
1919      * @deprecated Use {@link #updateCrosshairValues(CrosshairState, double,
1920      *         double, int, int, double, double, PlotOrientation)} -- see bug
1921      *         report 1086307.
1922      */
updateCrosshairValues(CrosshairState crosshairState, double x, double y, double transX, double transY, PlotOrientation orientation)1923     protected void updateCrosshairValues(CrosshairState crosshairState,
1924             double x, double y, double transX, double transY,
1925             PlotOrientation orientation) {
1926         updateCrosshairValues(crosshairState, x, y, 0, 0, transX, transY,
1927                 orientation);
1928     }
1929 
1930 
1931 }
1932