001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * ---------------------
028 * AbstractRenderer.java
029 * ---------------------
030 * (C) Copyright 2002-2013, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   Nicolas Brodu;
034 *
035 * Changes:
036 * --------
037 * 22-Aug-2002 : Version 1, draws code out of AbstractXYItemRenderer to share
038 *               with AbstractCategoryItemRenderer (DG);
039 * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
040 * 06-Nov-2002 : Moved to the com.jrefinery.chart.renderer package (DG);
041 * 21-Nov-2002 : Added a paint table for the renderer to use (DG);
042 * 17-Jan-2003 : Moved plot classes into a separate package (DG);
043 * 25-Mar-2003 : Implemented Serializable (DG);
044 * 29-Apr-2003 : Added valueLabelFont and valueLabelPaint attributes, based on
045 *               code from Arnaud Lelievre (DG);
046 * 29-Jul-2003 : Amended code that doesn't compile with JDK 1.2.2 (DG);
047 * 13-Aug-2003 : Implemented Cloneable (DG);
048 * 15-Sep-2003 : Fixed serialization (NB);
049 * 17-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
050 * 07-Oct-2003 : Moved PlotRenderingInfo into RendererState to allow for
051 *               multiple threads using a single renderer (DG);
052 * 20-Oct-2003 : Added missing setOutlinePaint() method (DG);
053 * 23-Oct-2003 : Split item label attributes into 'positive' and 'negative'
054 *               values (DG);
055 * 26-Nov-2003 : Added methods to get the positive and negative item label
056 *               positions (DG);
057 * 01-Mar-2004 : Modified readObject() method to prevent null pointer exceptions
058 *               after deserialization (DG);
059 * 19-Jul-2004 : Fixed bug in getItemLabelFont(int, int) method (DG);
060 * 04-Oct-2004 : Updated equals() method, eliminated use of NumberUtils,
061 *               renamed BooleanUtils --> BooleanUtilities, ShapeUtils -->
062 *               ShapeUtilities (DG);
063 * 15-Mar-2005 : Fixed serialization of baseFillPaint (DG);
064 * 16-May-2005 : Base outline stroke should never be null (DG);
065 * 01-Jun-2005 : Added hasListener() method for unit testing (DG);
066 * 08-Jun-2005 : Fixed equals() method to handle GradientPaint (DG);
067 * ------------- JFREECHART 1.0.x ---------------------------------------------
068 * 02-Feb-2007 : Minor API doc update (DG);
069 * 19-Feb-2007 : Fixes for clone() method (DG);
070 * 28-Feb-2007 : Use cached event to signal changes (DG);
071 * 19-Apr-2007 : Deprecated seriesVisible and seriesVisibleInLegend flags (DG);
072 * 20-Apr-2007 : Deprecated paint, fillPaint, outlinePaint, stroke,
073 *               outlineStroke, shape, itemLabelsVisible, itemLabelFont,
074 *               itemLabelPaint, positiveItemLabelPosition,
075 *               negativeItemLabelPosition and createEntities override
076 *               fields (DG);
077 * 13-Jun-2007 : Added new autoPopulate flags for core series attributes (DG);
078 * 23-Oct-2007 : Updated lookup methods to better handle overridden
079 *               methods (DG);
080 * 04-Dec-2007 : Modified hashCode() implementation (DG);
081 * 29-Apr-2008 : Minor API doc update (DG);
082 * 17-Jun-2008 : Added legendShape, legendTextFont and legendTextPaint
083 *               attributes (DG);
084 * 18-Aug-2008 : Added clearSeriesPaints() and clearSeriesStrokes() (DG);
085 * 28-Jan-2009 : Equals method doesn't test Shape equality correctly (DG);
086 * 27-Mar-2009 : Added dataBoundsIncludesVisibleSeriesOnly attribute, and
087 *               updated renderer events for series visibility changes (DG);
088 * 01-Apr-2009 : Factored up the defaultEntityRadius field from the
089 *               AbstractXYItemRenderer class (DG);
090 * 28-Apr-2009 : Added flag to allow a renderer to treat the legend shape as
091 *               a line (DG);
092 * 05-Jul-2012 : No need for BooleanUtilities now that min JDK = 1.4.2 (DG);
093 * 03-Jul-2013 : Use ParamChecks (DG);
094 *
095 */
096
097package org.jfree.chart.renderer;
098
099import java.awt.BasicStroke;
100import java.awt.Color;
101import java.awt.Font;
102import java.awt.Paint;
103import java.awt.Shape;
104import java.awt.Stroke;
105import java.awt.geom.Point2D;
106import java.awt.geom.Rectangle2D;
107import java.io.IOException;
108import java.io.ObjectInputStream;
109import java.io.ObjectOutputStream;
110import java.io.Serializable;
111import java.util.Arrays;
112import java.util.EventListener;
113import java.util.List;
114
115import javax.swing.event.EventListenerList;
116
117import org.jfree.chart.HashUtilities;
118import org.jfree.chart.event.RendererChangeEvent;
119import org.jfree.chart.event.RendererChangeListener;
120import org.jfree.chart.labels.ItemLabelAnchor;
121import org.jfree.chart.labels.ItemLabelPosition;
122import org.jfree.chart.plot.DrawingSupplier;
123import org.jfree.chart.plot.PlotOrientation;
124import org.jfree.chart.title.LegendTitle;
125import org.jfree.chart.util.ParamChecks;
126import org.jfree.io.SerialUtilities;
127import org.jfree.ui.TextAnchor;
128import org.jfree.util.BooleanList;
129import org.jfree.util.ObjectList;
130import org.jfree.util.ObjectUtilities;
131import org.jfree.util.PaintList;
132import org.jfree.util.PaintUtilities;
133import org.jfree.util.ShapeList;
134import org.jfree.util.ShapeUtilities;
135import org.jfree.util.StrokeList;
136
137/**
138 * Base class providing common services for renderers.  Most methods that update
139 * attributes of the renderer will fire a {@link RendererChangeEvent}, which
140 * normally means the plot that owns the renderer will receive notification that
141 * the renderer has been changed (the plot will, in turn, notify the chart).
142 */
143public abstract class AbstractRenderer implements Cloneable, Serializable {
144
145    /** For serialization. */
146    private static final long serialVersionUID = -828267569428206075L;
147
148    /** Zero represented as a <code>Double</code>. */
149    public static final Double ZERO = new Double(0.0);
150
151    /** The default paint. */
152    public static final Paint DEFAULT_PAINT = Color.blue;
153
154    /** The default outline paint. */
155    public static final Paint DEFAULT_OUTLINE_PAINT = Color.gray;
156
157    /** The default stroke. */
158    public static final Stroke DEFAULT_STROKE = new BasicStroke(1.0f);
159
160    /** The default outline stroke. */
161    public static final Stroke DEFAULT_OUTLINE_STROKE = new BasicStroke(1.0f);
162
163    /** The default shape. */
164    public static final Shape DEFAULT_SHAPE
165            = new Rectangle2D.Double(-3.0, -3.0, 6.0, 6.0);
166
167    /** The default value label font. */
168    public static final Font DEFAULT_VALUE_LABEL_FONT
169            = new Font("SansSerif", Font.PLAIN, 10);
170
171    /** The default value label paint. */
172    public static final Paint DEFAULT_VALUE_LABEL_PAINT = Color.black;
173
174    /** A list of flags that controls whether or not each series is visible. */
175    private BooleanList seriesVisibleList;
176
177    /** The default visibility for each series. */
178    private boolean baseSeriesVisible;
179
180    /**
181     * A list of flags that controls whether or not each series is visible in
182     * the legend.
183     */
184    private BooleanList seriesVisibleInLegendList;
185
186    /** The default visibility for each series in the legend. */
187    private boolean baseSeriesVisibleInLegend;
188
189    /** The paint list. */
190    private PaintList paintList;
191
192    /**
193     * A flag that controls whether or not the paintList is auto-populated
194     * in the {@link #lookupSeriesPaint(int)} method.
195     *
196     * @since 1.0.6
197     */
198    private boolean autoPopulateSeriesPaint;
199
200    /** The base paint. */
201    private transient Paint basePaint;
202
203    /** The fill paint list. */
204    private PaintList fillPaintList;
205
206    /**
207     * A flag that controls whether or not the fillPaintList is auto-populated
208     * in the {@link #lookupSeriesFillPaint(int)} method.
209     *
210     * @since 1.0.6
211     */
212    private boolean autoPopulateSeriesFillPaint;
213
214    /** The base fill paint. */
215    private transient Paint baseFillPaint;
216
217    /** The outline paint list. */
218    private PaintList outlinePaintList;
219
220    /**
221     * A flag that controls whether or not the outlinePaintList is
222     * auto-populated in the {@link #lookupSeriesOutlinePaint(int)} method.
223     *
224     * @since 1.0.6
225     */
226    private boolean autoPopulateSeriesOutlinePaint;
227
228    /** The base outline paint. */
229    private transient Paint baseOutlinePaint;
230
231    /** The stroke list. */
232    private StrokeList strokeList;
233
234    /**
235     * A flag that controls whether or not the strokeList is auto-populated
236     * in the {@link #lookupSeriesStroke(int)} method.
237     *
238     * @since 1.0.6
239     */
240    private boolean autoPopulateSeriesStroke;
241
242    /** The base stroke. */
243    private transient Stroke baseStroke;
244
245    /** The outline stroke list. */
246    private StrokeList outlineStrokeList;
247
248    /** The base outline stroke. */
249    private transient Stroke baseOutlineStroke;
250
251    /**
252     * A flag that controls whether or not the outlineStrokeList is
253     * auto-populated in the {@link #lookupSeriesOutlineStroke(int)} method.
254     *
255     * @since 1.0.6
256     */
257    private boolean autoPopulateSeriesOutlineStroke;
258
259    /** A shape list. */
260    private ShapeList shapeList;
261
262    /**
263     * A flag that controls whether or not the shapeList is auto-populated
264     * in the {@link #lookupSeriesShape(int)} method.
265     *
266     * @since 1.0.6
267     */
268    private boolean autoPopulateSeriesShape;
269
270    /** The base shape. */
271    private transient Shape baseShape;
272
273    /** Visibility of the item labels PER series. */
274    private BooleanList itemLabelsVisibleList;
275
276    /** The base item labels visible. */
277    private Boolean baseItemLabelsVisible;
278
279    /** The item label font list (one font per series). */
280    private ObjectList itemLabelFontList;
281
282    /** The base item label font. */
283    private Font baseItemLabelFont;
284
285    /** The item label paint list (one paint per series). */
286    private PaintList itemLabelPaintList;
287
288    /** The base item label paint. */
289    private transient Paint baseItemLabelPaint;
290
291    /** The positive item label position (per series). */
292    private ObjectList positiveItemLabelPositionList;
293
294    /** The fallback positive item label position. */
295    private ItemLabelPosition basePositiveItemLabelPosition;
296
297    /** The negative item label position (per series). */
298    private ObjectList negativeItemLabelPositionList;
299
300    /** The fallback negative item label position. */
301    private ItemLabelPosition baseNegativeItemLabelPosition;
302
303    /** The item label anchor offset. */
304    private double itemLabelAnchorOffset = 2.0;
305
306    /**
307     * Flags that control whether or not entities are generated for each
308     * series.  This will be overridden by 'createEntities'.
309     */
310    private BooleanList createEntitiesList;
311
312    /**
313     * The default flag that controls whether or not entities are generated.
314     * This flag is used when both the above flags return null.
315     */
316    private boolean baseCreateEntities;
317
318    /**
319     * The per-series legend shape settings.
320     *
321     * @since 1.0.11
322     */
323    private ShapeList legendShapeList;
324
325    /**
326     * The base shape for legend items.  If this is <code>null</code>, the
327     * series shape will be used.
328     *
329     * @since 1.0.11
330     */
331    private transient Shape baseLegendShape;
332
333    /**
334     * A special flag that, if true, will cause the getLegendItem() method
335     * to configure the legend shape as if it were a line.
336     *
337     * @since 1.0.14
338     */
339    private boolean treatLegendShapeAsLine;
340
341    /**
342     * The per-series legend text font.
343     *
344     * @since 1.0.11
345     */
346    private ObjectList legendTextFont;
347
348    /**
349     * The base legend font.
350     *
351     * @since 1.0.11
352     */
353    private Font baseLegendTextFont;
354
355    /**
356     * The per series legend text paint settings.
357     *
358     * @since 1.0.11
359     */
360    private PaintList legendTextPaint;
361
362    /**
363     * The default paint for the legend text items (if this is
364     * <code>null</code>, the {@link LegendTitle} class will determine the
365     * text paint to use.
366     *
367     * @since 1.0.11
368     */
369    private transient Paint baseLegendTextPaint;
370
371    /**
372     * A flag that controls whether or not the renderer will include the
373     * non-visible series when calculating the data bounds.
374     *
375     * @since 1.0.13
376     */
377    private boolean dataBoundsIncludesVisibleSeriesOnly = true;
378
379    /** The default radius for the entity 'hotspot' */
380    private int defaultEntityRadius;
381
382    /** Storage for registered change listeners. */
383    private transient EventListenerList listenerList;
384
385    /** An event for re-use. */
386    private transient RendererChangeEvent event;
387
388    /**
389     * Default constructor.
390     */
391    public AbstractRenderer() {
392
393        this.seriesVisible = null;
394        this.seriesVisibleList = new BooleanList();
395        this.baseSeriesVisible = true;
396
397        this.seriesVisibleInLegend = null;
398        this.seriesVisibleInLegendList = new BooleanList();
399        this.baseSeriesVisibleInLegend = true;
400
401        this.paint = null;
402        this.paintList = new PaintList();
403        this.basePaint = DEFAULT_PAINT;
404        this.autoPopulateSeriesPaint = true;
405
406        this.fillPaint = null;
407        this.fillPaintList = new PaintList();
408        this.baseFillPaint = Color.white;
409        this.autoPopulateSeriesFillPaint = false;
410
411        this.outlinePaint = null;
412        this.outlinePaintList = new PaintList();
413        this.baseOutlinePaint = DEFAULT_OUTLINE_PAINT;
414        this.autoPopulateSeriesOutlinePaint = false;
415
416        this.stroke = null;
417        this.strokeList = new StrokeList();
418        this.baseStroke = DEFAULT_STROKE;
419        this.autoPopulateSeriesStroke = true;
420
421        this.outlineStroke = null;
422        this.outlineStrokeList = new StrokeList();
423        this.baseOutlineStroke = DEFAULT_OUTLINE_STROKE;
424        this.autoPopulateSeriesOutlineStroke = false;
425
426        this.shape = null;
427        this.shapeList = new ShapeList();
428        this.baseShape = DEFAULT_SHAPE;
429        this.autoPopulateSeriesShape = true;
430
431        this.itemLabelsVisible = null;
432        this.itemLabelsVisibleList = new BooleanList();
433        this.baseItemLabelsVisible = Boolean.FALSE;
434
435        this.itemLabelFont = null;
436        this.itemLabelFontList = new ObjectList();
437        this.baseItemLabelFont = new Font("SansSerif", Font.PLAIN, 10);
438
439        this.itemLabelPaint = null;
440        this.itemLabelPaintList = new PaintList();
441        this.baseItemLabelPaint = Color.black;
442
443        this.positiveItemLabelPosition = null;
444        this.positiveItemLabelPositionList = new ObjectList();
445        this.basePositiveItemLabelPosition = new ItemLabelPosition(
446                ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER);
447
448        this.negativeItemLabelPosition = null;
449        this.negativeItemLabelPositionList = new ObjectList();
450        this.baseNegativeItemLabelPosition = new ItemLabelPosition(
451                ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER);
452
453        this.createEntities = null;
454        this.createEntitiesList = new BooleanList();
455        this.baseCreateEntities = true;
456
457        this.defaultEntityRadius = 3;
458
459        this.legendShapeList = new ShapeList();
460        this.baseLegendShape = null;
461
462        this.treatLegendShapeAsLine = false;
463
464        this.legendTextFont = new ObjectList();
465        this.baseLegendTextFont = null;
466
467        this.legendTextPaint = new PaintList();
468        this.baseLegendTextPaint = null;
469
470        this.listenerList = new EventListenerList();
471
472    }
473
474    /**
475     * Returns the drawing supplier from the plot.
476     *
477     * @return The drawing supplier.
478     */
479    public abstract DrawingSupplier getDrawingSupplier();
480
481    // SERIES VISIBLE (not yet respected by all renderers)
482
483    /**
484     * Returns a boolean that indicates whether or not the specified item
485     * should be drawn.
486     *
487     * @param series  the series index.
488     * @param item  the item index.
489     *
490     * @return A boolean.
491     */
492    public boolean getItemVisible(int series, int item) {
493        return isSeriesVisible(series);
494    }
495
496    /**
497     * Returns a boolean that indicates whether or not the specified series
498     * should be drawn.  In fact this method should be named 
499     * lookupSeriesVisible() to be consistent with the other series
500     * attributes and avoid confusion with the getSeriesVisible() method.
501     *
502     * @param series  the series index.
503     *
504     * @return A boolean.
505     */
506    public boolean isSeriesVisible(int series) {
507        boolean result = this.baseSeriesVisible;
508        if (this.seriesVisible != null) {
509            result = this.seriesVisible.booleanValue();
510        }
511        else {
512            Boolean b = this.seriesVisibleList.getBoolean(series);
513            if (b != null) {
514                result = b.booleanValue();
515            }
516        }
517        return result;
518    }
519
520    /**
521     * Returns the flag that controls whether a series is visible.
522     *
523     * @param series  the series index (zero-based).
524     *
525     * @return The flag (possibly <code>null</code>).
526     *
527     * @see #setSeriesVisible(int, Boolean)
528     */
529    public Boolean getSeriesVisible(int series) {
530        return this.seriesVisibleList.getBoolean(series);
531    }
532
533    /**
534     * Sets the flag that controls whether a series is visible and sends a
535     * {@link RendererChangeEvent} to all registered listeners.
536     *
537     * @param series  the series index (zero-based).
538     * @param visible  the flag (<code>null</code> permitted).
539     *
540     * @see #getSeriesVisible(int)
541     */
542    public void setSeriesVisible(int series, Boolean visible) {
543        setSeriesVisible(series, visible, true);
544    }
545
546    /**
547     * Sets the flag that controls whether a series is visible and, if
548     * requested, sends a {@link RendererChangeEvent} to all registered
549     * listeners.
550     *
551     * @param series  the series index.
552     * @param visible  the flag (<code>null</code> permitted).
553     * @param notify  notify listeners?
554     *
555     * @see #getSeriesVisible(int)
556     */
557    public void setSeriesVisible(int series, Boolean visible, boolean notify) {
558        this.seriesVisibleList.setBoolean(series, visible);
559        if (notify) {
560            // we create an event with a special flag set...the purpose of
561            // this is to communicate to the plot (the default receiver of
562            // the event) that series visibility has changed so the axis
563            // ranges might need updating...
564            RendererChangeEvent e = new RendererChangeEvent(this, true);
565            notifyListeners(e);
566        }
567    }
568
569    /**
570     * Returns the base visibility for all series.
571     *
572     * @return The base visibility.
573     *
574     * @see #setBaseSeriesVisible(boolean)
575     */
576    public boolean getBaseSeriesVisible() {
577        return this.baseSeriesVisible;
578    }
579
580    /**
581     * Sets the base visibility and sends a {@link RendererChangeEvent}
582     * to all registered listeners.
583     *
584     * @param visible  the flag.
585     *
586     * @see #getBaseSeriesVisible()
587     */
588    public void setBaseSeriesVisible(boolean visible) {
589        // defer argument checking...
590        setBaseSeriesVisible(visible, true);
591    }
592
593    /**
594     * Sets the base visibility and, if requested, sends
595     * a {@link RendererChangeEvent} to all registered listeners.
596     *
597     * @param visible  the visibility.
598     * @param notify  notify listeners?
599     *
600     * @see #getBaseSeriesVisible()
601     */
602    public void setBaseSeriesVisible(boolean visible, boolean notify) {
603        this.baseSeriesVisible = visible;
604        if (notify) {
605            // we create an event with a special flag set...the purpose of
606            // this is to communicate to the plot (the default receiver of
607            // the event) that series visibility has changed so the axis
608            // ranges might need updating...
609            RendererChangeEvent e = new RendererChangeEvent(this, true);
610            notifyListeners(e);
611        }
612    }
613
614    // SERIES VISIBLE IN LEGEND (not yet respected by all renderers)
615
616    /**
617     * Returns <code>true</code> if the series should be shown in the legend,
618     * and <code>false</code> otherwise.
619     *
620     * @param series  the series index.
621     *
622     * @return A boolean.
623     */
624    public boolean isSeriesVisibleInLegend(int series) {
625        boolean result = this.baseSeriesVisibleInLegend;
626        if (this.seriesVisibleInLegend != null) {
627            result = this.seriesVisibleInLegend.booleanValue();
628        }
629        else {
630            Boolean b = this.seriesVisibleInLegendList.getBoolean(series);
631            if (b != null) {
632                result = b.booleanValue();
633            }
634        }
635        return result;
636    }
637
638    /**
639     * Returns the flag that controls whether a series is visible in the
640     * legend.  This method returns only the "per series" settings - to
641     * incorporate the override and base settings as well, you need to use the
642     * {@link #isSeriesVisibleInLegend(int)} method.
643     *
644     * @param series  the series index (zero-based).
645     *
646     * @return The flag (possibly <code>null</code>).
647     *
648     * @see #setSeriesVisibleInLegend(int, Boolean)
649     */
650    public Boolean getSeriesVisibleInLegend(int series) {
651        return this.seriesVisibleInLegendList.getBoolean(series);
652    }
653
654    /**
655     * Sets the flag that controls whether a series is visible in the legend
656     * and sends a {@link RendererChangeEvent} to all registered listeners.
657     *
658     * @param series  the series index (zero-based).
659     * @param visible  the flag (<code>null</code> permitted).
660     *
661     * @see #getSeriesVisibleInLegend(int)
662     */
663    public void setSeriesVisibleInLegend(int series, Boolean visible) {
664        setSeriesVisibleInLegend(series, visible, true);
665    }
666
667    /**
668     * Sets the flag that controls whether a series is visible in the legend
669     * and, if requested, sends a {@link RendererChangeEvent} to all registered
670     * listeners.
671     *
672     * @param series  the series index.
673     * @param visible  the flag (<code>null</code> permitted).
674     * @param notify  notify listeners?
675     *
676     * @see #getSeriesVisibleInLegend(int)
677     */
678    public void setSeriesVisibleInLegend(int series, Boolean visible,
679                                         boolean notify) {
680        this.seriesVisibleInLegendList.setBoolean(series, visible);
681        if (notify) {
682            fireChangeEvent();
683        }
684    }
685
686    /**
687     * Returns the base visibility in the legend for all series.
688     *
689     * @return The base visibility.
690     *
691     * @see #setBaseSeriesVisibleInLegend(boolean)
692     */
693    public boolean getBaseSeriesVisibleInLegend() {
694        return this.baseSeriesVisibleInLegend;
695    }
696
697    /**
698     * Sets the base visibility in the legend and sends a
699     * {@link RendererChangeEvent} to all registered listeners.
700     *
701     * @param visible  the flag.
702     *
703     * @see #getBaseSeriesVisibleInLegend()
704     */
705    public void setBaseSeriesVisibleInLegend(boolean visible) {
706        // defer argument checking...
707        setBaseSeriesVisibleInLegend(visible, true);
708    }
709
710    /**
711     * Sets the base visibility in the legend and, if requested, sends
712     * a {@link RendererChangeEvent} to all registered listeners.
713     *
714     * @param visible  the visibility.
715     * @param notify  notify listeners?
716     *
717     * @see #getBaseSeriesVisibleInLegend()
718     */
719    public void setBaseSeriesVisibleInLegend(boolean visible, boolean notify) {
720        this.baseSeriesVisibleInLegend = visible;
721        if (notify) {
722            fireChangeEvent();
723        }
724    }
725
726    // PAINT
727
728    /**
729     * Returns the paint used to color data items as they are drawn.
730     * <p>
731     * The default implementation passes control to the
732     * <code>lookupSeriesPaint()</code> method. You can override this method
733     * if you require different behaviour.
734     *
735     * @param row  the row (or series) index (zero-based).
736     * @param column  the column (or category) index (zero-based).
737     *
738     * @return The paint (never <code>null</code>).
739     */
740    public Paint getItemPaint(int row, int column) {
741        return lookupSeriesPaint(row);
742    }
743
744    /**
745     * Returns the paint used to color an item drawn by the renderer.
746     *
747     * @param series  the series index (zero-based).
748     *
749     * @return The paint (never <code>null</code>).
750     *
751     * @since 1.0.6
752     */
753    public Paint lookupSeriesPaint(int series) {
754
755        // return the override, if there is one...
756        if (this.paint != null) {
757            return this.paint;
758        }
759
760        // otherwise look up the paint list
761        Paint seriesPaint = getSeriesPaint(series);
762        if (seriesPaint == null && this.autoPopulateSeriesPaint) {
763            DrawingSupplier supplier = getDrawingSupplier();
764            if (supplier != null) {
765                seriesPaint = supplier.getNextPaint();
766                setSeriesPaint(series, seriesPaint, false);
767            }
768        }
769        if (seriesPaint == null) {
770            seriesPaint = this.basePaint;
771        }
772        return seriesPaint;
773
774    }
775
776    /**
777     * Returns the paint used to color an item drawn by the renderer.
778     *
779     * @param series  the series index (zero-based).
780     *
781     * @return The paint (possibly <code>null</code>).
782     *
783     * @see #setSeriesPaint(int, Paint)
784     */
785    public Paint getSeriesPaint(int series) {
786        return this.paintList.getPaint(series);
787    }
788
789    /**
790     * Sets the paint used for a series and sends a {@link RendererChangeEvent}
791     * to all registered listeners.
792     *
793     * @param series  the series index (zero-based).
794     * @param paint  the paint (<code>null</code> permitted).
795     *
796     * @see #getSeriesPaint(int)
797     */
798    public void setSeriesPaint(int series, Paint paint) {
799        setSeriesPaint(series, paint, true);
800    }
801
802    /**
803     * Sets the paint used for a series and, if requested, sends a
804     * {@link RendererChangeEvent} to all registered listeners.
805     *
806     * @param series  the series index.
807     * @param paint  the paint (<code>null</code> permitted).
808     * @param notify  notify listeners?
809     *
810     * @see #getSeriesPaint(int)
811     */
812    public void setSeriesPaint(int series, Paint paint, boolean notify) {
813        this.paintList.setPaint(series, paint);
814        if (notify) {
815            fireChangeEvent();
816        }
817    }
818
819    /**
820     * Clears the series paint settings for this renderer and, if requested,
821     * sends a {@link RendererChangeEvent} to all registered listeners.
822     *
823     * @param notify  notify listeners?
824     *
825     * @since 1.0.11
826     */
827    public void clearSeriesPaints(boolean notify) {
828        this.paintList.clear();
829        if (notify) {
830            fireChangeEvent();
831        }
832    }
833
834    /**
835     * Returns the base paint.
836     *
837     * @return The base paint (never <code>null</code>).
838     *
839     * @see #setBasePaint(Paint)
840     */
841    public Paint getBasePaint() {
842        return this.basePaint;
843    }
844
845    /**
846     * Sets the base paint and sends a {@link RendererChangeEvent} to all
847     * registered listeners.
848     *
849     * @param paint  the paint (<code>null</code> not permitted).
850     *
851     * @see #getBasePaint()
852     */
853    public void setBasePaint(Paint paint) {
854        // defer argument checking...
855        setBasePaint(paint, true);
856    }
857
858    /**
859     * Sets the base paint and, if requested, sends a
860     * {@link RendererChangeEvent} to all registered listeners.
861     *
862     * @param paint  the paint (<code>null</code> not permitted).
863     * @param notify  notify listeners?
864     *
865     * @see #getBasePaint()
866     */
867    public void setBasePaint(Paint paint, boolean notify) {
868        this.basePaint = paint;
869        if (notify) {
870            fireChangeEvent();
871        }
872    }
873
874    /**
875     * Returns the flag that controls whether or not the series paint list is
876     * automatically populated when {@link #lookupSeriesPaint(int)} is called.
877     *
878     * @return A boolean.
879     *
880     * @since 1.0.6
881     *
882     * @see #setAutoPopulateSeriesPaint(boolean)
883     */
884    public boolean getAutoPopulateSeriesPaint() {
885        return this.autoPopulateSeriesPaint;
886    }
887
888    /**
889     * Sets the flag that controls whether or not the series paint list is
890     * automatically populated when {@link #lookupSeriesPaint(int)} is called.
891     *
892     * @param auto  the new flag value.
893     *
894     * @since 1.0.6
895     *
896     * @see #getAutoPopulateSeriesPaint()
897     */
898    public void setAutoPopulateSeriesPaint(boolean auto) {
899        this.autoPopulateSeriesPaint = auto;
900    }
901
902    //// FILL PAINT //////////////////////////////////////////////////////////
903
904    /**
905     * Returns the paint used to fill data items as they are drawn.  The
906     * default implementation passes control to the
907     * {@link #lookupSeriesFillPaint(int)} method - you can override this
908     * method if you require different behaviour.
909     *
910     * @param row  the row (or series) index (zero-based).
911     * @param column  the column (or category) index (zero-based).
912     *
913     * @return The paint (never <code>null</code>).
914     */
915    public Paint getItemFillPaint(int row, int column) {
916        return lookupSeriesFillPaint(row);
917    }
918
919    /**
920     * Returns the paint used to fill an item drawn by the renderer.
921     *
922     * @param series  the series (zero-based index).
923     *
924     * @return The paint (never <code>null</code>).
925     *
926     * @since 1.0.6
927     */
928    public Paint lookupSeriesFillPaint(int series) {
929
930        // return the override, if there is one...
931        if (this.fillPaint != null) {
932            return this.fillPaint;
933        }
934
935        // otherwise look up the paint table
936        Paint seriesFillPaint = getSeriesFillPaint(series);
937        if (seriesFillPaint == null && this.autoPopulateSeriesFillPaint) {
938            DrawingSupplier supplier = getDrawingSupplier();
939            if (supplier != null) {
940                seriesFillPaint = supplier.getNextFillPaint();
941                setSeriesFillPaint(series, seriesFillPaint, false);
942            }
943        }
944        if (seriesFillPaint == null) {
945            seriesFillPaint = this.baseFillPaint;
946        }
947        return seriesFillPaint;
948
949    }
950
951    /**
952     * Returns the paint used to fill an item drawn by the renderer.
953     *
954     * @param series  the series (zero-based index).
955     *
956     * @return The paint (never <code>null</code>).
957     *
958     * @see #setSeriesFillPaint(int, Paint)
959     */
960    public Paint getSeriesFillPaint(int series) {
961        return this.fillPaintList.getPaint(series);
962    }
963
964    /**
965     * Sets the paint used for a series fill and sends a
966     * {@link RendererChangeEvent} to all registered listeners.
967     *
968     * @param series  the series index (zero-based).
969     * @param paint  the paint (<code>null</code> permitted).
970     *
971     * @see #getSeriesFillPaint(int)
972     */
973    public void setSeriesFillPaint(int series, Paint paint) {
974        setSeriesFillPaint(series, paint, true);
975    }
976
977    /**
978     * Sets the paint used to fill a series and, if requested,
979     * sends a {@link RendererChangeEvent} to all registered listeners.
980     *
981     * @param series  the series index (zero-based).
982     * @param paint  the paint (<code>null</code> permitted).
983     * @param notify  notify listeners?
984     *
985     * @see #getSeriesFillPaint(int)
986     */
987    public void setSeriesFillPaint(int series, Paint paint, boolean notify) {
988        this.fillPaintList.setPaint(series, paint);
989        if (notify) {
990            fireChangeEvent();
991        }
992    }
993
994    /**
995     * Returns the base (or default) fill paint.
996     *
997     * @return The paint (never <code>null</code>).
998     *
999     * @see #setBaseFillPaint(Paint)
1000     */
1001    public Paint getBaseFillPaint() {
1002        return this.baseFillPaint;
1003    }
1004
1005    /**
1006     * Sets the base fill paint and sends a {@link RendererChangeEvent} to
1007     * all registered listeners.
1008     *
1009     * @param paint  the paint (<code>null</code> not permitted).
1010     *
1011     * @see #getBaseFillPaint()
1012     */
1013    public void setBaseFillPaint(Paint paint) {
1014        // defer argument checking...
1015        setBaseFillPaint(paint, true);
1016    }
1017
1018    /**
1019     * Sets the base fill paint and, if requested, sends a
1020     * {@link RendererChangeEvent} to all registered listeners.
1021     *
1022     * @param paint  the paint (<code>null</code> not permitted).
1023     * @param notify  notify listeners?
1024     *
1025     * @see #getBaseFillPaint()
1026     */
1027    public void setBaseFillPaint(Paint paint, boolean notify) {
1028        ParamChecks.nullNotPermitted(paint, "paint");
1029        this.baseFillPaint = paint;
1030        if (notify) {
1031            fireChangeEvent();
1032        }
1033    }
1034
1035    /**
1036     * Returns the flag that controls whether or not the series fill paint list
1037     * is automatically populated when {@link #lookupSeriesFillPaint(int)} is
1038     * called.
1039     *
1040     * @return A boolean.
1041     *
1042     * @since 1.0.6
1043     *
1044     * @see #setAutoPopulateSeriesFillPaint(boolean)
1045     */
1046    public boolean getAutoPopulateSeriesFillPaint() {
1047        return this.autoPopulateSeriesFillPaint;
1048    }
1049
1050    /**
1051     * Sets the flag that controls whether or not the series fill paint list is
1052     * automatically populated when {@link #lookupSeriesFillPaint(int)} is
1053     * called.
1054     *
1055     * @param auto  the new flag value.
1056     *
1057     * @since 1.0.6
1058     *
1059     * @see #getAutoPopulateSeriesFillPaint()
1060     */
1061    public void setAutoPopulateSeriesFillPaint(boolean auto) {
1062        this.autoPopulateSeriesFillPaint = auto;
1063    }
1064
1065    // OUTLINE PAINT //////////////////////////////////////////////////////////
1066
1067    /**
1068     * Returns the paint used to outline data items as they are drawn.
1069     * <p>
1070     * The default implementation passes control to the
1071     * {@link #lookupSeriesOutlinePaint} method.  You can override this method
1072     * if you require different behaviour.
1073     *
1074     * @param row  the row (or series) index (zero-based).
1075     * @param column  the column (or category) index (zero-based).
1076     *
1077     * @return The paint (never <code>null</code>).
1078     */
1079    public Paint getItemOutlinePaint(int row, int column) {
1080        return lookupSeriesOutlinePaint(row);
1081    }
1082
1083    /**
1084     * Returns the paint used to outline an item drawn by the renderer.
1085     *
1086     * @param series  the series (zero-based index).
1087     *
1088     * @return The paint (never <code>null</code>).
1089     *
1090     * @since 1.0.6
1091     */
1092    public Paint lookupSeriesOutlinePaint(int series) {
1093
1094        // return the override, if there is one...
1095        if (this.outlinePaint != null) {
1096            return this.outlinePaint;
1097        }
1098
1099        // otherwise look up the paint table
1100        Paint seriesOutlinePaint = getSeriesOutlinePaint(series);
1101        if (seriesOutlinePaint == null && this.autoPopulateSeriesOutlinePaint) {
1102            DrawingSupplier supplier = getDrawingSupplier();
1103            if (supplier != null) {
1104                seriesOutlinePaint = supplier.getNextOutlinePaint();
1105                setSeriesOutlinePaint(series, seriesOutlinePaint, false);
1106            }
1107        }
1108        if (seriesOutlinePaint == null) {
1109            seriesOutlinePaint = this.baseOutlinePaint;
1110        }
1111        return seriesOutlinePaint;
1112
1113    }
1114
1115    /**
1116     * Returns the paint used to outline an item drawn by the renderer.
1117     *
1118     * @param series  the series (zero-based index).
1119     *
1120     * @return The paint (possibly <code>null</code>).
1121     *
1122     * @see #setSeriesOutlinePaint(int, Paint)
1123     */
1124    public Paint getSeriesOutlinePaint(int series) {
1125        return this.outlinePaintList.getPaint(series);
1126    }
1127
1128    /**
1129     * Sets the paint used for a series outline and sends a
1130     * {@link RendererChangeEvent} to all registered listeners.
1131     *
1132     * @param series  the series index (zero-based).
1133     * @param paint  the paint (<code>null</code> permitted).
1134     *
1135     * @see #getSeriesOutlinePaint(int)
1136     */
1137    public void setSeriesOutlinePaint(int series, Paint paint) {
1138        setSeriesOutlinePaint(series, paint, true);
1139    }
1140
1141    /**
1142     * Sets the paint used to draw the outline for a series and, if requested,
1143     * sends a {@link RendererChangeEvent} to all registered listeners.
1144     *
1145     * @param series  the series index (zero-based).
1146     * @param paint  the paint (<code>null</code> permitted).
1147     * @param notify  notify listeners?
1148     *
1149     * @see #getSeriesOutlinePaint(int)
1150     */
1151    public void setSeriesOutlinePaint(int series, Paint paint, boolean notify) {
1152        this.outlinePaintList.setPaint(series, paint);
1153        if (notify) {
1154            fireChangeEvent();
1155        }
1156    }
1157
1158    /**
1159     * Returns the base (or default) outline paint.
1160     *
1161     * @return The paint (never <code>null</code>).
1162     *
1163     * @see #setBaseOutlinePaint(Paint)
1164     */
1165    public Paint getBaseOutlinePaint() {
1166        return this.baseOutlinePaint;
1167    }
1168
1169    /**
1170     * Sets the base outline paint and sends a {@link RendererChangeEvent} to
1171     * all registered listeners.
1172     *
1173     * @param paint  the paint (<code>null</code> not permitted).
1174     *
1175     * @see #getBaseOutlinePaint()
1176     */
1177    public void setBaseOutlinePaint(Paint paint) {
1178        // defer argument checking...
1179        setBaseOutlinePaint(paint, true);
1180    }
1181
1182    /**
1183     * Sets the base outline paint and, if requested, sends a
1184     * {@link RendererChangeEvent} to all registered listeners.
1185     *
1186     * @param paint  the paint (<code>null</code> not permitted).
1187     * @param notify  notify listeners?
1188     *
1189     * @see #getBaseOutlinePaint()
1190     */
1191    public void setBaseOutlinePaint(Paint paint, boolean notify) {
1192        ParamChecks.nullNotPermitted(paint, "paint");
1193        this.baseOutlinePaint = paint;
1194        if (notify) {
1195            fireChangeEvent();
1196        }
1197    }
1198
1199    /**
1200     * Returns the flag that controls whether or not the series outline paint
1201     * list is automatically populated when
1202     * {@link #lookupSeriesOutlinePaint(int)} is called.
1203     *
1204     * @return A boolean.
1205     *
1206     * @since 1.0.6
1207     *
1208     * @see #setAutoPopulateSeriesOutlinePaint(boolean)
1209     */
1210    public boolean getAutoPopulateSeriesOutlinePaint() {
1211        return this.autoPopulateSeriesOutlinePaint;
1212    }
1213
1214    /**
1215     * Sets the flag that controls whether or not the series outline paint list
1216     * is automatically populated when {@link #lookupSeriesOutlinePaint(int)}
1217     * is called.
1218     *
1219     * @param auto  the new flag value.
1220     *
1221     * @since 1.0.6
1222     *
1223     * @see #getAutoPopulateSeriesOutlinePaint()
1224     */
1225    public void setAutoPopulateSeriesOutlinePaint(boolean auto) {
1226        this.autoPopulateSeriesOutlinePaint = auto;
1227    }
1228
1229    // STROKE
1230
1231    /**
1232     * Returns the stroke used to draw data items.
1233     * <p>
1234     * The default implementation passes control to the getSeriesStroke method.
1235     * You can override this method if you require different behaviour.
1236     *
1237     * @param row  the row (or series) index (zero-based).
1238     * @param column  the column (or category) index (zero-based).
1239     *
1240     * @return The stroke (never <code>null</code>).
1241     */
1242    public Stroke getItemStroke(int row, int column) {
1243        return lookupSeriesStroke(row);
1244    }
1245
1246    /**
1247     * Returns the stroke used to draw the items in a series.
1248     *
1249     * @param series  the series (zero-based index).
1250     *
1251     * @return The stroke (never <code>null</code>).
1252     *
1253     * @since 1.0.6
1254     */
1255    public Stroke lookupSeriesStroke(int series) {
1256
1257        // return the override, if there is one...
1258        if (this.stroke != null) {
1259            return this.stroke;
1260        }
1261
1262        // otherwise look up the paint table
1263        Stroke result = getSeriesStroke(series);
1264        if (result == null && this.autoPopulateSeriesStroke) {
1265            DrawingSupplier supplier = getDrawingSupplier();
1266            if (supplier != null) {
1267                result = supplier.getNextStroke();
1268                setSeriesStroke(series, result, false);
1269            }
1270        }
1271        if (result == null) {
1272            result = this.baseStroke;
1273        }
1274        return result;
1275
1276    }
1277
1278    /**
1279     * Returns the stroke used to draw the items in a series.
1280     *
1281     * @param series  the series (zero-based index).
1282     *
1283     * @return The stroke (possibly <code>null</code>).
1284     *
1285     * @see #setSeriesStroke(int, Stroke)
1286     */
1287    public Stroke getSeriesStroke(int series) {
1288        return this.strokeList.getStroke(series);
1289    }
1290
1291    /**
1292     * Sets the stroke used for a series and sends a {@link RendererChangeEvent}
1293     * to all registered listeners.
1294     *
1295     * @param series  the series index (zero-based).
1296     * @param stroke  the stroke (<code>null</code> permitted).
1297     *
1298     * @see #getSeriesStroke(int)
1299     */
1300    public void setSeriesStroke(int series, Stroke stroke) {
1301        setSeriesStroke(series, stroke, true);
1302    }
1303
1304    /**
1305     * Sets the stroke for a series and, if requested, sends a
1306     * {@link RendererChangeEvent} to all registered listeners.
1307     *
1308     * @param series  the series index (zero-based).
1309     * @param stroke  the stroke (<code>null</code> permitted).
1310     * @param notify  notify listeners?
1311     *
1312     * @see #getSeriesStroke(int)
1313     */
1314    public void setSeriesStroke(int series, Stroke stroke, boolean notify) {
1315        this.strokeList.setStroke(series, stroke);
1316        if (notify) {
1317            fireChangeEvent();
1318        }
1319    }
1320
1321    /**
1322     * Clears the series stroke settings for this renderer and, if requested,
1323     * sends a {@link RendererChangeEvent} to all registered listeners.
1324     *
1325     * @param notify  notify listeners?
1326     *
1327     * @since 1.0.11
1328     */
1329    public void clearSeriesStrokes(boolean notify) {
1330        this.strokeList.clear();
1331        if (notify) {
1332            fireChangeEvent();
1333        }
1334    }
1335
1336    /**
1337     * Returns the base (or default) stroke.
1338     *
1339     * @return The base stroke (never <code>null</code>).
1340     *
1341     * @see #setBaseStroke(Stroke)
1342     */
1343    public Stroke getBaseStroke() {
1344        return this.baseStroke;
1345    }
1346
1347    /**
1348     * Sets the base stroke and sends a {@link RendererChangeEvent} to all
1349     * registered listeners.
1350     *
1351     * @param stroke  the stroke (<code>null</code> not permitted).
1352     *
1353     * @see #getBaseStroke()
1354     */
1355    public void setBaseStroke(Stroke stroke) {
1356        // defer argument checking...
1357        setBaseStroke(stroke, true);
1358    }
1359
1360    /**
1361     * Sets the base stroke and, if requested, sends a
1362     * {@link RendererChangeEvent} to all registered listeners.
1363     *
1364     * @param stroke  the stroke (<code>null</code> not permitted).
1365     * @param notify  notify listeners?
1366     *
1367     * @see #getBaseStroke()
1368     */
1369    public void setBaseStroke(Stroke stroke, boolean notify) {
1370        ParamChecks.nullNotPermitted(stroke, "stroke");
1371        this.baseStroke = stroke;
1372        if (notify) {
1373            fireChangeEvent();
1374        }
1375    }
1376
1377    /**
1378     * Returns the flag that controls whether or not the series stroke list is
1379     * automatically populated when {@link #lookupSeriesStroke(int)} is called.
1380     *
1381     * @return A boolean.
1382     *
1383     * @since 1.0.6
1384     *
1385     * @see #setAutoPopulateSeriesStroke(boolean)
1386     */
1387    public boolean getAutoPopulateSeriesStroke() {
1388        return this.autoPopulateSeriesStroke;
1389    }
1390
1391    /**
1392     * Sets the flag that controls whether or not the series stroke list is
1393     * automatically populated when {@link #lookupSeriesStroke(int)} is called.
1394     *
1395     * @param auto  the new flag value.
1396     *
1397     * @since 1.0.6
1398     *
1399     * @see #getAutoPopulateSeriesStroke()
1400     */
1401    public void setAutoPopulateSeriesStroke(boolean auto) {
1402        this.autoPopulateSeriesStroke = auto;
1403    }
1404
1405    // OUTLINE STROKE
1406
1407    /**
1408     * Returns the stroke used to outline data items.  The default
1409     * implementation passes control to the
1410     * {@link #lookupSeriesOutlineStroke(int)} method. You can override this
1411     * method if you require different behaviour.
1412     *
1413     * @param row  the row (or series) index (zero-based).
1414     * @param column  the column (or category) index (zero-based).
1415     *
1416     * @return The stroke (never <code>null</code>).
1417     */
1418    public Stroke getItemOutlineStroke(int row, int column) {
1419        return lookupSeriesOutlineStroke(row);
1420    }
1421
1422    /**
1423     * Returns the stroke used to outline the items in a series.
1424     *
1425     * @param series  the series (zero-based index).
1426     *
1427     * @return The stroke (never <code>null</code>).
1428     *
1429     * @since 1.0.6
1430     */
1431    public Stroke lookupSeriesOutlineStroke(int series) {
1432
1433        // return the override, if there is one...
1434        if (this.outlineStroke != null) {
1435            return this.outlineStroke;
1436        }
1437
1438        // otherwise look up the stroke table
1439        Stroke result = getSeriesOutlineStroke(series);
1440        if (result == null && this.autoPopulateSeriesOutlineStroke) {
1441            DrawingSupplier supplier = getDrawingSupplier();
1442            if (supplier != null) {
1443                result = supplier.getNextOutlineStroke();
1444                setSeriesOutlineStroke(series, result, false);
1445            }
1446        }
1447        if (result == null) {
1448            result = this.baseOutlineStroke;
1449        }
1450        return result;
1451
1452    }
1453
1454    /**
1455     * Returns the stroke used to outline the items in a series.
1456     *
1457     * @param series  the series (zero-based index).
1458     *
1459     * @return The stroke (possibly <code>null</code>).
1460     *
1461     * @see #setSeriesOutlineStroke(int, Stroke)
1462     */
1463    public Stroke getSeriesOutlineStroke(int series) {
1464        return this.outlineStrokeList.getStroke(series);
1465    }
1466
1467    /**
1468     * Sets the outline stroke used for a series and sends a
1469     * {@link RendererChangeEvent} to all registered listeners.
1470     *
1471     * @param series  the series index (zero-based).
1472     * @param stroke  the stroke (<code>null</code> permitted).
1473     *
1474     * @see #getSeriesOutlineStroke(int)
1475     */
1476    public void setSeriesOutlineStroke(int series, Stroke stroke) {
1477        setSeriesOutlineStroke(series, stroke, true);
1478    }
1479
1480    /**
1481     * Sets the outline stroke for a series and, if requested, sends a
1482     * {@link RendererChangeEvent} to all registered listeners.
1483     *
1484     * @param series  the series index.
1485     * @param stroke  the stroke (<code>null</code> permitted).
1486     * @param notify  notify listeners?
1487     *
1488     * @see #getSeriesOutlineStroke(int)
1489     */
1490    public void setSeriesOutlineStroke(int series, Stroke stroke,
1491                                       boolean notify) {
1492        this.outlineStrokeList.setStroke(series, stroke);
1493        if (notify) {
1494            fireChangeEvent();
1495        }
1496    }
1497
1498    /**
1499     * Returns the base (or default) outline stroke.
1500     *
1501     * @return The stroke (never <code>null</code>).
1502     *
1503     * @see #setBaseOutlineStroke(Stroke)
1504     */
1505    public Stroke getBaseOutlineStroke() {
1506        return this.baseOutlineStroke;
1507    }
1508
1509    /**
1510     * Sets the base outline stroke and sends a {@link RendererChangeEvent} to
1511     * all registered listeners.
1512     *
1513     * @param stroke  the stroke (<code>null</code> not permitted).
1514     *
1515     * @see #getBaseOutlineStroke()
1516     */
1517    public void setBaseOutlineStroke(Stroke stroke) {
1518        setBaseOutlineStroke(stroke, true);
1519    }
1520
1521    /**
1522     * Sets the base outline stroke and, if requested, sends a
1523     * {@link RendererChangeEvent} to all registered listeners.
1524     *
1525     * @param stroke  the stroke (<code>null</code> not permitted).
1526     * @param notify  a flag that controls whether or not listeners are
1527     *                notified.
1528     *
1529     * @see #getBaseOutlineStroke()
1530     */
1531    public void setBaseOutlineStroke(Stroke stroke, boolean notify) {
1532        ParamChecks.nullNotPermitted(stroke, "stroke");
1533        this.baseOutlineStroke = stroke;
1534        if (notify) {
1535            fireChangeEvent();
1536        }
1537    }
1538
1539    /**
1540     * Returns the flag that controls whether or not the series outline stroke
1541     * list is automatically populated when
1542     * {@link #lookupSeriesOutlineStroke(int)} is called.
1543     *
1544     * @return A boolean.
1545     *
1546     * @since 1.0.6
1547     *
1548     * @see #setAutoPopulateSeriesOutlineStroke(boolean)
1549     */
1550    public boolean getAutoPopulateSeriesOutlineStroke() {
1551        return this.autoPopulateSeriesOutlineStroke;
1552    }
1553
1554    /**
1555     * Sets the flag that controls whether or not the series outline stroke list
1556     * is automatically populated when {@link #lookupSeriesOutlineStroke(int)}
1557     * is called.
1558     *
1559     * @param auto  the new flag value.
1560     *
1561     * @since 1.0.6
1562     *
1563     * @see #getAutoPopulateSeriesOutlineStroke()
1564     */
1565    public void setAutoPopulateSeriesOutlineStroke(boolean auto) {
1566        this.autoPopulateSeriesOutlineStroke = auto;
1567    }
1568
1569    // SHAPE
1570
1571    /**
1572     * Returns a shape used to represent a data item.
1573     * <p>
1574     * The default implementation passes control to the 
1575     * {@link #lookupSeriesShape(int)} method. You can override this method if 
1576     * you require different behaviour.
1577     *
1578     * @param row  the row (or series) index (zero-based).
1579     * @param column  the column (or category) index (zero-based).
1580     *
1581     * @return The shape (never <code>null</code>).
1582     */
1583    public Shape getItemShape(int row, int column) {
1584        return lookupSeriesShape(row);
1585    }
1586
1587    /**
1588     * Returns a shape used to represent the items in a series.
1589     *
1590     * @param series  the series (zero-based index).
1591     *
1592     * @return The shape (never <code>null</code>).
1593     *
1594     * @since 1.0.6
1595     */
1596    public Shape lookupSeriesShape(int series) {
1597
1598        // return the override, if there is one...
1599        if (this.shape != null) {
1600            return this.shape;
1601        }
1602
1603        // otherwise look up the shape list
1604        Shape result = getSeriesShape(series);
1605        if (result == null && this.autoPopulateSeriesShape) {
1606            DrawingSupplier supplier = getDrawingSupplier();
1607            if (supplier != null) {
1608                result = supplier.getNextShape();
1609                setSeriesShape(series, result, false);
1610            }
1611        }
1612        if (result == null) {
1613            result = this.baseShape;
1614        }
1615        return result;
1616
1617    }
1618
1619    /**
1620     * Returns a shape used to represent the items in a series.
1621     *
1622     * @param series  the series (zero-based index).
1623     *
1624     * @return The shape (possibly <code>null</code>).
1625     *
1626     * @see #setSeriesShape(int, Shape)
1627     */
1628    public Shape getSeriesShape(int series) {
1629        return this.shapeList.getShape(series);
1630    }
1631
1632    /**
1633     * Sets the shape used for a series and sends a {@link RendererChangeEvent}
1634     * to all registered listeners.
1635     *
1636     * @param series  the series index (zero-based).
1637     * @param shape  the shape (<code>null</code> permitted).
1638     *
1639     * @see #getSeriesShape(int)
1640     */
1641    public void setSeriesShape(int series, Shape shape) {
1642        setSeriesShape(series, shape, true);
1643    }
1644
1645    /**
1646     * Sets the shape for a series and, if requested, sends a
1647     * {@link RendererChangeEvent} to all registered listeners.
1648     *
1649     * @param series  the series index (zero based).
1650     * @param shape  the shape (<code>null</code> permitted).
1651     * @param notify  notify listeners?
1652     *
1653     * @see #getSeriesShape(int)
1654     */
1655    public void setSeriesShape(int series, Shape shape, boolean notify) {
1656        this.shapeList.setShape(series, shape);
1657        if (notify) {
1658            fireChangeEvent();
1659        }
1660    }
1661
1662    /**
1663     * Returns the base (or default) shape.
1664     *
1665     * @return The shape (never <code>null</code>).
1666     *
1667     * @see #setBaseShape(Shape)
1668     */
1669    public Shape getBaseShape() {
1670        return this.baseShape;
1671    }
1672
1673    /**
1674     * Sets the base shape and sends a {@link RendererChangeEvent} to all
1675     * registered listeners.
1676     *
1677     * @param shape  the shape (<code>null</code> not permitted).
1678     *
1679     * @see #getBaseShape()
1680     */
1681    public void setBaseShape(Shape shape) {
1682        // defer argument checking...
1683        setBaseShape(shape, true);
1684    }
1685
1686    /**
1687     * Sets the base shape and, if requested, sends a
1688     * {@link RendererChangeEvent} to all registered listeners.
1689     *
1690     * @param shape  the shape (<code>null</code> not permitted).
1691     * @param notify  notify listeners?
1692     *
1693     * @see #getBaseShape()
1694     */
1695    public void setBaseShape(Shape shape, boolean notify) {
1696        ParamChecks.nullNotPermitted(shape, "shape");
1697        this.baseShape = shape;
1698        if (notify) {
1699            fireChangeEvent();
1700        }
1701    }
1702
1703    /**
1704     * Returns the flag that controls whether or not the series shape list is
1705     * automatically populated when {@link #lookupSeriesShape(int)} is called.
1706     *
1707     * @return A boolean.
1708     *
1709     * @since 1.0.6
1710     *
1711     * @see #setAutoPopulateSeriesShape(boolean)
1712     */
1713    public boolean getAutoPopulateSeriesShape() {
1714        return this.autoPopulateSeriesShape;
1715    }
1716
1717    /**
1718     * Sets the flag that controls whether or not the series shape list is
1719     * automatically populated when {@link #lookupSeriesShape(int)} is called.
1720     *
1721     * @param auto  the new flag value.
1722     *
1723     * @since 1.0.6
1724     *
1725     * @see #getAutoPopulateSeriesShape()
1726     */
1727    public void setAutoPopulateSeriesShape(boolean auto) {
1728        this.autoPopulateSeriesShape = auto;
1729    }
1730
1731    // ITEM LABEL VISIBILITY...
1732
1733    /**
1734     * Returns <code>true</code> if an item label is visible, and
1735     * <code>false</code> otherwise.
1736     *
1737     * @param row  the row index (zero-based).
1738     * @param column  the column index (zero-based).
1739     *
1740     * @return A boolean.
1741     */
1742    public boolean isItemLabelVisible(int row, int column) {
1743        return isSeriesItemLabelsVisible(row);
1744    }
1745
1746    /**
1747     * Returns <code>true</code> if the item labels for a series are visible,
1748     * and <code>false</code> otherwise.
1749     *
1750     * @param series  the series index (zero-based).
1751     *
1752     * @return A boolean.
1753     */
1754    public boolean isSeriesItemLabelsVisible(int series) {
1755
1756        // return the override, if there is one...
1757        if (this.itemLabelsVisible != null) {
1758            return this.itemLabelsVisible.booleanValue();
1759        }
1760
1761        // otherwise look up the boolean table
1762        Boolean b = this.itemLabelsVisibleList.getBoolean(series);
1763        if (b == null) {
1764            b = this.baseItemLabelsVisible;
1765        }
1766        if (b == null) {
1767            b = Boolean.FALSE;
1768        }
1769        return b.booleanValue();
1770
1771    }
1772
1773    /**
1774     * Sets a flag that controls the visibility of the item labels for a series,
1775     * and sends a {@link RendererChangeEvent} to all registered listeners.
1776     *
1777     * @param series  the series index (zero-based).
1778     * @param visible  the flag.
1779     */
1780    public void setSeriesItemLabelsVisible(int series, boolean visible) {
1781        setSeriesItemLabelsVisible(series, Boolean.valueOf(visible));
1782    }
1783
1784    /**
1785     * Sets the visibility of the item labels for a series and sends a
1786     * {@link RendererChangeEvent} to all registered listeners.
1787     *
1788     * @param series  the series index (zero-based).
1789     * @param visible  the flag (<code>null</code> permitted).
1790     */
1791    public void setSeriesItemLabelsVisible(int series, Boolean visible) {
1792        setSeriesItemLabelsVisible(series, visible, true);
1793    }
1794
1795    /**
1796     * Sets the visibility of item labels for a series and, if requested, sends
1797     * a {@link RendererChangeEvent} to all registered listeners.
1798     *
1799     * @param series  the series index (zero-based).
1800     * @param visible  the visible flag.
1801     * @param notify  a flag that controls whether or not listeners are
1802     *                notified.
1803     */
1804    public void setSeriesItemLabelsVisible(int series, Boolean visible,
1805                                           boolean notify) {
1806        this.itemLabelsVisibleList.setBoolean(series, visible);
1807        if (notify) {
1808            fireChangeEvent();
1809        }
1810    }
1811
1812    /**
1813     * Returns the base setting for item label visibility.  A <code>null</code>
1814     * result should be interpreted as equivalent to <code>Boolean.FALSE</code>.
1815     *
1816     * @return A flag (possibly <code>null</code>).
1817     *
1818     * @see #setBaseItemLabelsVisible(boolean)
1819     */
1820    public Boolean getBaseItemLabelsVisible() {
1821        // this should have been defined as a boolean primitive, because
1822        // allowing null values is a nuisance...but it is part of the final
1823        // API now, so we'll have to support it.
1824        return this.baseItemLabelsVisible;
1825    }
1826
1827    /**
1828     * Sets the base flag that controls whether or not item labels are visible,
1829     * and sends a {@link RendererChangeEvent} to all registered listeners.
1830     *
1831     * @param visible  the flag.
1832     *
1833     * @see #getBaseItemLabelsVisible()
1834     */
1835    public void setBaseItemLabelsVisible(boolean visible) {
1836        setBaseItemLabelsVisible(Boolean.valueOf(visible));
1837    }
1838
1839    /**
1840     * Sets the base setting for item label visibility and sends a
1841     * {@link RendererChangeEvent} to all registered listeners.
1842     *
1843     * @param visible  the flag (<code>null</code> is permitted, and viewed
1844     *     as equivalent to <code>Boolean.FALSE</code>).
1845     */
1846    public void setBaseItemLabelsVisible(Boolean visible) {
1847        setBaseItemLabelsVisible(visible, true);
1848    }
1849
1850    /**
1851     * Sets the base visibility for item labels and, if requested, sends a
1852     * {@link RendererChangeEvent} to all registered listeners.
1853     *
1854     * @param visible  the flag (<code>null</code> is permitted, and viewed
1855     *     as equivalent to <code>Boolean.FALSE</code>).
1856     * @param notify  a flag that controls whether or not listeners are
1857     *                notified.
1858     *
1859     * @see #getBaseItemLabelsVisible()
1860     */
1861    public void setBaseItemLabelsVisible(Boolean visible, boolean notify) {
1862        this.baseItemLabelsVisible = visible;
1863        if (notify) {
1864            fireChangeEvent();
1865        }
1866    }
1867
1868    //// ITEM LABEL FONT //////////////////////////////////////////////////////
1869
1870    /**
1871     * Returns the font for an item label.
1872     *
1873     * @param row  the row index (zero-based).
1874     * @param column  the column index (zero-based).
1875     *
1876     * @return The font (never <code>null</code>).
1877     */
1878    public Font getItemLabelFont(int row, int column) {
1879        Font result = this.itemLabelFont;
1880        if (result == null) {
1881            result = getSeriesItemLabelFont(row);
1882            if (result == null) {
1883                result = this.baseItemLabelFont;
1884            }
1885        }
1886        return result;
1887    }
1888
1889    /**
1890     * Returns the font for all the item labels in a series.
1891     *
1892     * @param series  the series index (zero-based).
1893     *
1894     * @return The font (possibly <code>null</code>).
1895     *
1896     * @see #setSeriesItemLabelFont(int, Font)
1897     */
1898    public Font getSeriesItemLabelFont(int series) {
1899        return (Font) this.itemLabelFontList.get(series);
1900    }
1901
1902    /**
1903     * Sets the item label font for a series and sends a
1904     * {@link RendererChangeEvent} to all registered listeners.
1905     *
1906     * @param series  the series index (zero-based).
1907     * @param font  the font (<code>null</code> permitted).
1908     *
1909     * @see #getSeriesItemLabelFont(int)
1910     */
1911    public void setSeriesItemLabelFont(int series, Font font) {
1912        setSeriesItemLabelFont(series, font, true);
1913    }
1914
1915    /**
1916     * Sets the item label font for a series and, if requested, sends a
1917     * {@link RendererChangeEvent} to all registered listeners.
1918     *
1919     * @param series  the series index (zero based).
1920     * @param font  the font (<code>null</code> permitted).
1921     * @param notify  a flag that controls whether or not listeners are
1922     *                notified.
1923     *
1924     * @see #getSeriesItemLabelFont(int)
1925     */
1926    public void setSeriesItemLabelFont(int series, Font font, boolean notify) {
1927        this.itemLabelFontList.set(series, font);
1928        if (notify) {
1929            fireChangeEvent();
1930        }
1931    }
1932
1933    /**
1934     * Returns the base item label font (this is used when no other font
1935     * setting is available).
1936     *
1937     * @return The font (<code>never</code> null).
1938     *
1939     * @see #setBaseItemLabelFont(Font)
1940     */
1941    public Font getBaseItemLabelFont() {
1942        return this.baseItemLabelFont;
1943    }
1944
1945    /**
1946     * Sets the base item label font and sends a {@link RendererChangeEvent} to
1947     * all registered listeners.
1948     *
1949     * @param font  the font (<code>null</code> not permitted).
1950     *
1951     * @see #getBaseItemLabelFont()
1952     */
1953    public void setBaseItemLabelFont(Font font) {
1954        ParamChecks.nullNotPermitted(font, "font");
1955        setBaseItemLabelFont(font, true);
1956    }
1957
1958    /**
1959     * Sets the base item label font and, if requested, sends a
1960     * {@link RendererChangeEvent} to all registered listeners.
1961     *
1962     * @param font  the font (<code>null</code> not permitted).
1963     * @param notify  a flag that controls whether or not listeners are
1964     *                notified.
1965     *
1966     * @see #getBaseItemLabelFont()
1967     */
1968    public void setBaseItemLabelFont(Font font, boolean notify) {
1969        this.baseItemLabelFont = font;
1970        if (notify) {
1971            fireChangeEvent();
1972        }
1973    }
1974
1975    //// ITEM LABEL PAINT  ////////////////////////////////////////////////////
1976
1977    /**
1978     * Returns the paint used to draw an item label.
1979     *
1980     * @param row  the row index (zero based).
1981     * @param column  the column index (zero based).
1982     *
1983     * @return The paint (never <code>null</code>).
1984     */
1985    public Paint getItemLabelPaint(int row, int column) {
1986        Paint result = this.itemLabelPaint;
1987        if (result == null) {
1988            result = getSeriesItemLabelPaint(row);
1989            if (result == null) {
1990                result = this.baseItemLabelPaint;
1991            }
1992        }
1993        return result;
1994    }
1995
1996    /**
1997     * Returns the paint used to draw the item labels for a series.
1998     *
1999     * @param series  the series index (zero based).
2000     *
2001     * @return The paint (possibly <code>null</code>).
2002     *
2003     * @see #setSeriesItemLabelPaint(int, Paint)
2004     */
2005    public Paint getSeriesItemLabelPaint(int series) {
2006        return this.itemLabelPaintList.getPaint(series);
2007    }
2008
2009    /**
2010     * Sets the item label paint for a series and sends a
2011     * {@link RendererChangeEvent} to all registered listeners.
2012     *
2013     * @param series  the series (zero based index).
2014     * @param paint  the paint (<code>null</code> permitted).
2015     *
2016     * @see #getSeriesItemLabelPaint(int)
2017     */
2018    public void setSeriesItemLabelPaint(int series, Paint paint) {
2019        setSeriesItemLabelPaint(series, paint, true);
2020    }
2021
2022    /**
2023     * Sets the item label paint for a series and, if requested, sends a
2024     * {@link RendererChangeEvent} to all registered listeners.
2025     *
2026     * @param series  the series index (zero based).
2027     * @param paint  the paint (<code>null</code> permitted).
2028     * @param notify  a flag that controls whether or not listeners are
2029     *                notified.
2030     *
2031     * @see #getSeriesItemLabelPaint(int)
2032     */
2033    public void setSeriesItemLabelPaint(int series, Paint paint,
2034                                        boolean notify) {
2035        this.itemLabelPaintList.setPaint(series, paint);
2036        if (notify) {
2037            fireChangeEvent();
2038        }
2039    }
2040
2041    /**
2042     * Returns the base item label paint.
2043     *
2044     * @return The paint (never <code>null</code>).
2045     *
2046     * @see #setBaseItemLabelPaint(Paint)
2047     */
2048    public Paint getBaseItemLabelPaint() {
2049        return this.baseItemLabelPaint;
2050    }
2051
2052    /**
2053     * Sets the base item label paint and sends a {@link RendererChangeEvent}
2054     * to all registered listeners.
2055     *
2056     * @param paint  the paint (<code>null</code> not permitted).
2057     *
2058     * @see #getBaseItemLabelPaint()
2059     */
2060    public void setBaseItemLabelPaint(Paint paint) {
2061        // defer argument checking...
2062        setBaseItemLabelPaint(paint, true);
2063    }
2064
2065    /**
2066     * Sets the base item label paint and, if requested, sends a
2067     * {@link RendererChangeEvent} to all registered listeners..
2068     *
2069     * @param paint  the paint (<code>null</code> not permitted).
2070     * @param notify  a flag that controls whether or not listeners are
2071     *                notified.
2072     *
2073     * @see #getBaseItemLabelPaint()
2074     */
2075    public void setBaseItemLabelPaint(Paint paint, boolean notify) {
2076        ParamChecks.nullNotPermitted(paint, "paint");
2077        this.baseItemLabelPaint = paint;
2078        if (notify) {
2079            fireChangeEvent();
2080        }
2081    }
2082
2083    // POSITIVE ITEM LABEL POSITION...
2084
2085    /**
2086     * Returns the item label position for positive values.
2087     *
2088     * @param row  the row index (zero-based).
2089     * @param column  the column index (zero-based).
2090     *
2091     * @return The item label position (never <code>null</code>).
2092     *
2093     * @see #getNegativeItemLabelPosition(int, int)
2094     */
2095    public ItemLabelPosition getPositiveItemLabelPosition(int row, int column) {
2096        return getSeriesPositiveItemLabelPosition(row);
2097    }
2098
2099    /**
2100     * Returns the item label position for all positive values in a series.
2101     *
2102     * @param series  the series index (zero-based).
2103     *
2104     * @return The item label position (never <code>null</code>).
2105     *
2106     * @see #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition)
2107     */
2108    public ItemLabelPosition getSeriesPositiveItemLabelPosition(int series) {
2109
2110        // return the override, if there is one...
2111        if (this.positiveItemLabelPosition != null) {
2112            return this.positiveItemLabelPosition;
2113        }
2114
2115        // otherwise look up the position table
2116        ItemLabelPosition position = (ItemLabelPosition)
2117            this.positiveItemLabelPositionList.get(series);
2118        if (position == null) {
2119            position = this.basePositiveItemLabelPosition;
2120        }
2121        return position;
2122
2123    }
2124
2125    /**
2126     * Sets the item label position for all positive values in a series and
2127     * sends a {@link RendererChangeEvent} to all registered listeners.
2128     *
2129     * @param series  the series index (zero-based).
2130     * @param position  the position (<code>null</code> permitted).
2131     *
2132     * @see #getSeriesPositiveItemLabelPosition(int)
2133     */
2134    public void setSeriesPositiveItemLabelPosition(int series,
2135                                                   ItemLabelPosition position) {
2136        setSeriesPositiveItemLabelPosition(series, position, true);
2137    }
2138
2139    /**
2140     * Sets the item label position for all positive values in a series and (if
2141     * requested) sends a {@link RendererChangeEvent} to all registered
2142     * listeners.
2143     *
2144     * @param series  the series index (zero-based).
2145     * @param position  the position (<code>null</code> permitted).
2146     * @param notify  notify registered listeners?
2147     *
2148     * @see #getSeriesPositiveItemLabelPosition(int)
2149     */
2150    public void setSeriesPositiveItemLabelPosition(int series,
2151                                                   ItemLabelPosition position,
2152                                                   boolean notify) {
2153        this.positiveItemLabelPositionList.set(series, position);
2154        if (notify) {
2155            fireChangeEvent();
2156        }
2157    }
2158
2159    /**
2160     * Returns the base positive item label position.
2161     *
2162     * @return The position (never <code>null</code>).
2163     *
2164     * @see #setBasePositiveItemLabelPosition(ItemLabelPosition)
2165     */
2166    public ItemLabelPosition getBasePositiveItemLabelPosition() {
2167        return this.basePositiveItemLabelPosition;
2168    }
2169
2170    /**
2171     * Sets the base positive item label position.
2172     *
2173     * @param position  the position (<code>null</code> not permitted).
2174     *
2175     * @see #getBasePositiveItemLabelPosition()
2176     */
2177    public void setBasePositiveItemLabelPosition(ItemLabelPosition position) {
2178        // defer argument checking...
2179        setBasePositiveItemLabelPosition(position, true);
2180    }
2181
2182    /**
2183     * Sets the base positive item label position and, if requested, sends a
2184     * {@link RendererChangeEvent} to all registered listeners.
2185     *
2186     * @param position  the position (<code>null</code> not permitted).
2187     * @param notify  notify registered listeners?
2188     *
2189     * @see #getBasePositiveItemLabelPosition()
2190     */
2191    public void setBasePositiveItemLabelPosition(ItemLabelPosition position,
2192            boolean notify) {
2193        ParamChecks.nullNotPermitted(position, "position");
2194        this.basePositiveItemLabelPosition = position;
2195        if (notify) {
2196            fireChangeEvent();
2197        }
2198    }
2199
2200    // NEGATIVE ITEM LABEL POSITION...
2201
2202    /**
2203     * Returns the item label position for negative values.  This method can be
2204     * overridden to provide customisation of the item label position for
2205     * individual data items.
2206     *
2207     * @param row  the row index (zero-based).
2208     * @param column  the column (zero-based).
2209     *
2210     * @return The item label position (never <code>null</code>).
2211     *
2212     * @see #getPositiveItemLabelPosition(int, int)
2213     */
2214    public ItemLabelPosition getNegativeItemLabelPosition(int row, int column) {
2215        return getSeriesNegativeItemLabelPosition(row);
2216    }
2217
2218    /**
2219     * Returns the item label position for all negative values in a series.
2220     *
2221     * @param series  the series index (zero-based).
2222     *
2223     * @return The item label position (never <code>null</code>).
2224     *
2225     * @see #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition)
2226     */
2227    public ItemLabelPosition getSeriesNegativeItemLabelPosition(int series) {
2228
2229        // return the override, if there is one...
2230        if (this.negativeItemLabelPosition != null) {
2231            return this.negativeItemLabelPosition;
2232        }
2233
2234        // otherwise look up the position list
2235        ItemLabelPosition position = (ItemLabelPosition)
2236            this.negativeItemLabelPositionList.get(series);
2237        if (position == null) {
2238            position = this.baseNegativeItemLabelPosition;
2239        }
2240        return position;
2241
2242    }
2243
2244    /**
2245     * Sets the item label position for negative values in a series and sends a
2246     * {@link RendererChangeEvent} to all registered listeners.
2247     *
2248     * @param series  the series index (zero-based).
2249     * @param position  the position (<code>null</code> permitted).
2250     *
2251     * @see #getSeriesNegativeItemLabelPosition(int)
2252     */
2253    public void setSeriesNegativeItemLabelPosition(int series,
2254                                                   ItemLabelPosition position) {
2255        setSeriesNegativeItemLabelPosition(series, position, true);
2256    }
2257
2258    /**
2259     * Sets the item label position for negative values in a series and (if
2260     * requested) sends a {@link RendererChangeEvent} to all registered
2261     * listeners.
2262     *
2263     * @param series  the series index (zero-based).
2264     * @param position  the position (<code>null</code> permitted).
2265     * @param notify  notify registered listeners?
2266     *
2267     * @see #getSeriesNegativeItemLabelPosition(int)
2268     */
2269    public void setSeriesNegativeItemLabelPosition(int series,
2270                                                   ItemLabelPosition position,
2271                                                   boolean notify) {
2272        this.negativeItemLabelPositionList.set(series, position);
2273        if (notify) {
2274            fireChangeEvent();
2275        }
2276    }
2277
2278    /**
2279     * Returns the base item label position for negative values.
2280     *
2281     * @return The position (never <code>null</code>).
2282     *
2283     * @see #setBaseNegativeItemLabelPosition(ItemLabelPosition)
2284     */
2285    public ItemLabelPosition getBaseNegativeItemLabelPosition() {
2286        return this.baseNegativeItemLabelPosition;
2287    }
2288
2289    /**
2290     * Sets the base item label position for negative values and sends a
2291     * {@link RendererChangeEvent} to all registered listeners.
2292     *
2293     * @param position  the position (<code>null</code> not permitted).
2294     *
2295     * @see #getBaseNegativeItemLabelPosition()
2296     */
2297    public void setBaseNegativeItemLabelPosition(ItemLabelPosition position) {
2298        setBaseNegativeItemLabelPosition(position, true);
2299    }
2300
2301    /**
2302     * Sets the base negative item label position and, if requested, sends a
2303     * {@link RendererChangeEvent} to all registered listeners.
2304     *
2305     * @param position  the position (<code>null</code> not permitted).
2306     * @param notify  notify registered listeners?
2307     *
2308     * @see #getBaseNegativeItemLabelPosition()
2309     */
2310    public void setBaseNegativeItemLabelPosition(ItemLabelPosition position,
2311            boolean notify) {
2312        ParamChecks.nullNotPermitted(position, "position");
2313        this.baseNegativeItemLabelPosition = position;
2314        if (notify) {
2315            fireChangeEvent();
2316        }
2317    }
2318
2319    /**
2320     * Returns the item label anchor offset.
2321     *
2322     * @return The offset.
2323     *
2324     * @see #setItemLabelAnchorOffset(double)
2325     */
2326    public double getItemLabelAnchorOffset() {
2327        return this.itemLabelAnchorOffset;
2328    }
2329
2330    /**
2331     * Sets the item label anchor offset.
2332     *
2333     * @param offset  the offset.
2334     *
2335     * @see #getItemLabelAnchorOffset()
2336     */
2337    public void setItemLabelAnchorOffset(double offset) {
2338        this.itemLabelAnchorOffset = offset;
2339        fireChangeEvent();
2340    }
2341
2342    /**
2343     * Returns a boolean that indicates whether or not the specified item
2344     * should have a chart entity created for it.
2345     *
2346     * @param series  the series index.
2347     * @param item  the item index.
2348     *
2349     * @return A boolean.
2350     */
2351    public boolean getItemCreateEntity(int series, int item) {
2352        if (this.createEntities != null) {
2353            return this.createEntities.booleanValue();
2354        }
2355        else {
2356            Boolean b = getSeriesCreateEntities(series);
2357            if (b != null) {
2358                return b.booleanValue();
2359            }
2360            else {
2361                return this.baseCreateEntities;
2362            }
2363        }
2364    }
2365
2366    /**
2367     * Returns the flag that controls whether entities are created for a
2368     * series.
2369     *
2370     * @param series  the series index (zero-based).
2371     *
2372     * @return The flag (possibly <code>null</code>).
2373     *
2374     * @see #setSeriesCreateEntities(int, Boolean)
2375     */
2376    public Boolean getSeriesCreateEntities(int series) {
2377        return this.createEntitiesList.getBoolean(series);
2378    }
2379
2380    /**
2381     * Sets the flag that controls whether entities are created for a series,
2382     * and sends a {@link RendererChangeEvent} to all registered listeners.
2383     *
2384     * @param series  the series index (zero-based).
2385     * @param create  the flag (<code>null</code> permitted).
2386     *
2387     * @see #getSeriesCreateEntities(int)
2388     */
2389    public void setSeriesCreateEntities(int series, Boolean create) {
2390        setSeriesCreateEntities(series, create, true);
2391    }
2392
2393    /**
2394     * Sets the flag that controls whether entities are created for a series
2395     * and, if requested, sends a {@link RendererChangeEvent} to all registered
2396     * listeners.
2397     *
2398     * @param series  the series index.
2399     * @param create  the flag (<code>null</code> permitted).
2400     * @param notify  notify listeners?
2401     *
2402     * @see #getSeriesCreateEntities(int)
2403     */
2404    public void setSeriesCreateEntities(int series, Boolean create,
2405                                        boolean notify) {
2406        this.createEntitiesList.setBoolean(series, create);
2407        if (notify) {
2408            fireChangeEvent();
2409        }
2410    }
2411
2412    /**
2413     * Returns the base visibility for all series.
2414     *
2415     * @return The base visibility.
2416     *
2417     * @see #setBaseCreateEntities(boolean)
2418     */
2419    public boolean getBaseCreateEntities() {
2420        return this.baseCreateEntities;
2421    }
2422
2423    /**
2424     * Sets the base flag that controls whether entities are created
2425     * for a series, and sends a {@link RendererChangeEvent}
2426     * to all registered listeners.
2427     *
2428     * @param create  the flag.
2429     *
2430     * @see #getBaseCreateEntities()
2431     */
2432    public void setBaseCreateEntities(boolean create) {
2433        // defer argument checking...
2434        setBaseCreateEntities(create, true);
2435    }
2436
2437    /**
2438     * Sets the base flag that controls whether entities are created and,
2439     * if requested, sends a {@link RendererChangeEvent} to all registered
2440     * listeners.
2441     *
2442     * @param create  the visibility.
2443     * @param notify  notify listeners?
2444     *
2445     * @see #getBaseCreateEntities()
2446     */
2447    public void setBaseCreateEntities(boolean create, boolean notify) {
2448        this.baseCreateEntities = create;
2449        if (notify) {
2450            fireChangeEvent();
2451        }
2452    }
2453
2454    /**
2455     * Returns the radius of the circle used for the default entity area
2456     * when no area is specified.
2457     *
2458     * @return A radius.
2459     *
2460     * @see #setDefaultEntityRadius(int)
2461     */
2462    public int getDefaultEntityRadius() {
2463        return this.defaultEntityRadius;
2464    }
2465
2466    /**
2467     * Sets the radius of the circle used for the default entity area
2468     * when no area is specified.
2469     *
2470     * @param radius  the radius.
2471     *
2472     * @see #getDefaultEntityRadius()
2473     */
2474    public void setDefaultEntityRadius(int radius) {
2475        this.defaultEntityRadius = radius;
2476    }
2477
2478    /**
2479     * Performs a lookup for the legend shape.
2480     *
2481     * @param series  the series index.
2482     *
2483     * @return The shape (possibly <code>null</code>).
2484     *
2485     * @since 1.0.11
2486     */
2487    public Shape lookupLegendShape(int series) {
2488        Shape result = getLegendShape(series);
2489        if (result == null) {
2490            result = this.baseLegendShape;
2491        }
2492        if (result == null) {
2493            result = lookupSeriesShape(series);
2494        }
2495        return result;
2496    }
2497
2498    /**
2499     * Returns the legend shape defined for the specified series (possibly
2500     * <code>null</code>).
2501     *
2502     * @param series  the series index.
2503     *
2504     * @return The shape (possibly <code>null</code>).
2505     *
2506     * @see #lookupLegendShape(int)
2507     *
2508     * @since 1.0.11
2509     */
2510    public Shape getLegendShape(int series) {
2511        return this.legendShapeList.getShape(series);
2512    }
2513
2514    /**
2515     * Sets the shape used for the legend item for the specified series, and
2516     * sends a {@link RendererChangeEvent} to all registered listeners.
2517     *
2518     * @param series  the series index.
2519     * @param shape  the shape (<code>null</code> permitted).
2520     *
2521     * @since 1.0.11
2522     */
2523    public void setLegendShape(int series, Shape shape) {
2524        this.legendShapeList.setShape(series, shape);
2525        fireChangeEvent();
2526    }
2527
2528    /**
2529     * Returns the default legend shape, which may be <code>null</code>.
2530     *
2531     * @return The default legend shape.
2532     *
2533     * @since 1.0.11
2534     */
2535    public Shape getBaseLegendShape() {
2536        return this.baseLegendShape;
2537    }
2538
2539    /**
2540     * Sets the default legend shape and sends a
2541     * {@link RendererChangeEvent} to all registered listeners.
2542     *
2543     * @param shape  the shape (<code>null</code> permitted).
2544     *
2545     * @since 1.0.11
2546     */
2547    public void setBaseLegendShape(Shape shape) {
2548        this.baseLegendShape = shape;
2549        fireChangeEvent();
2550    }
2551
2552    /**
2553     * Returns the flag that controls whether or not the legend shape is
2554     * treated as a line when creating legend items.
2555     * 
2556     * @return A boolean.
2557     * 
2558     * @since 1.0.14
2559     */
2560    protected boolean getTreatLegendShapeAsLine() {
2561        return this.treatLegendShapeAsLine;
2562    }
2563
2564    /**
2565     * Sets the flag that controls whether or not the legend shape is
2566     * treated as a line when creating legend items.
2567     *
2568     * @param treatAsLine  the new flag value.
2569     *
2570     * @since 1.0.14
2571     */
2572    protected void setTreatLegendShapeAsLine(boolean treatAsLine) {
2573        if (this.treatLegendShapeAsLine != treatAsLine) {
2574            this.treatLegendShapeAsLine = treatAsLine;
2575            fireChangeEvent();
2576        }
2577    }
2578
2579    /**
2580     * Performs a lookup for the legend text font.
2581     *
2582     * @param series  the series index.
2583     *
2584     * @return The font (possibly <code>null</code>).
2585     *
2586     * @since 1.0.11
2587     */
2588    public Font lookupLegendTextFont(int series) {
2589        Font result = getLegendTextFont(series);
2590        if (result == null) {
2591            result = this.baseLegendTextFont;
2592        }
2593        return result;
2594    }
2595
2596    /**
2597     * Returns the legend text font defined for the specified series (possibly
2598     * <code>null</code>).
2599     *
2600     * @param series  the series index.
2601     *
2602     * @return The font (possibly <code>null</code>).
2603     *
2604     * @see #lookupLegendTextFont(int)
2605     *
2606     * @since 1.0.11
2607     */
2608    public Font getLegendTextFont(int series) {
2609        return (Font) this.legendTextFont.get(series);
2610    }
2611
2612    /**
2613     * Sets the font used for the legend text for the specified series, and
2614     * sends a {@link RendererChangeEvent} to all registered listeners.
2615     *
2616     * @param series  the series index.
2617     * @param font  the font (<code>null</code> permitted).
2618     *
2619     * @since 1.0.11
2620     */
2621    public void setLegendTextFont(int series, Font font) {
2622        this.legendTextFont.set(series, font);
2623        fireChangeEvent();
2624    }
2625
2626    /**
2627     * Returns the default legend text font, which may be <code>null</code>.
2628     *
2629     * @return The default legend text font.
2630     *
2631     * @since 1.0.11
2632     */
2633    public Font getBaseLegendTextFont() {
2634        return this.baseLegendTextFont;
2635    }
2636
2637    /**
2638     * Sets the default legend text font and sends a
2639     * {@link RendererChangeEvent} to all registered listeners.
2640     *
2641     * @param font  the font (<code>null</code> permitted).
2642     *
2643     * @since 1.0.11
2644     */
2645    public void setBaseLegendTextFont(Font font) {
2646        this.baseLegendTextFont = font;
2647        fireChangeEvent();
2648    }
2649
2650    /**
2651     * Performs a lookup for the legend text paint.
2652     *
2653     * @param series  the series index.
2654     *
2655     * @return The paint (possibly <code>null</code>).
2656     *
2657     * @since 1.0.11
2658     */
2659    public Paint lookupLegendTextPaint(int series) {
2660        Paint result = getLegendTextPaint(series);
2661        if (result == null) {
2662            result = this.baseLegendTextPaint;
2663        }
2664        return result;
2665    }
2666
2667    /**
2668     * Returns the legend text paint defined for the specified series (possibly
2669     * <code>null</code>).
2670     *
2671     * @param series  the series index.
2672     *
2673     * @return The paint (possibly <code>null</code>).
2674     *
2675     * @see #lookupLegendTextPaint(int)
2676     *
2677     * @since 1.0.11
2678     */
2679    public Paint getLegendTextPaint(int series) {
2680        return this.legendTextPaint.getPaint(series);
2681    }
2682
2683    /**
2684     * Sets the paint used for the legend text for the specified series, and
2685     * sends a {@link RendererChangeEvent} to all registered listeners.
2686     *
2687     * @param series  the series index.
2688     * @param paint  the paint (<code>null</code> permitted).
2689     *
2690     * @since 1.0.11
2691     */
2692    public void setLegendTextPaint(int series, Paint paint) {
2693        this.legendTextPaint.setPaint(series, paint);
2694        fireChangeEvent();
2695    }
2696
2697    /**
2698     * Returns the default legend text paint, which may be <code>null</code>.
2699     *
2700     * @return The default legend text paint.
2701     *
2702     * @since 1.0.11
2703     */
2704    public Paint getBaseLegendTextPaint() {
2705        return this.baseLegendTextPaint;
2706    }
2707
2708    /**
2709     * Sets the default legend text paint and sends a
2710     * {@link RendererChangeEvent} to all registered listeners.
2711     *
2712     * @param paint  the paint (<code>null</code> permitted).
2713     *
2714     * @since 1.0.11
2715     */
2716    public void setBaseLegendTextPaint(Paint paint) {
2717        this.baseLegendTextPaint = paint;
2718        fireChangeEvent();
2719    }
2720
2721    /**
2722     * Returns the flag that controls whether or not the data bounds reported
2723     * by this renderer will exclude non-visible series.
2724     *
2725     * @return A boolean.
2726     *
2727     * @since 1.0.13
2728     */
2729    public boolean getDataBoundsIncludesVisibleSeriesOnly() {
2730        return this.dataBoundsIncludesVisibleSeriesOnly;
2731    }
2732
2733    /**
2734     * Sets the flag that controls whether or not the data bounds reported
2735     * by this renderer will exclude non-visible series and sends a
2736     * {@link RendererChangeEvent} to all registered listeners.
2737     *
2738     * @param visibleOnly  include only visible series.
2739     *
2740     * @since 1.0.13
2741     */
2742    public void setDataBoundsIncludesVisibleSeriesOnly(boolean visibleOnly) {
2743        this.dataBoundsIncludesVisibleSeriesOnly = visibleOnly;
2744        notifyListeners(new RendererChangeEvent(this, true));
2745    }
2746
2747    /** The adjacent offset. */
2748    private static final double ADJ = Math.cos(Math.PI / 6.0);
2749
2750    /** The opposite offset. */
2751    private static final double OPP = Math.sin(Math.PI / 6.0);
2752
2753    /**
2754     * Calculates the item label anchor point.
2755     *
2756     * @param anchor  the anchor.
2757     * @param x  the x coordinate.
2758     * @param y  the y coordinate.
2759     * @param orientation  the plot orientation.
2760     *
2761     * @return The anchor point (never <code>null</code>).
2762     */
2763    protected Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor,
2764            double x, double y, PlotOrientation orientation) {
2765        Point2D result = null;
2766        if (anchor == ItemLabelAnchor.CENTER) {
2767            result = new Point2D.Double(x, y);
2768        }
2769        else if (anchor == ItemLabelAnchor.INSIDE1) {
2770            result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset,
2771                    y - ADJ * this.itemLabelAnchorOffset);
2772        }
2773        else if (anchor == ItemLabelAnchor.INSIDE2) {
2774            result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset,
2775                    y - OPP * this.itemLabelAnchorOffset);
2776        }
2777        else if (anchor == ItemLabelAnchor.INSIDE3) {
2778            result = new Point2D.Double(x + this.itemLabelAnchorOffset, y);
2779        }
2780        else if (anchor == ItemLabelAnchor.INSIDE4) {
2781            result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset,
2782                    y + OPP * this.itemLabelAnchorOffset);
2783        }
2784        else if (anchor == ItemLabelAnchor.INSIDE5) {
2785            result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset,
2786                    y + ADJ * this.itemLabelAnchorOffset);
2787        }
2788        else if (anchor == ItemLabelAnchor.INSIDE6) {
2789            result = new Point2D.Double(x, y + this.itemLabelAnchorOffset);
2790        }
2791        else if (anchor == ItemLabelAnchor.INSIDE7) {
2792            result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset,
2793                    y + ADJ * this.itemLabelAnchorOffset);
2794        }
2795        else if (anchor == ItemLabelAnchor.INSIDE8) {
2796            result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset,
2797                    y + OPP * this.itemLabelAnchorOffset);
2798        }
2799        else if (anchor == ItemLabelAnchor.INSIDE9) {
2800            result = new Point2D.Double(x - this.itemLabelAnchorOffset, y);
2801        }
2802        else if (anchor == ItemLabelAnchor.INSIDE10) {
2803            result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset,
2804                    y - OPP * this.itemLabelAnchorOffset);
2805        }
2806        else if (anchor == ItemLabelAnchor.INSIDE11) {
2807            result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset,
2808                    y - ADJ * this.itemLabelAnchorOffset);
2809        }
2810        else if (anchor == ItemLabelAnchor.INSIDE12) {
2811            result = new Point2D.Double(x, y - this.itemLabelAnchorOffset);
2812        }
2813        else if (anchor == ItemLabelAnchor.OUTSIDE1) {
2814            result = new Point2D.Double(
2815                    x + 2.0 * OPP * this.itemLabelAnchorOffset,
2816                    y - 2.0 * ADJ * this.itemLabelAnchorOffset);
2817        }
2818        else if (anchor == ItemLabelAnchor.OUTSIDE2) {
2819            result = new Point2D.Double(
2820                    x + 2.0 * ADJ * this.itemLabelAnchorOffset,
2821                    y - 2.0 * OPP * this.itemLabelAnchorOffset);
2822        }
2823        else if (anchor == ItemLabelAnchor.OUTSIDE3) {
2824            result = new Point2D.Double(x + 2.0 * this.itemLabelAnchorOffset,
2825                    y);
2826        }
2827        else if (anchor == ItemLabelAnchor.OUTSIDE4) {
2828            result = new Point2D.Double(
2829                    x + 2.0 * ADJ * this.itemLabelAnchorOffset,
2830                    y + 2.0 * OPP * this.itemLabelAnchorOffset);
2831        }
2832        else if (anchor == ItemLabelAnchor.OUTSIDE5) {
2833            result = new Point2D.Double(
2834                    x + 2.0 * OPP * this.itemLabelAnchorOffset,
2835                    y + 2.0 * ADJ * this.itemLabelAnchorOffset);
2836        }
2837        else if (anchor == ItemLabelAnchor.OUTSIDE6) {
2838            result = new Point2D.Double(x,
2839                    y + 2.0 * this.itemLabelAnchorOffset);
2840        }
2841        else if (anchor == ItemLabelAnchor.OUTSIDE7) {
2842            result = new Point2D.Double(
2843                    x - 2.0 * OPP * this.itemLabelAnchorOffset,
2844                    y + 2.0 * ADJ * this.itemLabelAnchorOffset);
2845        }
2846        else if (anchor == ItemLabelAnchor.OUTSIDE8) {
2847            result = new Point2D.Double(
2848                    x - 2.0 * ADJ * this.itemLabelAnchorOffset,
2849                    y + 2.0 * OPP * this.itemLabelAnchorOffset);
2850        }
2851        else if (anchor == ItemLabelAnchor.OUTSIDE9) {
2852            result = new Point2D.Double(x - 2.0 * this.itemLabelAnchorOffset,
2853                    y);
2854        }
2855        else if (anchor == ItemLabelAnchor.OUTSIDE10) {
2856            result = new Point2D.Double(
2857                    x - 2.0 * ADJ * this.itemLabelAnchorOffset,
2858                    y - 2.0 * OPP * this.itemLabelAnchorOffset);
2859        }
2860        else if (anchor == ItemLabelAnchor.OUTSIDE11) {
2861            result = new Point2D.Double(
2862                x - 2.0 * OPP * this.itemLabelAnchorOffset,
2863                y - 2.0 * ADJ * this.itemLabelAnchorOffset);
2864        }
2865        else if (anchor == ItemLabelAnchor.OUTSIDE12) {
2866            result = new Point2D.Double(x,
2867                    y - 2.0 * this.itemLabelAnchorOffset);
2868        }
2869        return result;
2870    }
2871
2872    /**
2873     * Registers an object to receive notification of changes to the renderer.
2874     *
2875     * @param listener  the listener (<code>null</code> not permitted).
2876     *
2877     * @see #removeChangeListener(RendererChangeListener)
2878     */
2879    public void addChangeListener(RendererChangeListener listener) {
2880        ParamChecks.nullNotPermitted(listener, "listener");
2881        this.listenerList.add(RendererChangeListener.class, listener);
2882    }
2883
2884    /**
2885     * Deregisters an object so that it no longer receives
2886     * notification of changes to the renderer.
2887     *
2888     * @param listener  the object (<code>null</code> not permitted).
2889     *
2890     * @see #addChangeListener(RendererChangeListener)
2891     */
2892    public void removeChangeListener(RendererChangeListener listener) {
2893        ParamChecks.nullNotPermitted(listener, "listener");
2894        this.listenerList.remove(RendererChangeListener.class, listener);
2895    }
2896
2897    /**
2898     * Returns <code>true</code> if the specified object is registered with
2899     * the dataset as a listener.  Most applications won't need to call this
2900     * method, it exists mainly for use by unit testing code.
2901     *
2902     * @param listener  the listener.
2903     *
2904     * @return A boolean.
2905     */
2906    public boolean hasListener(EventListener listener) {
2907        List list = Arrays.asList(this.listenerList.getListenerList());
2908        return list.contains(listener);
2909    }
2910
2911    /**
2912     * Sends a {@link RendererChangeEvent} to all registered listeners.
2913     *
2914     * @since 1.0.5
2915     */
2916    protected void fireChangeEvent() {
2917
2918        // the commented out code would be better, but only if
2919        // RendererChangeEvent is immutable, which it isn't.  See if there is
2920        // a way to fix this...
2921
2922        //if (this.event == null) {
2923        //    this.event = new RendererChangeEvent(this);
2924        //}
2925        //notifyListeners(this.event);
2926
2927        notifyListeners(new RendererChangeEvent(this));
2928    }
2929
2930    /**
2931     * Notifies all registered listeners that the renderer has been modified.
2932     *
2933     * @param event  information about the change event.
2934     */
2935    public void notifyListeners(RendererChangeEvent event) {
2936        Object[] ls = this.listenerList.getListenerList();
2937        for (int i = ls.length - 2; i >= 0; i -= 2) {
2938            if (ls[i] == RendererChangeListener.class) {
2939                ((RendererChangeListener) ls[i + 1]).rendererChanged(event);
2940            }
2941        }
2942    }
2943
2944    /**
2945     * Tests this renderer for equality with another object.
2946     *
2947     * @param obj  the object (<code>null</code> permitted).
2948     *
2949     * @return <code>true</code> or <code>false</code>.
2950     */
2951    @Override
2952    public boolean equals(Object obj) {
2953        if (obj == this) {
2954            return true;
2955        }
2956        if (!(obj instanceof AbstractRenderer)) {
2957            return false;
2958        }
2959        AbstractRenderer that = (AbstractRenderer) obj;
2960        if (this.dataBoundsIncludesVisibleSeriesOnly
2961                != that.dataBoundsIncludesVisibleSeriesOnly) {
2962            return false;
2963        }
2964        if (this.treatLegendShapeAsLine != that.treatLegendShapeAsLine) {
2965            return false;
2966        }
2967        if (this.defaultEntityRadius != that.defaultEntityRadius) {
2968            return false;
2969        }
2970        if (!ObjectUtilities.equal(this.seriesVisible, that.seriesVisible)) {
2971            return false;
2972        }
2973        if (!this.seriesVisibleList.equals(that.seriesVisibleList)) {
2974            return false;
2975        }
2976        if (this.baseSeriesVisible != that.baseSeriesVisible) {
2977            return false;
2978        }
2979        if (!ObjectUtilities.equal(this.seriesVisibleInLegend,
2980                that.seriesVisibleInLegend)) {
2981            return false;
2982        }
2983        if (!this.seriesVisibleInLegendList.equals(
2984                that.seriesVisibleInLegendList)) {
2985            return false;
2986        }
2987        if (this.baseSeriesVisibleInLegend != that.baseSeriesVisibleInLegend) {
2988            return false;
2989        }
2990        if (!PaintUtilities.equal(this.paint, that.paint)) {
2991            return false;
2992        }
2993        if (!ObjectUtilities.equal(this.paintList, that.paintList)) {
2994            return false;
2995        }
2996        if (!PaintUtilities.equal(this.basePaint, that.basePaint)) {
2997            return false;
2998        }
2999        if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
3000            return false;
3001        }
3002        if (!ObjectUtilities.equal(this.fillPaintList, that.fillPaintList)) {
3003            return false;
3004        }
3005        if (!PaintUtilities.equal(this.baseFillPaint, that.baseFillPaint)) {
3006            return false;
3007        }
3008        if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
3009            return false;
3010        }
3011        if (!ObjectUtilities.equal(this.outlinePaintList,
3012                that.outlinePaintList)) {
3013            return false;
3014        }
3015        if (!PaintUtilities.equal(this.baseOutlinePaint,
3016                that.baseOutlinePaint)) {
3017            return false;
3018        }
3019        if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
3020            return false;
3021        }
3022        if (!ObjectUtilities.equal(this.strokeList, that.strokeList)) {
3023            return false;
3024        }
3025        if (!ObjectUtilities.equal(this.baseStroke, that.baseStroke)) {
3026            return false;
3027        }
3028        if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
3029            return false;
3030        }
3031        if (!ObjectUtilities.equal(this.outlineStrokeList,
3032                that.outlineStrokeList)) {
3033            return false;
3034        }
3035        if (!ObjectUtilities.equal(
3036            this.baseOutlineStroke, that.baseOutlineStroke)
3037        ) {
3038            return false;
3039        }
3040        if (!ShapeUtilities.equal(this.shape, that.shape)) {
3041            return false;
3042        }
3043        if (!ObjectUtilities.equal(this.shapeList, that.shapeList)) {
3044            return false;
3045        }
3046        if (!ShapeUtilities.equal(this.baseShape, that.baseShape)) {
3047            return false;
3048        }
3049        if (!ObjectUtilities.equal(this.itemLabelsVisible,
3050                that.itemLabelsVisible)) {
3051            return false;
3052        }
3053        if (!ObjectUtilities.equal(this.itemLabelsVisibleList,
3054                that.itemLabelsVisibleList)) {
3055            return false;
3056        }
3057        if (!ObjectUtilities.equal(this.baseItemLabelsVisible,
3058                that.baseItemLabelsVisible)) {
3059            return false;
3060        }
3061        if (!ObjectUtilities.equal(this.itemLabelFont, that.itemLabelFont)) {
3062            return false;
3063        }
3064        if (!ObjectUtilities.equal(this.itemLabelFontList,
3065                that.itemLabelFontList)) {
3066            return false;
3067        }
3068        if (!ObjectUtilities.equal(this.baseItemLabelFont,
3069                that.baseItemLabelFont)) {
3070            return false;
3071        }
3072
3073        if (!PaintUtilities.equal(this.itemLabelPaint, that.itemLabelPaint)) {
3074            return false;
3075        }
3076        if (!ObjectUtilities.equal(this.itemLabelPaintList,
3077                that.itemLabelPaintList)) {
3078            return false;
3079        }
3080        if (!PaintUtilities.equal(this.baseItemLabelPaint,
3081                that.baseItemLabelPaint)) {
3082            return false;
3083        }
3084
3085        if (!ObjectUtilities.equal(this.positiveItemLabelPosition,
3086                that.positiveItemLabelPosition)) {
3087            return false;
3088        }
3089        if (!ObjectUtilities.equal(this.positiveItemLabelPositionList,
3090                that.positiveItemLabelPositionList)) {
3091            return false;
3092        }
3093        if (!ObjectUtilities.equal(this.basePositiveItemLabelPosition,
3094                that.basePositiveItemLabelPosition)) {
3095            return false;
3096        }
3097
3098        if (!ObjectUtilities.equal(this.negativeItemLabelPosition,
3099                that.negativeItemLabelPosition)) {
3100            return false;
3101        }
3102        if (!ObjectUtilities.equal(this.negativeItemLabelPositionList,
3103                that.negativeItemLabelPositionList)) {
3104            return false;
3105        }
3106        if (!ObjectUtilities.equal(this.baseNegativeItemLabelPosition,
3107                that.baseNegativeItemLabelPosition)) {
3108            return false;
3109        }
3110        if (this.itemLabelAnchorOffset != that.itemLabelAnchorOffset) {
3111            return false;
3112        }
3113        if (!ObjectUtilities.equal(this.createEntities, that.createEntities)) {
3114            return false;
3115        }
3116        if (!ObjectUtilities.equal(this.createEntitiesList,
3117                that.createEntitiesList)) {
3118            return false;
3119        }
3120        if (this.baseCreateEntities != that.baseCreateEntities) {
3121            return false;
3122        }
3123        if (!ObjectUtilities.equal(this.legendShapeList,
3124                that.legendShapeList)) {
3125            return false;
3126        }
3127        if (!ShapeUtilities.equal(this.baseLegendShape,
3128                that.baseLegendShape)) {
3129            return false;
3130        }
3131        if (!ObjectUtilities.equal(this.legendTextFont, that.legendTextFont)) {
3132            return false;
3133        }
3134        if (!ObjectUtilities.equal(this.baseLegendTextFont,
3135                that.baseLegendTextFont)) {
3136            return false;
3137        }
3138        if (!ObjectUtilities.equal(this.legendTextPaint,
3139                that.legendTextPaint)) {
3140            return false;
3141        }
3142        if (!PaintUtilities.equal(this.baseLegendTextPaint,
3143                that.baseLegendTextPaint)) {
3144            return false;
3145        }
3146        return true;
3147    }
3148
3149    /**
3150     * Returns a hashcode for the renderer.
3151     *
3152     * @return The hashcode.
3153     */
3154    @Override
3155    public int hashCode() {
3156        int result = 193;
3157        result = HashUtilities.hashCode(result, this.seriesVisibleList);
3158        result = HashUtilities.hashCode(result, this.baseSeriesVisible);
3159        result = HashUtilities.hashCode(result, this.seriesVisibleInLegendList);
3160        result = HashUtilities.hashCode(result, this.baseSeriesVisibleInLegend);
3161        result = HashUtilities.hashCode(result, this.paintList);
3162        result = HashUtilities.hashCode(result, this.basePaint);
3163        result = HashUtilities.hashCode(result, this.fillPaintList);
3164        result = HashUtilities.hashCode(result, this.baseFillPaint);
3165        result = HashUtilities.hashCode(result, this.outlinePaintList);
3166        result = HashUtilities.hashCode(result, this.baseOutlinePaint);
3167        result = HashUtilities.hashCode(result, this.strokeList);
3168        result = HashUtilities.hashCode(result, this.baseStroke);
3169        result = HashUtilities.hashCode(result, this.outlineStrokeList);
3170        result = HashUtilities.hashCode(result, this.baseOutlineStroke);
3171        // shapeList
3172        // baseShape
3173        result = HashUtilities.hashCode(result, this.itemLabelsVisibleList);
3174        result = HashUtilities.hashCode(result, this.baseItemLabelsVisible);
3175        // itemLabelFontList
3176        // baseItemLabelFont
3177        // itemLabelPaintList
3178        // baseItemLabelPaint
3179        // positiveItemLabelPositionList
3180        // basePositiveItemLabelPosition
3181        // negativeItemLabelPositionList
3182        // baseNegativeItemLabelPosition
3183        // itemLabelAnchorOffset
3184        // createEntityList
3185        // baseCreateEntities
3186        return result;
3187    }
3188
3189    /**
3190     * Returns an independent copy of the renderer.
3191     *
3192     * @return A clone.
3193     *
3194     * @throws CloneNotSupportedException if some component of the renderer
3195     *         does not support cloning.
3196     */
3197    @Override
3198    protected Object clone() throws CloneNotSupportedException {
3199        AbstractRenderer clone = (AbstractRenderer) super.clone();
3200
3201        if (this.seriesVisibleList != null) {
3202            clone.seriesVisibleList
3203                    = (BooleanList) this.seriesVisibleList.clone();
3204        }
3205
3206        if (this.seriesVisibleInLegendList != null) {
3207            clone.seriesVisibleInLegendList
3208                    = (BooleanList) this.seriesVisibleInLegendList.clone();
3209        }
3210
3211        // 'paint' : immutable, no need to clone reference
3212        if (this.paintList != null) {
3213            clone.paintList = (PaintList) this.paintList.clone();
3214        }
3215        // 'basePaint' : immutable, no need to clone reference
3216
3217        if (this.fillPaintList != null) {
3218            clone.fillPaintList = (PaintList) this.fillPaintList.clone();
3219        }
3220        // 'outlinePaint' : immutable, no need to clone reference
3221        if (this.outlinePaintList != null) {
3222            clone.outlinePaintList = (PaintList) this.outlinePaintList.clone();
3223        }
3224        // 'baseOutlinePaint' : immutable, no need to clone reference
3225
3226        // 'stroke' : immutable, no need to clone reference
3227        if (this.strokeList != null) {
3228            clone.strokeList = (StrokeList) this.strokeList.clone();
3229        }
3230        // 'baseStroke' : immutable, no need to clone reference
3231
3232        // 'outlineStroke' : immutable, no need to clone reference
3233        if (this.outlineStrokeList != null) {
3234            clone.outlineStrokeList
3235                = (StrokeList) this.outlineStrokeList.clone();
3236        }
3237        // 'baseOutlineStroke' : immutable, no need to clone reference
3238
3239        if (this.shape != null) {
3240            clone.shape = ShapeUtilities.clone(this.shape);
3241        }
3242        if (this.shapeList != null) {
3243            clone.shapeList = (ShapeList) this.shapeList.clone();
3244        }
3245        if (this.baseShape != null) {
3246            clone.baseShape = ShapeUtilities.clone(this.baseShape);
3247        }
3248
3249        // 'itemLabelsVisible' : immutable, no need to clone reference
3250        if (this.itemLabelsVisibleList != null) {
3251            clone.itemLabelsVisibleList
3252                = (BooleanList) this.itemLabelsVisibleList.clone();
3253        }
3254        // 'basePaint' : immutable, no need to clone reference
3255
3256        // 'itemLabelFont' : immutable, no need to clone reference
3257        if (this.itemLabelFontList != null) {
3258            clone.itemLabelFontList
3259                = (ObjectList) this.itemLabelFontList.clone();
3260        }
3261        // 'baseItemLabelFont' : immutable, no need to clone reference
3262
3263        // 'itemLabelPaint' : immutable, no need to clone reference
3264        if (this.itemLabelPaintList != null) {
3265            clone.itemLabelPaintList
3266                = (PaintList) this.itemLabelPaintList.clone();
3267        }
3268        // 'baseItemLabelPaint' : immutable, no need to clone reference
3269
3270        // 'postiveItemLabelAnchor' : immutable, no need to clone reference
3271        if (this.positiveItemLabelPositionList != null) {
3272            clone.positiveItemLabelPositionList
3273                = (ObjectList) this.positiveItemLabelPositionList.clone();
3274        }
3275        // 'baseItemLabelAnchor' : immutable, no need to clone reference
3276
3277        // 'negativeItemLabelAnchor' : immutable, no need to clone reference
3278        if (this.negativeItemLabelPositionList != null) {
3279            clone.negativeItemLabelPositionList
3280                = (ObjectList) this.negativeItemLabelPositionList.clone();
3281        }
3282        // 'baseNegativeItemLabelAnchor' : immutable, no need to clone reference
3283
3284        if (this.createEntitiesList != null) {
3285            clone.createEntitiesList
3286                    = (BooleanList) this.createEntitiesList.clone();
3287        }
3288
3289        if (this.legendShapeList != null) {
3290            clone.legendShapeList = (ShapeList) this.legendShapeList.clone();
3291        }
3292        if (this.legendTextFont != null) {
3293            clone.legendTextFont = (ObjectList) this.legendTextFont.clone();
3294        }
3295        if (this.legendTextPaint != null) {
3296            clone.legendTextPaint = (PaintList) this.legendTextPaint.clone();
3297        }
3298        clone.listenerList = new EventListenerList();
3299        clone.event = null;
3300        return clone;
3301    }
3302
3303    /**
3304     * Provides serialization support.
3305     *
3306     * @param stream  the output stream.
3307     *
3308     * @throws IOException  if there is an I/O error.
3309     */
3310    private void writeObject(ObjectOutputStream stream) throws IOException {
3311
3312        stream.defaultWriteObject();
3313        SerialUtilities.writePaint(this.paint, stream);
3314        SerialUtilities.writePaint(this.basePaint, stream);
3315        SerialUtilities.writePaint(this.fillPaint, stream);
3316        SerialUtilities.writePaint(this.baseFillPaint, stream);
3317        SerialUtilities.writePaint(this.outlinePaint, stream);
3318        SerialUtilities.writePaint(this.baseOutlinePaint, stream);
3319        SerialUtilities.writeStroke(this.stroke, stream);
3320        SerialUtilities.writeStroke(this.baseStroke, stream);
3321        SerialUtilities.writeStroke(this.outlineStroke, stream);
3322        SerialUtilities.writeStroke(this.baseOutlineStroke, stream);
3323        SerialUtilities.writeShape(this.shape, stream);
3324        SerialUtilities.writeShape(this.baseShape, stream);
3325        SerialUtilities.writePaint(this.itemLabelPaint, stream);
3326        SerialUtilities.writePaint(this.baseItemLabelPaint, stream);
3327        SerialUtilities.writeShape(this.baseLegendShape, stream);
3328        SerialUtilities.writePaint(this.baseLegendTextPaint, stream);
3329
3330    }
3331
3332    /**
3333     * Provides serialization support.
3334     *
3335     * @param stream  the input stream.
3336     *
3337     * @throws IOException  if there is an I/O error.
3338     * @throws ClassNotFoundException  if there is a classpath problem.
3339     */
3340    private void readObject(ObjectInputStream stream)
3341        throws IOException, ClassNotFoundException {
3342
3343        stream.defaultReadObject();
3344        this.paint = SerialUtilities.readPaint(stream);
3345        this.basePaint = SerialUtilities.readPaint(stream);
3346        this.fillPaint = SerialUtilities.readPaint(stream);
3347        this.baseFillPaint = SerialUtilities.readPaint(stream);
3348        this.outlinePaint = SerialUtilities.readPaint(stream);
3349        this.baseOutlinePaint = SerialUtilities.readPaint(stream);
3350        this.stroke = SerialUtilities.readStroke(stream);
3351        this.baseStroke = SerialUtilities.readStroke(stream);
3352        this.outlineStroke = SerialUtilities.readStroke(stream);
3353        this.baseOutlineStroke = SerialUtilities.readStroke(stream);
3354        this.shape = SerialUtilities.readShape(stream);
3355        this.baseShape = SerialUtilities.readShape(stream);
3356        this.itemLabelPaint = SerialUtilities.readPaint(stream);
3357        this.baseItemLabelPaint = SerialUtilities.readPaint(stream);
3358        this.baseLegendShape = SerialUtilities.readShape(stream);
3359        this.baseLegendTextPaint = SerialUtilities.readPaint(stream);
3360
3361        // listeners are not restored automatically, but storage must be
3362        // provided...
3363        this.listenerList = new EventListenerList();
3364
3365    }
3366
3367    // === DEPRECATED CODE ===
3368
3369    /**
3370     * A flag that controls the visibility of ALL series.
3371     *
3372     * @deprecated This field is redundant, you can rely on seriesVisibleList
3373     *     and baseSeriesVisible.  Deprecated from version 1.0.6 onwards.
3374     */
3375    private Boolean seriesVisible;
3376
3377    /**
3378     * A flag that controls the visibility of ALL series in the legend.
3379     *
3380     * @deprecated This field is redundant, you can rely on
3381     *     seriesVisibleInLegendList and baseSeriesVisibleInLegend.
3382     *     Deprecated from version 1.0.6 onwards.
3383     */
3384    private Boolean seriesVisibleInLegend;
3385
3386    /**
3387     * The paint for ALL series (optional).
3388     *
3389     * @deprecated This field is redundant, you can rely on paintList and
3390     *     basePaint.  Deprecated from version 1.0.6 onwards.
3391     */
3392    private transient Paint paint;
3393
3394    /**
3395     * The fill paint for ALL series (optional).
3396     *
3397     * @deprecated This field is redundant, you can rely on fillPaintList and
3398     *     baseFillPaint.  Deprecated from version 1.0.6 onwards.
3399     */
3400    private transient Paint fillPaint;
3401
3402    /**
3403     * The outline paint for ALL series (optional).
3404     *
3405     * @deprecated This field is redundant, you can rely on outlinePaintList
3406     *         and baseOutlinePaint.  Deprecated from version 1.0.6 onwards.
3407     */
3408    private transient Paint outlinePaint;
3409
3410    /**
3411     * The stroke for ALL series (optional).
3412     *
3413     * @deprecated This field is redundant, you can rely on strokeList and
3414     *     baseStroke.  Deprecated from version 1.0.6 onwards.
3415     */
3416    private transient Stroke stroke;
3417
3418    /**
3419     * The outline stroke for ALL series (optional).
3420     *
3421     * @deprecated This field is redundant, you can rely on strokeList and
3422     *     baseStroke.  Deprecated from version 1.0.6 onwards.
3423     */
3424    private transient Stroke outlineStroke;
3425
3426    /**
3427     * The shape for ALL series (optional).
3428     *
3429     * @deprecated This field is redundant, you can rely on shapeList and
3430     *     baseShape.  Deprecated from version 1.0.6 onwards.
3431     */
3432    private transient Shape shape;
3433
3434    /**
3435     * Visibility of the item labels for ALL series (optional).
3436     *
3437     * @deprecated This field is redundant, you can rely on
3438     *     itemLabelsVisibleList and baseItemLabelsVisible.  Deprecated from
3439     *     version 1.0.6 onwards.
3440     */
3441    private Boolean itemLabelsVisible;
3442
3443    /**
3444     * The item label font for ALL series (optional).
3445     *
3446     * @deprecated This field is redundant, you can rely on itemLabelFontList
3447     *     and baseItemLabelFont.  Deprecated from version 1.0.6 onwards.
3448     */
3449    private Font itemLabelFont;
3450
3451    /**
3452     * The item label paint for ALL series.
3453     *
3454     * @deprecated This field is redundant, you can rely on itemLabelPaintList
3455     *     and baseItemLabelPaint.  Deprecated from version 1.0.6 onwards.
3456     */
3457    private transient Paint itemLabelPaint;
3458
3459    /**
3460     * The positive item label position for ALL series (optional).
3461     *
3462     * @deprecated This field is redundant, you can rely on the
3463     *     positiveItemLabelPositionList and basePositiveItemLabelPosition
3464     *     fields.  Deprecated from version 1.0.6 onwards.
3465     */
3466    private ItemLabelPosition positiveItemLabelPosition;
3467
3468    /**
3469     * The negative item label position for ALL series (optional).
3470     *
3471     * @deprecated This field is redundant, you can rely on the
3472     *     negativeItemLabelPositionList and baseNegativeItemLabelPosition
3473     *     fields.  Deprecated from version 1.0.6 onwards.
3474     */
3475    private ItemLabelPosition negativeItemLabelPosition;
3476
3477    /**
3478     * A flag that controls whether or not entities are generated for
3479     * ALL series (optional).
3480     *
3481     * @deprecated This field is redundant, you can rely on the
3482     *     createEntitiesList and baseCreateEntities fields.  Deprecated from
3483     *     version 1.0.6 onwards.
3484     */
3485    private Boolean createEntities;
3486
3487    /**
3488     * Returns the flag that controls the visibility of ALL series.  This flag
3489     * overrides the per series and default settings - you must set it to
3490     * <code>null</code> if you want the other settings to apply.
3491     *
3492     * @return The flag (possibly <code>null</code>).
3493     *
3494     * @see #setSeriesVisible(Boolean)
3495     *
3496     * @deprecated This method should no longer be used (as of version 1.0.6).
3497     *     It is sufficient to rely on {@link #getSeriesVisible(int)} and
3498     *     {@link #getBaseSeriesVisible()}.
3499     */
3500    public Boolean getSeriesVisible() {
3501        return this.seriesVisible;
3502    }
3503
3504    /**
3505     * Sets the flag that controls the visibility of ALL series and sends a
3506     * {@link RendererChangeEvent} to all registered listeners.  This flag
3507     * overrides the per series and default settings - you must set it to
3508     * <code>null</code> if you want the other settings to apply.
3509     *
3510     * @param visible  the flag (<code>null</code> permitted).
3511     *
3512     * @see #getSeriesVisible()
3513     *
3514     * @deprecated This method should no longer be used (as of version 1.0.6).
3515     *     It is sufficient to rely on {@link #setSeriesVisible(int, Boolean)}
3516     *     and {@link #setBaseSeriesVisible(boolean)}.
3517     */
3518    public void setSeriesVisible(Boolean visible) {
3519         setSeriesVisible(visible, true);
3520    }
3521
3522    /**
3523     * Sets the flag that controls the visibility of ALL series and sends a
3524     * {@link RendererChangeEvent} to all registered listeners.  This flag
3525     * overrides the per series and default settings - you must set it to
3526     * <code>null</code> if you want the other settings to apply.
3527     *
3528     * @param visible  the flag (<code>null</code> permitted).
3529     * @param notify  notify listeners?
3530     *
3531     * @see #getSeriesVisible()
3532     *
3533     * @deprecated This method should no longer be used (as of version 1.0.6).
3534     *     It is sufficient to rely on {@link #setSeriesVisible(int, Boolean)}
3535     *     and {@link #setBaseSeriesVisible(boolean)}.
3536     */
3537    public void setSeriesVisible(Boolean visible, boolean notify) {
3538        this.seriesVisible = visible;
3539        if (notify) {
3540            // we create an event with a special flag set...the purpose of
3541            // this is to communicate to the plot (the default receiver of
3542            // the event) that series visibility has changed so the axis
3543            // ranges might need updating...
3544            RendererChangeEvent e = new RendererChangeEvent(this, true);
3545            notifyListeners(e);
3546        }
3547    }
3548
3549    /**
3550     * Returns the flag that controls the visibility of ALL series in the
3551     * legend.  This flag overrides the per series and default settings - you
3552     * must set it to <code>null</code> if you want the other settings to
3553     * apply.
3554     *
3555     * @return The flag (possibly <code>null</code>).
3556     *
3557     * @see #setSeriesVisibleInLegend(Boolean)
3558     *
3559     * @deprecated This method should no longer be used (as of version 1.0.6).
3560     *     It is sufficient to rely on {@link #getSeriesVisibleInLegend(int)}
3561     *     and {@link #getBaseSeriesVisibleInLegend()}.
3562     */
3563    public Boolean getSeriesVisibleInLegend() {
3564        return this.seriesVisibleInLegend;
3565    }
3566
3567    /**
3568     * Sets the flag that controls the visibility of ALL series in the legend
3569     * and sends a {@link RendererChangeEvent} to all registered listeners.
3570     * This flag overrides the per series and default settings - you must set
3571     * it to <code>null</code> if you want the other settings to apply.
3572     *
3573     * @param visible  the flag (<code>null</code> permitted).
3574     *
3575     * @see #getSeriesVisibleInLegend()
3576     *
3577     * @deprecated This method should no longer be used (as of version 1.0.6).
3578     *     It is sufficient to rely on {@link #setSeriesVisibleInLegend(int,
3579     *     Boolean)} and {@link #setBaseSeriesVisibleInLegend(boolean)}.
3580     */
3581    public void setSeriesVisibleInLegend(Boolean visible) {
3582         setSeriesVisibleInLegend(visible, true);
3583    }
3584
3585    /**
3586     * Sets the flag that controls the visibility of ALL series in the legend
3587     * and sends a {@link RendererChangeEvent} to all registered listeners.
3588     * This flag overrides the per series and default settings - you must set
3589     * it to <code>null</code> if you want the other settings to apply.
3590     *
3591     * @param visible  the flag (<code>null</code> permitted).
3592     * @param notify  notify listeners?
3593     *
3594     * @see #getSeriesVisibleInLegend()
3595     *
3596     * @deprecated This method should no longer be used (as of version 1.0.6).
3597     *     It is sufficient to rely on {@link #setSeriesVisibleInLegend(int,
3598     *     Boolean, boolean)} and {@link #setBaseSeriesVisibleInLegend(boolean,
3599     *     boolean)}.
3600     */
3601    public void setSeriesVisibleInLegend(Boolean visible, boolean notify) {
3602        this.seriesVisibleInLegend = visible;
3603        if (notify) {
3604            fireChangeEvent();
3605        }
3606    }
3607
3608    /**
3609     * Sets the paint to be used for ALL series, and sends a
3610     * {@link RendererChangeEvent} to all registered listeners.  If this is
3611     * <code>null</code>, the renderer will use the paint for the series.
3612     *
3613     * @param paint  the paint (<code>null</code> permitted).
3614     *
3615     * @deprecated This method should no longer be used (as of version 1.0.6).
3616     *     It is sufficient to rely on {@link #setSeriesPaint(int, Paint)} and
3617     *     {@link #setBasePaint(Paint)}.
3618     */
3619    public void setPaint(Paint paint) {
3620        setPaint(paint, true);
3621    }
3622
3623    /**
3624     * Sets the paint to be used for all series and, if requested, sends a
3625     * {@link RendererChangeEvent} to all registered listeners.
3626     *
3627     * @param paint  the paint (<code>null</code> permitted).
3628     * @param notify  notify listeners?
3629     *
3630     * @deprecated This method should no longer be used (as of version 1.0.6).
3631     *     It is sufficient to rely on {@link #setSeriesPaint(int, Paint,
3632     *     boolean)} and {@link #setBasePaint(Paint, boolean)}.
3633     */
3634    public void setPaint(Paint paint, boolean notify) {
3635        this.paint = paint;
3636        if (notify) {
3637            fireChangeEvent();
3638        }
3639    }
3640
3641    /**
3642     * Sets the fill paint for ALL series (optional).
3643     *
3644     * @param paint  the paint (<code>null</code> permitted).
3645     *
3646     * @deprecated This method should no longer be used (as of version 1.0.6).
3647     *     It is sufficient to rely on {@link #setSeriesFillPaint(int, Paint)}
3648     *     and {@link #setBaseFillPaint(Paint)}.
3649     */
3650    public void setFillPaint(Paint paint) {
3651        setFillPaint(paint, true);
3652    }
3653
3654    /**
3655     * Sets the fill paint for ALL series and, if requested, sends a
3656     * {@link RendererChangeEvent} to all registered listeners.
3657     *
3658     * @param paint  the paint (<code>null</code> permitted).
3659     * @param notify  notify listeners?
3660     *
3661     * @deprecated This method should no longer be used (as of version 1.0.6).
3662     *     It is sufficient to rely on {@link #setSeriesFillPaint(int, Paint,
3663     *     boolean)} and {@link #setBaseFillPaint(Paint, boolean)}.
3664     */
3665    public void setFillPaint(Paint paint, boolean notify) {
3666        this.fillPaint = paint;
3667        if (notify) {
3668            fireChangeEvent();
3669        }
3670    }
3671
3672    /**
3673     * Sets the outline paint for ALL series (optional) and sends a
3674     * {@link RendererChangeEvent} to all registered listeners.
3675     *
3676     * @param paint  the paint (<code>null</code> permitted).
3677     *
3678     * @deprecated This method should no longer be used (as of version 1.0.6).
3679     *     It is sufficient to rely on {@link #setSeriesOutlinePaint(int,
3680     *     Paint)} and {@link #setBaseOutlinePaint(Paint)}.
3681     */
3682    public void setOutlinePaint(Paint paint) {
3683        setOutlinePaint(paint, true);
3684    }
3685
3686    /**
3687     * Sets the outline paint for ALL series and, if requested, sends a
3688     * {@link RendererChangeEvent} to all registered listeners.
3689     *
3690     * @param paint  the paint (<code>null</code> permitted).
3691     * @param notify  notify listeners?
3692     *
3693     * @deprecated This method should no longer be used (as of version 1.0.6).
3694     *     It is sufficient to rely on {@link #setSeriesOutlinePaint(int,
3695     *     Paint, boolean)} and {@link #setBaseOutlinePaint(Paint, boolean)}.
3696     */
3697    public void setOutlinePaint(Paint paint, boolean notify) {
3698        this.outlinePaint = paint;
3699        if (notify) {
3700            fireChangeEvent();
3701        }
3702    }
3703
3704    /**
3705     * Sets the stroke for ALL series and sends a {@link RendererChangeEvent}
3706     * to all registered listeners.
3707     *
3708     * @param stroke  the stroke (<code>null</code> permitted).
3709     *
3710     * @deprecated This method should no longer be used (as of version 1.0.6).
3711     *     It is sufficient to rely on {@link #setSeriesStroke(int, Stroke)}
3712     *     and {@link #setBaseStroke(Stroke)}.
3713     */
3714    public void setStroke(Stroke stroke) {
3715        setStroke(stroke, true);
3716    }
3717
3718    /**
3719     * Sets the stroke for ALL series and, if requested, sends a
3720     * {@link RendererChangeEvent} to all registered listeners.
3721     *
3722     * @param stroke  the stroke (<code>null</code> permitted).
3723     * @param notify  notify listeners?
3724     *
3725     * @deprecated This method should no longer be used (as of version 1.0.6).
3726     *     It is sufficient to rely on {@link #setSeriesStroke(int, Stroke,
3727     *     boolean)} and {@link #setBaseStroke(Stroke, boolean)}.
3728     */
3729    public void setStroke(Stroke stroke, boolean notify) {
3730        this.stroke = stroke;
3731        if (notify) {
3732            fireChangeEvent();
3733        }
3734    }
3735
3736    /**
3737     * Sets the outline stroke for ALL series and sends a
3738     * {@link RendererChangeEvent} to all registered listeners.
3739     *
3740     * @param stroke  the stroke (<code>null</code> permitted).
3741     *
3742     * @deprecated This method should no longer be used (as of version 1.0.6).
3743     *     It is sufficient to rely on {@link #setSeriesOutlineStroke(int,
3744     *     Stroke)} and {@link #setBaseOutlineStroke(Stroke)}.
3745     */
3746    public void setOutlineStroke(Stroke stroke) {
3747        setOutlineStroke(stroke, true);
3748    }
3749
3750    /**
3751     * Sets the outline stroke for ALL series and, if requested, sends a
3752     * {@link RendererChangeEvent} to all registered listeners.
3753     *
3754     * @param stroke  the stroke (<code>null</code> permitted).
3755     * @param notify  notify listeners?
3756     *
3757     * @deprecated This method should no longer be used (as of version 1.0.6).
3758     *     It is sufficient to rely on {@link #setSeriesOutlineStroke(int,
3759     *     Stroke, boolean)} and {@link #setBaseOutlineStroke(Stroke, boolean)}.
3760     */
3761    public void setOutlineStroke(Stroke stroke, boolean notify) {
3762        this.outlineStroke = stroke;
3763        if (notify) {
3764            fireChangeEvent();
3765        }
3766    }
3767
3768    /**
3769     * Sets the shape for ALL series (optional) and sends a
3770     * {@link RendererChangeEvent} to all registered listeners.
3771     *
3772     * @param shape  the shape (<code>null</code> permitted).
3773     *
3774     * @deprecated This method should no longer be used (as of version 1.0.6).
3775     *     It is sufficient to rely on {@link #setSeriesShape(int, Shape)}
3776     *     and {@link #setBaseShape(Shape)}.
3777     */
3778    public void setShape(Shape shape) {
3779        setShape(shape, true);
3780    }
3781
3782    /**
3783     * Sets the shape for ALL series and, if requested, sends a
3784     * {@link RendererChangeEvent} to all registered listeners.
3785     *
3786     * @param shape  the shape (<code>null</code> permitted).
3787     * @param notify  notify listeners?
3788     *
3789     * @deprecated This method should no longer be used (as of version 1.0.6).
3790     *     It is sufficient to rely on {@link #setSeriesShape(int, Shape,
3791     *     boolean)} and {@link #setBaseShape(Shape, boolean)}.
3792     */
3793    public void setShape(Shape shape, boolean notify) {
3794        this.shape = shape;
3795        if (notify) {
3796            fireChangeEvent();
3797        }
3798    }
3799
3800    /**
3801     * Sets the visibility of the item labels for ALL series.
3802     *
3803     * @param visible  the flag.
3804     *
3805     * @deprecated This method should no longer be used (as of version 1.0.6).
3806     *     It is sufficient to rely on {@link #setSeriesItemLabelsVisible(int,
3807     *     Boolean)} and {@link #setBaseItemLabelsVisible(boolean)}.
3808     */
3809    public void setItemLabelsVisible(boolean visible) {
3810        setItemLabelsVisible(Boolean.valueOf(visible));
3811        // The following alternative is only supported in JDK 1.4 - we support
3812        // JDK 1.3.1 onwards
3813        // setItemLabelsVisible(Boolean.valueOf(visible));
3814    }
3815
3816    /**
3817     * Sets the visibility of the item labels for ALL series (optional).
3818     *
3819     * @param visible  the flag (<code>null</code> permitted).
3820     *
3821     * @deprecated This method should no longer be used (as of version 1.0.6).
3822     *     It is sufficient to rely on {@link #setSeriesItemLabelsVisible(int,
3823     *     Boolean)} and {@link #setBaseItemLabelsVisible(boolean)}.
3824     */
3825    public void setItemLabelsVisible(Boolean visible) {
3826        setItemLabelsVisible(visible, true);
3827    }
3828
3829    /**
3830     * Sets the visibility of item labels for ALL series and, if requested,
3831     * sends a {@link RendererChangeEvent} to all registered listeners.
3832     *
3833     * @param visible  a flag that controls whether or not the item labels are
3834     *                 visible (<code>null</code> permitted).
3835     * @param notify  a flag that controls whether or not listeners are
3836     *                notified.
3837     *
3838     * @deprecated This method should no longer be used (as of version 1.0.6).
3839     *     It is sufficient to rely on {@link #setSeriesItemLabelsVisible(int,
3840     *     Boolean, boolean)} and {@link #setBaseItemLabelsVisible(Boolean,
3841     *     boolean)}.
3842     */
3843    public void setItemLabelsVisible(Boolean visible, boolean notify) {
3844        this.itemLabelsVisible = visible;
3845        if (notify) {
3846            fireChangeEvent();
3847        }
3848    }
3849
3850    /**
3851     * Returns the font used for all item labels.  This may be
3852     * <code>null</code>, in which case the per series font settings will apply.
3853     *
3854     * @return The font (possibly <code>null</code>).
3855     *
3856     * @deprecated This method should no longer be used (as of version 1.0.6).
3857     *     It is sufficient to rely on {@link #getSeriesItemLabelFont(int)} and
3858     *     {@link #getBaseItemLabelFont()}.
3859     */
3860    public Font getItemLabelFont() {
3861        return this.itemLabelFont;
3862    }
3863
3864    /**
3865     * Sets the item label font for ALL series and sends a
3866     * {@link RendererChangeEvent} to all registered listeners.  You can set
3867     * this to <code>null</code> if you prefer to set the font on a per series
3868     * basis.
3869     *
3870     * @param font  the font (<code>null</code> permitted).
3871     *
3872     * @deprecated This method should no longer be used (as of version 1.0.6).
3873     *     It is sufficient to rely on {@link #setSeriesItemLabelFont(int,
3874     *     Font)} and {@link #setBaseItemLabelFont(Font)}.
3875     */
3876    public void setItemLabelFont(Font font) {
3877        setItemLabelFont(font, true);
3878    }
3879
3880    /**
3881     * Sets the item label font for ALL series and, if requested, sends a
3882     * {@link RendererChangeEvent} to all registered listeners.
3883     *
3884     * @param font  the font (<code>null</code> permitted).
3885     * @param notify  a flag that controls whether or not listeners are
3886     *                notified.
3887     *
3888     * @deprecated This method should no longer be used (as of version 1.0.6).
3889     *     It is sufficient to rely on {@link #setSeriesItemLabelFont(int,
3890     *     Font, boolean)} and {@link #setBaseItemLabelFont(Font, boolean)}.
3891     */
3892    public void setItemLabelFont(Font font, boolean notify) {
3893        this.itemLabelFont = font;
3894        if (notify) {
3895            fireChangeEvent();
3896        }
3897    }
3898
3899    /**
3900     * Returns the paint used for all item labels.  This may be
3901     * <code>null</code>, in which case the per series paint settings will
3902     * apply.
3903     *
3904     * @return The paint (possibly <code>null</code>).
3905     *
3906     * @deprecated This method should no longer be used (as of version 1.0.6).
3907     *     It is sufficient to rely on {@link #getSeriesItemLabelPaint(int)}
3908     *     and {@link #getBaseItemLabelPaint()}.
3909     */
3910    public Paint getItemLabelPaint() {
3911        return this.itemLabelPaint;
3912    }
3913
3914    /**
3915     * Sets the item label paint for ALL series and sends a
3916     * {@link RendererChangeEvent} to all registered listeners.
3917     *
3918     * @param paint  the paint (<code>null</code> permitted).
3919     *
3920     * @deprecated This method should no longer be used (as of version 1.0.6).
3921     *     It is sufficient to rely on {@link #setSeriesItemLabelPaint(int,
3922     *     Paint)} and {@link #setBaseItemLabelPaint(Paint)}.
3923     */
3924    public void setItemLabelPaint(Paint paint) {
3925        setItemLabelPaint(paint, true);
3926    }
3927
3928    /**
3929     * Sets the item label paint for ALL series and, if requested, sends a
3930     * {@link RendererChangeEvent} to all registered listeners.
3931     *
3932     * @param paint  the paint.
3933     * @param notify  a flag that controls whether or not listeners are
3934     *                notified.
3935     *
3936     * @deprecated This method should no longer be used (as of version 1.0.6).
3937     *     It is sufficient to rely on {@link #setSeriesItemLabelPaint(int,
3938     *     Paint, boolean)} and {@link #setBaseItemLabelPaint(Paint, boolean)}.
3939     */
3940    public void setItemLabelPaint(Paint paint, boolean notify) {
3941        this.itemLabelPaint = paint;
3942        if (notify) {
3943            fireChangeEvent();
3944        }
3945    }
3946
3947    /**
3948     * Returns the item label position for positive values in ALL series.
3949     *
3950     * @return The item label position (possibly <code>null</code>).
3951     *
3952     * @see #setPositiveItemLabelPosition(ItemLabelPosition)
3953     *
3954     * @deprecated This method should no longer be used (as of version 1.0.6).
3955     *     It is sufficient to rely on
3956     *     {@link #getSeriesPositiveItemLabelPosition(int)}
3957     *     and {@link #getBasePositiveItemLabelPosition()}.
3958     */
3959    public ItemLabelPosition getPositiveItemLabelPosition() {
3960        return this.positiveItemLabelPosition;
3961    }
3962
3963    /**
3964     * Sets the item label position for positive values in ALL series, and
3965     * sends a {@link RendererChangeEvent} to all registered listeners.  You
3966     * need to set this to <code>null</code> to expose the settings for
3967     * individual series.
3968     *
3969     * @param position  the position (<code>null</code> permitted).
3970     *
3971     * @see #getPositiveItemLabelPosition()
3972     *
3973     * @deprecated This method should no longer be used (as of version 1.0.6).
3974     *     It is sufficient to rely on
3975     *     {@link #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition)}
3976     *     and {@link #setBasePositiveItemLabelPosition(ItemLabelPosition)}.
3977     */
3978    public void setPositiveItemLabelPosition(ItemLabelPosition position) {
3979        setPositiveItemLabelPosition(position, true);
3980    }
3981
3982    /**
3983     * Sets the positive item label position for ALL series and (if requested)
3984     * sends a {@link RendererChangeEvent} to all registered listeners.
3985     *
3986     * @param position  the position (<code>null</code> permitted).
3987     * @param notify  notify registered listeners?
3988     *
3989     * @see #getPositiveItemLabelPosition()
3990     *
3991     * @deprecated This method should no longer be used (as of version 1.0.6).
3992     *     It is sufficient to rely on
3993     *     {@link #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition,
3994     *     boolean)} and {@link #setBasePositiveItemLabelPosition(
3995     *     ItemLabelPosition, boolean)}.
3996     */
3997    public void setPositiveItemLabelPosition(ItemLabelPosition position,
3998                                             boolean notify) {
3999        this.positiveItemLabelPosition = position;
4000        if (notify) {
4001            fireChangeEvent();
4002        }
4003    }
4004
4005    /**
4006     * Returns the item label position for negative values in ALL series.
4007     *
4008     * @return The item label position (possibly <code>null</code>).
4009     *
4010     * @see #setNegativeItemLabelPosition(ItemLabelPosition)
4011     *
4012     * @deprecated This method should no longer be used (as of version 1.0.6).
4013     *     It is sufficient to rely on
4014     *     {@link #getSeriesNegativeItemLabelPosition(int)}
4015     *     and {@link #getBaseNegativeItemLabelPosition()}.
4016     */
4017    public ItemLabelPosition getNegativeItemLabelPosition() {
4018        return this.negativeItemLabelPosition;
4019    }
4020
4021    /**
4022     * Sets the item label position for negative values in ALL series, and
4023     * sends a {@link RendererChangeEvent} to all registered listeners.  You
4024     * need to set this to <code>null</code> to expose the settings for
4025     * individual series.
4026     *
4027     * @param position  the position (<code>null</code> permitted).
4028     *
4029     * @see #getNegativeItemLabelPosition()
4030     *
4031     * @deprecated This method should no longer be used (as of version 1.0.6).
4032     *     It is sufficient to rely on
4033     *     {@link #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition)}
4034     *     and {@link #setBaseNegativeItemLabelPosition(ItemLabelPosition)}.
4035     */
4036    public void setNegativeItemLabelPosition(ItemLabelPosition position) {
4037        setNegativeItemLabelPosition(position, true);
4038    }
4039
4040    /**
4041     * Sets the item label position for negative values in ALL series and (if
4042     * requested) sends a {@link RendererChangeEvent} to all registered
4043     * listeners.
4044     *
4045     * @param position  the position (<code>null</code> permitted).
4046     * @param notify  notify registered listeners?
4047     *
4048     * @see #getNegativeItemLabelPosition()
4049     *
4050     * @deprecated This method should no longer be used (as of version 1.0.6).
4051     *     It is sufficient to rely on
4052     *     {@link #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition,
4053     *     boolean)} and {@link #setBaseNegativeItemLabelPosition(
4054     *     ItemLabelPosition, boolean)}.
4055     */
4056    public void setNegativeItemLabelPosition(ItemLabelPosition position,
4057                                             boolean notify) {
4058        this.negativeItemLabelPosition = position;
4059        if (notify) {
4060            fireChangeEvent();
4061        }
4062    }
4063
4064    /**
4065     * Returns the flag that controls whether or not chart entities are created
4066     * for the items in ALL series.  This flag overrides the per series and
4067     * default settings - you must set it to <code>null</code> if you want the
4068     * other settings to apply.
4069     *
4070     * @return The flag (possibly <code>null</code>).
4071     *
4072     * @deprecated This method should no longer be used (as of version 1.0.6).
4073     *     It is sufficient to rely on {@link #getSeriesCreateEntities(int)}
4074     *     and {@link #getBaseCreateEntities()}.
4075     */
4076    public Boolean getCreateEntities() {
4077        return this.createEntities;
4078    }
4079
4080    /**
4081     * Sets the flag that controls whether or not chart entities are created
4082     * for the items in ALL series, and sends a {@link RendererChangeEvent} to
4083     * all registered listeners.  This flag overrides the per series and
4084     * default settings - you must set it to <code>null</code> if you want the
4085     * other settings to apply.
4086     *
4087     * @param create  the flag (<code>null</code> permitted).
4088     *
4089     * @deprecated This method should no longer be used (as of version 1.0.6).
4090     *     It is sufficient to rely on {@link #setSeriesCreateEntities(int,
4091     *     Boolean)} and {@link #setBaseCreateEntities(boolean)}.
4092     */
4093    public void setCreateEntities(Boolean create) {
4094         setCreateEntities(create, true);
4095    }
4096
4097    /**
4098     * Sets the flag that controls whether or not chart entities are created
4099     * for the items in ALL series, and sends a {@link RendererChangeEvent} to
4100     * all registered listeners.  This flag overrides the per series and
4101     * default settings - you must set it to <code>null</code> if you want the
4102     * other settings to apply.
4103     *
4104     * @param create  the flag (<code>null</code> permitted).
4105     * @param notify  notify listeners?
4106     *
4107     * @deprecated This method should no longer be used (as of version 1.0.6).
4108     *     It is sufficient to rely on {@link #setSeriesItemLabelFont(int,
4109     *     Font, boolean)} and {@link #setBaseItemLabelFont(Font, boolean)}.
4110     */
4111    public void setCreateEntities(Boolean create, boolean notify) {
4112        this.createEntities = create;
4113        if (notify) {
4114            fireChangeEvent();
4115        }
4116    }
4117
4118}