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