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