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     * LegendItem.java
029     * ---------------
030     * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   Andrzej Porebski;
034     *                   David Li;
035     *                   Wolfgang Irler;
036     *                   Luke Quinane;
037     *
038     * $Id: LegendItem.java,v 1.9.2.7 2007/05/18 10:28:17 mungady Exp $
039     *
040     * Changes (from 2-Oct-2002)
041     * -------------------------
042     * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
043     * 17-Jan-2003 : Dropped outlineStroke attribute (DG);
044     * 08-Oct-2003 : Applied patch for displaying series line style, contributed by
045     *               Luke Quinane (DG);
046     * 21-Jan-2004 : Added the shapeFilled flag (DG);
047     * 04-Jun-2004 : Added equals() method, implemented Serializable (DG);
048     * 25-Nov-2004 : Changes required by new LegendTitle implementation (DG);
049     * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0 
050     *               release (DG);
051     * 20-Apr-2005 : Added tooltip and URL text (DG);
052     * 28-Nov-2005 : Separated constructors for AttributedString labels (DG);
053     * 10-Dec-2005 : Fixed serialization bug (1377239) (DG);
054     * ------------- JFREECHART 1.0.x ---------------------------------------------
055     * 20-Jul-2006 : Added dataset and series index fields (DG);
056     * 13-Dec-2006 : Added fillPaintTransformer attribute (DG);
057     * 18-May-2007 : Added dataset and seriesKey fields (DG);
058     *
059     */
060    
061    package org.jfree.chart;
062    
063    import java.awt.BasicStroke;
064    import java.awt.Color;
065    import java.awt.Paint;
066    import java.awt.Shape;
067    import java.awt.Stroke;
068    import java.awt.geom.Line2D;
069    import java.io.IOException;
070    import java.io.ObjectInputStream;
071    import java.io.ObjectOutputStream;
072    import java.io.Serializable;
073    import java.text.AttributedString;
074    import java.text.CharacterIterator;
075    
076    import org.jfree.data.general.Dataset;
077    import org.jfree.io.SerialUtilities;
078    import org.jfree.ui.GradientPaintTransformer;
079    import org.jfree.ui.StandardGradientPaintTransformer;
080    import org.jfree.util.AttributedStringUtilities;
081    import org.jfree.util.ObjectUtilities;
082    import org.jfree.util.ShapeUtilities;
083    
084    /**
085     * A temporary storage object for recording the properties of a legend item, 
086     * without any consideration for layout issues. 
087     */
088    public class LegendItem implements Serializable {
089    
090        /** For serialization. */
091        private static final long serialVersionUID = -797214582948827144L;
092        
093        /**
094         * The dataset.
095         * 
096         * @since 1.0.6
097         */
098        private Dataset dataset;
099        
100        /**
101         * The series key.
102         * 
103         * @since 1.0.6
104         */
105        private Comparable seriesKey;
106        
107        /** The dataset index. */
108        private int datasetIndex;
109        
110        /** The series index. */
111        private int series;
112        
113        /** The label. */
114        private String label;
115        
116        /** The attributed label (if null, fall back to the regular label). */
117        private transient AttributedString attributedLabel;
118    
119        /** 
120         * The description (not currently used - could be displayed as a tool tip). 
121         */
122        private String description;
123        
124        /** The tool tip text. */
125        private String toolTipText;
126        
127        /** The url text. */
128        private String urlText;
129    
130        /** A flag that controls whether or not the shape is visible. */
131        private boolean shapeVisible;
132        
133        /** The shape. */
134        private transient Shape shape;
135        
136        /** A flag that controls whether or not the shape is filled. */
137        private boolean shapeFilled;
138    
139        /** The paint. */
140        private transient Paint fillPaint;
141        
142        /** 
143         * A gradient paint transformer. 
144         * 
145         * @since 1.0.4
146         */
147        private GradientPaintTransformer fillPaintTransformer;
148        
149        /** A flag that controls whether or not the shape outline is visible. */
150        private boolean shapeOutlineVisible;
151        
152        /** The outline paint. */
153        private transient Paint outlinePaint;
154        
155        /** The outline stroke. */
156        private transient Stroke outlineStroke;
157    
158        /** A flag that controls whether or not the line is visible. */
159        private boolean lineVisible;
160        
161        /** The line. */
162        private transient Shape line;
163        
164        /** The stroke. */
165        private transient Stroke lineStroke;
166        
167        /** The line paint. */
168        private transient Paint linePaint;
169    
170        /**
171         * The shape must be non-null for a LegendItem - if no shape is required,
172         * use this.
173         */
174        private static final Shape UNUSED_SHAPE = new Line2D.Float();
175        
176        /**
177         * The stroke must be non-null for a LegendItem - if no stroke is required,
178         * use this.
179         */
180        private static final Stroke UNUSED_STROKE = new BasicStroke(0.0f);
181        
182        /**
183         * Creates a legend item with a filled shape.  The shape is not outlined,
184         * and no line is visible.
185         * 
186         * @param label  the label (<code>null</code> not permitted).
187         * @param description  the description (<code>null</code> permitted).
188         * @param toolTipText  the tool tip text (<code>null</code> permitted).
189         * @param urlText  the URL text (<code>null</code> permitted).
190         * @param shape  the shape (<code>null</code> not permitted).
191         * @param fillPaint  the paint used to fill the shape (<code>null</code>
192         *                   not permitted).
193         */
194        public LegendItem(String label, String description, 
195                          String toolTipText, String urlText, 
196                          Shape shape, Paint fillPaint) {
197            
198            this(label, description, toolTipText, urlText, 
199                    /* shape visible = */ true, shape, 
200                    /* shape filled = */ true, fillPaint, 
201                    /* shape outlined */ false, Color.black, UNUSED_STROKE,
202                    /* line visible */ false, UNUSED_SHAPE, UNUSED_STROKE,
203                    Color.black);
204    
205        }
206        
207        /**
208         * Creates a legend item with a filled and outlined shape.
209         * 
210         * @param label  the label (<code>null</code> not permitted).
211         * @param description  the description (<code>null</code> permitted).
212         * @param toolTipText  the tool tip text (<code>null</code> permitted).
213         * @param urlText  the URL text (<code>null</code> permitted).
214         * @param shape  the shape (<code>null</code> not permitted).
215         * @param fillPaint  the paint used to fill the shape (<code>null</code>
216         *                   not permitted).
217         * @param outlineStroke  the outline stroke (<code>null</code> not 
218         *                       permitted).
219         * @param outlinePaint  the outline paint (<code>null</code> not 
220         *                      permitted).
221         */
222        public LegendItem(String label, String description, 
223                          String toolTipText, String urlText, 
224                          Shape shape, Paint fillPaint, 
225                          Stroke outlineStroke, Paint outlinePaint) {
226            
227            this(label, description, toolTipText, urlText,
228                    /* shape visible = */ true, shape, 
229                    /* shape filled = */ true, fillPaint, 
230                    /* shape outlined = */ true, outlinePaint, outlineStroke,
231                    /* line visible */ false, UNUSED_SHAPE, UNUSED_STROKE,
232                    Color.black);
233    
234        }
235        
236        /**
237         * Creates a legend item using a line.
238         * 
239         * @param label  the label (<code>null</code> not permitted).
240         * @param description  the description (<code>null</code> permitted).
241         * @param toolTipText  the tool tip text (<code>null</code> permitted).
242         * @param urlText  the URL text (<code>null</code> permitted).
243         * @param line  the line (<code>null</code> not permitted).
244         * @param lineStroke  the line stroke (<code>null</code> not permitted).
245         * @param linePaint  the line paint (<code>null</code> not permitted).
246         */
247        public LegendItem(String label, String description, 
248                          String toolTipText, String urlText, 
249                          Shape line, Stroke lineStroke, Paint linePaint) {
250            
251            this(label, description, toolTipText, urlText,
252                    /* shape visible = */ false, UNUSED_SHAPE,
253                    /* shape filled = */ false, Color.black,
254                    /* shape outlined = */ false, Color.black, UNUSED_STROKE,
255                    /* line visible = */ true, line, lineStroke, linePaint);
256        }
257        
258        /**
259         * Creates a new legend item.
260         *
261         * @param label  the label (<code>null</code> not permitted).
262         * @param description  the description (not currently used, 
263         *        <code>null</code> permitted).
264         * @param toolTipText  the tool tip text (<code>null</code> permitted).
265         * @param urlText  the URL text (<code>null</code> permitted).
266         * @param shapeVisible  a flag that controls whether or not the shape is 
267         *                      displayed.
268         * @param shape  the shape (<code>null</code> permitted).
269         * @param shapeFilled  a flag that controls whether or not the shape is 
270         *                     filled.
271         * @param fillPaint  the fill paint (<code>null</code> not permitted).
272         * @param shapeOutlineVisible  a flag that controls whether or not the 
273         *                             shape is outlined.
274         * @param outlinePaint  the outline paint (<code>null</code> not permitted).
275         * @param outlineStroke  the outline stroke (<code>null</code> not 
276         *                       permitted).
277         * @param lineVisible  a flag that controls whether or not the line is 
278         *                     visible.
279         * @param line  the line.
280         * @param lineStroke  the stroke (<code>null</code> not permitted).
281         * @param linePaint  the line paint (<code>null</code> not permitted).
282         */
283        public LegendItem(String label, String description,
284                          String toolTipText, String urlText,
285                          boolean shapeVisible, Shape shape,
286                          boolean shapeFilled, Paint fillPaint, 
287                          boolean shapeOutlineVisible, Paint outlinePaint,
288                          Stroke outlineStroke,
289                          boolean lineVisible, Shape line,
290                          Stroke lineStroke, Paint linePaint) {
291            
292            if (label == null) {
293                throw new IllegalArgumentException("Null 'label' argument.");   
294            }
295            if (fillPaint == null) {
296                throw new IllegalArgumentException("Null 'fillPaint' argument.");   
297            }
298            if (lineStroke == null) {
299                throw new IllegalArgumentException("Null 'lineStroke' argument.");
300            }
301            if (outlinePaint == null) {
302                throw new IllegalArgumentException("Null 'outlinePaint' argument.");
303            }
304            if (outlineStroke == null) {
305                throw new IllegalArgumentException(
306                        "Null 'outlineStroke' argument.");   
307            }
308            this.label = label;
309            this.attributedLabel = null;
310            this.description = description;
311            this.shapeVisible = shapeVisible;
312            this.shape = shape;
313            this.shapeFilled = shapeFilled;
314            this.fillPaint = fillPaint;
315            this.fillPaintTransformer = new StandardGradientPaintTransformer();
316            this.shapeOutlineVisible = shapeOutlineVisible;
317            this.outlinePaint = outlinePaint;
318            this.outlineStroke = outlineStroke;
319            this.lineVisible = lineVisible;
320            this.line = line;
321            this.lineStroke = lineStroke;
322            this.linePaint = linePaint;
323            this.toolTipText = toolTipText;
324            this.urlText = urlText;
325        }
326        
327        /**
328         * Creates a legend item with a filled shape.  The shape is not outlined,
329         * and no line is visible.
330         * 
331         * @param label  the label (<code>null</code> not permitted).
332         * @param description  the description (<code>null</code> permitted).
333         * @param toolTipText  the tool tip text (<code>null</code> permitted).
334         * @param urlText  the URL text (<code>null</code> permitted).
335         * @param shape  the shape (<code>null</code> not permitted).
336         * @param fillPaint  the paint used to fill the shape (<code>null</code>
337         *                   not permitted).
338         */
339        public LegendItem(AttributedString label, String description, 
340                          String toolTipText, String urlText, 
341                          Shape shape, Paint fillPaint) {
342            
343            this(label, description, toolTipText, urlText, 
344                    /* shape visible = */ true, shape,
345                    /* shape filled = */ true, fillPaint,
346                    /* shape outlined = */ false, Color.black, UNUSED_STROKE,
347                    /* line visible = */ false, UNUSED_SHAPE, UNUSED_STROKE,
348                    Color.black);
349            
350        }
351        
352        /**
353         * Creates a legend item with a filled and outlined shape.
354         * 
355         * @param label  the label (<code>null</code> not permitted).
356         * @param description  the description (<code>null</code> permitted).
357         * @param toolTipText  the tool tip text (<code>null</code> permitted).
358         * @param urlText  the URL text (<code>null</code> permitted).
359         * @param shape  the shape (<code>null</code> not permitted).
360         * @param fillPaint  the paint used to fill the shape (<code>null</code>
361         *                   not permitted).
362         * @param outlineStroke  the outline stroke (<code>null</code> not 
363         *                       permitted).
364         * @param outlinePaint  the outline paint (<code>null</code> not 
365         *                      permitted).
366         */
367        public LegendItem(AttributedString label, String description, 
368                          String toolTipText, String urlText, 
369                          Shape shape, Paint fillPaint, 
370                          Stroke outlineStroke, Paint outlinePaint) {
371            
372            this(label, description, toolTipText, urlText,
373                    /* shape visible = */ true, shape,
374                    /* shape filled = */ true, fillPaint,
375                    /* shape outlined = */ true, outlinePaint, outlineStroke,
376                    /* line visible = */ false, UNUSED_SHAPE, UNUSED_STROKE,
377                    Color.black);
378        }
379        
380        /**
381         * Creates a legend item using a line.
382         * 
383         * @param label  the label (<code>null</code> not permitted).
384         * @param description  the description (<code>null</code> permitted).
385         * @param toolTipText  the tool tip text (<code>null</code> permitted).
386         * @param urlText  the URL text (<code>null</code> permitted).
387         * @param line  the line (<code>null</code> not permitted).
388         * @param lineStroke  the line stroke (<code>null</code> not permitted).
389         * @param linePaint  the line paint (<code>null</code> not permitted).
390         */
391        public LegendItem(AttributedString label, String description, 
392                          String toolTipText, String urlText, 
393                          Shape line, Stroke lineStroke, Paint linePaint) {
394            
395            this(label, description, toolTipText, urlText,
396                    /* shape visible = */ false, UNUSED_SHAPE,
397                    /* shape filled = */ false, Color.black,
398                    /* shape outlined = */ false, Color.black, UNUSED_STROKE,
399                    /* line visible = */ true, line, lineStroke, linePaint
400            );
401        }
402        
403        /**
404         * Creates a new legend item.
405         *
406         * @param label  the label (<code>null</code> not permitted).
407         * @param description  the description (not currently used, 
408         *        <code>null</code> permitted).
409         * @param toolTipText  the tool tip text (<code>null</code> permitted).
410         * @param urlText  the URL text (<code>null</code> permitted).
411         * @param shapeVisible  a flag that controls whether or not the shape is 
412         *                      displayed.
413         * @param shape  the shape (<code>null</code> permitted).
414         * @param shapeFilled  a flag that controls whether or not the shape is 
415         *                     filled.
416         * @param fillPaint  the fill paint (<code>null</code> not permitted).
417         * @param shapeOutlineVisible  a flag that controls whether or not the 
418         *                             shape is outlined.
419         * @param outlinePaint  the outline paint (<code>null</code> not permitted).
420         * @param outlineStroke  the outline stroke (<code>null</code> not 
421         *                       permitted).
422         * @param lineVisible  a flag that controls whether or not the line is 
423         *                     visible.
424         * @param line  the line.
425         * @param lineStroke  the stroke (<code>null</code> not permitted).
426         * @param linePaint  the line paint (<code>null</code> not permitted).
427         */
428        public LegendItem(AttributedString label, String description,
429                          String toolTipText, String urlText,
430                          boolean shapeVisible, Shape shape,
431                          boolean shapeFilled, Paint fillPaint, 
432                          boolean shapeOutlineVisible, Paint outlinePaint,
433                          Stroke outlineStroke,
434                          boolean lineVisible, Shape line, Stroke lineStroke,
435                          Paint linePaint) {
436            
437            if (label == null) {
438                throw new IllegalArgumentException("Null 'label' argument.");   
439            }
440            if (fillPaint == null) {
441                throw new IllegalArgumentException("Null 'fillPaint' argument.");   
442            }
443            if (lineStroke == null) {
444                throw new IllegalArgumentException("Null 'lineStroke' argument.");
445            }
446            if (outlinePaint == null) {
447                throw new IllegalArgumentException("Null 'outlinePaint' argument.");
448            }
449            if (outlineStroke == null) {
450                throw new IllegalArgumentException(
451                    "Null 'outlineStroke' argument.");   
452            }
453            this.label = characterIteratorToString(label.getIterator());
454            this.attributedLabel = label;
455            this.description = description;
456            this.shapeVisible = shapeVisible;
457            this.shape = shape;
458            this.shapeFilled = shapeFilled;
459            this.fillPaint = fillPaint;
460            this.shapeOutlineVisible = shapeOutlineVisible;
461            this.outlinePaint = outlinePaint;
462            this.outlineStroke = outlineStroke;
463            this.lineVisible = lineVisible;
464            this.line = line;
465            this.lineStroke = lineStroke;
466            this.linePaint = linePaint;
467            this.toolTipText = toolTipText;
468            this.urlText = urlText;
469        }
470    
471        /**
472         * Returns a string containing the characters from the given iterator.
473         * 
474         * @param iterator  the iterator (<code>null</code> not permitted).
475         * 
476         * @return A string.
477         */
478        private String characterIteratorToString(CharacterIterator iterator) {
479            int endIndex = iterator.getEndIndex();
480            int beginIndex = iterator.getBeginIndex();
481            int count = endIndex - beginIndex;
482            if (count <= 0) {
483                return "";
484            }
485            char[] chars = new char[count];
486            int i = 0;
487            char c = iterator.first();
488            while (c != CharacterIterator.DONE) {
489                chars[i] = c;
490                i++;
491                c = iterator.next();
492            }
493            return new String(chars);
494        }
495        
496        /**
497         * Returns the dataset.
498         * 
499         * @return The dataset.
500         * 
501         * @since 1.0.6
502         * 
503         * @see #setDatasetIndex(int)
504         */
505        public Dataset getDataset() {
506            return this.dataset;
507        }
508        
509        /**
510         * Sets the dataset.
511         * 
512         * @param dataset  the dataset.
513         * 
514         * @since 1.0.6
515         */
516        public void setDataset(Dataset dataset) {
517            this.dataset = dataset;
518        }
519        
520        /**
521         * Returns the dataset index for this legend item.
522         * 
523         * @return The dataset index.
524         * 
525         * @since 1.0.2
526         * 
527         * @see #setDatasetIndex(int)
528         * @see #getDataset()
529         */
530        public int getDatasetIndex() {
531            return this.datasetIndex;
532        }
533        
534        /**
535         * Sets the dataset index for this legend item.
536         * 
537         * @param index  the index.
538         * 
539         * @since 1.0.2
540         * 
541         * @see #getDatasetIndex()
542         */
543        public void setDatasetIndex(int index) {
544            this.datasetIndex = index;
545        }
546        
547        /**
548         * Returns the series key.
549         * 
550         * @return The series key.
551         * 
552         * @since 1.0.6
553         * 
554         * @see #setSeriesKey(Comparable)
555         */
556        public Comparable getSeriesKey() {
557            return this.seriesKey;
558        }
559        
560        /**
561         * Sets the series key.
562         * 
563         * @param key  the series key.
564         * 
565         * @since 1.0.6
566         */
567        public void setSeriesKey(Comparable key) {
568            this.seriesKey = key;
569        }
570        
571        /**
572         * Returns the series index for this legend item.
573         * 
574         * @return The series index.
575         * 
576         * @since 1.0.2
577         */
578        public int getSeriesIndex() {
579            return this.series;
580        }
581        
582        /**
583         * Sets the series index for this legend item.
584         * 
585         * @param index  the index.
586         * 
587         * @since 1.0.2
588         */
589        public void setSeriesIndex(int index) {
590            this.series = index;
591        }
592        
593        /**
594         * Returns the label.
595         *
596         * @return The label (never <code>null</code>).
597         */
598        public String getLabel() {
599            return this.label;
600        }
601    
602        /**
603         * Returns the attributed label.
604         *
605         * @return The attributed label (possibly <code>null</code>).
606         */
607        public AttributedString getAttributedLabel() {
608            return this.attributedLabel;
609        }
610    
611        /**
612         * Returns the description for the legend item.
613         * 
614         * @return The description.
615         */
616        public String getDescription() {
617            return this.description;   
618        }
619        
620        /**
621         * Returns the tool tip text.
622         * 
623         * @return The tool tip text (possibly <code>null</code>).
624         */
625        public String getToolTipText() {
626            return this.toolTipText;   
627        }
628        
629        /**
630         * Returns the URL text.
631         * 
632         * @return The URL text (possibly <code>null</code>).
633         */
634        public String getURLText() {
635            return this.urlText; 
636        }
637        
638        /**
639         * Returns a flag that indicates whether or not the shape is visible.
640         * 
641         * @return A boolean.
642         */
643        public boolean isShapeVisible() {
644            return this.shapeVisible;
645        }
646        
647        /**
648         * Returns the shape used to label the series represented by this legend 
649         * item.
650         *
651         * @return The shape (never <code>null</code>).
652         */
653        public Shape getShape() {
654            return this.shape;
655        }
656        
657        /**
658         * Returns a flag that controls whether or not the shape is filled.
659         * 
660         * @return A boolean.
661         */
662        public boolean isShapeFilled() {
663            return this.shapeFilled;
664        }
665    
666        /**
667         * Returns the fill paint.
668         *
669         * @return The fill paint (never <code>null</code>).
670         */
671        public Paint getFillPaint() {
672            return this.fillPaint;
673        }
674    
675        /**
676         * Returns the flag that controls whether or not the shape outline
677         * is visible.
678         * 
679         * @return A boolean.
680         */
681        public boolean isShapeOutlineVisible() {
682            return this.shapeOutlineVisible;
683        }
684        
685        /**
686         * Returns the line stroke for the series.
687         *
688         * @return The stroke (never <code>null</code>).
689         */
690        public Stroke getLineStroke() {
691            return this.lineStroke;
692        }
693        
694        /**
695         * Returns the paint used for lines.
696         * 
697         * @return The paint.
698         */
699        public Paint getLinePaint() {
700            return this.linePaint;
701        }
702        
703        /**
704         * Returns the outline paint.
705         *
706         * @return The outline paint (never <code>null</code>).
707         */
708        public Paint getOutlinePaint() {
709            return this.outlinePaint;
710        }
711    
712        /**
713         * Returns the outline stroke.
714         *
715         * @return The outline stroke (never <code>null</code>).
716         */
717        public Stroke getOutlineStroke() {
718            return this.outlineStroke;
719        }
720        
721        /**
722         * Returns a flag that indicates whether or not the line is visible.
723         * 
724         * @return A boolean.
725         */
726        public boolean isLineVisible() {
727            return this.lineVisible;
728        }
729        
730        /**
731         * Returns the line.
732         * 
733         * @return The line.
734         */
735        public Shape getLine() {
736            return this.line;
737        }
738        
739        /**
740         * Returns the transformer used when the fill paint is an instance of 
741         * <code>GradientPaint</code>.
742         * 
743         * @return The transformer (never <code>null</code>).
744         * 
745         * @since 1.0.4
746         * 
747         * @see #setFillPaintTransformer(GradientPaintTransformer)
748         */
749        public GradientPaintTransformer getFillPaintTransformer() {
750            return this.fillPaintTransformer;
751        }
752        
753        /**
754         * Sets the transformer used when the fill paint is an instance of 
755         * <code>GradientPaint</code>.
756         * 
757         * @param transformer  the transformer (<code>null</code> not permitted).
758         * 
759         * @since 1.0.4
760         * 
761         * @see #getFillPaintTransformer()
762         */
763        public void setFillPaintTransformer(GradientPaintTransformer transformer) {
764            if (transformer == null) { 
765                throw new IllegalArgumentException("Null 'transformer' attribute.");
766            }
767            this.fillPaintTransformer = transformer;
768        }
769        
770        /**
771         * Tests this item for equality with an arbitrary object.
772         * 
773         * @param obj  the object (<code>null</code> permitted).
774         * 
775         * @return A boolean.
776         */
777        public boolean equals(Object obj) {
778            if (obj == this) {
779                return true;   
780            }
781            if (!(obj instanceof LegendItem)) {
782                    return false;
783            }
784            LegendItem that = (LegendItem) obj;
785            if (this.datasetIndex != that.datasetIndex) {
786                return false;
787            }
788            if (this.series != that.series) {
789                return false;
790            }
791            if (!this.label.equals(that.label)) {
792                return false;
793            }
794            if (!AttributedStringUtilities.equal(this.attributedLabel, 
795                    that.attributedLabel)) {
796                return false;
797            }
798            if (!ObjectUtilities.equal(this.description, that.description)) {
799                return false;
800            }
801            if (this.shapeVisible != that.shapeVisible) {
802                return false;
803            }
804            if (!ShapeUtilities.equal(this.shape, that.shape)) {
805                return false;
806            }
807            if (this.shapeFilled != that.shapeFilled) {
808                return false;
809            }
810            if (!this.fillPaint.equals(that.fillPaint)) {
811                return false;   
812            }
813            if (!ObjectUtilities.equal(this.fillPaintTransformer, 
814                    that.fillPaintTransformer)) {
815                return false;
816            }
817            if (this.shapeOutlineVisible != that.shapeOutlineVisible) {
818                return false;
819            }
820            if (!this.outlineStroke.equals(that.outlineStroke)) {
821                return false;   
822            }
823            if (!this.outlinePaint.equals(that.outlinePaint)) {
824                return false;   
825            }
826            if (!this.lineVisible == that.lineVisible) {
827                return false;
828            }
829            if (!ShapeUtilities.equal(this.line, that.line)) {
830                return false;
831            }
832            if (!this.lineStroke.equals(that.lineStroke)) {
833                return false;   
834            }
835            if (!this.linePaint.equals(that.linePaint)) {
836                return false;
837            }
838            return true;
839        }
840        
841        /**
842         * Provides serialization support.
843         *
844         * @param stream  the output stream (<code>null</code> not permitted).
845         *
846         * @throws IOException  if there is an I/O error.
847         */
848        private void writeObject(ObjectOutputStream stream) throws IOException {
849            stream.defaultWriteObject();
850            SerialUtilities.writeAttributedString(this.attributedLabel, stream);
851            SerialUtilities.writeShape(this.shape, stream);
852            SerialUtilities.writePaint(this.fillPaint, stream);
853            SerialUtilities.writeStroke(this.outlineStroke, stream);
854            SerialUtilities.writePaint(this.outlinePaint, stream);
855            SerialUtilities.writeShape(this.line, stream);
856            SerialUtilities.writeStroke(this.lineStroke, stream);
857            SerialUtilities.writePaint(this.linePaint, stream);
858        }
859    
860        /**
861         * Provides serialization support.
862         *
863         * @param stream  the input stream (<code>null</code> not permitted).
864         *
865         * @throws IOException  if there is an I/O error.
866         * @throws ClassNotFoundException  if there is a classpath problem.
867         */
868        private void readObject(ObjectInputStream stream) 
869            throws IOException, ClassNotFoundException {
870            stream.defaultReadObject();
871            this.attributedLabel = SerialUtilities.readAttributedString(stream);
872            this.shape = SerialUtilities.readShape(stream);
873            this.fillPaint = SerialUtilities.readPaint(stream);
874            this.outlineStroke = SerialUtilities.readStroke(stream);
875            this.outlinePaint = SerialUtilities.readPaint(stream);
876            this.line = SerialUtilities.readShape(stream);
877            this.lineStroke = SerialUtilities.readStroke(stream);
878            this.linePaint = SerialUtilities.readPaint(stream);
879        }
880        
881    }