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