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