    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
    064package org.jfree.chart;
    065
    066import java.awt.BasicStroke;
    067import java.awt.Color;
    068import java.awt.Font;
    069import java.awt.Paint;
    070import java.awt.Shape;
    071import java.awt.Stroke;
    072import java.awt.geom.Line2D;
    073import java.awt.geom.Rectangle2D;
    074import java.io.IOException;
    075import java.io.ObjectInputStream;
    076import java.io.ObjectOutputStream;
    077import java.io.Serializable;
    078import java.text.AttributedString;
    079import java.text.CharacterIterator;
    080
    081import org.jfree.data.general.Dataset;
    082import org.jfree.io.SerialUtilities;
    083import org.jfree.ui.GradientPaintTransformer;
    084import org.jfree.ui.StandardGradientPaintTransformer;
    085import org.jfree.util.AttributedStringUtilities;
    086import org.jfree.util.ObjectUtilities;
    087import org.jfree.util.PaintUtilities;
    088import org.jfree.util.PublicCloneable;
    089import 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 */
    095public 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}