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