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