001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2014, 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-2014, 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} is permitted).
127     *
128     * @since 1.0.11
129     */
130    private Font labelFont;
131
132    /**
133     * The label paint ({@code null} 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} 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} not permitted).
222     * @param paint  the paint ({@code null} 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} not permitted).
236     * @param description  the description ({@code null} permitted).
237     * @param toolTipText  the tool tip text ({@code null} permitted).
238     * @param urlText  the URL text ({@code null} permitted).
239     * @param shape  the shape ({@code null} not permitted).
240     * @param fillPaint  the paint used to fill the shape ({@code null}
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} not permitted).
260     * @param description  the description ({@code null} permitted).
261     * @param toolTipText  the tool tip text ({@code null} permitted).
262     * @param urlText  the URL text ({@code null} permitted).
263     * @param shape  the shape ({@code null} not permitted).
264     * @param fillPaint  the paint used to fill the shape ({@code null}
265     *                   not permitted).
266     * @param outlineStroke  the outline stroke ({@code null} not
267     *                       permitted).
268     * @param outlinePaint  the outline paint ({@code null} not
269     *                      permitted).
270     */
271    public LegendItem(String label, String description, String toolTipText, 
272            String urlText, Shape shape, Paint fillPaint, Stroke outlineStroke, 
273            Paint outlinePaint) {
274
275        this(label, description, toolTipText, urlText,
276                /* shape visible = */ true, shape,
277                /* shape filled = */ true, fillPaint,
278                /* shape outlined = */ true, outlinePaint, outlineStroke,
279                /* line visible */ false, UNUSED_SHAPE, UNUSED_STROKE,
280                Color.black);
281
282    }
283
284    /**
285     * Creates a legend item using a line.
286     *
287     * @param label  the label ({@code null} not permitted).
288     * @param description  the description ({@code null} permitted).
289     * @param toolTipText  the tool tip text ({@code null} permitted).
290     * @param urlText  the URL text ({@code null} permitted).
291     * @param line  the line ({@code null} not permitted).
292     * @param lineStroke  the line stroke ({@code null} not permitted).
293     * @param linePaint  the line paint ({@code null} not permitted).
294     */
295    public LegendItem(String label, String description, String toolTipText, 
296            String urlText, 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} 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        ParamChecks.nullNotPermitted(label, "label");
340        ParamChecks.nullNotPermitted(fillPaint, "fillPaint");
341        ParamChecks.nullNotPermitted(lineStroke, "lineStroke");
342        ParamChecks.nullNotPermitted(outlinePaint, "outlinePaint");
343        ParamChecks.nullNotPermitted(outlineStroke, "outlineStroke");
344        this.label = label;
345        this.labelPaint = null;
346        this.attributedLabel = null;
347        this.description = description;
348        this.shapeVisible = shapeVisible;
349        this.shape = shape;
350        this.shapeFilled = shapeFilled;
351        this.fillPaint = fillPaint;
352        this.fillPaintTransformer = new StandardGradientPaintTransformer();
353        this.shapeOutlineVisible = shapeOutlineVisible;
354        this.outlinePaint = outlinePaint;
355        this.outlineStroke = outlineStroke;
356        this.lineVisible = lineVisible;
357        this.line = line;
358        this.lineStroke = lineStroke;
359        this.linePaint = linePaint;
360        this.toolTipText = toolTipText;
361        this.urlText = urlText;
362    }
363
364    /**
365     * Creates a legend item with a filled shape.  The shape is not outlined,
366     * and no line is visible.
367     *
368     * @param label  the label (<code>null</code> not permitted).
369     * @param description  the description (<code>null</code> permitted).
370     * @param toolTipText  the tool tip text (<code>null</code> permitted).
371     * @param urlText  the URL text (<code>null</code> permitted).
372     * @param shape  the shape (<code>null</code> not permitted).
373     * @param fillPaint  the paint used to fill the shape (<code>null</code>
374     *                   not permitted).
375     */
376    public LegendItem(AttributedString label, String description,
377                      String toolTipText, String urlText,
378                      Shape shape, Paint fillPaint) {
379
380        this(label, description, toolTipText, urlText,
381                /* shape visible = */ true, shape,
382                /* shape filled = */ true, fillPaint,
383                /* shape outlined = */ false, Color.black, UNUSED_STROKE,
384                /* line visible = */ false, UNUSED_SHAPE, UNUSED_STROKE,
385                Color.black);
386
387    }
388
389    /**
390     * Creates a legend item with a filled and outlined shape.
391     *
392     * @param label  the label (<code>null</code> not permitted).
393     * @param description  the description (<code>null</code> permitted).
394     * @param toolTipText  the tool tip text (<code>null</code> permitted).
395     * @param urlText  the URL text (<code>null</code> permitted).
396     * @param shape  the shape (<code>null</code> not permitted).
397     * @param fillPaint  the paint used to fill the shape (<code>null</code>
398     *                   not permitted).
399     * @param outlineStroke  the outline stroke (<code>null</code> not
400     *                       permitted).
401     * @param outlinePaint  the outline paint (<code>null</code> not
402     *                      permitted).
403     */
404    public LegendItem(AttributedString label, String description,
405                      String toolTipText, String urlText,
406                      Shape shape, Paint fillPaint,
407                      Stroke outlineStroke, Paint outlinePaint) {
408
409        this(label, description, toolTipText, urlText,
410                /* shape visible = */ true, shape,
411                /* shape filled = */ true, fillPaint,
412                /* shape outlined = */ true, outlinePaint, outlineStroke,
413                /* line visible = */ false, UNUSED_SHAPE, UNUSED_STROKE,
414                Color.black);
415    }
416
417    /**
418     * Creates a legend item using a line.
419     *
420     * @param label  the label (<code>null</code> not permitted).
421     * @param description  the description (<code>null</code> permitted).
422     * @param toolTipText  the tool tip text (<code>null</code> permitted).
423     * @param urlText  the URL text (<code>null</code> permitted).
424     * @param line  the line (<code>null</code> not permitted).
425     * @param lineStroke  the line stroke (<code>null</code> not permitted).
426     * @param linePaint  the line paint (<code>null</code> not permitted).
427     */
428    public LegendItem(AttributedString label, String description,
429                      String toolTipText, String urlText,
430                      Shape line, Stroke lineStroke, Paint linePaint) {
431
432        this(label, description, toolTipText, urlText,
433                /* shape visible = */ false, UNUSED_SHAPE,
434                /* shape filled = */ false, Color.black,
435                /* shape outlined = */ false, Color.black, UNUSED_STROKE,
436                /* line visible = */ true, line, lineStroke, linePaint);
437    }
438
439    /**
440     * Creates a new legend item.
441     *
442     * @param label  the label (<code>null</code> not permitted).
443     * @param description  the description (not currently used,
444     *        <code>null</code> permitted).
445     * @param toolTipText  the tool tip text (<code>null</code> permitted).
446     * @param urlText  the URL text (<code>null</code> permitted).
447     * @param shapeVisible  a flag that controls whether or not the shape is
448     *                      displayed.
449     * @param shape  the shape (<code>null</code> permitted).
450     * @param shapeFilled  a flag that controls whether or not the shape is
451     *                     filled.
452     * @param fillPaint  the fill paint (<code>null</code> not permitted).
453     * @param shapeOutlineVisible  a flag that controls whether or not the
454     *                             shape is outlined.
455     * @param outlinePaint  the outline paint (<code>null</code> not permitted).
456     * @param outlineStroke  the outline stroke (<code>null</code> not
457     *                       permitted).
458     * @param lineVisible  a flag that controls whether or not the line is
459     *                     visible.
460     * @param line  the line (<code>null</code> not permitted).
461     * @param lineStroke  the stroke (<code>null</code> not permitted).
462     * @param linePaint  the line paint (<code>null</code> not permitted).
463     */
464    public LegendItem(AttributedString label, String description,
465                      String toolTipText, String urlText,
466                      boolean shapeVisible, Shape shape,
467                      boolean shapeFilled, Paint fillPaint,
468                      boolean shapeOutlineVisible, Paint outlinePaint,
469                      Stroke outlineStroke,
470                      boolean lineVisible, Shape line, Stroke lineStroke,
471                      Paint linePaint) {
472
473        ParamChecks.nullNotPermitted(label, "label");
474        ParamChecks.nullNotPermitted(fillPaint, "fillPaint");
475        ParamChecks.nullNotPermitted(lineStroke, "lineStroke");
476        ParamChecks.nullNotPermitted(line, "line");
477        ParamChecks.nullNotPermitted(linePaint, "linePaint");
478        ParamChecks.nullNotPermitted(outlinePaint, "outlinePaint");
479        ParamChecks.nullNotPermitted(outlineStroke, "outlineStroke");
480        this.label = characterIteratorToString(label.getIterator());
481        this.attributedLabel = label;
482        this.description = description;
483        this.shapeVisible = shapeVisible;
484        this.shape = shape;
485        this.shapeFilled = shapeFilled;
486        this.fillPaint = fillPaint;
487        this.fillPaintTransformer = new StandardGradientPaintTransformer();
488        this.shapeOutlineVisible = shapeOutlineVisible;
489        this.outlinePaint = outlinePaint;
490        this.outlineStroke = outlineStroke;
491        this.lineVisible = lineVisible;
492        this.line = line;
493        this.lineStroke = lineStroke;
494        this.linePaint = linePaint;
495        this.toolTipText = toolTipText;
496        this.urlText = urlText;
497    }
498
499    /**
500     * Returns a string containing the characters from the given iterator.
501     *
502     * @param iterator  the iterator (<code>null</code> not permitted).
503     *
504     * @return A string.
505     */
506    private String characterIteratorToString(CharacterIterator iterator) {
507        int endIndex = iterator.getEndIndex();
508        int beginIndex = iterator.getBeginIndex();
509        int count = endIndex - beginIndex;
510        if (count <= 0) {
511            return "";
512        }
513        char[] chars = new char[count];
514        int i = 0;
515        char c = iterator.first();
516        while (c != CharacterIterator.DONE) {
517            chars[i] = c;
518            i++;
519            c = iterator.next();
520        }
521        return new String(chars);
522    }
523
524    /**
525     * Returns the dataset.
526     *
527     * @return The dataset.
528     *
529     * @since 1.0.6
530     *
531     * @see #setDatasetIndex(int)
532     */
533    public Dataset getDataset() {
534        return this.dataset;
535    }
536
537    /**
538     * Sets the dataset.
539     *
540     * @param dataset  the dataset.
541     *
542     * @since 1.0.6
543     */
544    public void setDataset(Dataset dataset) {
545        this.dataset = dataset;
546    }
547
548    /**
549     * Returns the dataset index for this legend item.
550     *
551     * @return The dataset index.
552     *
553     * @since 1.0.2
554     *
555     * @see #setDatasetIndex(int)
556     * @see #getDataset()
557     */
558    public int getDatasetIndex() {
559        return this.datasetIndex;
560    }
561
562    /**
563     * Sets the dataset index for this legend item.
564     *
565     * @param index  the index.
566     *
567     * @since 1.0.2
568     *
569     * @see #getDatasetIndex()
570     */
571    public void setDatasetIndex(int index) {
572        this.datasetIndex = index;
573    }
574
575    /**
576     * Returns the series key.
577     *
578     * @return The series key.
579     *
580     * @since 1.0.6
581     *
582     * @see #setSeriesKey(Comparable)
583     */
584    public Comparable getSeriesKey() {
585        return this.seriesKey;
586    }
587
588    /**
589     * Sets the series key.
590     *
591     * @param key  the series key.
592     *
593     * @since 1.0.6
594     */
595    public void setSeriesKey(Comparable key) {
596        this.seriesKey = key;
597    }
598
599    /**
600     * Returns the series index for this legend item.
601     *
602     * @return The series index.
603     *
604     * @since 1.0.2
605     */
606    public int getSeriesIndex() {
607        return this.series;
608    }
609
610    /**
611     * Sets the series index for this legend item.
612     *
613     * @param index  the index.
614     *
615     * @since 1.0.2
616     */
617    public void setSeriesIndex(int index) {
618        this.series = index;
619    }
620
621    /**
622     * Returns the label.
623     *
624     * @return The label (never <code>null</code>).
625     */
626    public String getLabel() {
627        return this.label;
628    }
629
630    /**
631     * Returns the label font.
632     *
633     * @return The label font (possibly <code>null</code>).
634     *
635     * @since 1.0.11
636     */
637    public Font getLabelFont() {
638        return this.labelFont;
639    }
640
641    /**
642     * Sets the label font.
643     *
644     * @param font  the font (<code>null</code> permitted).
645     *
646     * @since 1.0.11
647     */
648    public void setLabelFont(Font font) {
649        this.labelFont = font;
650    }
651
652    /**
653     * Returns the paint used to draw the label.
654     *
655     * @return The paint (possibly <code>null</code>).
656     *
657     * @since 1.0.11
658     */
659    public Paint getLabelPaint() {
660        return this.labelPaint;
661    }
662
663    /**
664     * Sets the paint used to draw the label.
665     *
666     * @param paint  the paint (<code>null</code> permitted).
667     *
668     * @since 1.0.11
669     */
670    public void setLabelPaint(Paint paint) {
671        this.labelPaint = paint;
672    }
673
674    /**
675     * Returns the attributed label.
676     *
677     * @return The attributed label (possibly <code>null</code>).
678     */
679    public AttributedString getAttributedLabel() {
680        return this.attributedLabel;
681    }
682
683    /**
684     * Returns the description for the legend item.
685     *
686     * @return The description (possibly <code>null</code>).
687     *
688     * @see #setDescription(java.lang.String) 
689     */
690    public String getDescription() {
691        return this.description;
692    }
693
694    /**
695     * Sets the description for this legend item.
696     *
697     * @param text  the description (<code>null</code> permitted).
698     *
699     * @see #getDescription()
700     * @since 1.0.14
701     */
702    public void setDescription(String text) {
703        this.description = text;
704    }
705
706    /**
707     * Returns the tool tip text.
708     *
709     * @return The tool tip text (possibly <code>null</code>).
710     *
711     * @see #setToolTipText(java.lang.String) 
712     */
713    public String getToolTipText() {
714        return this.toolTipText;
715    }
716
717    /**
718     * Sets the tool tip text for this legend item.
719     *
720     * @param text  the text (<code>null</code> permitted).
721     *
722     * @see #getToolTipText()
723     * @since 1.0.14
724     */
725    public void setToolTipText(String text) {
726        this.toolTipText = text;
727    }
728
729    /**
730     * Returns the URL text.
731     *
732     * @return The URL text (possibly <code>null</code>).
733     *
734     * @see #setURLText(java.lang.String) 
735     */
736    public String getURLText() {
737        return this.urlText;
738    }
739
740    /**
741     * Sets the URL text.
742     *
743     * @param text  the text (<code>null</code> permitted).
744     *
745     * @see #getURLText()
746     *
747     * @since 1.0.14
748     */
749    public void setURLText(String text) {
750        this.urlText = text;
751    }
752
753    /**
754     * Returns a flag that indicates whether or not the shape is visible.
755     *
756     * @return A boolean.
757     *
758     * @see #setShapeVisible(boolean)
759     */
760    public boolean isShapeVisible() {
761        return this.shapeVisible;
762    }
763
764    /**
765     * Sets the flag that controls whether or not the shape is visible.
766     *
767     * @param visible  the new flag value.
768     *
769     * @see #isShapeVisible()
770     * @see #isLineVisible()
771     *
772     * @since 1.0.14
773     */
774    public void setShapeVisible(boolean visible) {
775        this.shapeVisible = visible;
776    }
777
778    /**
779     * Returns the shape used to label the series represented by this legend
780     * item.
781     *
782     * @return The shape (never <code>null</code>).
783     *
784     * @see #setShape(java.awt.Shape) 
785     */
786    public Shape getShape() {
787        return this.shape;
788    }
789
790    /**
791     * Sets the shape for the legend item.
792     *
793     * @param shape  the shape (<code>null</code> not permitted).
794     *
795     * @see #getShape()
796     * @since 1.0.14
797     */
798    public void setShape(Shape shape) {
799        ParamChecks.nullNotPermitted(shape, "shape");
800        this.shape = shape;
801    }
802
803    /**
804     * Returns a flag that controls whether or not the shape is filled.
805     *
806     * @return A boolean.
807     */
808    public boolean isShapeFilled() {
809        return this.shapeFilled;
810    }
811
812    /**
813     * Returns the fill paint.
814     *
815     * @return The fill paint (never <code>null</code>).
816     */
817    public Paint getFillPaint() {
818        return this.fillPaint;
819    }
820
821    /**
822     * Sets the fill paint.
823     *
824     * @param paint  the paint (<code>null</code> not permitted).
825     *
826     * @since 1.0.11
827     */
828    public void setFillPaint(Paint paint) {
829        ParamChecks.nullNotPermitted(paint, "paint");
830        this.fillPaint = paint;
831    }
832
833    /**
834     * Returns the flag that controls whether or not the shape outline
835     * is visible.
836     *
837     * @return A boolean.
838     */
839    public boolean isShapeOutlineVisible() {
840        return this.shapeOutlineVisible;
841    }
842
843    /**
844     * Returns the line stroke for the series.
845     *
846     * @return The stroke (never <code>null</code>).
847     */
848    public Stroke getLineStroke() {
849        return this.lineStroke;
850    }
851    
852    /**
853     * Sets the line stroke.
854     * 
855     * @param stroke  the stroke (<code>null</code> not permitted).
856     * 
857     * @since 1.0.18
858     */
859    public void setLineStroke(Stroke stroke) {
860        ParamChecks.nullNotPermitted(stroke, "stroke");
861        this.lineStroke = stroke;
862    }
863
864    /**
865     * Returns the paint used for lines.
866     *
867     * @return The paint (never <code>null</code>).
868     */
869    public Paint getLinePaint() {
870        return this.linePaint;
871    }
872
873    /**
874     * Sets the line paint.
875     *
876     * @param paint  the paint (<code>null</code> not permitted).
877     *
878     * @since 1.0.11
879     */
880    public void setLinePaint(Paint paint) {
881        ParamChecks.nullNotPermitted(paint, "paint");
882        this.linePaint = paint;
883    }
884
885    /**
886     * Returns the outline paint.
887     *
888     * @return The outline paint (never <code>null</code>).
889     */
890    public Paint getOutlinePaint() {
891        return this.outlinePaint;
892    }
893
894    /**
895     * Sets the outline paint.
896     *
897     * @param paint  the paint (<code>null</code> not permitted).
898     *
899     * @since 1.0.11
900     */
901    public void setOutlinePaint(Paint paint) {
902        ParamChecks.nullNotPermitted(paint, "paint");
903        this.outlinePaint = paint;
904    }
905
906    /**
907     * Returns the outline stroke.
908     *
909     * @return The outline stroke (never <code>null</code>).
910     *
911     * @see #setOutlineStroke(java.awt.Stroke) 
912     */
913    public Stroke getOutlineStroke() {
914        return this.outlineStroke;
915    }
916
917    /**
918     * Sets the outline stroke.
919     *
920     * @param stroke  the stroke (<code>null</code> not permitted).
921     *
922     * @see #getOutlineStroke()
923     *
924     * @since 1.0.14
925     */
926    public void setOutlineStroke(Stroke stroke) {
927        ParamChecks.nullNotPermitted(stroke, "stroke");
928        this.outlineStroke = stroke;
929    }
930
931    /**
932     * Returns a flag that indicates whether or not the line is visible.
933     *
934     * @return A boolean.
935     *
936     * @see #setLineVisible(boolean) 
937     */
938    public boolean isLineVisible() {
939        return this.lineVisible;
940    }
941
942    /**
943     * Sets the flag that controls whether or not the line shape is visible for
944     * this legend item.
945     *
946     * @param visible  the new flag value.
947     *
948     * @see #isLineVisible()
949     * @since 1.0.14
950     */
951    public void setLineVisible(boolean visible) {
952        this.lineVisible = visible;
953    }
954
955    /**
956     * Returns the line.
957     *
958     * @return The line (never <code>null</code>).
959     *
960     * @see #setLine(java.awt.Shape)
961     * @see #isLineVisible() 
962     */
963    public Shape getLine() {
964        return this.line;
965    }
966
967    /**
968     * Sets the line.
969     *
970     * @param line  the line (<code>null</code> not permitted).
971     *
972     * @see #getLine()
973     * @since 1.0.14
974     */
975    public void setLine(Shape line) {
976        ParamChecks.nullNotPermitted(line, "line");
977        this.line = line;
978    }
979
980    /**
981     * Returns the transformer used when the fill paint is an instance of
982     * <code>GradientPaint</code>.
983     *
984     * @return The transformer (never <code>null</code>).
985     *
986     * @since 1.0.4
987     *
988     * @see #setFillPaintTransformer(GradientPaintTransformer)
989     */
990    public GradientPaintTransformer getFillPaintTransformer() {
991        return this.fillPaintTransformer;
992    }
993
994    /**
995     * Sets the transformer used when the fill paint is an instance of
996     * <code>GradientPaint</code>.
997     *
998     * @param transformer  the transformer (<code>null</code> not permitted).
999     *
1000     * @since 1.0.4
1001     *
1002     * @see #getFillPaintTransformer()
1003     */
1004    public void setFillPaintTransformer(GradientPaintTransformer transformer) {
1005        ParamChecks.nullNotPermitted(transformer, "transformer");
1006        this.fillPaintTransformer = transformer;
1007    }
1008
1009    /**
1010     * Tests this item for equality with an arbitrary object.
1011     *
1012     * @param obj  the object (<code>null</code> permitted).
1013     *
1014     * @return A boolean.
1015     */
1016    @Override
1017    public boolean equals(Object obj) {
1018        if (obj == this) {
1019            return true;
1020        }
1021        if (!(obj instanceof LegendItem)) {
1022            return false;
1023        }
1024        LegendItem that = (LegendItem) obj;
1025        if (this.datasetIndex != that.datasetIndex) {
1026            return false;
1027        }
1028        if (this.series != that.series) {
1029            return false;
1030        }
1031        if (!this.label.equals(that.label)) {
1032            return false;
1033        }
1034        if (!AttributedStringUtilities.equal(this.attributedLabel,
1035                that.attributedLabel)) {
1036            return false;
1037        }
1038        if (!ObjectUtilities.equal(this.description, that.description)) {
1039            return false;
1040        }
1041        if (this.shapeVisible != that.shapeVisible) {
1042            return false;
1043        }
1044        if (!ShapeUtilities.equal(this.shape, that.shape)) {
1045            return false;
1046        }
1047        if (this.shapeFilled != that.shapeFilled) {
1048            return false;
1049        }
1050        if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
1051            return false;
1052        }
1053        if (!ObjectUtilities.equal(this.fillPaintTransformer,
1054                that.fillPaintTransformer)) {
1055            return false;
1056        }
1057        if (this.shapeOutlineVisible != that.shapeOutlineVisible) {
1058            return false;
1059        }
1060        if (!this.outlineStroke.equals(that.outlineStroke)) {
1061            return false;
1062        }
1063        if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
1064            return false;
1065        }
1066        if (!this.lineVisible == that.lineVisible) {
1067            return false;
1068        }
1069        if (!ShapeUtilities.equal(this.line, that.line)) {
1070            return false;
1071        }
1072        if (!this.lineStroke.equals(that.lineStroke)) {
1073            return false;
1074        }
1075        if (!PaintUtilities.equal(this.linePaint, that.linePaint)) {
1076            return false;
1077        }
1078        if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) {
1079            return false;
1080        }
1081        if (!PaintUtilities.equal(this.labelPaint, that.labelPaint)) {
1082            return false;
1083        }
1084        return true;
1085    }
1086
1087    /**
1088     * Returns an independent copy of this object (except that the clone will
1089     * still reference the same dataset as the original
1090     * <code>LegendItem</code>).
1091     *
1092     * @return A clone.
1093     *
1094     * @throws CloneNotSupportedException if the legend item cannot be cloned.
1095     *
1096     * @since 1.0.10
1097     */
1098    @Override
1099    public Object clone() throws CloneNotSupportedException {
1100        LegendItem clone = (LegendItem) super.clone();
1101        if (this.seriesKey instanceof PublicCloneable) {
1102            PublicCloneable pc = (PublicCloneable) this.seriesKey;
1103            clone.seriesKey = (Comparable) pc.clone();
1104        }
1105        // FIXME: Clone the attributed string if it is not null
1106        clone.shape = ShapeUtilities.clone(this.shape);
1107        if (this.fillPaintTransformer instanceof PublicCloneable) {
1108            PublicCloneable pc = (PublicCloneable) this.fillPaintTransformer;
1109            clone.fillPaintTransformer = (GradientPaintTransformer) pc.clone();
1110
1111        }
1112        clone.line = ShapeUtilities.clone(this.line);
1113        return clone;
1114    }
1115
1116    /**
1117     * Provides serialization support.
1118     *
1119     * @param stream  the output stream (<code>null</code> not permitted).
1120     *
1121     * @throws IOException  if there is an I/O error.
1122     */
1123    private void writeObject(ObjectOutputStream stream) throws IOException {
1124        stream.defaultWriteObject();
1125        SerialUtilities.writeAttributedString(this.attributedLabel, stream);
1126        SerialUtilities.writeShape(this.shape, stream);
1127        SerialUtilities.writePaint(this.fillPaint, stream);
1128        SerialUtilities.writeStroke(this.outlineStroke, stream);
1129        SerialUtilities.writePaint(this.outlinePaint, stream);
1130        SerialUtilities.writeShape(this.line, stream);
1131        SerialUtilities.writeStroke(this.lineStroke, stream);
1132        SerialUtilities.writePaint(this.linePaint, stream);
1133        SerialUtilities.writePaint(this.labelPaint, stream);
1134    }
1135
1136    /**
1137     * Provides serialization support.
1138     *
1139     * @param stream  the input stream (<code>null</code> not permitted).
1140     *
1141     * @throws IOException  if there is an I/O error.
1142     * @throws ClassNotFoundException  if there is a classpath problem.
1143     */
1144    private void readObject(ObjectInputStream stream)
1145        throws IOException, ClassNotFoundException {
1146        stream.defaultReadObject();
1147        this.attributedLabel = SerialUtilities.readAttributedString(stream);
1148        this.shape = SerialUtilities.readShape(stream);
1149        this.fillPaint = SerialUtilities.readPaint(stream);
1150        this.outlineStroke = SerialUtilities.readStroke(stream);
1151        this.outlinePaint = SerialUtilities.readPaint(stream);
1152        this.line = SerialUtilities.readShape(stream);
1153        this.lineStroke = SerialUtilities.readStroke(stream);
1154        this.linePaint = SerialUtilities.readPaint(stream);
1155        this.labelPaint = SerialUtilities.readPaint(stream);
1156    }
1157
1158}