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