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