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