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