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