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