    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2005, 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-2005, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   Nicolas Brodu;
    034     *
    035     * $Id: AbstractRenderer.java,v 1.22.2.3 2005/12/13 17:08:51 mungady Exp $
    036     *
    037     * Changes:
    038     * --------
    039     * 22-Aug-2002 : Version 1, draws code out of AbstractXYItemRenderer to share
    040     *               with AbstractCategoryItemRenderer (DG);
    041     * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
    042     * 06-Nov-2002 : Moved to the com.jrefinery.chart.renderer package (DG);
    043     * 21-Nov-2002 : Added a paint table for the renderer to use (DG);
    044     * 17-Jan-2003 : Moved plot classes into a separate package (DG);
    045     * 25-Mar-2003 : Implemented Serializable (DG);
    046     * 29-Apr-2003 : Added valueLabelFont and valueLabelPaint attributes, based on
    047     *               code from Arnaud Lelievre (DG);
    048     * 29-Jul-2003 : Amended code that doesn't compile with JDK 1.2.2 (DG);
    049     * 13-Aug-2003 : Implemented Cloneable (DG);
    050     * 15-Sep-2003 : Fixed serialization (NB);
    051     * 17-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
    052     * 07-Oct-2003 : Moved PlotRenderingInfo into RendererState to allow for
    053     *               multiple threads using a single renderer (DG);
    054     * 20-Oct-2003 : Added missing setOutlinePaint() method (DG);
    055     * 23-Oct-2003 : Split item label attributes into 'positive' and 'negative'
    056     *               values (DG);
    057     * 26-Nov-2003 : Added methods to get the positive and negative item label
    058     *               positions (DG);
    059     * 01-Mar-2004 : Modified readObject() method to prevent null pointer exceptions
    060     *               after deserialization (DG);
    061     * 19-Jul-2004 : Fixed bug in getItemLabelFont(int, int) method (DG);
    062     * 04-Oct-2004 : Updated equals() method, eliminated use of NumberUtils,
    063     *               renamed BooleanUtils --> BooleanUtilities, ShapeUtils -->
    064     *               ShapeUtilities (DG);
    065     * 15-Mar-2005 : Fixed serialization of baseFillPaint (DG);
    066     * 16-May-2005 : Base outline stroke should never be null (DG);
    067     * 01-Jun-2005 : Added hasListener() method for unit testing (DG);
    068     * 08-Jun-2005 : Fixed equals() method to handle GradientPaint (DG);
    069     *
    070     */
    071
    072    package org.jfree.chart.renderer;
    073
    074    import java.awt.BasicStroke;
    075    import java.awt.Color;
    076    import java.awt.Font;
    077    import java.awt.Paint;
    078    import java.awt.Shape;
    079    import java.awt.Stroke;
    080    import java.awt.geom.Point2D;
    081    import java.awt.geom.Rectangle2D;
    082    import java.io.IOException;
    083    import java.io.ObjectInputStream;
    084    import java.io.ObjectOutputStream;
    085    import java.io.Serializable;
    086    import java.util.Arrays;
    087    import java.util.EventListener;
    088    import java.util.List;
    089
    090    import javax.swing.event.EventListenerList;
    091
    092    import org.jfree.chart.event.RendererChangeEvent;
    093    import org.jfree.chart.event.RendererChangeListener;
    094    import org.jfree.chart.labels.ItemLabelAnchor;
    095    import org.jfree.chart.labels.ItemLabelPosition;
    096    import org.jfree.chart.plot.DrawingSupplier;
    097    import org.jfree.chart.plot.PlotOrientation;
    098    import org.jfree.io.SerialUtilities;
    099    import org.jfree.ui.TextAnchor;
    100    import org.jfree.util.BooleanList;
    101    import org.jfree.util.BooleanUtilities;
    102    import org.jfree.util.ObjectList;
    103    import org.jfree.util.ObjectUtilities;
    104    import org.jfree.util.PaintList;
    105    import org.jfree.util.PaintUtilities;
    106    import org.jfree.util.ShapeList;
    107    import org.jfree.util.ShapeUtilities;
    108    import org.jfree.util.StrokeList;
    109
    110    /**
    111     * Base class providing common services for renderers.  Most methods that update
    112     * attributes of the renderer will fire a {@link RendererChangeEvent}, which
    113     * normally means the plot that owns the renderer will receive notification that
    114     * the renderer has been changed (the plot will, in turn, notify the chart).
    115     */
    116    public abstract class AbstractRenderer implements Cloneable, Serializable {
    117
    118        /** For serialization. */
    119        private static final long serialVersionUID = -828267569428206075L;
    120
    121        /** A useful constant. */
    122        public static final Double ZERO = new Double(0.0);
    123
    124        /** The default paint. */
    125        public static final Paint DEFAULT_PAINT = Color.blue;
    126
    127        /** The default outline paint. */
    128        public static final Paint DEFAULT_OUTLINE_PAINT = Color.gray;
    129
    130        /** The default stroke. */
    131        public static final Stroke DEFAULT_STROKE = new BasicStroke(1.0f);
    132
    133        /** The default outline stroke. */
    134        public static final Stroke DEFAULT_OUTLINE_STROKE = new BasicStroke(1.0f);
    135
    136        /** The default shape. */
    137        public static final Shape DEFAULT_SHAPE
    138            = new Rectangle2D.Double(-3.0, -3.0, 6.0, 6.0);
    139
    140        /** The default value label font. */
    141        public static final Font DEFAULT_VALUE_LABEL_FONT
    142            = new Font("SansSerif", Font.PLAIN, 10);
    143
    144        /** The default value label paint. */
    145        public static final Paint DEFAULT_VALUE_LABEL_PAINT = Color.black;
    146
    147        /** A flag that controls the visibility of ALL series. */
    148        private Boolean seriesVisible;
    149
    150        /** A list of flags that controls whether or not each series is visible. */
    151        private BooleanList seriesVisibleList;
    152
    153        /** The default visibility for each series. */
    154        private boolean baseSeriesVisible;
    155
    156        /** A flag that controls the visibility of ALL series in the legend. */
    157        private Boolean seriesVisibleInLegend;
    158
    159        /**
    160         * A list of flags that controls whether or not each series is visible in
    161         * the legend.
    162         */
    163        private BooleanList seriesVisibleInLegendList;
    164
    165        /** The default visibility for each series in the legend. */
    166        private boolean baseSeriesVisibleInLegend;
    167
    168        /** The paint for ALL series (optional). */
    169        private transient Paint paint;
    170
    171        /** The paint list. */
    172        private PaintList paintList;
    173
    174        /** The base paint. */
    175        private transient Paint basePaint;
    176
    177        /** The fill paint for ALL series (optional). */
    178        private transient Paint fillPaint;
    179
    180        /** The fill paint list. */
    181        private PaintList fillPaintList;
    182
    183        /** The base fill paint. */
    184        private transient Paint baseFillPaint;
    185
    186        /** The outline paint for ALL series (optional). */
    187        private transient Paint outlinePaint;
    188
    189        /** The outline paint list. */
    190        private PaintList outlinePaintList;
    191
    192        /** The base outline paint. */
    193        private transient Paint baseOutlinePaint;
    194
    195        /** The stroke for ALL series (optional). */
    196        private transient Stroke stroke;
    197
    198        /** The stroke list. */
    199        private StrokeList strokeList;
    200
    201        /** The base stroke. */
    202        private transient Stroke baseStroke;
    203
    204        /** The outline stroke for ALL series (optional). */
    205        private transient Stroke outlineStroke;
    206
    207        /** The outline stroke list. */
    208        private StrokeList outlineStrokeList;
    209
    210        /** The base outline stroke. */
    211        private transient Stroke baseOutlineStroke;
    212
    213        /** The shape for ALL series (optional). */
    214        private transient Shape shape;
    215
    216        /** A shape list. */
    217        private ShapeList shapeList;
    218
    219        /** The base shape. */
    220        private transient Shape baseShape;
    221
    222        /** Visibility of the item labels for ALL series (optional). */
    223        private Boolean itemLabelsVisible;
    224
    225        /** Visibility of the item labels PER series. */
    226        private BooleanList itemLabelsVisibleList;
    227
    228        /** The base item labels visible. */
    229        private Boolean baseItemLabelsVisible;
    230
    231        /** The item label font for ALL series (optional). */
    232        private Font itemLabelFont;
    233
    234        /** The item label font list (one font per series). */
    235        private ObjectList itemLabelFontList;
    236
    237        /** The base item label font. */
    238        private Font baseItemLabelFont;
    239
    240        /** The item label paint for ALL series. */
    241        private transient Paint itemLabelPaint;
    242
    243        /** The item label paint list (one paint per series). */
    244        private PaintList itemLabelPaintList;
    245
    246        /** The base item label paint. */
    247        private transient Paint baseItemLabelPaint;
    248
    249        /** The positive item label position for ALL series (optional). */
    250        private ItemLabelPosition positiveItemLabelPosition;
    251
    252        /** The positive item label position (per series). */
    253        private ObjectList positiveItemLabelPositionList;
    254
    255        /** The fallback positive item label position. */
    256        private ItemLabelPosition basePositiveItemLabelPosition;
    257
    258        /** The negative item label position for ALL series (optional). */
    259        private ItemLabelPosition negativeItemLabelPosition;
    260
    261        /** The negative item label position (per series). */
    262        private ObjectList negativeItemLabelPositionList;
    263
    264        /** The fallback negative item label position. */
    265        private ItemLabelPosition baseNegativeItemLabelPosition;
    266
    267        /** The item label anchor offset. */
    268        private double itemLabelAnchorOffset = 2.0;
    269
    270        /**
    271         * A flag that controls whether or not entities are generated for
    272         * ALL series (optional).
    273         */
    274        private Boolean createEntities;
    275
    276        /**
    277         * Flags that control whether or not entities are generated for each
    278         * series.  This will be overridden by 'createEntities'.
    279         */
    280        private BooleanList createEntitiesList;
    281
    282        /**
    283         * The default flag that controls whether or not entities are generated.
    284         * This flag is used when both the above flags return null.
    285         */
    286        private boolean baseCreateEntities;
    287
    288        /** Storage for registered change listeners. */
    289        private transient EventListenerList listenerList;
    290
    291        /**
    292         * Default constructor.
    293         */
    294        public AbstractRenderer() {
    295
    296            this.seriesVisible = null;
    297            this.seriesVisibleList = new BooleanList();
    298            this.baseSeriesVisible = true;
    299
    300            this.seriesVisibleInLegend = null;
    301            this.seriesVisibleInLegendList = new BooleanList();
    302            this.baseSeriesVisibleInLegend = true;
    303
    304            this.paint = null;
    305            this.paintList = new PaintList();
    306            this.basePaint = DEFAULT_PAINT;
    307
    308            this.fillPaint = null;
    309            this.fillPaintList = new PaintList();
    310            this.baseFillPaint = Color.white;
    311
    312            this.outlinePaint = null;
    313            this.outlinePaintList = new PaintList();
    314            this.baseOutlinePaint = DEFAULT_OUTLINE_PAINT;
    315
    316            this.stroke = null;
    317            this.strokeList = new StrokeList();
    318            this.baseStroke = DEFAULT_STROKE;
    319
    320            this.outlineStroke = null;
    321            this.outlineStrokeList = new StrokeList();
    322            this.baseOutlineStroke = DEFAULT_OUTLINE_STROKE;
    323
    324            this.shape = null;
    325            this.shapeList = new ShapeList();
    326            this.baseShape = DEFAULT_SHAPE;
    327
    328            this.itemLabelsVisible = null;
    329            this.itemLabelsVisibleList = new BooleanList();
    330            this.baseItemLabelsVisible = Boolean.FALSE;
    331
    332            this.itemLabelFont = null;
    333            this.itemLabelFontList = new ObjectList();
    334            this.baseItemLabelFont = new Font("SansSerif", Font.PLAIN, 10);
    335
    336            this.itemLabelPaint = null;
    337            this.itemLabelPaintList = new PaintList();
    338            this.baseItemLabelPaint = Color.black;
    339
    340            this.positiveItemLabelPosition = null;
    341            this.positiveItemLabelPositionList = new ObjectList();
    342            this.basePositiveItemLabelPosition = new ItemLabelPosition(
    343                ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER
    344            );
    345
    346            this.negativeItemLabelPosition = null;
    347            this.negativeItemLabelPositionList = new ObjectList();
    348            this.baseNegativeItemLabelPosition = new ItemLabelPosition(
    349                ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER
    350            );
    351
    352            this.createEntities = null;
    353            this.createEntitiesList = new BooleanList();
    354            this.baseCreateEntities = true;
    355
    356            this.listenerList = new EventListenerList();
    357
    358        }
    359
    360        /**
    361         * Returns the drawing supplier from the plot.
    362         *
    363         * @return The drawing supplier.
    364         */
    365        public abstract DrawingSupplier getDrawingSupplier();
    366
    367        // SERIES VISIBLE (not yet respected by all renderers)
    368
    369        /**
    370         * Returns a boolean that indicates whether or not the specified item
    371         * should be drawn (this is typically used to hide an entire series).
    372         *
    373         * @param series  the series index.
    374         * @param item  the item index.
    375         *
    376         * @return A boolean.
    377         */
    378        public boolean getItemVisible(int series, int item) {
    379            return isSeriesVisible(series);
    380        }
    381
    382        /**
    383         * Returns a boolean that indicates whether or not the specified series
    384         * should be drawn.
    385         *
    386         * @param series  the series index.
    387         *
    388         * @return A boolean.
    389         */
    390        public boolean isSeriesVisible(int series) {
    391            boolean result = this.baseSeriesVisible;
    392            if (this.seriesVisible != null) {
    393                result = this.seriesVisible.booleanValue();
    394            }
    395            else {
    396                Boolean b = this.seriesVisibleList.getBoolean(series);
    397                if (b != null) {
    398                    result = b.booleanValue();
    399                }
    400            }
    401            return result;
    402        }
    403
    404        /**
    405         * Returns the flag that controls the visibility of ALL series.  This flag
    406         * overrides the per series and default settings - you must set it to
    407         * <code>null</code> if you want the other settings to apply.
    408         *
    409         * @return The flag (possibly <code>null</code>).
    410         */
    411        public Boolean getSeriesVisible() {
    412            return this.seriesVisible;
    413        }
    414
    415        /**
    416         * Sets the flag that controls the visibility of ALL series and sends a
    417         * {@link RendererChangeEvent} to all registered listeners.  This flag
    418         * overrides the per series and default settings - you must set it to
    419         * <code>null</code> if you want the other settings to apply.
    420         *
    421         * @param visible  the flag (<code>null</code> permitted).
    422         */
    423        public void setSeriesVisible(Boolean visible) {
    424             setSeriesVisible(visible, true);
    425        }
    426
    427        /**
    428         * Sets the flag that controls the visibility of ALL series and sends a
    429         * {@link RendererChangeEvent} to all registered listeners.  This flag
    430         * overrides the per series and default settings - you must set it to
    431         * <code>null</code> if you want the other settings to apply.
    432         *
    433         * @param visible  the flag (<code>null</code> permitted).
    434         * @param notify  notify listeners?
    435         */
    436        public void setSeriesVisible(Boolean visible, boolean notify) {
    437            this.seriesVisible = visible;
    438            if (notify) {
    439                notifyListeners(new RendererChangeEvent(this));
    440            }
    441        }
    442
    443        /**
    444         * Returns the flag that controls whether a series is visible.
    445         *
    446         * @param series  the series index (zero-based).
    447         *
    448         * @return The flag (possibly <code>null</code>).
    449         */
    450        public Boolean getSeriesVisible(int series) {
    451            return this.seriesVisibleList.getBoolean(series);
    452        }
    453
    454        /**
    455         * Sets the flag that controls whether a series is visible and sends a
    456         * {@link RendererChangeEvent} to all registered listeners.
    457         *
    458         * @param series  the series index (zero-based).
    459         * @param visible  the flag (<code>null</code> permitted).
    460         */
    461        public void setSeriesVisible(int series, Boolean visible) {
    462            setSeriesVisible(series, visible, true);
    463        }
    464
    465        /**
    466         * Sets the flag that controls whether a series is visible and, if
    467         * requested, sends a {@link RendererChangeEvent} to all registered
    468         * listeners.
    469         *
    470         * @param series  the series index.
    471         * @param visible  the flag (<code>null</code> permitted).
    472         * @param notify  notify listeners?
    473         */
    474        public void setSeriesVisible(int series, Boolean visible, boolean notify) {
    475            this.seriesVisibleList.setBoolean(series, visible);
    476            if (notify) {
    477                notifyListeners(new RendererChangeEvent(this));
    478            }
    479        }
    480
    481        /**
    482         * Returns the base visibility for all series.
    483         *
    484         * @return The base visibility.
    485         */
    486        public boolean getBaseSeriesVisible() {
    487            return this.baseSeriesVisible;
    488        }
    489
    490        /**
    491         * Sets the base visibility and sends a {@link RendererChangeEvent}
    492         * to all registered listeners.
    493         *
    494         * @param visible  the flag.
    495         */
    496        public void setBaseSeriesVisible(boolean visible) {
    497            // defer argument checking...
    498            setBaseSeriesVisible(visible, true);
    499        }
    500
    501        /**
    502         * Sets the base visibility and, if requested, sends
    503         * a {@link RendererChangeEvent} to all registered listeners.
    504         *
    505         * @param visible  the visibility.
    506         * @param notify  notify listeners?
    507         */
    508        public void setBaseSeriesVisible(boolean visible, boolean notify) {
    509            this.baseSeriesVisible = visible;
    510            if (notify) {
    511                notifyListeners(new RendererChangeEvent(this));
    512            }
    513        }
    514
    515        // SERIES VISIBLE IN LEGEND (not yet respected by all renderers)
    516
    517        /**
    518         * Returns <code>true</code> if the series should be shown in the legend,
    519         * and <code>false</code> otherwise.
    520         *
    521         * @param series  the series index.
    522         *
    523         * @return A boolean.
    524         */
    525        public boolean isSeriesVisibleInLegend(int series) {
    526            boolean result = this.baseSeriesVisibleInLegend;
    527            if (this.seriesVisibleInLegend != null) {
    528                result = this.seriesVisibleInLegend.booleanValue();
    529            }
    530            else {
    531                Boolean b = this.seriesVisibleInLegendList.getBoolean(series);
    532                if (b != null) {
    533                    result = b.booleanValue();
    534                }
    535            }
    536            return result;
    537        }
    538
    539        /**
    540         * Returns the flag that controls the visibility of ALL series in the
    541         * legend.  This flag overrides the per series and default settings - you
    542         * must set it to <code>null</code> if you want the other settings to
    543         * apply.
    544         *
    545         * @return The flag (possibly <code>null</code>).
    546         */
    547        public Boolean getSeriesVisibleInLegend() {
    548            return this.seriesVisibleInLegend;
    549        }
    550
    551        /**
    552         * Sets the flag that controls the visibility of ALL series in the legend
    553         * and sends a {@link RendererChangeEvent} to all registered listeners.
    554         * This flag overrides the per series and default settings - you must set
    555         * it to <code>null</code> if you want the other settings to apply.
    556         *
    557         * @param visible  the flag (<code>null</code> permitted).
    558         */
    559        public void setSeriesVisibleInLegend(Boolean visible) {
    560             setSeriesVisibleInLegend(visible, true);
    561        }
    562
    563        /**
    564         * Sets the flag that controls the visibility of ALL series in the legend
    565         * and sends a {@link RendererChangeEvent} to all registered listeners.
    566         * This flag overrides the per series and default settings - you must set
    567         * it to <code>null</code> if you want the other settings to apply.
    568         *
    569         * @param visible  the flag (<code>null</code> permitted).
    570         * @param notify  notify listeners?
    571         */
    572        public void setSeriesVisibleInLegend(Boolean visible, boolean notify) {
    573            this.seriesVisibleInLegend = visible;
    574            if (notify) {
    575                notifyListeners(new RendererChangeEvent(this));
    576            }
    577        }
    578
    579        /**
    580         * Returns the flag that controls whether a series is visible in the
    581         * legend.  This method returns only the "per series" settings - to
    582         * incorporate the override and base settings as well, you need to use the
    583         * {@link #isSeriesVisibleInLegend(int)} method.
    584         *
    585         * @param series  the series index (zero-based).
    586         *
    587         * @return The flag (possibly <code>null</code>).
    588         */
    589        public Boolean getSeriesVisibleInLegend(int series) {
    590            return this.seriesVisibleInLegendList.getBoolean(series);
    591        }
    592
    593        /**
    594         * Sets the flag that controls whether a series is visible in the legend
    595         * and sends a {@link RendererChangeEvent} to all registered listeners.
    596         *
    597         * @param series  the series index (zero-based).
    598         * @param visible  the flag (<code>null</code> permitted).
    599         */
    600        public void setSeriesVisibleInLegend(int series, Boolean visible) {
    601            setSeriesVisibleInLegend(series, visible, true);
    602        }
    603
    604        /**
    605         * Sets the flag that controls whether a series is visible in the legend
    606         * and, if requested, sends a {@link RendererChangeEvent} to all registered
    607         * listeners.
    608         *
    609         * @param series  the series index.
    610         * @param visible  the flag (<code>null</code> permitted).
    611         * @param notify  notify listeners?
    612         */
    613        public void setSeriesVisibleInLegend(int series, Boolean visible,
    614                                             boolean notify) {
    615            this.seriesVisibleInLegendList.setBoolean(series, visible);
    616            if (notify) {
    617                notifyListeners(new RendererChangeEvent(this));
    618            }
    619        }
    620
    621        /**
    622         * Returns the base visibility in the legend for all series.
    623         *
    624         * @return The base visibility.
    625         */
    626        public boolean getBaseSeriesVisibleInLegend() {
    627            return this.baseSeriesVisibleInLegend;
    628        }
    629
    630        /**
    631         * Sets the base visibility in the legend and sends a
    632         * {@link RendererChangeEvent} to all registered listeners.
    633         *
    634         * @param visible  the flag.
    635         */
    636        public void setBaseSeriesVisibleInLegend(boolean visible) {
    637            // defer argument checking...
    638            setBaseSeriesVisibleInLegend(visible, true);
    639        }
    640
    641        /**
    642         * Sets the base visibility in the legend and, if requested, sends
    643         * a {@link RendererChangeEvent} to all registered listeners.
    644         *
    645         * @param visible  the visibility.
    646         * @param notify  notify listeners?
    647         */
    648        public void setBaseSeriesVisibleInLegend(boolean visible, boolean notify) {
    649            this.baseSeriesVisibleInLegend = visible;
    650            if (notify) {
    651                notifyListeners(new RendererChangeEvent(this));
    652            }
    653        }
    654
    655        // PAINT
    656
    657        /**
    658         * Returns the paint used to fill data items as they are drawn.
    659         * <p>
    660         * The default implementation passes control to the
    661         * <code>getSeriesPaint</code> method. You can override this method if you
    662         * require different behaviour.
    663         *
    664         * @param row  the row (or series) index (zero-based).
    665         * @param column  the column (or category) index (zero-based).
    666         *
    667         * @return The paint (never <code>null</code>).
    668         */
    669        public Paint getItemPaint(int row, int column) {
    670            return getSeriesPaint(row);
    671        }
    672
    673        /**
    674         * Returns the paint used to fill an item drawn by the renderer.
    675         *
    676         * @param series  the series index (zero-based).
    677         *
    678         * @return The paint (never <code>null</code>).
    679         */
    680        public Paint getSeriesPaint(int series) {
    681
    682            // return the override, if there is one...
    683            if (this.paint != null) {
    684                return this.paint;
    685            }
    686
    687            // otherwise look up the paint list
    688            Paint seriesPaint = this.paintList.getPaint(series);
    689            if (seriesPaint == null) {
    690                DrawingSupplier supplier = getDrawingSupplier();
    691                if (supplier != null) {
    692                    seriesPaint = supplier.getNextPaint();
    693                    this.paintList.setPaint(series, seriesPaint);
    694                }
    695                else {
    696                    seriesPaint = this.basePaint;
    697                }
    698            }
    699            return seriesPaint;
    700
    701        }
    702
    703        /**
    704         * Sets the paint to be used for ALL series, and sends a
    705         * {@link RendererChangeEvent} to all registered listeners.  If this is
    706         * <code>null</code>, the renderer will use the paint for the series.
    707         *
    708         * @param paint  the paint (<code>null</code> permitted).
    709         */
    710        public void setPaint(Paint paint) {
    711            setPaint(paint, true);
    712        }
    713
    714        /**
    715         * Sets the paint to be used for all series and, if requested, sends a
    716         * {@link RendererChangeEvent} to all registered listeners.
    717         *
    718         * @param paint  the paint (<code>null</code> permitted).
    719         * @param notify  notify listeners?
    720         */
    721        public void setPaint(Paint paint, boolean notify) {
    722            this.paint = paint;
    723            if (notify) {
    724                notifyListeners(new RendererChangeEvent(this));
    725            }
    726        }
    727
    728        /**
    729         * Sets the paint used for a series and sends a {@link RendererChangeEvent}
    730         * to all registered listeners.
    731         *
    732         * @param series  the series index (zero-based).
    733         * @param paint  the paint (<code>null</code> permitted).
    734         */
    735        public void setSeriesPaint(int series, Paint paint) {
    736            setSeriesPaint(series, paint, true);
    737        }
    738
    739        /**
    740         * Sets the paint used for a series and, if requested, sends a
    741         * {@link RendererChangeEvent} to all registered listeners.
    742         *
    743         * @param series  the series index.
    744         * @param paint  the paint (<code>null</code> permitted).
    745         * @param notify  notify listeners?
    746         */
    747        public void setSeriesPaint(int series, Paint paint, boolean notify) {
    748            this.paintList.setPaint(series, paint);
    749            if (notify) {
    750                notifyListeners(new RendererChangeEvent(this));
    751            }
    752        }
    753
    754        /**
    755         * Returns the base paint.
    756         *
    757         * @return The base paint (never <code>null</code>).
    758         */
    759        public Paint getBasePaint() {
    760            return this.basePaint;
    761        }
    762
    763        /**
    764         * Sets the base paint and sends a {@link RendererChangeEvent} to all
    765         * registered listeners.
    766         *
    767         * @param paint  the paint (<code>null</code> not permitted).
    768         */
    769        public void setBasePaint(Paint paint) {
    770            // defer argument checking...
    771            setBasePaint(paint, true);
    772        }
    773
    774        /**
    775         * Sets the base paint and, if requested, sends a
    776         * {@link RendererChangeEvent} to all registered listeners.
    777         *
    778         * @param paint  the paint (<code>null</code> not permitted).
    779         * @param notify  notify listeners?
    780         */
    781        public void setBasePaint(Paint paint, boolean notify) {
    782            this.basePaint = paint;
    783            if (notify) {
    784                notifyListeners(new RendererChangeEvent(this));
    785            }
    786        }
    787
    788        //// FILL PAINT //////////////////////////////////////////////////////////
    789
    790        /**
    791         * Returns the paint used to fill data items as they are drawn.  The
    792         * default implementation passes control to the
    793         * {@link #getSeriesFillPaint(int)} method - you can override this method
    794         * if you require different behaviour.
    795         *
    796         * @param row  the row (or series) index (zero-based).
    797         * @param column  the column (or category) index (zero-based).
    798         *
    799         * @return The paint (never <code>null</code>).
    800         */
    801        public Paint getItemFillPaint(int row, int column) {
    802            return getSeriesFillPaint(row);
    803        }
    804
    805        /**
    806         * Returns the paint used to fill an item drawn by the renderer.
    807         *
    808         * @param series  the series (zero-based index).
    809         *
    810         * @return The paint (never <code>null</code>).
    811         */
    812        public Paint getSeriesFillPaint(int series) {
    813
    814            // return the override, if there is one...
    815            if (this.fillPaint != null) {
    816                return this.fillPaint;
    817            }
    818
    819            // otherwise look up the paint table
    820            Paint seriesFillPaint = this.fillPaintList.getPaint(series);
    821            if (seriesFillPaint == null) {
    822                seriesFillPaint = this.baseFillPaint;
    823            }
    824            return seriesFillPaint;
    825
    826        }
    827
    828        /**
    829         * Sets the paint used for a series fill and sends a
    830         * {@link RendererChangeEvent} to all registered listeners.
    831         *
    832         * @param series  the series index (zero-based).
    833         * @param paint  the paint (<code>null</code> permitted).
    834         */
    835        public void setSeriesFillPaint(int series, Paint paint) {
    836            setSeriesFillPaint(series, paint, true);
    837        }
    838
    839        /**
    840         * Sets the paint used to fill a series and, if requested,
    841         * sends a {@link RendererChangeEvent} to all registered listeners.
    842         *
    843         * @param series  the series index (zero-based).
    844         * @param paint  the paint (<code>null</code> permitted).
    845         * @param notify  notify listeners?
    846         */
    847        public void setSeriesFillPaint(int series, Paint paint, boolean notify) {
    848            this.fillPaintList.setPaint(series, paint);
    849            if (notify) {
    850                notifyListeners(new RendererChangeEvent(this));
    851            }
    852        }
    853
    854        /**
    855         * Sets the fill paint for ALL series (optional).
    856         *
    857         * @param paint  the paint (<code>null</code> permitted).
    858         */
    859        public void setFillPaint(Paint paint) {
    860            setFillPaint(paint, true);
    861        }
    862
    863        /**
    864         * Sets the fill paint for ALL series and, if requested, sends a
    865         * {@link RendererChangeEvent} to all registered listeners.
    866         *
    867         * @param paint  the paint (<code>null</code> permitted).
    868         * @param notify  notify listeners?
    869         */
    870        public void setFillPaint(Paint paint, boolean notify) {
    871            this.fillPaint = paint;
    872            if (notify) {
    873                notifyListeners(new RendererChangeEvent(this));
    874            }
    875        }
    876
    877        /**
    878         * Returns the base fill paint.
    879         *
    880         * @return The paint (never <code>null</code>).
    881         */
    882        public Paint getBaseFillPaint() {
    883            return this.baseFillPaint;
    884        }
    885
    886        /**
    887         * Sets the base fill paint and sends a {@link RendererChangeEvent} to
    888         * all registered listeners.
    889         *
    890         * @param paint  the paint (<code>null</code> not permitted).
    891         */
    892        public void setBaseFillPaint(Paint paint) {
    893            // defer argument checking...
    894            setBaseFillPaint(paint, true);
    895        }
    896
    897        /**
    898         * Sets the base fill paint and, if requested, sends a
    899         * {@link RendererChangeEvent} to all registered listeners.
    900         *
    901         * @param paint  the paint (<code>null</code> not permitted).
    902         * @param notify  notify listeners?
    903         */
    904        public void setBaseFillPaint(Paint paint, boolean notify) {
    905            if (paint == null) {
    906                throw new IllegalArgumentException("Null 'paint' argument.");
    907            }
    908            this.baseFillPaint = paint;
    909            if (notify) {
    910                notifyListeners(new RendererChangeEvent(this));
    911            }
    912        }
    913
    914        // OUTLINE PAINT //////////////////////////////////////////////////////////
    915
    916        /**
    917         * Returns the paint used to outline data items as they are drawn.
    918         * <p>
    919         * The default implementation passes control to the getSeriesOutlinePaint
    920         * method.  You can override this method if you require different behaviour.
    921         *
    922         * @param row  the row (or series) index (zero-based).
    923         * @param column  the column (or category) index (zero-based).
    924         *
    925         * @return The paint (never <code>null</code>).
    926         */
    927        public Paint getItemOutlinePaint(int row, int column) {
    928            return getSeriesOutlinePaint(row);
    929        }
    930
    931        /**
    932         * Returns the paint used to outline an item drawn by the renderer.
    933         *
    934         * @param series  the series (zero-based index).
    935         *
    936         * @return The paint (never <code>null</code>).
    937         */
    938        public Paint getSeriesOutlinePaint(int series) {
    939
    940            // return the override, if there is one...
    941            if (this.outlinePaint != null) {
    942                return this.outlinePaint;
    943            }
    944
    945            // otherwise look up the paint table
    946            Paint seriesOutlinePaint = this.outlinePaintList.getPaint(series);
    947            if (seriesOutlinePaint == null) {
    948                DrawingSupplier supplier = getDrawingSupplier();
    949                if (supplier != null) {
    950                    seriesOutlinePaint = supplier.getNextOutlinePaint();
    951                    this.outlinePaintList.setPaint(series, seriesOutlinePaint);
    952                }
    953                else {
    954                    seriesOutlinePaint = this.baseOutlinePaint;
    955                }
    956            }
    957            return seriesOutlinePaint;
    958
    959        }
    960
    961        /**
    962         * Sets the paint used for a series outline and sends a
    963         * {@link RendererChangeEvent} to all registered listeners.
    964         *
    965         * @param series  the series index (zero-based).
    966         * @param paint  the paint (<code>null</code> permitted).
    967         */
    968        public void setSeriesOutlinePaint(int series, Paint paint) {
    969            setSeriesOutlinePaint(series, paint, true);
    970        }
    971
    972        /**
    973         * Sets the paint used to draw the outline for a series and, if requested,
    974         * sends a {@link RendererChangeEvent} to all registered listeners.
    975         *
    976         * @param series  the series index (zero-based).
    977         * @param paint  the paint (<code>null</code> permitted).
    978         * @param notify  notify listeners?
    979         */
    980        public void setSeriesOutlinePaint(int series, Paint paint, boolean notify) {
    981            this.outlinePaintList.setPaint(series, paint);
    982            if (notify) {
    983                notifyListeners(new RendererChangeEvent(this));
    984            }
    985        }
    986
    987        /**
    988         * Sets the outline paint for ALL series (optional).
    989         *
    990         * @param paint  the paint (<code>null</code> permitted).
    991         */
    992        public void setOutlinePaint(Paint paint) {
    993            setOutlinePaint(paint, true);
    994        }
    995
    996        /**
    997         * Sets the outline paint for ALL series and, if requested, sends a
    998         * {@link RendererChangeEvent} to all registered listeners.
    999         *
    1000         * @param paint  the paint (<code>null</code> permitted).
    1001         * @param notify  notify listeners?
    1002         */
    1003        public void setOutlinePaint(Paint paint, boolean notify) {
    1004            this.outlinePaint = paint;
    1005            if (notify) {
    1006                notifyListeners(new RendererChangeEvent(this));
    1007            }
    1008        }
    1009
    1010        /**
    1011         * Returns the base outline paint.
    1012         *
    1013         * @return The paint (never <code>null</code>).
    1014         */
    1015        public Paint getBaseOutlinePaint() {
    1016            return this.baseOutlinePaint;
    1017        }
    1018
    1019        /**
    1020         * Sets the base outline paint and sends a {@link RendererChangeEvent} to
    1021         * all registered listeners.
    1022         *
    1023         * @param paint  the paint (<code>null</code> not permitted).
    1024         */
    1025        public void setBaseOutlinePaint(Paint paint) {
    1026            // defer argument checking...
    1027            setBaseOutlinePaint(paint, true);
    1028        }
    1029
    1030        /**
    1031         * Sets the base outline paint and, if requested, sends a
    1032         * {@link RendererChangeEvent} to all registered listeners.
    1033         *
    1034         * @param paint  the paint (<code>null</code> not permitted).
    1035         * @param notify  notify listeners?
    1036         */
    1037        public void setBaseOutlinePaint(Paint paint, boolean notify) {
    1038            if (paint == null) {
    1039                throw new IllegalArgumentException("Null 'paint' argument.");
    1040            }
    1041            this.baseOutlinePaint = paint;
    1042            if (notify) {
    1043                notifyListeners(new RendererChangeEvent(this));
    1044            }
    1045        }
    1046
    1047        // STROKE
    1048
    1049        /**
    1050         * Returns the stroke used to draw data items.
    1051         * <p>
    1052         * The default implementation passes control to the getSeriesStroke method.
    1053         * You can override this method if you require different behaviour.
    1054         *
    1055         * @param row  the row (or series) index (zero-based).
    1056         * @param column  the column (or category) index (zero-based).
    1057         *
    1058         * @return The stroke (never <code>null</code>).
    1059         */
    1060        public Stroke getItemStroke(int row, int column) {
    1061            return getSeriesStroke(row);
    1062        }
    1063
    1064        /**
    1065         * Returns the stroke used to draw the items in a series.
    1066         *
    1067         * @param series  the series (zero-based index).
    1068         *
    1069         * @return The stroke (never <code>null</code>).
    1070         */
    1071        public Stroke getSeriesStroke(int series) {
    1072
    1073            // return the override, if there is one...
    1074            if (this.stroke != null) {
    1075                return this.stroke;
    1076            }
    1077
    1078            // otherwise look up the paint table
    1079            Stroke result = this.strokeList.getStroke(series);
    1080            if (result == null) {
    1081                DrawingSupplier supplier = getDrawingSupplier();
    1082                if (supplier != null) {
    1083                    result = supplier.getNextStroke();
    1084                    this.strokeList.setStroke(series, result);
    1085                }
    1086                else {
    1087                    result = this.baseStroke;
    1088                }
    1089            }
    1090            return result;
    1091
    1092        }
    1093
    1094        /**
    1095         * Sets the stroke for ALL series and sends a {@link RendererChangeEvent}
    1096         * to all registered listeners.
    1097         *
    1098         * @param stroke  the stroke (<code>null</code> permitted).
    1099         */
    1100        public void setStroke(Stroke stroke) {
    1101            setStroke(stroke, true);
    1102        }
    1103
    1104        /**
    1105         * Sets the stroke for ALL series and, if requested, sends a
    1106         * {@link RendererChangeEvent} to all registered listeners.
    1107         *
    1108         * @param stroke  the stroke (<code>null</code> permitted).
    1109         * @param notify  notify listeners?
    1110         */
    1111        public void setStroke(Stroke stroke, boolean notify) {
    1112            this.stroke = stroke;
    1113            if (notify) {
    1114                notifyListeners(new RendererChangeEvent(this));
    1115            }
    1116        }
    1117
    1118        /**
    1119         * Sets the stroke used for a series and sends a {@link RendererChangeEvent}
    1120         * to all registered listeners.
    1121         *
    1122         * @param series  the series index (zero-based).
    1123         * @param stroke  the stroke (<code>null</code> permitted).
    1124         */
    1125        public void setSeriesStroke(int series, Stroke stroke) {
    1126            setSeriesStroke(series, stroke, true);
    1127        }
    1128
    1129        /**
    1130         * Sets the stroke for a series and, if requested, sends a
    1131         * {@link RendererChangeEvent} to all registered listeners.
    1132         *
    1133         * @param series  the series index (zero-based).
    1134         * @param stroke  the stroke (<code>null</code> permitted).
    1135         * @param notify  notify listeners?
    1136         */
    1137        public void setSeriesStroke(int series, Stroke stroke, boolean notify) {
    1138            this.strokeList.setStroke(series, stroke);
    1139            if (notify) {
    1140                notifyListeners(new RendererChangeEvent(this));
    1141            }
    1142        }
    1143
    1144        /**
    1145         * Returns the base stroke.
    1146         *
    1147         * @return The base stroke (never <code>null</code>).
    1148         */
    1149        public Stroke getBaseStroke() {
    1150            return this.baseStroke;
    1151        }
    1152
    1153        /**
    1154         * Sets the base stroke.
    1155         *
    1156         * @param stroke  the stroke (<code>null</code> not permitted).
    1157         */
    1158        public void setBaseStroke(Stroke stroke) {
    1159            // defer argument checking...
    1160            setBaseStroke(stroke, true);
    1161        }
    1162
    1163        /**
    1164         * Sets the base stroke and, if requested, sends a
    1165         * {@link RendererChangeEvent} to all registered listeners.
    1166         *
    1167         * @param stroke  the stroke (<code>null</code> not permitted).
    1168         * @param notify  notify listeners?
    1169         */
    1170        public void setBaseStroke(Stroke stroke, boolean notify) {
    1171            if (stroke == null) {
    1172                throw new IllegalArgumentException("Null 'stroke' argument.");
    1173            }
    1174            this.baseStroke = stroke;
    1175            if (notify) {
    1176                notifyListeners(new RendererChangeEvent(this));
    1177            }
    1178        }
    1179
    1180        // OUTLINE STROKE
    1181
    1182        /**
    1183         * Returns the stroke used to outline data items.  The default
    1184         * implementation passes control to the {@link #getSeriesOutlineStroke(int)}
    1185         * method. You can override this method if you require different behaviour.
    1186         *
    1187         * @param row  the row (or series) index (zero-based).
    1188         * @param column  the column (or category) index (zero-based).
    1189         *
    1190         * @return The stroke (never <code>null</code>).
    1191         */
    1192        public Stroke getItemOutlineStroke(int row, int column) {
    1193            return getSeriesOutlineStroke(row);
    1194        }
    1195
    1196        /**
    1197         * Returns the stroke used to outline the items in a series.
    1198         *
    1199         * @param series  the series (zero-based index).
    1200         *
    1201         * @return The stroke (never <code>null</code>).
    1202         */
    1203        public Stroke getSeriesOutlineStroke(int series) {
    1204
    1205            // return the override, if there is one...
    1206            if (this.outlineStroke != null) {
    1207                return this.outlineStroke;
    1208            }
    1209
    1210            // otherwise look up the stroke table
    1211            Stroke result = this.outlineStrokeList.getStroke(series);
    1212            if (result == null) {
    1213                DrawingSupplier supplier = getDrawingSupplier();
    1214                if (supplier != null) {
    1215                    result = supplier.getNextOutlineStroke();
    1216                    this.outlineStrokeList.setStroke(series, result);
    1217                }
    1218                else {
    1219                    result = this.baseOutlineStroke;
    1220                }
    1221            }
    1222            return result;
    1223
    1224        }
    1225
    1226        /**
    1227         * Sets the outline stroke for ALL series and sends a
    1228         * {@link RendererChangeEvent} to all registered listeners.
    1229         *
    1230         * @param stroke  the stroke (<code>null</code> permitted).
    1231         */
    1232        public void setOutlineStroke(Stroke stroke) {
    1233            setOutlineStroke(stroke, true);
    1234        }
    1235
    1236        /**
    1237         * Sets the outline stroke for ALL series and, if requested, sends a
    1238         * {@link RendererChangeEvent} to all registered listeners.
    1239         *
    1240         * @param stroke  the stroke (<code>null</code> permitted).
    1241         * @param notify  notify listeners?
    1242         */
    1243        public void setOutlineStroke(Stroke stroke, boolean notify) {
    1244            this.outlineStroke = stroke;
    1245            if (notify) {
    1246                notifyListeners(new RendererChangeEvent(this));
    1247            }
    1248        }
    1249
    1250        /**
    1251         * Sets the outline stroke used for a series and sends a
    1252         * {@link RendererChangeEvent} to all registered listeners.
    1253         *
    1254         * @param series  the series index (zero-based).
    1255         * @param stroke  the stroke (<code>null</code> permitted).
    1256         */
    1257        public void setSeriesOutlineStroke(int series, Stroke stroke) {
    1258            setSeriesOutlineStroke(series, stroke, true);
    1259        }
    1260
    1261        /**
    1262         * Sets the outline stroke for a series and, if requested, sends a
    1263         * {@link RendererChangeEvent} to all registered listeners.
    1264         *
    1265         * @param series  the series index.
    1266         * @param stroke  the stroke (<code>null</code> permitted).
    1267         * @param notify  notify listeners?
    1268         */
    1269        public void setSeriesOutlineStroke(int series, Stroke stroke,
    1270                                           boolean notify) {
    1271            this.outlineStrokeList.setStroke(series, stroke);
    1272            if (notify) {
    1273                notifyListeners(new RendererChangeEvent(this));
    1274            }
    1275        }
    1276
    1277        /**
    1278         * Returns the base outline stroke.
    1279         *
    1280         * @return The stroke (never <code>null</code>).
    1281         */
    1282        public Stroke getBaseOutlineStroke() {
    1283            return this.baseOutlineStroke;
    1284        }
    1285
    1286        /**
    1287         * Sets the base outline stroke and sends a {@link RendererChangeEvent} to
    1288         * all registered listeners.
    1289         *
    1290         * @param stroke  the stroke (<code>null</code> not permitted).
    1291         */
    1292        public void setBaseOutlineStroke(Stroke stroke) {
    1293            setBaseOutlineStroke(stroke, true);
    1294        }
    1295
    1296        /**
    1297         * Sets the base outline stroke and, if requested, sends a
    1298         * {@link RendererChangeEvent} to all registered listeners.
    1299         *
    1300         * @param stroke  the stroke (<code>null</code> not permitted).
    1301         * @param notify  a flag that controls whether or not listeners are
    1302         *                notified.
    1303         */
    1304        public void setBaseOutlineStroke(Stroke stroke, boolean notify) {
    1305            if (stroke == null) {
    1306                throw new IllegalArgumentException("Null 'stroke' argument.");
    1307            }
    1308            this.baseOutlineStroke = stroke;
    1309            if (notify) {
    1310                notifyListeners(new RendererChangeEvent(this));
    1311            }
    1312        }
    1313
    1314        // SHAPE
    1315
    1316        /**
    1317         * Returns a shape used to represent a data item.
    1318         * <p>
    1319         * The default implementation passes control to the getSeriesShape method.
    1320         * You can override this method if you require different behaviour.
    1321         *
    1322         * @param row  the row (or series) index (zero-based).
    1323         * @param column  the column (or category) index (zero-based).
    1324         *
    1325         * @return The shape (never <code>null</code>).
    1326         */
    1327        public Shape getItemShape(int row, int column) {
    1328            return getSeriesShape(row);
    1329        }
    1330
    1331        /**
    1332         * Returns a shape used to represent the items in a series.
    1333         *
    1334         * @param series  the series (zero-based index).
    1335         *
    1336         * @return The shape (never <code>null</code>).
    1337         */
    1338        public Shape getSeriesShape(int series) {
    1339
    1340            // return the override, if there is one...
    1341            if (this.shape != null) {
    1342                return this.shape;
    1343            }
    1344
    1345            // otherwise look up the shape list
    1346            Shape result = this.shapeList.getShape(series);
    1347            if (result == null) {
    1348                DrawingSupplier supplier = getDrawingSupplier();
    1349                if (supplier != null) {
    1350                    result = supplier.getNextShape();
    1351                    this.shapeList.setShape(series, result);
    1352                }
    1353                else {
    1354                    result = this.baseShape;
    1355                }
    1356            }
    1357            return result;
    1358
    1359        }
    1360
    1361        /**
    1362         * Sets the shape for ALL series (optional) and sends a
    1363         * {@link RendererChangeEvent} to all registered listeners.
    1364         *
    1365         * @param shape  the shape (<code>null</code> permitted).
    1366         */
    1367        public void setShape(Shape shape) {
    1368            setShape(shape, true);
    1369        }
    1370
    1371        /**
    1372         * Sets the shape for ALL series and, if requested, sends a
    1373         * {@link RendererChangeEvent} to all registered listeners.
    1374         *
    1375         * @param shape  the shape (<code>null</code> permitted).
    1376         * @param notify  notify listeners?
    1377         */
    1378        public void setShape(Shape shape, boolean notify) {
    1379            this.shape = shape;
    1380            if (notify) {
    1381                notifyListeners(new RendererChangeEvent(this));
    1382            }
    1383        }
    1384
    1385        /**
    1386         * Sets the shape used for a series and sends a {@link RendererChangeEvent}
    1387         * to all registered listeners.
    1388         *
    1389         * @param series  the series index (zero-based).
    1390         * @param shape  the shape (<code>null</code> permitted).
    1391         */
    1392        public void setSeriesShape(int series, Shape shape) {
    1393            setSeriesShape(series, shape, true);
    1394        }
    1395
    1396        /**
    1397         * Sets the shape for a series and, if requested, sends a
    1398         * {@link RendererChangeEvent} to all registered listeners.
    1399         *
    1400         * @param series  the series index (zero based).
    1401         * @param shape  the shape (<code>null</code> permitted).
    1402         * @param notify  notify listeners?
    1403         */
    1404        public void setSeriesShape(int series, Shape shape, boolean notify) {
    1405            this.shapeList.setShape(series, shape);
    1406            if (notify) {
    1407                notifyListeners(new RendererChangeEvent(this));
    1408            }
    1409        }
    1410
    1411        /**
    1412         * Returns the base shape.
    1413         *
    1414         * @return The shape (never <code>null</code>).
    1415         */
    1416        public Shape getBaseShape() {
    1417            return this.baseShape;
    1418        }
    1419
    1420        /**
    1421         * Sets the base shape and sends a {@link RendererChangeEvent} to all
    1422         * registered listeners.
    1423         *
    1424         * @param shape  the shape (<code>null</code> not permitted).
    1425         */
    1426        public void setBaseShape(Shape shape) {
    1427            // defer argument checking...
    1428            setBaseShape(shape, true);
    1429        }
    1430
    1431        /**
    1432         * Sets the base shape and, if requested, sends a
    1433         * {@link RendererChangeEvent} to all registered listeners.
    1434         *
    1435         * @param shape  the shape (<code>null</code> not permitted).
    1436         * @param notify  notify listeners?
    1437         */
    1438        public void setBaseShape(Shape shape, boolean notify) {
    1439            if (shape == null) {
    1440                throw new IllegalArgumentException("Null 'shape' argument.");
    1441            }
    1442            this.baseShape = shape;
    1443            if (notify) {
    1444                notifyListeners(new RendererChangeEvent(this));
    1445            }
    1446        }
    1447
    1448        // ITEM LABEL VISIBILITY...
    1449
    1450        /**
    1451         * Returns <code>true</code> if an item label is visible, and
    1452         * <code>false</code> otherwise.
    1453         *
    1454         * @param row  the row index (zero-based).
    1455         * @param column  the column index (zero-based).
    1456         *
    1457         * @return A boolean.
    1458         */
    1459        public boolean isItemLabelVisible(int row, int column) {
    1460            return isSeriesItemLabelsVisible(row);
    1461        }
    1462
    1463        /**
    1464         * Returns <code>true</code> if the item labels for a series are visible,
    1465         * and <code>false</code> otherwise.
    1466         *
    1467         * @param series  the series index (zero-based).
    1468         *
    1469         * @return A boolean.
    1470         */
    1471        public boolean isSeriesItemLabelsVisible(int series) {
    1472
    1473            // return the override, if there is one...
    1474            if (this.itemLabelsVisible != null) {
    1475                return this.itemLabelsVisible.booleanValue();
    1476            }
    1477
    1478            // otherwise look up the boolean table
    1479            Boolean b = this.itemLabelsVisibleList.getBoolean(series);
    1480            if (b == null) {
    1481                b = this.baseItemLabelsVisible;
    1482            }
    1483            if (b == null) {
    1484                b = Boolean.FALSE;
    1485            }
    1486            return b.booleanValue();
    1487
    1488        }
    1489
    1490        /**
    1491         * Sets the visibility of the item labels for ALL series.
    1492         *
    1493         * @param visible  the flag.
    1494         */
    1495        public void setItemLabelsVisible(boolean visible) {
    1496            setItemLabelsVisible(BooleanUtilities.valueOf(visible));
    1497            // The following alternative is only supported in JDK 1.4 - we support
    1498            // JDK 1.2.2
    1499            // setItemLabelsVisible(Boolean.valueOf(visible));
    1500        }
    1501
    1502        /**
    1503         * Sets the visibility of the item labels for ALL series (optional).
    1504         *
    1505         * @param visible  the flag (<code>null</code> permitted).
    1506         */
    1507        public void setItemLabelsVisible(Boolean visible) {
    1508            setItemLabelsVisible(visible, true);
    1509        }
    1510
    1511        /**
    1512         * Sets the visibility of item labels for ALL series and, if requested,
    1513         * sends a {@link RendererChangeEvent} to all registered listeners.
    1514         *
    1515         * @param visible  a flag that controls whether or not the item labels are
    1516         *                 visible (<code>null</code> permitted).
    1517         * @param notify  a flag that controls whether or not listeners are
    1518         *                notified.
    1519         */
    1520        public void setItemLabelsVisible(Boolean visible, boolean notify) {
    1521            this.itemLabelsVisible = visible;
    1522            if (notify) {
    1523                notifyListeners(new RendererChangeEvent(this));
    1524            }
    1525        }
    1526
    1527        /**
    1528         * Sets a flag that controls the visibility of the item labels for a series.
    1529         *
    1530         * @param series  the series index (zero-based).
    1531         * @param visible  the flag.
    1532         */
    1533        public void setSeriesItemLabelsVisible(int series, boolean visible) {
    1534            setSeriesItemLabelsVisible(series, BooleanUtilities.valueOf(visible));
    1535        }
    1536
    1537        /**
    1538         * Sets the visibility of the item labels for a series.
    1539         *
    1540         * @param series  the series index (zero-based).
    1541         * @param visible  the flag (<code>null</code> permitted).
    1542         */
    1543        public void setSeriesItemLabelsVisible(int series, Boolean visible) {
    1544            setSeriesItemLabelsVisible(series, visible, true);
    1545        }
    1546
    1547        /**
    1548         * Sets the visibility of item labels for a series and, if requested, sends
    1549         * a {@link RendererChangeEvent} to all registered listeners.
    1550         *
    1551         * @param series  the series index (zero-based).
    1552         * @param visible  the visible flag.
    1553         * @param notify  a flag that controls whether or not listeners are
    1554         *                notified.
    1555         */
    1556        public void setSeriesItemLabelsVisible(int series, Boolean visible,
    1557                                               boolean notify) {
    1558            this.itemLabelsVisibleList.setBoolean(series, visible);
    1559            if (notify) {
    1560                notifyListeners(new RendererChangeEvent(this));
    1561            }
    1562        }
    1563
    1564        /**
    1565         * Returns the base setting for item label visibility.
    1566         *
    1567         * @return A flag (possibly <code>null</code>).
    1568         */
    1569        public Boolean getBaseItemLabelsVisible() {
    1570            return this.baseItemLabelsVisible;
    1571        }
    1572
    1573        /**
    1574         * Sets the base flag that controls whether or not item labels are visible.
    1575         *
    1576         * @param visible  the flag.
    1577         */
    1578        public void setBaseItemLabelsVisible(boolean visible) {
    1579            setBaseItemLabelsVisible(BooleanUtilities.valueOf(visible));
    1580        }
    1581
    1582        /**
    1583         * Sets the base setting for item label visibility.
    1584         *
    1585         * @param visible  the flag (<code>null</code> permitted).
    1586         */
    1587        public void setBaseItemLabelsVisible(Boolean visible) {
    1588            setBaseItemLabelsVisible(visible, true);
    1589        }
    1590
    1591        /**
    1592         * Sets the base visibility for item labels and, if requested, sends a
    1593         * {@link RendererChangeEvent} to all registered listeners.
    1594         *
    1595         * @param visible  the visibility flag.
    1596         * @param notify  a flag that controls whether or not listeners are
    1597         *                notified.
    1598         */
    1599        public void setBaseItemLabelsVisible(Boolean visible, boolean notify) {
    1600            this.baseItemLabelsVisible = visible;
    1601            if (notify) {
    1602                notifyListeners(new RendererChangeEvent(this));
    1603            }
    1604        }
    1605
    1606        //// ITEM LABEL FONT //////////////////////////////////////////////////////
    1607
    1608        /**
    1609         * Returns the font for an item label.
    1610         *
    1611         * @param row  the row index (zero-based).
    1612         * @param column  the column index (zero-based).
    1613         *
    1614         * @return The font (never <code>null</code>).
    1615         */
    1616        public Font getItemLabelFont(int row, int column) {
    1617            Font result = this.itemLabelFont;
    1618            if (result == null) {
    1619                result = getSeriesItemLabelFont(row);
    1620                if (result == null) {
    1621                    result = this.baseItemLabelFont;
    1622                }
    1623            }
    1624            return result;
    1625        }
    1626
    1627        /**
    1628         * Returns the font used for all item labels.  This may be
    1629         * <code>null</code>, in which case the per series font settings will apply.
    1630         *
    1631         * @return The font (possibly <code>null</code>).
    1632         */
    1633        public Font getItemLabelFont() {
    1634            return this.itemLabelFont;
    1635        }
    1636
    1637        /**
    1638         * Sets the item label font for ALL series and sends a
    1639         * {@link RendererChangeEvent} to all registered listeners.  You can set
    1640         * this to <code>null</code> if you prefer to set the font on a per series
    1641         * basis.
    1642         *
    1643         * @param font  the font (<code>null</code> permitted).
    1644         */
    1645        public void setItemLabelFont(Font font) {
    1646            setItemLabelFont(font, true);
    1647        }
    1648
    1649        /**
    1650         * Sets the item label font for ALL series and, if requested, sends a
    1651         * {@link RendererChangeEvent} to all registered listeners.
    1652         *
    1653         * @param font  the font (<code>null</code> permitted).
    1654         * @param notify  a flag that controls whether or not listeners are
    1655         *                notified.
    1656         */
    1657        public void setItemLabelFont(Font font, boolean notify) {
    1658            this.itemLabelFont = font;
    1659            if (notify) {
    1660                notifyListeners(new RendererChangeEvent(this));
    1661            }
    1662        }
    1663
    1664        /**
    1665         * Returns the font for all the item labels in a series.
    1666         *
    1667         * @param series  the series index (zero-based).
    1668         *
    1669         * @return The font (possibly <code>null</code>).
    1670         */
    1671        public Font getSeriesItemLabelFont(int series) {
    1672            return (Font) this.itemLabelFontList.get(series);
    1673        }
    1674
    1675        /**
    1676         * Sets the item label font for a series and sends a
    1677         * {@link RendererChangeEvent} to all registered listeners.
    1678         *
    1679         * @param series  the series index (zero-based).
    1680         * @param font  the font (<code>null</code> permitted).
    1681         */
    1682        public void setSeriesItemLabelFont(int series, Font font) {
    1683            setSeriesItemLabelFont(series, font, true);
    1684        }
    1685
    1686        /**
    1687         * Sets the item label font for a series and, if requested, sends a
    1688         * {@link RendererChangeEvent} to all registered listeners.
    1689         *
    1690         * @param series  the series index (zero based).
    1691         * @param font  the font (<code>null</code> permitted).
    1692         * @param notify  a flag that controls whether or not listeners are
    1693         *                notified.
    1694         */
    1695        public void setSeriesItemLabelFont(int series, Font font, boolean notify) {
    1696            this.itemLabelFontList.set(series, font);
    1697            if (notify) {
    1698                notifyListeners(new RendererChangeEvent(this));
    1699            }
    1700        }
    1701
    1702        /**
    1703         * Returns the base item label font (this is used when no other font
    1704         * setting is available).
    1705         *
    1706         * @return The font (<code>never</code> null).
    1707         */
    1708        public Font getBaseItemLabelFont() {
    1709            return this.baseItemLabelFont;
    1710        }
    1711
    1712        /**
    1713         * Sets the base item label font and sends a {@link RendererChangeEvent} to
    1714         * all registered listeners.
    1715         *
    1716         * @param font  the font (<code>null</code> not permitted).
    1717         */
    1718        public void setBaseItemLabelFont(Font font) {
    1719            if (font == null) {
    1720                throw new IllegalArgumentException("Null 'font' argument.");
    1721            }
    1722            setBaseItemLabelFont(font, true);
    1723        }
    1724
    1725        /**
    1726         * Sets the base item label font and, if requested, sends a
    1727         * {@link RendererChangeEvent} to all registered listeners.
    1728         *
    1729         * @param font  the font (<code>null</code> not permitted).
    1730         * @param notify  a flag that controls whether or not listeners are
    1731         *                notified.
    1732         */
    1733        public void setBaseItemLabelFont(Font font, boolean notify) {
    1734            this.baseItemLabelFont = font;
    1735            if (notify) {
    1736                notifyListeners(new RendererChangeEvent(this));
    1737            }
    1738        }
    1739
    1740        //// ITEM LABEL PAINT  ////////////////////////////////////////////////////
    1741
    1742        /**
    1743         * Returns the paint used to draw an item label.
    1744         *
    1745         * @param row  the row index (zero based).
    1746         * @param column  the column index (zero based).
    1747         *
    1748         * @return The paint (never <code>null</code>).
    1749         */
    1750        public Paint getItemLabelPaint(int row, int column) {
    1751            Paint result = this.itemLabelPaint;
    1752            if (result == null) {
    1753                result = getSeriesItemLabelPaint(row);
    1754                if (result == null) {
    1755                    result = this.baseItemLabelPaint;
    1756                }
    1757            }
    1758            return result;
    1759        }
    1760
    1761        /**
    1762         * Returns the paint used for all item labels.  This may be
    1763         * <code>null</code>, in which case the per series paint settings will
    1764         * apply.
    1765         *
    1766         * @return The paint (possibly <code>null</code>).
    1767         */
    1768        public Paint getItemLabelPaint() {
    1769            return this.itemLabelPaint;
    1770        }
    1771
    1772        /**
    1773         * Sets the item label paint for ALL series and sends a
    1774         * {@link RendererChangeEvent} to all registered listeners.
    1775         *
    1776         * @param paint  the paint (<code>null</code> permitted).
    1777         */
    1778        public void setItemLabelPaint(Paint paint) {
    1779            setItemLabelPaint(paint, true);
    1780        }
    1781
    1782        /**
    1783         * Sets the item label paint for ALL series and, if requested, sends a
    1784         * {@link RendererChangeEvent} to all registered listeners.
    1785         *
    1786         * @param paint  the paint.
    1787         * @param notify  a flag that controls whether or not listeners are
    1788         *                notified.
    1789         */
    1790        public void setItemLabelPaint(Paint paint, boolean notify) {
    1791            this.itemLabelPaint = paint;
    1792            if (notify) {
    1793                notifyListeners(new RendererChangeEvent(this));
    1794            }
    1795        }
    1796
    1797        /**
    1798         * Returns the paint used to draw the item labels for a series.
    1799         *
    1800         * @param series  the series index (zero based).
    1801         *
    1802         * @return The paint (possibly <code>null<code>).
    1803         */
    1804        public Paint getSeriesItemLabelPaint(int series) {
    1805            return this.itemLabelPaintList.getPaint(series);
    1806        }
    1807
    1808        /**
    1809         * Sets the item label paint for a series and sends a
    1810         * {@link RendererChangeEvent} to all registered listeners.
    1811         *
    1812         * @param series  the series (zero based index).
    1813         * @param paint  the paint (<code>null</code> permitted).
    1814         */
    1815        public void setSeriesItemLabelPaint(int series, Paint paint) {
    1816            setSeriesItemLabelPaint(series, paint, true);
    1817        }
    1818
    1819        /**
    1820         * Sets the item label paint for a series and, if requested, sends a
    1821         * {@link RendererChangeEvent} to all registered listeners.
    1822         *
    1823         * @param series  the series index (zero based).
    1824         * @param paint  the paint (<code>null</code> permitted).
    1825         * @param notify  a flag that controls whether or not listeners are
    1826         *                notified.
    1827         */
    1828        public void setSeriesItemLabelPaint(int series, Paint paint,
    1829                                            boolean notify) {
    1830            this.itemLabelPaintList.setPaint(series, paint);
    1831            if (notify) {
    1832                notifyListeners(new RendererChangeEvent(this));
    1833            }
    1834        }
    1835
    1836        /**
    1837         * Returns the base item label paint.
    1838         *
    1839         * @return The paint (never <code>null<code>).
    1840         */
    1841        public Paint getBaseItemLabelPaint() {
    1842            return this.baseItemLabelPaint;
    1843        }
    1844
    1845        /**
    1846         * Sets the base item label paint and sends a {@link RendererChangeEvent}
    1847         * to all registered listeners.
    1848         *
    1849         * @param paint  the paint (<code>null</code> not permitted).
    1850         */
    1851        public void setBaseItemLabelPaint(Paint paint) {
    1852            // defer argument checking...
    1853            setBaseItemLabelPaint(paint, true);
    1854        }
    1855
    1856        /**
    1857         * Sets the base item label paint and, if requested, sends a
    1858         * {@link RendererChangeEvent} to all registered listeners..
    1859         *
    1860         * @param paint  the paint (<code>null</code> not permitted).
    1861         * @param notify  a flag that controls whether or not listeners are
    1862         *                notified.
    1863         */
    1864        public void setBaseItemLabelPaint(Paint paint, boolean notify) {
    1865            if (paint == null) {
    1866                throw new IllegalArgumentException("Null 'paint' argument.");
    1867            }
    1868            this.baseItemLabelPaint = paint;
    1869            if (notify) {
    1870                notifyListeners(new RendererChangeEvent(this));
    1871            }
    1872        }
    1873
    1874        // POSITIVE ITEM LABEL POSITION...
    1875
    1876        /**
    1877         * Returns the item label position for positive values.
    1878         *
    1879         * @param row  the row index (zero-based).
    1880         * @param column  the column index (zero-based).
    1881         *
    1882         * @return The item label position (never <code>null</code>).
    1883         */
    1884        public ItemLabelPosition getPositiveItemLabelPosition(int row, int column) {
    1885            return getSeriesPositiveItemLabelPosition(row);
    1886        }
    1887
    1888        /**
    1889         * Returns the item label position for positive values in ALL series.
    1890         *
    1891         * @return The item label position (possibly <code>null</code>).
    1892         */
    1893        public ItemLabelPosition getPositiveItemLabelPosition() {
    1894            return this.positiveItemLabelPosition;
    1895        }
    1896
    1897        /**
    1898         * Sets the item label position for positive values in ALL series, and
    1899         * sends a {@link RendererChangeEvent} to all registered listeners.  You
    1900         * need to set this to <code>null</code> to expose the settings for
    1901         * individual series.
    1902         *
    1903         * @param position  the position (<code>null</code> permitted).
    1904         */
    1905        public void setPositiveItemLabelPosition(ItemLabelPosition position) {
    1906            setPositiveItemLabelPosition(position, true);
    1907        }
    1908
    1909        /**
    1910         * Sets the positive item label position for ALL series and (if requested)
    1911         * sends a {@link RendererChangeEvent} to all registered listeners.
    1912         *
    1913         * @param position  the position (<code>null</code> permitted).
    1914         * @param notify  notify registered listeners?
    1915         */
    1916        public void setPositiveItemLabelPosition(ItemLabelPosition position,
    1917                                                 boolean notify) {
    1918            this.positiveItemLabelPosition = position;
    1919            if (notify) {
    1920                notifyListeners(new RendererChangeEvent(this));
    1921            }
    1922        }
    1923
    1924        /**
    1925         * Returns the item label position for all positive values in a series.
    1926         *
    1927         * @param series  the series index (zero-based).
    1928         *
    1929         * @return The item label position (never <code>null</code>).
    1930         */
    1931        public ItemLabelPosition getSeriesPositiveItemLabelPosition(int series) {
    1932
    1933            // return the override, if there is one...
    1934            if (this.positiveItemLabelPosition != null) {
    1935                return this.positiveItemLabelPosition;
    1936            }
    1937
    1938            // otherwise look up the position table
    1939            ItemLabelPosition position = (ItemLabelPosition)
    1940                this.positiveItemLabelPositionList.get(series);
    1941            if (position == null) {
    1942                position = this.basePositiveItemLabelPosition;
    1943            }
    1944            return position;
    1945
    1946        }
    1947
    1948        /**
    1949         * Sets the item label position for all positive values in a series and
    1950         * sends a {@link RendererChangeEvent} to all registered listeners.
    1951         *
    1952         * @param series  the series index (zero-based).
    1953         * @param position  the position (<code>null</code> permitted).
    1954         */
    1955        public void setSeriesPositiveItemLabelPosition(int series,
    1956                                                       ItemLabelPosition position) {
    1957            setSeriesPositiveItemLabelPosition(series, position, true);
    1958        }
    1959
    1960        /**
    1961         * Sets the item label position for all positive values in a series and (if
    1962         * requested) sends a {@link RendererChangeEvent} to all registered
    1963         * listeners.
    1964         *
    1965         * @param series  the series index (zero-based).
    1966         * @param position  the position (<code>null</code> permitted).
    1967         * @param notify  notify registered listeners?
    1968         */
    1969        public void setSeriesPositiveItemLabelPosition(int series,
    1970                                                       ItemLabelPosition position,
    1971                                                       boolean notify) {
    1972            this.positiveItemLabelPositionList.set(series, position);
    1973            if (notify) {
    1974                notifyListeners(new RendererChangeEvent(this));
    1975            }
    1976        }
    1977
    1978        /**
    1979         * Returns the base positive item label position.
    1980         *
    1981         * @return The position (never <code>null</code>).
    1982         */
    1983        public ItemLabelPosition getBasePositiveItemLabelPosition() {
    1984            return this.basePositiveItemLabelPosition;
    1985        }
    1986
    1987        /**
    1988         * Sets the base positive item label position.
    1989         *
    1990         * @param position  the position (<code>null</code> not permitted).
    1991         */
    1992        public void setBasePositiveItemLabelPosition(ItemLabelPosition position) {
    1993            // defer argument checking...
    1994            setBasePositiveItemLabelPosition(position, true);
    1995        }
    1996
    1997        /**
    1998         * Sets the base positive item label position and, if requested, sends a
    1999         * {@link RendererChangeEvent} to all registered listeners.
    2000         *
    2001         * @param position  the position (<code>null</code> not permitted).
    2002         * @param notify  notify registered listeners?
    2003         */
    2004        public void setBasePositiveItemLabelPosition(ItemLabelPosition position,
    2005                                                     boolean notify) {
    2006            if (position == null) {
    2007                throw new IllegalArgumentException("Null 'position' argument.");
    2008            }
    2009            this.basePositiveItemLabelPosition = position;
    2010            if (notify) {
    2011                notifyListeners(new RendererChangeEvent(this));
    2012            }
    2013        }
    2014
    2015        // NEGATIVE ITEM LABEL POSITION...
    2016
    2017        /**
    2018         * Returns the item label position for negative values.  This method can be
    2019         * overridden to provide customisation of the item label position for
    2020         * individual data items.
    2021         *
    2022         * @param row  the row index (zero-based).
    2023         * @param column  the column (zero-based).
    2024         *
    2025         * @return The item label position (never <code>null</code>).
    2026         */
    2027        public ItemLabelPosition getNegativeItemLabelPosition(int row, int column) {
    2028            return getSeriesNegativeItemLabelPosition(row);
    2029        }
    2030
    2031        /**
    2032         * Returns the item label position for negative values in ALL series.
    2033         *
    2034         * @return The item label position (possibly <code>null</code>).
    2035         */
    2036        public ItemLabelPosition getNegativeItemLabelPosition() {
    2037            return this.negativeItemLabelPosition;
    2038        }
    2039
    2040        /**
    2041         * Sets the item label position for negative values in ALL series, and
    2042         * sends a {@link RendererChangeEvent} to all registered listeners.  You
    2043         * need to set this to <code>null</code> to expose the settings for
    2044         * individual series.
    2045         *
    2046         * @param position  the position (<code>null</code> permitted).
    2047         */
    2048        public void setNegativeItemLabelPosition(ItemLabelPosition position) {
    2049            setNegativeItemLabelPosition(position, true);
    2050        }
    2051
    2052        /**
    2053         * Sets the item label position for negative values in ALL series and (if
    2054         * requested) sends a {@link RendererChangeEvent} to all registered
    2055         * listeners.
    2056         *
    2057         * @param position  the position (<code>null</code> permitted).
    2058         * @param notify  notify registered listeners?
    2059         */
    2060        public void setNegativeItemLabelPosition(ItemLabelPosition position,
    2061                                                 boolean notify) {
    2062            this.negativeItemLabelPosition = position;
    2063            if (notify) {
    2064                notifyListeners(new RendererChangeEvent(this));
    2065            }
    2066        }
    2067
    2068        /**
    2069         * Returns the item label position for all negative values in a series.
    2070         *
    2071         * @param series  the series index (zero-based).
    2072         *
    2073         * @return The item label position (never <code>null</code>).
    2074         */
    2075        public ItemLabelPosition getSeriesNegativeItemLabelPosition(int series) {
    2076
    2077            // return the override, if there is one...
    2078            if (this.negativeItemLabelPosition != null) {
    2079                return this.negativeItemLabelPosition;
    2080            }
    2081
    2082            // otherwise look up the position list
    2083            ItemLabelPosition position = (ItemLabelPosition)
    2084                this.negativeItemLabelPositionList.get(series);
    2085            if (position == null) {
    2086                position = this.baseNegativeItemLabelPosition;
    2087            }
    2088            return position;
    2089
    2090        }
    2091
    2092        /**
    2093         * Sets the item label position for negative values in a series and sends a
    2094         * {@link RendererChangeEvent} to all registered listeners.
    2095         *
    2096         * @param series  the series index (zero-based).
    2097         * @param position  the position (<code>null</code> permitted).
    2098         */
    2099        public void setSeriesNegativeItemLabelPosition(int series,
    2100                                                       ItemLabelPosition position) {
    2101            setSeriesNegativeItemLabelPosition(series, position, true);
    2102        }
    2103
    2104        /**
    2105         * Sets the item label position for negative values in a series and (if
    2106         * requested) sends a {@link RendererChangeEvent} to all registered
    2107         * listeners.
    2108         *
    2109         * @param series  the series index (zero-based).
    2110         * @param position  the position (<code>null</code> permitted).
    2111         * @param notify  notify registered listeners?
    2112         */
    2113        public void setSeriesNegativeItemLabelPosition(int series,
    2114                                                       ItemLabelPosition position,
    2115                                                       boolean notify) {
    2116            this.negativeItemLabelPositionList.set(series, position);
    2117            if (notify) {
    2118                notifyListeners(new RendererChangeEvent(this));
    2119            }
    2120        }
    2121
    2122        /**
    2123         * Returns the base item label position for negative values.
    2124         *
    2125         * @return The position (never <code>null</code>).
    2126         */
    2127        public ItemLabelPosition getBaseNegativeItemLabelPosition() {
    2128            return this.baseNegativeItemLabelPosition;
    2129        }
    2130
    2131        /**
    2132         * Sets the base item label position for negative values and sends a
    2133         * {@link RendererChangeEvent} to all registered listeners.
    2134         *
    2135         * @param position  the position (<code>null</code> not permitted).
    2136         */
    2137        public void setBaseNegativeItemLabelPosition(ItemLabelPosition position) {
    2138            setBaseNegativeItemLabelPosition(position, true);
    2139        }
    2140
    2141        /**
    2142         * Sets the base negative item label position and, if requested, sends a
    2143         * {@link RendererChangeEvent} to all registered listeners.
    2144         *
    2145         * @param position  the position (<code>null</code> not permitted).
    2146         * @param notify  notify registered listeners?
    2147         */
    2148        public void setBaseNegativeItemLabelPosition(ItemLabelPosition position,
    2149                                                     boolean notify) {
    2150            if (position == null) {
    2151                throw new IllegalArgumentException("Null 'position' argument.");
    2152            }
    2153            this.baseNegativeItemLabelPosition = position;
    2154            if (notify) {
    2155                notifyListeners(new RendererChangeEvent(this));
    2156            }
    2157        }
    2158
    2159        /**
    2160         * Returns the item label anchor offset.
    2161         *
    2162         * @return The offset.
    2163         */
    2164        public double getItemLabelAnchorOffset() {
    2165            return this.itemLabelAnchorOffset;
    2166        }
    2167
    2168        /**
    2169         * Sets the item label anchor offset.
    2170         *
    2171         * @param offset  the offset.
    2172         */
    2173        public void setItemLabelAnchorOffset(double offset) {
    2174            this.itemLabelAnchorOffset = offset;
    2175            notifyListeners(new RendererChangeEvent(this));
    2176        }
    2177
    2178        /**
    2179         * Returns a boolean that indicates whether or not the specified item
    2180         * should have a chart entity created for it.
    2181         *
    2182         * @param series  the series index.
    2183         * @param item  the item index.
    2184         *
    2185         * @return A boolean.
    2186         */
    2187        public boolean getItemCreateEntity(int series, int item) {
    2188            if (this.createEntities != null) {
    2189                return this.createEntities.booleanValue();
    2190            }
    2191            else {
    2192                Boolean b = getSeriesCreateEntities(series);
    2193                if (b != null) {
    2194                    return b.booleanValue();
    2195                }
    2196                else {
    2197                    return this.baseCreateEntities;
    2198                }
    2199            }
    2200        }
    2201
    2202        /**
    2203         * Returns the flag that controls whether or not chart entities are created
    2204         * for the items in ALL series.  This flag overrides the per series and
    2205         * default settings - you must set it to <code>null</code> if you want the
    2206         * other settings to apply.
    2207         *
    2208         * @return The flag (possibly <code>null</code>).
    2209         */
    2210        public Boolean getCreateEntities() {
    2211            return this.createEntities;
    2212        }
    2213
    2214        /**
    2215         * Sets the flag that controls whether or not chart entities are created
    2216         * for the items in ALL series, and sends a {@link RendererChangeEvent} to
    2217         * all registered listeners.  This flag overrides the per series and
    2218         * default settings - you must set it to <code>null</code> if you want the
    2219         * other settings to apply.
    2220         *
    2221         * @param create  the flag (<code>null</code> permitted).
    2222         */
    2223        public void setCreateEntities(Boolean create) {
    2224             setCreateEntities(create, true);
    2225        }
    2226
    2227        /**
    2228         * Sets the flag that controls whether or not chart entities are created
    2229         * for the items in ALL series, and sends a {@link RendererChangeEvent} to
    2230         * all registered listeners.  This flag overrides the per series and
    2231         * default settings - you must set it to <code>null</code> if you want the
    2232         * other settings to apply.
    2233         *
    2234         * @param create  the flag (<code>null</code> permitted).
    2235         * @param notify  notify listeners?
    2236         */
    2237        public void setCreateEntities(Boolean create, boolean notify) {
    2238            this.createEntities = create;
    2239            if (notify) {
    2240                notifyListeners(new RendererChangeEvent(this));
    2241            }
    2242        }
    2243
    2244        /**
    2245         * Returns the flag that controls whether entities are created for a
    2246         * series.
    2247         *
    2248         * @param series  the series index (zero-based).
    2249         *
    2250         * @return The flag (possibly <code>null</code>).
    2251         */
    2252        public Boolean getSeriesCreateEntities(int series) {
    2253            return this.createEntitiesList.getBoolean(series);
    2254        }
    2255
    2256        /**
    2257         * Sets the flag that controls whether entities are created for a series,
    2258         * and sends a {@link RendererChangeEvent} to all registered listeners.
    2259         *
    2260         * @param series  the series index (zero-based).
    2261         * @param create  the flag (<code>null</code> permitted).
    2262         */
    2263        public void setSeriesCreateEntities(int series, Boolean create) {
    2264            setSeriesCreateEntities(series, create, true);
    2265        }
    2266
    2267        /**
    2268         * Sets the flag that controls whether entities are created for a series
    2269         * and, if requested, sends a {@link RendererChangeEvent} to all registered
    2270         * listeners.
    2271         *
    2272         * @param series  the series index.
    2273         * @param create  the flag (<code>null</code> permitted).
    2274         * @param notify  notify listeners?
    2275         */
    2276        public void setSeriesCreateEntities(int series, Boolean create,
    2277                                            boolean notify) {
    2278            this.createEntitiesList.setBoolean(series, create);
    2279            if (notify) {
    2280                notifyListeners(new RendererChangeEvent(this));
    2281            }
    2282        }
    2283
    2284        /**
    2285         * Returns the base visibility for all series.
    2286         *
    2287         * @return The base visibility.
    2288         */
    2289        public boolean getBaseCreateEntities() {
    2290            return this.baseCreateEntities;
    2291        }
    2292
    2293        /**
    2294         * Sets the base flag that controls whether entities are created
    2295         * for a series, and sends a {@link RendererChangeEvent}
    2296         * to all registered listeners.
    2297         *
    2298         * @param create  the flag.
    2299         */
    2300        public void setBaseCreateEntities(boolean create) {
    2301            // defer argument checking...
    2302            setBaseCreateEntities(create, true);
    2303        }
    2304
    2305        /**
    2306         * Sets the base flag that controls whether entities are created and,
    2307         * if requested, sends a {@link RendererChangeEvent} to all registered
    2308         * listeners.
    2309         *
    2310         * @param create  the visibility.
    2311         * @param notify  notify listeners?
    2312         */
    2313        public void setBaseCreateEntities(boolean create, boolean notify) {
    2314            this.baseCreateEntities = create;
    2315            if (notify) {
    2316                notifyListeners(new RendererChangeEvent(this));
    2317            }
    2318        }
    2319
    2320        /** The adjacent offset. */
    2321        private static final double ADJ = Math.cos(Math.PI / 6.0);
    2322
    2323        /** The opposite offset. */
    2324        private static final double OPP = Math.sin(Math.PI / 6.0);
    2325
    2326        /**
    2327         * Calculates the item label anchor point.
    2328         *
    2329         * @param anchor  the anchor.
    2330         * @param x  the x coordinate.
    2331         * @param y  the y coordinate.
    2332         * @param orientation  the plot orientation.
    2333         *
    2334         * @return The anchor point (never <code>null</code>).
    2335         */
    2336        protected Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor,
    2337                double x, double y, PlotOrientation orientation) {
    2338            Point2D result = null;
    2339            if (anchor == ItemLabelAnchor.CENTER) {
    2340                result = new Point2D.Double(x, y);
    2341            }
    2342            else if (anchor == ItemLabelAnchor.INSIDE1) {
    2343                result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset,
    2344                        y - ADJ * this.itemLabelAnchorOffset);
    2345            }
    2346            else if (anchor == ItemLabelAnchor.INSIDE2) {
    2347                result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset,
    2348                        y - OPP * this.itemLabelAnchorOffset);
    2349            }
    2350            else if (anchor == ItemLabelAnchor.INSIDE3) {
    2351                result = new Point2D.Double(x + this.itemLabelAnchorOffset, y);
    2352            }
    2353            else if (anchor == ItemLabelAnchor.INSIDE4) {
    2354                result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset,
    2355                        y + OPP * this.itemLabelAnchorOffset);
    2356            }
    2357            else if (anchor == ItemLabelAnchor.INSIDE5) {
    2358                result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset,
    2359                        y + ADJ * this.itemLabelAnchorOffset);
    2360            }
    2361            else if (anchor == ItemLabelAnchor.INSIDE6) {
    2362                result = new Point2D.Double(x, y + this.itemLabelAnchorOffset);
    2363            }
    2364            else if (anchor == ItemLabelAnchor.INSIDE7) {
    2365                result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset,
    2366                        y + ADJ * this.itemLabelAnchorOffset);
    2367            }
    2368            else if (anchor == ItemLabelAnchor.INSIDE8) {
    2369                result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset,
    2370                        y + OPP * this.itemLabelAnchorOffset);
    2371            }
    2372            else if (anchor == ItemLabelAnchor.INSIDE9) {
    2373                result = new Point2D.Double(x - this.itemLabelAnchorOffset, y);
    2374            }
    2375            else if (anchor == ItemLabelAnchor.INSIDE10) {
    2376                result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset,
    2377                        y - OPP * this.itemLabelAnchorOffset);
    2378            }
    2379            else if (anchor == ItemLabelAnchor.INSIDE11) {
    2380                result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset,
    2381                        y - ADJ * this.itemLabelAnchorOffset);
    2382            }
    2383            else if (anchor == ItemLabelAnchor.INSIDE12) {
    2384                result = new Point2D.Double(x, y - this.itemLabelAnchorOffset);
    2385            }
    2386            else if (anchor == ItemLabelAnchor.OUTSIDE1) {
    2387                result = new Point2D.Double(
    2388                        x + 2.0 * OPP * this.itemLabelAnchorOffset,
    2389                        y - 2.0 * ADJ * this.itemLabelAnchorOffset);
    2390            }
    2391            else if (anchor == ItemLabelAnchor.OUTSIDE2) {
    2392                result = new Point2D.Double(
    2393                        x + 2.0 * ADJ * this.itemLabelAnchorOffset,
    2394                        y - 2.0 * OPP * this.itemLabelAnchorOffset);
    2395            }
    2396            else if (anchor == ItemLabelAnchor.OUTSIDE3) {
    2397                result = new Point2D.Double(x + 2.0 * this.itemLabelAnchorOffset,
    2398                        y);
    2399            }
    2400            else if (anchor == ItemLabelAnchor.OUTSIDE4) {
    2401                result = new Point2D.Double(
    2402                        x + 2.0 * ADJ * this.itemLabelAnchorOffset,
    2403                        y + 2.0 * OPP * this.itemLabelAnchorOffset);
    2404            }
    2405            else if (anchor == ItemLabelAnchor.OUTSIDE5) {
    2406                result = new Point2D.Double(
    2407                        x + 2.0 * OPP * this.itemLabelAnchorOffset,
    2408                        y + 2.0 * ADJ * this.itemLabelAnchorOffset);
    2409            }
    2410            else if (anchor == ItemLabelAnchor.OUTSIDE6) {
    2411                result = new Point2D.Double(x,
    2412                        y + 2.0 * this.itemLabelAnchorOffset);
    2413            }
    2414            else if (anchor == ItemLabelAnchor.OUTSIDE7) {
    2415                result = new Point2D.Double(
    2416                        x - 2.0 * OPP * this.itemLabelAnchorOffset,
    2417                        y + 2.0 * ADJ * this.itemLabelAnchorOffset);
    2418            }
    2419            else if (anchor == ItemLabelAnchor.OUTSIDE8) {
    2420                result = new Point2D.Double(
    2421                        x - 2.0 * ADJ * this.itemLabelAnchorOffset,
    2422                        y + 2.0 * OPP * this.itemLabelAnchorOffset);
    2423            }
    2424            else if (anchor == ItemLabelAnchor.OUTSIDE9) {
    2425                result = new Point2D.Double(x - 2.0 * this.itemLabelAnchorOffset,
    2426                        y);
    2427            }
    2428            else if (anchor == ItemLabelAnchor.OUTSIDE10) {
    2429                result = new Point2D.Double(
    2430                        x - 2.0 * ADJ * this.itemLabelAnchorOffset,
    2431                        y - 2.0 * OPP * this.itemLabelAnchorOffset);
    2432            }
    2433            else if (anchor == ItemLabelAnchor.OUTSIDE11) {
    2434                result = new Point2D.Double(
    2435                    x - 2.0 * OPP * this.itemLabelAnchorOffset,
    2436                    y - 2.0 * ADJ * this.itemLabelAnchorOffset);
    2437            }
    2438            else if (anchor == ItemLabelAnchor.OUTSIDE12) {
    2439                result = new Point2D.Double(x,
    2440                        y - 2.0 * this.itemLabelAnchorOffset);
    2441            }
    2442            return result;
    2443        }
    2444
    2445        /**
    2446         * Registers an object to receive notification of changes to the renderer.
    2447         *
    2448         * @param listener  the listener (<code>null</code> not permitted).
    2449         */
    2450        public void addChangeListener(RendererChangeListener listener) {
    2451            if (listener == null) {
    2452                throw new IllegalArgumentException("Null 'listener' argument.");
    2453            }
    2454            this.listenerList.add(RendererChangeListener.class, listener);
    2455        }
    2456
    2457        /**
    2458         * Deregisters an object so that it no longer receives
    2459         * notification of changes to the renderer.
    2460         *
    2461         * @param listener  the object (<code>null</code> not permitted).
    2462         */
    2463        public void removeChangeListener(RendererChangeListener listener) {
    2464            if (listener == null) {
    2465                throw new IllegalArgumentException("Null 'listener' argument.");
    2466            }
    2467            this.listenerList.remove(RendererChangeListener.class, listener);
    2468        }
    2469
    2470        /**
    2471         * Returns <code>true</code> if the specified object is registered with
    2472         * the dataset as a listener.  Most applications won't need to call this
    2473         * method, it exists mainly for use by unit testing code.
    2474         *
    2475         * @param listener  the listener.
    2476         *
    2477         * @return A boolean.
    2478         */
    2479        public boolean hasListener(EventListener listener) {
    2480            List list = Arrays.asList(this.listenerList.getListenerList());
    2481            return list.contains(listener);
    2482        }
    2483
    2484        /**
    2485         * Notifies all registered listeners that the renderer has been modified.
    2486         *
    2487         * @param event  information about the change event.
    2488         */
    2489        public void notifyListeners(RendererChangeEvent event) {
    2490
    2491            Object[] ls = this.listenerList.getListenerList();
    2492            for (int i = ls.length - 2; i >= 0; i -= 2) {
    2493                if (ls[i] == RendererChangeListener.class) {
    2494                    ((RendererChangeListener) ls[i + 1]).rendererChanged(event);
    2495                }
    2496            }
    2497
    2498        }
    2499
    2500        /**
    2501         * Tests this renderer for equality with another object.
    2502         *
    2503         * @param obj  the object (<code>null</code> permitted).
    2504         *
    2505         * @return <code>true</code> or <code>false</code>.
    2506         */
    2507        public boolean equals(Object obj) {
    2508            if (obj == this) {
    2509                return true;
    2510            }
    2511            if (!(obj instanceof AbstractRenderer)) {
    2512                return false;
    2513            }
    2514            AbstractRenderer that = (AbstractRenderer) obj;
    2515            if (!ObjectUtilities.equal(this.seriesVisible, that.seriesVisible)) {
    2516                return false;
    2517            }
    2518            if (!this.seriesVisibleList.equals(that.seriesVisibleList)) {
    2519                return false;
    2520            }
    2521            if (this.baseSeriesVisible != that.baseSeriesVisible) {
    2522                return false;
    2523            }
    2524            if (!ObjectUtilities.equal(this.seriesVisibleInLegend,
    2525                    that.seriesVisibleInLegend)) {
    2526                return false;
    2527            }
    2528            if (!this.seriesVisibleInLegendList.equals(
    2529                    that.seriesVisibleInLegendList)) {
    2530                return false;
    2531            }
    2532            if (this.baseSeriesVisibleInLegend != that.baseSeriesVisibleInLegend) {
    2533                return false;
    2534            }
    2535            if (!PaintUtilities.equal(this.paint, that.paint)) {
    2536                return false;
    2537            }
    2538            if (!ObjectUtilities.equal(this.paintList, that.paintList)) {
    2539                return false;
    2540            }
    2541            if (!PaintUtilities.equal(this.basePaint, that.basePaint)) {
    2542                return false;
    2543            }
    2544            if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
    2545                return false;
    2546            }
    2547            if (!ObjectUtilities.equal(this.fillPaintList, that.fillPaintList)) {
    2548                return false;
    2549            }
    2550            if (!PaintUtilities.equal(this.baseFillPaint, that.baseFillPaint)) {
    2551                return false;
    2552            }
    2553            if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
    2554                return false;
    2555            }
    2556            if (!ObjectUtilities.equal(this.outlinePaintList,
    2557                    that.outlinePaintList)) {
    2558                return false;
    2559            }
    2560            if (!PaintUtilities.equal(this.baseOutlinePaint,
    2561                    that.baseOutlinePaint)) {
    2562                return false;
    2563            }
    2564            if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
    2565                return false;
    2566            }
    2567            if (!ObjectUtilities.equal(this.strokeList, that.strokeList)) {
    2568                return false;
    2569            }
    2570            if (!ObjectUtilities.equal(this.baseStroke, that.baseStroke)) {
    2571                return false;
    2572            }
    2573            if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
    2574                return false;
    2575            }
    2576            if (!ObjectUtilities.equal(
    2577                this.outlineStrokeList, that.outlineStrokeList
    2578            )) {
    2579                return false;
    2580            }
    2581            if (!ObjectUtilities.equal(
    2582                this.baseOutlineStroke, that.baseOutlineStroke)
    2583            ) {
    2584                return false;
    2585            }
    2586            if (!ObjectUtilities.equal(this.shape, that.shape)) {
    2587                return false;
    2588            }
    2589            if (!ObjectUtilities.equal(this.shapeList, that.shapeList)) {
    2590                return false;
    2591            }
    2592            if (!ObjectUtilities.equal(this.baseShape, that.baseShape)) {
    2593                return false;
    2594            }
    2595            if (!ObjectUtilities.equal(
    2596                this.itemLabelsVisible, that.itemLabelsVisible
    2597            )) {
    2598                return false;
    2599            }
    2600            if (!ObjectUtilities.equal(
    2601                this.itemLabelsVisibleList, that.itemLabelsVisibleList)
    2602            ) {
    2603                return false;
    2604            }
    2605            if (!ObjectUtilities.equal(
    2606                this.baseItemLabelsVisible, that.baseItemLabelsVisible
    2607            )) {
    2608                return false;
    2609            }
    2610            if (!ObjectUtilities.equal(this.itemLabelFont, that.itemLabelFont)) {
    2611                return false;
    2612            }
    2613            if (!ObjectUtilities.equal(
    2614                this.itemLabelFontList, that.itemLabelFontList
    2615            )) {
    2616                return false;
    2617            }
    2618            if (!ObjectUtilities.equal(
    2619                this.baseItemLabelFont, that.baseItemLabelFont
    2620            )) {
    2621                return false;
    2622            }
    2623
    2624            if (!PaintUtilities.equal(this.itemLabelPaint, that.itemLabelPaint)) {
    2625                return false;
    2626            }
    2627            if (!ObjectUtilities.equal(
    2628                this.itemLabelPaintList, that.itemLabelPaintList
    2629            )) {
    2630                return false;
    2631            }
    2632            if (!PaintUtilities.equal(
    2633                this.baseItemLabelPaint, that.baseItemLabelPaint
    2634            )) {
    2635                return false;
    2636            }
    2637
    2638            if (!ObjectUtilities.equal(
    2639                    this.positiveItemLabelPosition, that.positiveItemLabelPosition
    2640                )) {
    2641                return false;
    2642            }
    2643            if (!ObjectUtilities.equal(
    2644                    this.positiveItemLabelPositionList,
    2645                    that.positiveItemLabelPositionList
    2646                )) {
    2647                return false;
    2648            }
    2649            if (!ObjectUtilities.equal(
    2650                    this.basePositiveItemLabelPosition,
    2651                    that.basePositiveItemLabelPosition
    2652                )) {
    2653                return false;
    2654            }
    2655
    2656            if (!ObjectUtilities.equal(
    2657                    this.negativeItemLabelPosition, that.negativeItemLabelPosition
    2658                )) {
    2659                return false;
    2660            }
    2661            if (!ObjectUtilities.equal(
    2662                    this.negativeItemLabelPositionList,
    2663                    that.negativeItemLabelPositionList
    2664                )) {
    2665                return false;
    2666            }
    2667            if (!ObjectUtilities.equal(
    2668                    this.baseNegativeItemLabelPosition,
    2669                    that.baseNegativeItemLabelPosition
    2670                )) {
    2671                return false;
    2672            }
    2673            if (this.itemLabelAnchorOffset != that.itemLabelAnchorOffset) {
    2674                return false;
    2675            }
    2676            if (!ObjectUtilities.equal(this.createEntities, that.createEntities)) {
    2677                return false;
    2678            }
    2679            if (!ObjectUtilities.equal(this.createEntitiesList,
    2680                    that.createEntitiesList)) {
    2681                return false;
    2682            }
    2683            if (this.baseCreateEntities != that.baseCreateEntities) {
    2684                return false;
    2685            }
    2686            return true;
    2687        }
    2688
    2689        /**
    2690         * Returns a hashcode for the renderer.
    2691         *
    2692         * @return The hashcode.
    2693         */
    2694        public int hashCode() {
    2695            int result = 193;
    2696            result = 37 * result + ObjectUtilities.hashCode(this.stroke);
    2697            result = 37 * result + ObjectUtilities.hashCode(this.baseStroke);
    2698            result = 37 * result + ObjectUtilities.hashCode(this.outlineStroke);
    2699            result = 37 * result + ObjectUtilities.hashCode(this.baseOutlineStroke);
    2700            return result;
    2701        }
    2702
    2703        /**
    2704         * Returns an independent copy of the renderer.
    2705         *
    2706         * @return A clone.
    2707         *
    2708         * @throws CloneNotSupportedException if some component of the renderer
    2709         *         does not support cloning.
    2710         */
    2711        protected Object clone() throws CloneNotSupportedException {
    2712            AbstractRenderer clone = (AbstractRenderer) super.clone();
    2713
    2714            // 'paint' : immutable, no need to clone reference
    2715            if (this.paintList != null) {
    2716                clone.paintList = (PaintList) this.paintList.clone();
    2717            }
    2718            // 'basePaint' : immutable, no need to clone reference
    2719
    2720            if (this.fillPaintList != null) {
    2721                clone.fillPaintList = (PaintList) this.fillPaintList.clone();
    2722            }
    2723            // 'outlinePaint' : immutable, no need to clone reference
    2724            if (this.outlinePaintList != null) {
    2725                clone.outlinePaintList = (PaintList) this.outlinePaintList.clone();
    2726            }
    2727            // 'baseOutlinePaint' : immutable, no need to clone reference
    2728
    2729            // 'stroke' : immutable, no need to clone reference
    2730            if (this.strokeList != null) {
    2731                clone.strokeList = (StrokeList) this.strokeList.clone();
    2732            }
    2733            // 'baseStroke' : immutable, no need to clone reference
    2734
    2735            // 'outlineStroke' : immutable, no need to clone reference
    2736            if (this.outlineStrokeList != null) {
    2737                clone.outlineStrokeList
    2738                    = (StrokeList) this.outlineStrokeList.clone();
    2739            }
    2740            // 'baseOutlineStroke' : immutable, no need to clone reference
    2741
    2742            if (this.shape != null) {
    2743                clone.shape = ShapeUtilities.clone(this.shape);
    2744            }
    2745            if (this.baseShape != null) {
    2746                clone.baseShape = ShapeUtilities.clone(this.baseShape);
    2747            }
    2748
    2749            // 'itemLabelsVisible' : immutable, no need to clone reference
    2750            if (this.itemLabelsVisibleList != null) {
    2751                clone.itemLabelsVisibleList
    2752                    = (BooleanList) this.itemLabelsVisibleList.clone();
    2753            }
    2754            // 'basePaint' : immutable, no need to clone reference
    2755
    2756            // 'itemLabelFont' : immutable, no need to clone reference
    2757            if (this.itemLabelFontList != null) {
    2758                clone.itemLabelFontList
    2759                    = (ObjectList) this.itemLabelFontList.clone();
    2760            }
    2761            // 'baseItemLabelFont' : immutable, no need to clone reference
    2762
    2763            // 'itemLabelPaint' : immutable, no need to clone reference
    2764            if (this.itemLabelPaintList != null) {
    2765                clone.itemLabelPaintList
    2766                    = (PaintList) this.itemLabelPaintList.clone();
    2767            }
    2768            // 'baseItemLabelPaint' : immutable, no need to clone reference
    2769
    2770            // 'postiveItemLabelAnchor' : immutable, no need to clone reference
    2771            if (this.positiveItemLabelPositionList != null) {
    2772                clone.positiveItemLabelPositionList
    2773                    = (ObjectList) this.positiveItemLabelPositionList.clone();
    2774            }
    2775            // 'baseItemLabelAnchor' : immutable, no need to clone reference
    2776
    2777            // 'negativeItemLabelAnchor' : immutable, no need to clone reference
    2778            if (this.negativeItemLabelPositionList != null) {
    2779                clone.negativeItemLabelPositionList
    2780                    = (ObjectList) this.negativeItemLabelPositionList.clone();
    2781            }
    2782            // 'baseNegativeItemLabelAnchor' : immutable, no need to clone reference
    2783
    2784            return clone;
    2785        }
    2786
    2787        /**
    2788         * Provides serialization support.
    2789         *
    2790         * @param stream  the output stream.
    2791         *
    2792         * @throws IOException  if there is an I/O error.
    2793         */
    2794        private void writeObject(ObjectOutputStream stream) throws IOException {
    2795
    2796            stream.defaultWriteObject();
    2797            SerialUtilities.writePaint(this.paint, stream);
    2798            SerialUtilities.writePaint(this.basePaint, stream);
    2799            SerialUtilities.writePaint(this.fillPaint, stream);
    2800            SerialUtilities.writePaint(this.baseFillPaint, stream);
    2801            SerialUtilities.writePaint(this.outlinePaint, stream);
    2802            SerialUtilities.writePaint(this.baseOutlinePaint, stream);
    2803            SerialUtilities.writeStroke(this.stroke, stream);
    2804            SerialUtilities.writeStroke(this.baseStroke, stream);
    2805            SerialUtilities.writeStroke(this.outlineStroke, stream);
    2806            SerialUtilities.writeStroke(this.baseOutlineStroke, stream);
    2807            SerialUtilities.writeShape(this.shape, stream);
    2808            SerialUtilities.writeShape(this.baseShape, stream);
    2809            SerialUtilities.writePaint(this.itemLabelPaint, stream);
    2810            SerialUtilities.writePaint(this.baseItemLabelPaint, stream);
    2811
    2812        }
    2813
    2814        /**
    2815         * Provides serialization support.
    2816         *
    2817         * @param stream  the input stream.
    2818         *
    2819         * @throws IOException  if there is an I/O error.
    2820         * @throws ClassNotFoundException  if there is a classpath problem.
    2821         */
    2822        private void readObject(ObjectInputStream stream)
    2823            throws IOException, ClassNotFoundException {
    2824
    2825            stream.defaultReadObject();
    2826            this.paint = SerialUtilities.readPaint(stream);
    2827            this.basePaint = SerialUtilities.readPaint(stream);
    2828            this.fillPaint = SerialUtilities.readPaint(stream);
    2829            this.baseFillPaint = SerialUtilities.readPaint(stream);
    2830            this.outlinePaint = SerialUtilities.readPaint(stream);
    2831            this.baseOutlinePaint = SerialUtilities.readPaint(stream);
    2832            this.stroke = SerialUtilities.readStroke(stream);
    2833            this.baseStroke = SerialUtilities.readStroke(stream);
    2834            this.outlineStroke = SerialUtilities.readStroke(stream);
    2835            this.baseOutlineStroke = SerialUtilities.readStroke(stream);
    2836            this.shape = SerialUtilities.readShape(stream);
    2837            this.baseShape = SerialUtilities.readShape(stream);
    2838            this.itemLabelPaint = SerialUtilities.readPaint(stream);
    2839            this.baseItemLabelPaint = SerialUtilities.readPaint(stream);
    2840
    2841            // listeners are not restored automatically, but storage must be
    2842            // provided...
    2843            this.listenerList = new EventListenerList();
    2844
    2845        }
    2846
    2847    }