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