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    
092    package org.jfree.chart.renderer;
093    
094    import java.awt.BasicStroke;
095    import java.awt.Color;
096    import java.awt.Font;
097    import java.awt.Paint;
098    import java.awt.Shape;
099    import java.awt.Stroke;
100    import java.awt.geom.Point2D;
101    import java.awt.geom.Rectangle2D;
102    import java.io.IOException;
103    import java.io.ObjectInputStream;
104    import java.io.ObjectOutputStream;
105    import java.io.Serializable;
106    import java.util.Arrays;
107    import java.util.EventListener;
108    import java.util.List;
109    
110    import javax.swing.event.EventListenerList;
111    
112    import org.jfree.chart.HashUtilities;
113    import org.jfree.chart.event.RendererChangeEvent;
114    import org.jfree.chart.event.RendererChangeListener;
115    import org.jfree.chart.labels.ItemLabelAnchor;
116    import org.jfree.chart.labels.ItemLabelPosition;
117    import org.jfree.chart.plot.DrawingSupplier;
118    import org.jfree.chart.plot.PlotOrientation;
119    import org.jfree.chart.title.LegendTitle;
120    import org.jfree.io.SerialUtilities;
121    import org.jfree.ui.TextAnchor;
122    import org.jfree.util.BooleanList;
123    import org.jfree.util.BooleanUtilities;
124    import org.jfree.util.ObjectList;
125    import org.jfree.util.ObjectUtilities;
126    import org.jfree.util.PaintList;
127    import org.jfree.util.PaintUtilities;
128    import org.jfree.util.ShapeList;
129    import org.jfree.util.ShapeUtilities;
130    import 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     */
138    public 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    }