    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     * StandardChartTheme.java
    029     * -----------------------
    030     * (C) Copyright 2008-2011, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * Changes
    036     * -------
    037     * 14-Aug-2008 : Version 1 (DG);
    038     * 10-Apr-2009 : Added getter/setter for smallFont (DG);
    039     * 10-Jul-2009 : Added shadowGenerator field (DG);
    040     * 29-Oct-2011 : Fixed Eclipse warnings (DG);
    041     *
    042     */
    043
    044    package org.jfree.chart;
    045
    046    import java.awt.BasicStroke;
    047    import java.awt.Color;
    048    import java.awt.Font;
    049    import java.awt.Paint;
    050    import java.awt.Stroke;
    051    import java.io.IOException;
    052    import java.io.ObjectInputStream;
    053    import java.io.ObjectOutputStream;
    054    import java.io.Serializable;
    055    import java.util.Iterator;
    056    import java.util.List;
    057
    058    import org.jfree.chart.annotations.XYAnnotation;
    059    import org.jfree.chart.annotations.XYTextAnnotation;
    060    import org.jfree.chart.axis.CategoryAxis;
    061    import org.jfree.chart.axis.PeriodAxis;
    062    import org.jfree.chart.axis.PeriodAxisLabelInfo;
    063    import org.jfree.chart.axis.SubCategoryAxis;
    064    import org.jfree.chart.axis.SymbolAxis;
    065    import org.jfree.chart.axis.ValueAxis;
    066    import org.jfree.chart.block.Block;
    067    import org.jfree.chart.block.BlockContainer;
    068    import org.jfree.chart.block.LabelBlock;
    069    import org.jfree.chart.plot.CategoryPlot;
    070    import org.jfree.chart.plot.CombinedDomainCategoryPlot;
    071    import org.jfree.chart.plot.CombinedDomainXYPlot;
    072    import org.jfree.chart.plot.CombinedRangeCategoryPlot;
    073    import org.jfree.chart.plot.CombinedRangeXYPlot;
    074    import org.jfree.chart.plot.DefaultDrawingSupplier;
    075    import org.jfree.chart.plot.DrawingSupplier;
    076    import org.jfree.chart.plot.FastScatterPlot;
    077    import org.jfree.chart.plot.MeterPlot;
    078    import org.jfree.chart.plot.MultiplePiePlot;
    079    import org.jfree.chart.plot.PieLabelLinkStyle;
    080    import org.jfree.chart.plot.PiePlot;
    081    import org.jfree.chart.plot.Plot;
    082    import org.jfree.chart.plot.PolarPlot;
    083    import org.jfree.chart.plot.SpiderWebPlot;
    084    import org.jfree.chart.plot.ThermometerPlot;
    085    import org.jfree.chart.plot.XYPlot;
    086    import org.jfree.chart.renderer.AbstractRenderer;
    087    import org.jfree.chart.renderer.category.BarPainter;
    088    import org.jfree.chart.renderer.category.BarRenderer;
    089    import org.jfree.chart.renderer.category.BarRenderer3D;
    090    import org.jfree.chart.renderer.category.CategoryItemRenderer;
    091    import org.jfree.chart.renderer.category.GradientBarPainter;
    092    import org.jfree.chart.renderer.category.LineRenderer3D;
    093    import org.jfree.chart.renderer.category.MinMaxCategoryRenderer;
    094    import org.jfree.chart.renderer.category.StatisticalBarRenderer;
    095    import org.jfree.chart.renderer.xy.GradientXYBarPainter;
    096    import org.jfree.chart.renderer.xy.XYBarPainter;
    097    import org.jfree.chart.renderer.xy.XYBarRenderer;
    098    import org.jfree.chart.renderer.xy.XYItemRenderer;
    099    import org.jfree.chart.title.CompositeTitle;
    100    import org.jfree.chart.title.LegendTitle;
    101    import org.jfree.chart.title.PaintScaleLegend;
    102    import org.jfree.chart.title.TextTitle;
    103    import org.jfree.chart.title.Title;
    104    import org.jfree.chart.util.DefaultShadowGenerator;
    105    import org.jfree.chart.util.ShadowGenerator;
    106    import org.jfree.io.SerialUtilities;
    107    import org.jfree.ui.RectangleInsets;
    108    import org.jfree.util.PaintUtilities;
    109    import org.jfree.util.PublicCloneable;
    110
    111    /**
    112     * A default implementation of the {@link ChartTheme} interface.  This
    113     * implementation just collects a whole bunch of chart attributes and mimics
    114     * the manual process of applying each attribute to the right sub-object
    115     * within the JFreeChart instance.  It's not elegant code, but it works.
    116     *
    117     * @since 1.0.11
    118     */
    119    public class StandardChartTheme implements ChartTheme, Cloneable,
    120            PublicCloneable, Serializable {
    121
    122        /** The name of this theme. */
    123        private String name;
    124
    125        /**
    126         * The largest font size.  Use for the main chart title.
    127         */
    128        private Font extraLargeFont;
    129
    130        /**
    131         * A large font.  Used for subtitles.
    132         */
    133        private Font largeFont;
    134
    135        /**
    136         * The regular font size.  Used for axis tick labels, legend items etc.
    137         */
    138        private Font regularFont;
    139
    140        /**
    141         * The small font size.
    142         */
    143        private Font smallFont;
    144
    145        /** The paint used to display the main chart title. */
    146        private transient Paint titlePaint;
    147
    148        /** The paint used to display subtitles. */
    149        private transient Paint subtitlePaint;
    150
    151        /** The background paint for the chart. */
    152        private transient Paint chartBackgroundPaint;
    153
    154        /** The legend background paint. */
    155        private transient Paint legendBackgroundPaint;
    156
    157        /** The legend item paint. */
    158        private transient Paint legendItemPaint;
    159
    160        /** The drawing supplier. */
    161        private DrawingSupplier drawingSupplier;
    162
    163        /** The background paint for the plot. */
    164        private transient Paint plotBackgroundPaint;
    165
    166        /** The plot outline paint. */
    167        private transient Paint plotOutlinePaint;
    168
    169        /** The label link style for pie charts. */
    170        private PieLabelLinkStyle labelLinkStyle;
    171
    172        /** The label link paint for pie charts. */
    173        private transient Paint labelLinkPaint;
    174
    175        /** The domain grid line paint. */
    176        private transient Paint domainGridlinePaint;
    177
    178        /** The range grid line paint. */
    179        private transient Paint rangeGridlinePaint;
    180
    181        /**
    182         * The baseline paint (used for domain and range zero baselines)
    183         *
    184         * @since 1.0.13
    185         */
    186        private transient Paint baselinePaint;
    187
    188        /** The crosshair paint. */
    189        private transient Paint crosshairPaint;
    190
    191        /** The axis offsets. */
    192        private RectangleInsets axisOffset;
    193
    194        /** The axis label paint. */
    195        private transient Paint axisLabelPaint;
    196
    197        /** The tick label paint. */
    198        private transient Paint tickLabelPaint;
    199
    200        /** The item label paint. */
    201        private transient Paint itemLabelPaint;
    202
    203        /**
    204         * A flag that controls whether or not shadows are visible (for example,
    205         * in a bar renderer).
    206         */
    207        private boolean shadowVisible;
    208
    209        /** The shadow paint. */
    210        private transient Paint shadowPaint;
    211
    212        /** The bar painter. */
    213        private BarPainter barPainter;
    214
    215        /** The XY bar painter. */
    216        private XYBarPainter xyBarPainter;
    217
    218        /** The thermometer paint. */
    219        private transient Paint thermometerPaint;
    220
    221        /**
    222         * The paint used to fill the interior of the 'walls' in the background
    223         * of a plot with a 3D effect.  Applied to BarRenderer3D.
    224         */
    225        private transient Paint wallPaint;
    226
    227        /** The error indicator paint for the {@link StatisticalBarRenderer}. */
    228        private transient Paint errorIndicatorPaint;
    229
    230        /** The grid band paint for a {@link SymbolAxis}. */
    231        private transient Paint gridBandPaint = SymbolAxis.DEFAULT_GRID_BAND_PAINT;
    232
    233        /** The grid band alternate paint for a {@link SymbolAxis}. */
    234        private transient Paint gridBandAlternatePaint
    235                = SymbolAxis.DEFAULT_GRID_BAND_ALTERNATE_PAINT;
    236
    237        /**
    238         * The shadow generator (can be null).
    239         *
    240         * @since 1.0.14
    241         */
    242        private ShadowGenerator shadowGenerator;
    243
    244        /**
    245         * Creates and returns the default 'JFree' chart theme.
    246         *
    247         * @return A chart theme.
    248         */
    249        public static ChartTheme createJFreeTheme() {
    250            return new StandardChartTheme("JFree");
    251        }
    252
    253        /**
    254         * Creates and returns a theme called "Darkness".  In this theme, the
    255         * charts have a black background.
    256         *
    257         * @return The "Darkness" theme.
    258         */
    259        public static ChartTheme createDarknessTheme() {
    260            StandardChartTheme theme = new StandardChartTheme("Darkness");
    261            theme.titlePaint = Color.white;
    262            theme.subtitlePaint = Color.white;
    263            theme.legendBackgroundPaint = Color.black;
    264            theme.legendItemPaint = Color.white;
    265            theme.chartBackgroundPaint = Color.black;
    266            theme.plotBackgroundPaint = Color.black;
    267            theme.plotOutlinePaint = Color.yellow;
    268            theme.baselinePaint = Color.white;
    269            theme.crosshairPaint = Color.red;
    270            theme.labelLinkPaint = Color.lightGray;
    271            theme.tickLabelPaint = Color.white;
    272            theme.axisLabelPaint = Color.white;
    273            theme.shadowPaint = Color.darkGray;
    274            theme.itemLabelPaint = Color.white;
    275            theme.drawingSupplier = new DefaultDrawingSupplier(
    276                    new Paint[] {Color.decode("0xFFFF00"),
    277                            Color.decode("0x0036CC"), Color.decode("0xFF0000"),
    278                            Color.decode("0xFFFF7F"), Color.decode("0x6681CC"),
    279                            Color.decode("0xFF7F7F"), Color.decode("0xFFFFBF"),
    280                            Color.decode("0x99A6CC"), Color.decode("0xFFBFBF"),
    281                            Color.decode("0xA9A938"), Color.decode("0x2D4587")},
    282                    new Paint[] {Color.decode("0xFFFF00"),
    283                            Color.decode("0x0036CC")},
    284                    new Stroke[] {new BasicStroke(2.0f)},
    285                    new Stroke[] {new BasicStroke(0.5f)},
    286                    DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
    287            theme.wallPaint = Color.darkGray;
    288            theme.errorIndicatorPaint = Color.lightGray;
    289            theme.gridBandPaint = new Color(255, 255, 255, 20);
    290            theme.gridBandAlternatePaint = new Color(255, 255, 255, 40);
    291            theme.shadowGenerator = null;
    292            return theme;
    293        }
    294
    295        /**
    296         * Creates and returns a {@link ChartTheme} that doesn't apply any changes
    297         * to the JFreeChart defaults.  This produces the "legacy" look for
    298         * JFreeChart.
    299         *
    300         * @return A legacy theme.
    301         */
    302        public static ChartTheme createLegacyTheme() {
    303            StandardChartTheme theme = new StandardChartTheme("Legacy") {
    304                public void apply(JFreeChart chart) {
    305                    // do nothing at all
    306                }
    307            };
    308            return theme;
    309        }
    310
    311        /**
    312         * Creates a new default instance.
    313         *
    314         * @param name  the name of the theme (<code>null</code> not permitted).
    315         */
    316        public StandardChartTheme(String name) {
    317            this(name, false);
    318        }
    319
    320        /**
    321         * Creates a new default instance.
    322         *
    323         * @param name  the name of the theme (<code>null</code> not permitted).
    324         * @param shadow  a flag that controls whether a shadow generator is
    325         *                included.
    326         *
    327         * @since 1.0.14
    328         */
    329        public StandardChartTheme(String name, boolean shadow) {
    330            if (name == null) {
    331                throw new IllegalArgumentException("Null 'name' argument.");
    332            }
    333            this.name = name;
    334            this.extraLargeFont = new Font("Tahoma", Font.BOLD, 20);
    335            this.largeFont = new Font("Tahoma", Font.BOLD, 14);
    336            this.regularFont = new Font("Tahoma", Font.PLAIN, 12);
    337            this.smallFont = new Font("Tahoma", Font.PLAIN, 10);
    338            this.titlePaint = Color.black;
    339            this.subtitlePaint = Color.black;
    340            this.legendBackgroundPaint = Color.white;
    341            this.legendItemPaint = Color.darkGray;
    342            this.chartBackgroundPaint = Color.white;
    343            this.drawingSupplier = new DefaultDrawingSupplier();
    344            this.plotBackgroundPaint = Color.lightGray;
    345            this.plotOutlinePaint = Color.black;
    346            this.labelLinkPaint = Color.black;
    347            this.labelLinkStyle = PieLabelLinkStyle.CUBIC_CURVE;
    348            this.axisOffset = new RectangleInsets(4, 4, 4, 4);
    349            this.domainGridlinePaint = Color.white;
    350            this.rangeGridlinePaint = Color.white;
    351            this.baselinePaint = Color.black;
    352            this.crosshairPaint = Color.blue;
    353            this.axisLabelPaint = Color.darkGray;
    354            this.tickLabelPaint = Color.darkGray;
    355            this.barPainter = new GradientBarPainter();
    356            this.xyBarPainter = new GradientXYBarPainter();
    357            this.shadowVisible = false;
    358            this.shadowPaint = Color.gray;
    359            this.itemLabelPaint = Color.black;
    360            this.thermometerPaint = Color.white;
    361            this.wallPaint = BarRenderer3D.DEFAULT_WALL_PAINT;
    362            this.errorIndicatorPaint = Color.black;
    363            this.shadowGenerator = shadow ? new DefaultShadowGenerator() : null;
    364        }
    365
    366        /**
    367         * Returns the largest font for this theme.
    368         *
    369         * @return The largest font for this theme.
    370         *
    371         * @see #setExtraLargeFont(Font)
    372         */
    373        public Font getExtraLargeFont() {
    374            return this.extraLargeFont;
    375        }
    376
    377        /**
    378         * Sets the largest font for this theme.
    379         *
    380         * @param font  the font (<code>null</code> not permitted).
    381         *
    382         * @see #getExtraLargeFont()
    383         */
    384        public void setExtraLargeFont(Font font) {
    385            if (font == null) {
    386                throw new IllegalArgumentException("Null 'font' argument.");
    387            }
    388            this.extraLargeFont = font;
    389        }
    390
    391        /**
    392         * Returns the large font for this theme.
    393         *
    394         * @return The large font (never <code>null</code>).
    395         *
    396         * @see #setLargeFont(Font)
    397         */
    398        public Font getLargeFont() {
    399            return this.largeFont;
    400        }
    401
    402        /**
    403         * Sets the large font for this theme.
    404         *
    405         * @param font  the font (<code>null</code> not permitted).
    406         *
    407         * @see #getLargeFont()
    408         */
    409        public void setLargeFont(Font font) {
    410            if (font == null) {
    411                throw new IllegalArgumentException("Null 'font' argument.");
    412            }
    413            this.largeFont = font;
    414        }
    415
    416        /**
    417         * Returns the regular font.
    418         *
    419         * @return The regular font (never <code>null</code>).
    420         *
    421         * @see #setRegularFont(Font)
    422         */
    423        public Font getRegularFont() {
    424            return this.regularFont;
    425        }
    426
    427        /**
    428         * Sets the regular font for this theme.
    429         *
    430         * @param font  the font (<code>null</code> not permitted).
    431         *
    432         * @see #getRegularFont()
    433         */
    434        public void setRegularFont(Font font) {
    435            if (font == null) {
    436                throw new IllegalArgumentException("Null 'font' argument.");
    437            }
    438            this.regularFont = font;
    439        }
    440
    441        /**
    442         * Returns the small font.
    443         *
    444         * @return The small font (never <code>null</code>).
    445         *
    446         * @see #setSmallFont(Font)
    447         *
    448         * @since 1.0.13
    449         */
    450        public Font getSmallFont() {
    451            return this.smallFont;
    452        }
    453
    454        /**
    455         * Sets the small font for this theme.
    456         *
    457         * @param font  the font (<code>null</code> not permitted).
    458         *
    459         * @see #getSmallFont()
    460         *
    461         * @since 1.0.13
    462         */
    463        public void setSmallFont(Font font) {
    464            if (font == null) {
    465                throw new IllegalArgumentException("Null 'font' argument.");
    466            }
    467            this.smallFont = font;
    468        }
    469
    470        /**
    471         * Returns the title paint.
    472         *
    473         * @return The title paint (never <code>null</code>).
    474         *
    475         * @see #setTitlePaint(Paint)
    476         */
    477        public Paint getTitlePaint() {
    478            return this.titlePaint;
    479        }
    480
    481        /**
    482         * Sets the title paint.
    483         *
    484         * @param paint  the paint (<code>null</code> not permitted).
    485         *
    486         * @see #getTitlePaint()
    487         */
    488        public void setTitlePaint(Paint paint) {
    489            if (paint == null) {
    490                throw new IllegalArgumentException("Null 'paint' argument.");
    491            }
    492            this.titlePaint = paint;
    493        }
    494
    495        /**
    496         * Returns the subtitle paint.
    497         *
    498         * @return The subtitle paint (never <code>null</code>).
    499         *
    500         * @see #setSubtitlePaint(Paint)
    501         */
    502        public Paint getSubtitlePaint() {
    503            return this.subtitlePaint;
    504        }
    505
    506        /**
    507         * Sets the subtitle paint.
    508         *
    509         * @param paint  the paint (<code>null</code> not permitted).
    510         *
    511         * @see #getSubtitlePaint()
    512         */
    513        public void setSubtitlePaint(Paint paint) {
    514            if (paint == null) {
    515                throw new IllegalArgumentException("Null 'paint' argument.");
    516            }
    517            this.subtitlePaint = paint;
    518        }
    519
    520        /**
    521         * Returns the chart background paint.
    522         *
    523         * @return The chart background paint (never <code>null</code>).
    524         *
    525         * @see #setChartBackgroundPaint(Paint)
    526         */
    527        public Paint getChartBackgroundPaint() {
    528            return this.chartBackgroundPaint;
    529        }
    530
    531        /**
    532         * Sets the chart background paint.
    533         *
    534         * @param paint  the paint (<code>null</code> not permitted).
    535         *
    536         * @see #getChartBackgroundPaint()
    537         */
    538        public void setChartBackgroundPaint(Paint paint) {
    539            if (paint == null) {
    540                throw new IllegalArgumentException("Null 'paint' argument.");
    541            }
    542            this.chartBackgroundPaint = paint;
    543        }
    544
    545        /**
    546         * Returns the legend background paint.
    547         *
    548         * @return The legend background paint (never <code>null</code>).
    549         *
    550         * @see #setLegendBackgroundPaint(Paint)
    551         */
    552        public Paint getLegendBackgroundPaint() {
    553            return this.legendBackgroundPaint;
    554        }
    555
    556        /**
    557         * Sets the legend background paint.
    558         *
    559         * @param paint  the paint (<code>null</code> not permitted).
    560         *
    561         * @see #getLegendBackgroundPaint()
    562         */
    563        public void setLegendBackgroundPaint(Paint paint) {
    564            if (paint == null) {
    565                throw new IllegalArgumentException("Null 'paint' argument.");
    566            }
    567            this.legendBackgroundPaint = paint;
    568        }
    569
    570        /**
    571         * Returns the legend item paint.
    572         *
    573         * @return The legend item paint (never <code>null</code>).
    574         *
    575         * @see #setLegendItemPaint(Paint)
    576         */
    577        public Paint getLegendItemPaint() {
    578            return this.legendItemPaint;
    579        }
    580
    581        /**
    582         * Sets the legend item paint.
    583         *
    584         * @param paint  the paint (<code>null</code> not permitted).
    585         *
    586         * @see #getLegendItemPaint()
    587         */
    588        public void setLegendItemPaint(Paint paint) {
    589            if (paint == null) {
    590                throw new IllegalArgumentException("Null 'paint' argument.");
    591            }
    592            this.legendItemPaint = paint;
    593        }
    594
    595        /**
    596         * Returns the plot background paint.
    597         *
    598         * @return The plot background paint (never <code>null</code>).
    599         *
    600         * @see #setPlotBackgroundPaint(Paint)
    601         */
    602        public Paint getPlotBackgroundPaint() {
    603            return this.plotBackgroundPaint;
    604        }
    605
    606        /**
    607         * Sets the plot background paint.
    608         *
    609         * @param paint  the paint (<code>null</code> not permitted).
    610         *
    611         * @see #getPlotBackgroundPaint()
    612         */
    613        public void setPlotBackgroundPaint(Paint paint) {
    614            if (paint == null) {
    615                throw new IllegalArgumentException("Null 'paint' argument.");
    616            }
    617            this.plotBackgroundPaint = paint;
    618        }
    619
    620        /**
    621         * Returns the plot outline paint.
    622         *
    623         * @return The plot outline paint (never <code>null</code>).
    624         *
    625         * @see #setPlotOutlinePaint(Paint)
    626         */
    627        public Paint getPlotOutlinePaint() {
    628            return this.plotOutlinePaint;
    629        }
    630
    631        /**
    632         * Sets the plot outline paint.
    633         *
    634         * @param paint  the paint (<code>null</code> not permitted).
    635         *
    636         * @see #getPlotOutlinePaint()
    637         */
    638        public void setPlotOutlinePaint(Paint paint) {
    639            if (paint == null) {
    640                throw new IllegalArgumentException("Null 'paint' argument.");
    641            }
    642            this.plotOutlinePaint = paint;
    643        }
    644
    645        /**
    646         * Returns the label link style for pie charts.
    647         *
    648         * @return The label link style (never <code>null</code>).
    649         *
    650         * @see #setLabelLinkStyle(PieLabelLinkStyle)
    651         */
    652        public PieLabelLinkStyle getLabelLinkStyle() {
    653            return this.labelLinkStyle;
    654        }
    655
    656        /**
    657         * Sets the label link style for pie charts.
    658         *
    659         * @param style  the style (<code>null</code> not permitted).
    660         *
    661         * @see #getLabelLinkStyle()
    662         */
    663        public void setLabelLinkStyle(PieLabelLinkStyle style) {
    664            if (style == null) {
    665                throw new IllegalArgumentException("Null 'style' argument.");
    666            }
    667            this.labelLinkStyle = style;
    668        }
    669
    670        /**
    671         * Returns the label link paint for pie charts.
    672         *
    673         * @return The label link paint (never <code>null</code>).
    674         *
    675         * @see #setLabelLinkPaint(Paint)
    676         */
    677        public Paint getLabelLinkPaint() {
    678            return this.labelLinkPaint;
    679        }
    680
    681        /**
    682         * Sets the label link paint for pie charts.
    683         *
    684         * @param paint  the paint (<code>null</code> not permitted).
    685         *
    686         * @see #getLabelLinkPaint()
    687         */
    688        public void setLabelLinkPaint(Paint paint) {
    689            if (paint == null) {
    690                throw new IllegalArgumentException("Null 'paint' argument.");
    691            }
    692            this.labelLinkPaint = paint;
    693        }
    694
    695        /**
    696         * Returns the domain grid line paint.
    697         *
    698         * @return The domain grid line paint (never <code>null</code>).
    699         *
    700         * @see #setDomainGridlinePaint(Paint)
    701         */
    702        public Paint getDomainGridlinePaint() {
    703            return this.domainGridlinePaint;
    704        }
    705
    706        /**
    707         * Sets the domain grid line paint.
    708         *
    709         * @param paint  the paint (<code>null</code> not permitted).
    710         *
    711         * @see #getDomainGridlinePaint()
    712         */
    713        public void setDomainGridlinePaint(Paint paint) {
    714            if (paint == null) {
    715                throw new IllegalArgumentException("Null 'paint' argument.");
    716            }
    717            this.domainGridlinePaint = paint;
    718        }
    719
    720        /**
    721         * Returns the range grid line paint.
    722         *
    723         * @return The range grid line paint (never <code>null</code>).
    724         *
    725         * @see #setRangeGridlinePaint(Paint)
    726         */
    727        public Paint getRangeGridlinePaint() {
    728            return this.rangeGridlinePaint;
    729        }
    730
    731        /**
    732         * Sets the range grid line paint.
    733         *
    734         * @param paint  the paint (<code>null</code> not permitted).
    735         *
    736         * @see #getRangeGridlinePaint()
    737         */
    738        public void setRangeGridlinePaint(Paint paint) {
    739            if (paint == null) {
    740                throw new IllegalArgumentException("Null 'paint' argument.");
    741            }
    742            this.rangeGridlinePaint = paint;
    743        }
    744
    745        /**
    746         * Returns the baseline paint.
    747         *
    748         * @return The baseline paint.
    749         *
    750         * @since 1.0.13
    751         */
    752        public Paint getBaselinePaint() {
    753            return this.baselinePaint;
    754        }
    755
    756        /**
    757         * Sets the baseline paint.
    758         *
    759         * @param paint  the paint (<code>null</code> not permitted).
    760         *
    761         * @since 1.0.13
    762         */
    763        public void setBaselinePaint(Paint paint) {
    764            if (paint == null) {
    765                throw new IllegalArgumentException("Null 'paint' argument.");
    766            }
    767            this.baselinePaint = paint;
    768        }
    769
    770        /**
    771         * Returns the crosshair paint.
    772         *
    773         * @return The crosshair paint.
    774         */
    775        public Paint getCrosshairPaint() {
    776            return this.crosshairPaint;
    777        }
    778
    779        /**
    780         * Sets the crosshair paint.
    781         *
    782         * @param paint  the paint (<code>null</code> not permitted).
    783         */
    784        public void setCrosshairPaint(Paint paint) {
    785            if (paint == null) {
    786                throw new IllegalArgumentException("Null 'paint' argument.");
    787            }
    788            this.crosshairPaint = paint;
    789        }
    790
    791        /**
    792         * Returns the axis offsets.
    793         *
    794         * @return The axis offsets (never <code>null</code>).
    795         *
    796         * @see #setAxisOffset(RectangleInsets)
    797         */
    798        public RectangleInsets getAxisOffset() {
    799            return this.axisOffset;
    800        }
    801
    802        /**
    803         * Sets the axis offset.
    804         *
    805         * @param offset  the offset (<code>null</code> not permitted).
    806         *
    807         * @see #getAxisOffset()
    808         */
    809        public void setAxisOffset(RectangleInsets offset) {
    810            if (offset == null) {
    811                throw new IllegalArgumentException("Null 'offset' argument.");
    812            }
    813            this.axisOffset = offset;
    814        }
    815
    816        /**
    817         * Returns the axis label paint.
    818         *
    819         * @return The axis label paint (never <code>null</code>).
    820         *
    821         * @see #setAxisLabelPaint(Paint)
    822         */
    823        public Paint getAxisLabelPaint() {
    824            return this.axisLabelPaint;
    825        }
    826
    827        /**
    828         * Sets the axis label paint.
    829         *
    830         * @param paint  the paint (<code>null</code> not permitted).
    831         *
    832         * @see #getAxisLabelPaint()
    833         */
    834        public void setAxisLabelPaint(Paint paint) {
    835            if (paint == null) {
    836                throw new IllegalArgumentException("Null 'paint' argument.");
    837            }
    838            this.axisLabelPaint = paint;
    839        }
    840
    841        /**
    842         * Returns the tick label paint.
    843         *
    844         * @return The tick label paint (never <code>null</code>).
    845         *
    846         * @see #setTickLabelPaint(Paint)
    847         */
    848        public Paint getTickLabelPaint() {
    849            return this.tickLabelPaint;
    850        }
    851
    852        /**
    853         * Sets the tick label paint.
    854         *
    855         * @param paint  the paint (<code>null</code> not permitted).
    856         *
    857         * @see #getTickLabelPaint()
    858         */
    859        public void setTickLabelPaint(Paint paint) {
    860            if (paint == null) {
    861                throw new IllegalArgumentException("Null 'paint' argument.");
    862            }
    863            this.tickLabelPaint = paint;
    864        }
    865
    866        /**
    867         * Returns the item label paint.
    868         *
    869         * @return The item label paint (never <code>null</code>).
    870         *
    871         * @see #setItemLabelPaint(Paint)
    872         */
    873        public Paint getItemLabelPaint() {
    874            return this.itemLabelPaint;
    875        }
    876
    877        /**
    878         * Sets the item label paint.
    879         *
    880         * @param paint  the paint (<code>null</code> not permitted).
    881         *
    882         * @see #getItemLabelPaint()
    883         */
    884        public void setItemLabelPaint(Paint paint) {
    885            if (paint == null) {
    886                throw new IllegalArgumentException("Null 'paint' argument.");
    887            }
    888            this.itemLabelPaint = paint;
    889        }
    890
    891        /**
    892         * Returns the shadow visibility flag.
    893         *
    894         * @return The shadow visibility flag.
    895         *
    896         * @see #setShadowVisible(boolean)
    897         */
    898        public boolean isShadowVisible() {
    899            return this.shadowVisible;
    900        }
    901
    902        /**
    903         * Sets the shadow visibility flag.
    904         *
    905         * @param visible  the flag.
    906         *
    907         * @see #isShadowVisible()
    908         */
    909        public void setShadowVisible(boolean visible) {
    910            this.shadowVisible = visible;
    911        }
    912
    913        /**
    914         * Returns the shadow paint.
    915         *
    916         * @return The shadow paint (never <code>null</code>).
    917         *
    918         * @see #setShadowPaint(Paint)
    919         */
    920        public Paint getShadowPaint() {
    921            return this.shadowPaint;
    922        }
    923
    924        /**
    925         * Sets the shadow paint.
    926         *
    927         * @param paint  the paint (<code>null</code> not permitted).
    928         *
    929         * @see #getShadowPaint()
    930         */
    931        public void setShadowPaint(Paint paint) {
    932            if (paint == null) {
    933                throw new IllegalArgumentException("Null 'paint' argument.");
    934            }
    935            this.shadowPaint = paint;
    936        }
    937
    938        /**
    939         * Returns the bar painter.
    940         *
    941         * @return The bar painter (never <code>null</code>).
    942         *
    943         * @see #setBarPainter(BarPainter)
    944         */
    945        public BarPainter getBarPainter() {
    946            return this.barPainter;
    947        }
    948
    949        /**
    950         * Sets the bar painter.
    951         *
    952         * @param painter  the painter (<code>null</code> not permitted).
    953         *
    954         * @see #getBarPainter()
    955         */
    956        public void setBarPainter(BarPainter painter) {
    957            if (painter == null) {
    958                throw new IllegalArgumentException("Null 'painter' argument.");
    959            }
    960            this.barPainter = painter;
    961        }
    962
    963        /**
    964         * Returns the XY bar painter.
    965         *
    966         * @return The XY bar painter (never <code>null</code>).
    967         *
    968         * @see #setXYBarPainter(XYBarPainter)
    969         */
    970        public XYBarPainter getXYBarPainter() {
    971            return this.xyBarPainter;
    972        }
    973
    974        /**
    975         * Sets the XY bar painter.
    976         *
    977         * @param painter  the painter (<code>null</code> not permitted).
    978         *
    979         * @see #getXYBarPainter()
    980         */
    981        public void setXYBarPainter(XYBarPainter painter) {
    982            if (painter == null) {
    983                throw new IllegalArgumentException("Null 'painter' argument.");
    984            }
    985            this.xyBarPainter = painter;
    986        }
    987
    988        /**
    989         * Returns the thermometer paint.
    990         *
    991         * @return The thermometer paint (never <code>null</code>).
    992         *
    993         * @see #setThermometerPaint(Paint)
    994         */
    995        public Paint getThermometerPaint() {
    996            return this.thermometerPaint;
    997        }
    998
    999        /**
    1000         * Sets the thermometer paint.
    1001         *
    1002         * @param paint  the paint (<code>null</code> not permitted).
    1003         *
    1004         * @see #getThermometerPaint()
    1005         */
    1006        public void setThermometerPaint(Paint paint) {
    1007            if (paint == null) {
    1008                throw new IllegalArgumentException("Null 'paint' argument.");
    1009            }
    1010            this.thermometerPaint = paint;
    1011        }
    1012
    1013        /**
    1014         * Returns the wall paint for charts with a 3D effect.
    1015         *
    1016         * @return The wall paint (never <code>null</code>).
    1017         *
    1018         * @see #setWallPaint(Paint)
    1019         */
    1020        public Paint getWallPaint() {
    1021            return this.wallPaint;
    1022        }
    1023
    1024        /**
    1025         * Sets the wall paint for charts with a 3D effect.
    1026         *
    1027         * @param paint  the paint (<code>null</code> not permitted).
    1028         *
    1029         * @see #getWallPaint()
    1030         */
    1031        public void setWallPaint(Paint paint) {
    1032            if (paint == null) {
    1033                throw new IllegalArgumentException("Null 'paint' argument.");
    1034            }
    1035            this.wallPaint = paint;
    1036        }
    1037
    1038        /**
    1039         * Returns the error indicator paint.
    1040         *
    1041         * @return The error indicator paint (never <code>null</code>).
    1042         *
    1043         * @see #setErrorIndicatorPaint(Paint)
    1044         */
    1045        public Paint getErrorIndicatorPaint() {
    1046            return this.errorIndicatorPaint;
    1047        }
    1048
    1049        /**
    1050         * Sets the error indicator paint.
    1051         *
    1052         * @param paint  the paint (<code>null</code> not permitted).
    1053         *
    1054         * @see #getErrorIndicatorPaint()
    1055         */
    1056        public void setErrorIndicatorPaint(Paint paint) {
    1057            if (paint == null) {
    1058                throw new IllegalArgumentException("Null 'paint' argument.");
    1059            }
    1060            this.errorIndicatorPaint = paint;
    1061        }
    1062
    1063        /**
    1064         * Returns the grid band paint.
    1065         *
    1066         * @return The grid band paint (never <code>null</code>).
    1067         *
    1068         * @see #setGridBandPaint(Paint)
    1069         */
    1070        public Paint getGridBandPaint() {
    1071            return this.gridBandPaint;
    1072        }
    1073
    1074        /**
    1075         * Sets the grid band paint.
    1076         *
    1077         * @param paint  the paint (<code>null</code> not permitted).
    1078         *
    1079         * @see #getGridBandPaint()
    1080         */
    1081        public void setGridBandPaint(Paint paint) {
    1082            if (paint == null) {
    1083                throw new IllegalArgumentException("Null 'paint' argument.");
    1084            }
    1085            this.gridBandPaint = paint;
    1086        }
    1087
    1088        /**
    1089         * Returns the grid band alternate paint (used for a {@link SymbolAxis}).
    1090         *
    1091         * @return The paint (never <code>null</code>).
    1092         *
    1093         * @see #setGridBandAlternatePaint(Paint)
    1094         */
    1095        public Paint getGridBandAlternatePaint() {
    1096            return this.gridBandAlternatePaint;
    1097        }
    1098
    1099        /**
    1100         * Sets the grid band alternate paint (used for a {@link SymbolAxis}).
    1101         *
    1102         * @param paint  the paint (<code>null</code> not permitted).
    1103         *
    1104         * @see #getGridBandAlternatePaint()
    1105         */
    1106        public void setGridBandAlternatePaint(Paint paint) {
    1107            if (paint == null) {
    1108                throw new IllegalArgumentException("Null 'paint' argument.");
    1109            }
    1110            this.gridBandAlternatePaint = paint;
    1111        }
    1112
    1113        /**
    1114         * Returns the name of this theme.
    1115         *
    1116         * @return The name of this theme.
    1117         */
    1118        public String getName() {
    1119            return this.name;
    1120        }
    1121
    1122        /**
    1123         * Returns a clone of the drawing supplier for this theme.
    1124         *
    1125         * @return A clone of the drawing supplier.
    1126         */
    1127        public DrawingSupplier getDrawingSupplier() {
    1128            DrawingSupplier result = null;
    1129            if (this.drawingSupplier instanceof PublicCloneable) {
    1130                PublicCloneable pc = (PublicCloneable) this.drawingSupplier;
    1131                  try {
    1132                    result = (DrawingSupplier) pc.clone();
    1133                }
    1134                catch (CloneNotSupportedException e) {
    1135                    e.printStackTrace();
    1136                }
    1137            }
    1138            return result;
    1139        }
    1140
    1141        /**
    1142         * Sets the drawing supplier for this theme.
    1143         *
    1144         * @param supplier  the supplier (<code>null</code> not permitted).
    1145         *
    1146         * @see #getDrawingSupplier()
    1147         */
    1148        public void setDrawingSupplier(DrawingSupplier supplier) {
    1149            if (supplier == null) {
    1150                throw new IllegalArgumentException("Null 'supplier' argument.");
    1151            }
    1152            this.drawingSupplier = supplier;
    1153        }
    1154
    1155        /**
    1156         * Applies this theme to the supplied chart.
    1157         *
    1158         * @param chart  the chart (<code>null</code> not permitted).
    1159         */
    1160        public void apply(JFreeChart chart) {
    1161            if (chart == null) {
    1162                throw new IllegalArgumentException("Null 'chart' argument.");
    1163            }
    1164            TextTitle title = chart.getTitle();
    1165            if (title != null) {
    1166                title.setFont(this.extraLargeFont);
    1167                title.setPaint(this.titlePaint);
    1168            }
    1169
    1170            int subtitleCount = chart.getSubtitleCount();
    1171            for (int i = 0; i < subtitleCount; i++) {
    1172                applyToTitle(chart.getSubtitle(i));
    1173            }
    1174
    1175            chart.setBackgroundPaint(this.chartBackgroundPaint);
    1176
    1177            // now process the plot if there is one
    1178            Plot plot = chart.getPlot();
    1179            if (plot != null) {
    1180                applyToPlot(plot);
    1181            }
    1182        }
    1183
    1184        /**
    1185         * Applies the attributes of this theme to the specified title.
    1186         *
    1187         * @param title  the title.
    1188         */
    1189        protected void applyToTitle(Title title) {
    1190            if (title instanceof TextTitle) {
    1191                TextTitle tt = (TextTitle) title;
    1192                tt.setFont(this.largeFont);
    1193                tt.setPaint(this.subtitlePaint);
    1194            }
    1195            else if (title instanceof LegendTitle) {
    1196                LegendTitle lt = (LegendTitle) title;
    1197                if (lt.getBackgroundPaint() != null) {
    1198                    lt.setBackgroundPaint(this.legendBackgroundPaint);
    1199                }
    1200                lt.setItemFont(this.regularFont);
    1201                lt.setItemPaint(this.legendItemPaint);
    1202                if (lt.getWrapper() != null) {
    1203                    applyToBlockContainer(lt.getWrapper());
    1204                }
    1205            }
    1206            else if (title instanceof PaintScaleLegend) {
    1207                PaintScaleLegend psl = (PaintScaleLegend) title;
    1208                psl.setBackgroundPaint(this.legendBackgroundPaint);
    1209                ValueAxis axis = psl.getAxis();
    1210                if (axis != null) {
    1211                    applyToValueAxis(axis);
    1212                }
    1213            }
    1214            else if (title instanceof CompositeTitle) {
    1215                CompositeTitle ct = (CompositeTitle) title;
    1216                BlockContainer bc = ct.getContainer();
    1217                List blocks = bc.getBlocks();
    1218                Iterator iterator = blocks.iterator();
    1219                while (iterator.hasNext()) {
    1220                    Block b = (Block) iterator.next();
    1221                    if (b instanceof Title) {
    1222                        applyToTitle((Title) b);
    1223                    }
    1224                }
    1225            }
    1226        }
    1227
    1228        /**
    1229         * Applies the attributes of this theme to the specified container.
    1230         *
    1231         * @param bc  a block container (<code>null</code> not permitted).
    1232         */
    1233        protected void applyToBlockContainer(BlockContainer bc) {
    1234            Iterator iterator = bc.getBlocks().iterator();
    1235            while (iterator.hasNext()) {
    1236                Block b = (Block) iterator.next();
    1237                applyToBlock(b);
    1238            }
    1239        }
    1240
    1241        /**
    1242         * Applies the attributes of this theme to the specified block.
    1243         *
    1244         * @param b  the block.
    1245         */
    1246        protected void applyToBlock(Block b) {
    1247            if (b instanceof Title) {
    1248                applyToTitle((Title) b);
    1249            }
    1250            else if (b instanceof LabelBlock) {
    1251                LabelBlock lb = (LabelBlock) b;
    1252                lb.setFont(this.regularFont);
    1253                lb.setPaint(this.legendItemPaint);
    1254            }
    1255        }
    1256
    1257        /**
    1258         * Applies the attributes of this theme to a plot.
    1259         *
    1260         * @param plot  the plot (<code>null</code>).
    1261         */
    1262        protected void applyToPlot(Plot plot) {
    1263            if (plot == null) {
    1264                throw new IllegalArgumentException("Null 'plot' argument.");
    1265            }
    1266            if (plot.getDrawingSupplier() != null) {
    1267                plot.setDrawingSupplier(getDrawingSupplier());
    1268            }
    1269            if (plot.getBackgroundPaint() != null) {
    1270                plot.setBackgroundPaint(this.plotBackgroundPaint);
    1271            }
    1272            plot.setOutlinePaint(this.plotOutlinePaint);
    1273
    1274            // now handle specific plot types (and yes, I know this is some
    1275            // really ugly code that has to be manually updated any time a new
    1276            // plot type is added - I should have written something much cooler,
    1277            // but I didn't and neither did anyone else).
    1278            if (plot instanceof PiePlot) {
    1279                applyToPiePlot((PiePlot) plot);
    1280            }
    1281            else if (plot instanceof MultiplePiePlot) {
    1282                applyToMultiplePiePlot((MultiplePiePlot) plot);
    1283            }
    1284            else if (plot instanceof CategoryPlot) {
    1285                applyToCategoryPlot((CategoryPlot) plot);
    1286            }
    1287            else if (plot instanceof XYPlot) {
    1288                applyToXYPlot((XYPlot) plot);
    1289            }
    1290            else if (plot instanceof FastScatterPlot) {
    1291                applyToFastScatterPlot((FastScatterPlot) plot);
    1292            }
    1293            else if (plot instanceof MeterPlot) {
    1294                applyToMeterPlot((MeterPlot) plot);
    1295            }
    1296            else if (plot instanceof ThermometerPlot) {
    1297                applyToThermometerPlot((ThermometerPlot) plot);
    1298            }
    1299            else if (plot instanceof SpiderWebPlot) {
    1300                applyToSpiderWebPlot((SpiderWebPlot) plot);
    1301            }
    1302            else if (plot instanceof PolarPlot) {
    1303                applyToPolarPlot((PolarPlot) plot);
    1304            }
    1305        }
    1306
    1307        /**
    1308         * Applies the attributes of this theme to a {@link PiePlot} instance.
    1309         * This method also clears any set values for the section paint, outline
    1310         * etc, so that the theme's {@link DrawingSupplier} will be used.
    1311         *
    1312         * @param plot  the plot (<code>null</code> not permitted).
    1313         */
    1314        protected void applyToPiePlot(PiePlot plot) {
    1315            plot.setLabelLinkPaint(this.labelLinkPaint);
    1316            plot.setLabelLinkStyle(this.labelLinkStyle);
    1317            plot.setLabelFont(this.regularFont);
    1318            plot.setShadowGenerator(this.shadowGenerator);
    1319
    1320            // clear the section attributes so that the theme's DrawingSupplier
    1321            // will be used
    1322            if (plot.getAutoPopulateSectionPaint()) {
    1323                plot.clearSectionPaints(false);
    1324            }
    1325            if (plot.getAutoPopulateSectionOutlinePaint()) {
    1326                plot.clearSectionOutlinePaints(false);
    1327            }
    1328            if (plot.getAutoPopulateSectionOutlineStroke()) {
    1329                plot.clearSectionOutlineStrokes(false);
    1330            }
    1331        }
    1332
    1333        /**
    1334         * Applies the attributes of this theme to a {@link MultiplePiePlot}.
    1335         *
    1336         * @param plot  the plot (<code>null</code> not permitted).
    1337         */
    1338        protected void applyToMultiplePiePlot(MultiplePiePlot plot) {
    1339            apply(plot.getPieChart());
    1340        }
    1341
    1342        /**
    1343         * Applies the attributes of this theme to a {@link CategoryPlot}.
    1344         *
    1345         * @param plot  the plot (<code>null</code> not permitted).
    1346         */
    1347        protected void applyToCategoryPlot(CategoryPlot plot) {
    1348            plot.setAxisOffset(this.axisOffset);
    1349            plot.setDomainGridlinePaint(this.domainGridlinePaint);
    1350            plot.setRangeGridlinePaint(this.rangeGridlinePaint);
    1351            plot.setRangeZeroBaselinePaint(this.baselinePaint);
    1352            plot.setShadowGenerator(this.shadowGenerator);
    1353
    1354            // process all domain axes
    1355            int domainAxisCount = plot.getDomainAxisCount();
    1356            for (int i = 0; i < domainAxisCount; i++) {
    1357                CategoryAxis axis = plot.getDomainAxis(i);
    1358                if (axis != null) {
    1359                    applyToCategoryAxis(axis);
    1360                }
    1361            }
    1362
    1363            // process all range axes
    1364            int rangeAxisCount = plot.getRangeAxisCount();
    1365            for (int i = 0; i < rangeAxisCount; i++) {
    1366                ValueAxis axis = plot.getRangeAxis(i);
    1367                if (axis != null) {
    1368                    applyToValueAxis(axis);
    1369                }
    1370            }
    1371
    1372            // process all renderers
    1373            int rendererCount = plot.getRendererCount();
    1374            for (int i = 0; i < rendererCount; i++) {
    1375                CategoryItemRenderer r = plot.getRenderer(i);
    1376                if (r != null) {
    1377                    applyToCategoryItemRenderer(r);
    1378                }
    1379            }
    1380
    1381            if (plot instanceof CombinedDomainCategoryPlot) {
    1382                CombinedDomainCategoryPlot cp = (CombinedDomainCategoryPlot) plot;
    1383                Iterator iterator = cp.getSubplots().iterator();
    1384                while (iterator.hasNext()) {
    1385                    CategoryPlot subplot = (CategoryPlot) iterator.next();
    1386                    if (subplot != null) {
    1387                        applyToPlot(subplot);
    1388                    }
    1389                }
    1390            }
    1391            if (plot instanceof CombinedRangeCategoryPlot) {
    1392                CombinedRangeCategoryPlot cp = (CombinedRangeCategoryPlot) plot;
    1393                Iterator iterator = cp.getSubplots().iterator();
    1394                while (iterator.hasNext()) {
    1395                    CategoryPlot subplot = (CategoryPlot) iterator.next();
    1396                    if (subplot != null) {
    1397                        applyToPlot(subplot);
    1398                    }
    1399                }
    1400            }
    1401        }
    1402
    1403        /**
    1404         * Applies the attributes of this theme to a {@link XYPlot}.
    1405         *
    1406         * @param plot  the plot (<code>null</code> not permitted).
    1407         */
    1408        protected void applyToXYPlot(XYPlot plot) {
    1409            plot.setAxisOffset(this.axisOffset);
    1410            plot.setDomainZeroBaselinePaint(this.baselinePaint);
    1411            plot.setRangeZeroBaselinePaint(this.baselinePaint);
    1412            plot.setDomainGridlinePaint(this.domainGridlinePaint);
    1413            plot.setRangeGridlinePaint(this.rangeGridlinePaint);
    1414            plot.setDomainCrosshairPaint(this.crosshairPaint);
    1415            plot.setRangeCrosshairPaint(this.crosshairPaint);
    1416            plot.setShadowGenerator(this.shadowGenerator);
    1417
    1418            // process all domain axes
    1419            int domainAxisCount = plot.getDomainAxisCount();
    1420            for (int i = 0; i < domainAxisCount; i++) {
    1421                ValueAxis axis = plot.getDomainAxis(i);
    1422                if (axis != null) {
    1423                    applyToValueAxis(axis);
    1424                }
    1425            }
    1426
    1427            // process all range axes
    1428            int rangeAxisCount = plot.getRangeAxisCount();
    1429            for (int i = 0; i < rangeAxisCount; i++) {
    1430                ValueAxis axis = plot.getRangeAxis(i);
    1431                if (axis != null) {
    1432                    applyToValueAxis(axis);
    1433                }
    1434            }
    1435
    1436            // process all renderers
    1437            int rendererCount = plot.getRendererCount();
    1438            for (int i = 0; i < rendererCount; i++) {
    1439                XYItemRenderer r = plot.getRenderer(i);
    1440                if (r != null) {
    1441                    applyToXYItemRenderer(r);
    1442                }
    1443            }
    1444
    1445            // process all annotations
    1446            Iterator iter = plot.getAnnotations().iterator();
    1447            while (iter.hasNext()) {
    1448                XYAnnotation a = (XYAnnotation) iter.next();
    1449                applyToXYAnnotation(a);
    1450            }
    1451
    1452            if (plot instanceof CombinedDomainXYPlot) {
    1453                CombinedDomainXYPlot cp = (CombinedDomainXYPlot) plot;
    1454                Iterator iterator = cp.getSubplots().iterator();
    1455                while (iterator.hasNext()) {
    1456                    XYPlot subplot = (XYPlot) iterator.next();
    1457                    if (subplot != null) {
    1458                        applyToPlot(subplot);
    1459                    }
    1460                }
    1461            }
    1462            if (plot instanceof CombinedRangeXYPlot) {
    1463                CombinedRangeXYPlot cp = (CombinedRangeXYPlot) plot;
    1464                Iterator iterator = cp.getSubplots().iterator();
    1465                while (iterator.hasNext()) {
    1466                    XYPlot subplot = (XYPlot) iterator.next();
    1467                    if (subplot != null) {
    1468                        applyToPlot(subplot);
    1469                    }
    1470                }
    1471            }
    1472        }
    1473
    1474        /**
    1475         * Applies the attributes of this theme to a {@link FastScatterPlot}.
    1476         * @param plot
    1477         */
    1478        protected void applyToFastScatterPlot(FastScatterPlot plot) {
    1479            plot.setDomainGridlinePaint(this.domainGridlinePaint);
    1480            plot.setRangeGridlinePaint(this.rangeGridlinePaint);
    1481            ValueAxis xAxis = plot.getDomainAxis();
    1482            if (xAxis != null) {
    1483                applyToValueAxis(xAxis);
    1484            }
    1485            ValueAxis yAxis = plot.getRangeAxis();
    1486            if (yAxis != null) {
    1487                applyToValueAxis(yAxis);
    1488            }
    1489
    1490        }
    1491
    1492        /**
    1493         * Applies the attributes of this theme to a {@link PolarPlot}.  This
    1494         * method is called from the {@link #applyToPlot(Plot)} method.
    1495         *
    1496         * @param plot  the plot (<code>null</code> not permitted).
    1497         */
    1498        protected void applyToPolarPlot(PolarPlot plot) {
    1499            plot.setAngleLabelFont(this.regularFont);
    1500            plot.setAngleLabelPaint(this.tickLabelPaint);
    1501            plot.setAngleGridlinePaint(this.domainGridlinePaint);
    1502            plot.setRadiusGridlinePaint(this.rangeGridlinePaint);
    1503            ValueAxis axis = plot.getAxis();
    1504            if (axis != null) {
    1505                applyToValueAxis(axis);
    1506            }
    1507        }
    1508
    1509        /**
    1510         * Applies the attributes of this theme to a {@link SpiderWebPlot}.
    1511         *
    1512         * @param plot  the plot (<code>null</code> not permitted).
    1513         */
    1514        protected void applyToSpiderWebPlot(SpiderWebPlot plot) {
    1515            plot.setLabelFont(this.regularFont);
    1516            plot.setLabelPaint(this.axisLabelPaint);
    1517            plot.setAxisLinePaint(this.axisLabelPaint);
    1518        }
    1519
    1520        /**
    1521         * Applies the attributes of this theme to a {@link MeterPlot}.
    1522         *
    1523         * @param plot  the plot (<code>null</code> not permitted).
    1524         */
    1525        protected void applyToMeterPlot(MeterPlot plot) {
    1526            plot.setDialBackgroundPaint(this.plotBackgroundPaint);
    1527            plot.setValueFont(this.largeFont);
    1528            plot.setValuePaint(this.axisLabelPaint);
    1529            plot.setDialOutlinePaint(this.plotOutlinePaint);
    1530            plot.setNeedlePaint(this.thermometerPaint);
    1531            plot.setTickLabelFont(this.regularFont);
    1532            plot.setTickLabelPaint(this.tickLabelPaint);
    1533        }
    1534
    1535        /**
    1536         * Applies the attributes for this theme to a {@link ThermometerPlot}.
    1537         * This method is called from the {@link #applyToPlot(Plot)} method.
    1538         *
    1539         * @param plot  the plot.
    1540         */
    1541        protected void applyToThermometerPlot(ThermometerPlot plot) {
    1542            plot.setValueFont(this.largeFont);
    1543            plot.setThermometerPaint(this.thermometerPaint);
    1544            ValueAxis axis = plot.getRangeAxis();
    1545            if (axis != null) {
    1546                applyToValueAxis(axis);
    1547            }
    1548        }
    1549
    1550        /**
    1551         * Applies the attributes for this theme to a {@link CategoryAxis}.
    1552         *
    1553         * @param axis  the axis (<code>null</code> not permitted).
    1554         */
    1555        protected void applyToCategoryAxis(CategoryAxis axis) {
    1556            axis.setLabelFont(this.largeFont);
    1557            axis.setLabelPaint(this.axisLabelPaint);
    1558            axis.setTickLabelFont(this.regularFont);
    1559            axis.setTickLabelPaint(this.tickLabelPaint);
    1560            if (axis instanceof SubCategoryAxis) {
    1561                SubCategoryAxis sca = (SubCategoryAxis) axis;
    1562                sca.setSubLabelFont(this.regularFont);
    1563                sca.setSubLabelPaint(this.tickLabelPaint);
    1564            }
    1565        }
    1566
    1567        /**
    1568         * Applies the attributes for this theme to a {@link ValueAxis}.
    1569         *
    1570         * @param axis  the axis (<code>null</code> not permitted).
    1571         */
    1572        protected void applyToValueAxis(ValueAxis axis) {
    1573            axis.setLabelFont(this.largeFont);
    1574            axis.setLabelPaint(this.axisLabelPaint);
    1575            axis.setTickLabelFont(this.regularFont);
    1576            axis.setTickLabelPaint(this.tickLabelPaint);
    1577            if (axis instanceof SymbolAxis) {
    1578                applyToSymbolAxis((SymbolAxis) axis);
    1579            }
    1580            if (axis instanceof PeriodAxis) {
    1581                applyToPeriodAxis((PeriodAxis) axis);
    1582            }
    1583        }
    1584
    1585        /**
    1586         * Applies the attributes for this theme to a {@link SymbolAxis}.
    1587         *
    1588         * @param axis  the axis (<code>null</code> not permitted).
    1589         */
    1590        protected void applyToSymbolAxis(SymbolAxis axis) {
    1591            axis.setGridBandPaint(this.gridBandPaint);
    1592            axis.setGridBandAlternatePaint(this.gridBandAlternatePaint);
    1593        }
    1594
    1595        /**
    1596         * Applies the attributes for this theme to a {@link PeriodAxis}.
    1597         *
    1598         * @param axis  the axis (<code>null</code> not permitted).
    1599         */
    1600        protected void applyToPeriodAxis(PeriodAxis axis) {
    1601            PeriodAxisLabelInfo[] info = axis.getLabelInfo();
    1602            for (int i = 0; i < info.length; i++) {
    1603                PeriodAxisLabelInfo e = info[i];
    1604                PeriodAxisLabelInfo n = new PeriodAxisLabelInfo(e.getPeriodClass(),
    1605                        e.getDateFormat(), e.getPadding(), this.regularFont,
    1606                        this.tickLabelPaint, e.getDrawDividers(),
    1607                        e.getDividerStroke(), e.getDividerPaint());
    1608                info[i] = n;
    1609            }
    1610            axis.setLabelInfo(info);
    1611        }
    1612
    1613        /**
    1614         * Applies the attributes for this theme to an {@link AbstractRenderer}.
    1615         *
    1616         * @param renderer  the renderer (<code>null</code> not permitted).
    1617         */
    1618        protected void applyToAbstractRenderer(AbstractRenderer renderer) {
    1619            if (renderer.getAutoPopulateSeriesPaint()) {
    1620                renderer.clearSeriesPaints(false);
    1621            }
    1622            if (renderer.getAutoPopulateSeriesStroke()) {
    1623                renderer.clearSeriesStrokes(false);
    1624            }
    1625        }
    1626
    1627        /**
    1628         * Applies the settings of this theme to the specified renderer.
    1629         *
    1630         * @param renderer  the renderer (<code>null</code> not permitted).
    1631         */
    1632        protected void applyToCategoryItemRenderer(CategoryItemRenderer renderer) {
    1633            if (renderer == null) {
    1634                throw new IllegalArgumentException("Null 'renderer' argument.");
    1635            }
    1636
    1637            if (renderer instanceof AbstractRenderer) {
    1638                applyToAbstractRenderer((AbstractRenderer) renderer);
    1639            }
    1640
    1641            renderer.setBaseItemLabelFont(this.regularFont);
    1642            renderer.setBaseItemLabelPaint(this.itemLabelPaint);
    1643
    1644            // now we handle some special cases - yes, UGLY code alert!
    1645
    1646            // BarRenderer
    1647            if (renderer instanceof BarRenderer) {
    1648                BarRenderer br = (BarRenderer) renderer;
    1649                br.setBarPainter(this.barPainter);
    1650                br.setShadowVisible(this.shadowVisible);
    1651                br.setShadowPaint(this.shadowPaint);
    1652            }
    1653
    1654            // BarRenderer3D
    1655            if (renderer instanceof BarRenderer3D) {
    1656                BarRenderer3D br3d = (BarRenderer3D) renderer;
    1657                br3d.setWallPaint(this.wallPaint);
    1658            }
    1659
    1660            // LineRenderer3D
    1661            if (renderer instanceof LineRenderer3D) {
    1662                LineRenderer3D lr3d = (LineRenderer3D) renderer;
    1663                lr3d.setWallPaint(this.wallPaint);
    1664            }
    1665
    1666            //  StatisticalBarRenderer
    1667            if (renderer instanceof StatisticalBarRenderer) {
    1668                StatisticalBarRenderer sbr = (StatisticalBarRenderer) renderer;
    1669                sbr.setErrorIndicatorPaint(this.errorIndicatorPaint);
    1670            }
    1671
    1672            // MinMaxCategoryRenderer
    1673            if (renderer instanceof MinMaxCategoryRenderer) {
    1674                MinMaxCategoryRenderer mmcr = (MinMaxCategoryRenderer) renderer;
    1675                mmcr.setGroupPaint(this.errorIndicatorPaint);
    1676            }
    1677        }
    1678
    1679        /**
    1680         * Applies the settings of this theme to the specified renderer.
    1681         *
    1682         * @param renderer  the renderer (<code>null</code> not permitted).
    1683         */
    1684        protected void applyToXYItemRenderer(XYItemRenderer renderer) {
    1685            if (renderer == null) {
    1686                throw new IllegalArgumentException("Null 'renderer' argument.");
    1687            }
    1688            if (renderer instanceof AbstractRenderer) {
    1689                applyToAbstractRenderer((AbstractRenderer) renderer);
    1690            }
    1691            renderer.setBaseItemLabelFont(this.regularFont);
    1692            renderer.setBaseItemLabelPaint(this.itemLabelPaint);
    1693            if (renderer instanceof XYBarRenderer) {
    1694                XYBarRenderer br = (XYBarRenderer) renderer;
    1695                br.setBarPainter(this.xyBarPainter);
    1696                br.setShadowVisible(this.shadowVisible);
    1697            }
    1698        }
    1699
    1700        /**
    1701         * Applies the settings of this theme to the specified annotation.
    1702         *
    1703         * @param annotation  the annotation.
    1704         */
    1705        protected void applyToXYAnnotation(XYAnnotation annotation) {
    1706            if (annotation == null) {
    1707                throw new IllegalArgumentException("Null 'annotation' argument.");
    1708            }
    1709            if (annotation instanceof XYTextAnnotation) {
    1710                XYTextAnnotation xyta = (XYTextAnnotation) annotation;
    1711                xyta.setFont(this.smallFont);
    1712                xyta.setPaint(this.itemLabelPaint);
    1713            }
    1714        }
    1715
    1716        /**
    1717         * Tests this theme for equality with an arbitrary object.
    1718         *
    1719         * @param obj  the object (<code>null</code> permitted).
    1720         *
    1721         * @return A boolean.
    1722         */
    1723        public boolean equals(Object obj) {
    1724            if (obj == this) {
    1725                return true;
    1726            }
    1727            if (!(obj instanceof StandardChartTheme)) {
    1728                return false;
    1729            }
    1730            StandardChartTheme that = (StandardChartTheme) obj;
    1731            if (!this.name.equals(that.name)) {
    1732                return false;
    1733            }
    1734            if (!this.extraLargeFont.equals(that.extraLargeFont)) {
    1735                return false;
    1736            }
    1737            if (!this.largeFont.equals(that.largeFont)) {
    1738                return false;
    1739            }
    1740            if (!this.regularFont.equals(that.regularFont)) {
    1741                return false;
    1742            }
    1743            if (!this.smallFont.equals(that.smallFont)) {
    1744                return false;
    1745            }
    1746            if (!PaintUtilities.equal(this.titlePaint, that.titlePaint)) {
    1747                return false;
    1748            }
    1749            if (!PaintUtilities.equal(this.subtitlePaint, that.subtitlePaint)) {
    1750                return false;
    1751            }
    1752            if (!PaintUtilities.equal(this.chartBackgroundPaint,
    1753                    that.chartBackgroundPaint)) {
    1754                return false;
    1755            }
    1756            if (!PaintUtilities.equal(this.legendBackgroundPaint,
    1757                    that.legendBackgroundPaint)) {
    1758                return false;
    1759            }
    1760            if (!PaintUtilities.equal(this.legendItemPaint, that.legendItemPaint)) {
    1761                return false;
    1762            }
    1763            if (!this.drawingSupplier.equals(that.drawingSupplier)) {
    1764                return false;
    1765            }
    1766            if (!PaintUtilities.equal(this.plotBackgroundPaint,
    1767                    that.plotBackgroundPaint)) {
    1768                return false;
    1769            }
    1770            if (!PaintUtilities.equal(this.plotOutlinePaint,
    1771                    that.plotOutlinePaint)) {
    1772                return false;
    1773            }
    1774            if (!this.labelLinkStyle.equals(that.labelLinkStyle)) {
    1775                return false;
    1776            }
    1777            if (!PaintUtilities.equal(this.labelLinkPaint, that.labelLinkPaint)) {
    1778                return false;
    1779            }
    1780            if (!PaintUtilities.equal(this.domainGridlinePaint,
    1781                    that.domainGridlinePaint)) {
    1782                return false;
    1783            }
    1784            if (!PaintUtilities.equal(this.rangeGridlinePaint,
    1785                    that.rangeGridlinePaint)) {
    1786                return false;
    1787            }
    1788            if (!PaintUtilities.equal(this.crosshairPaint, that.crosshairPaint)) {
    1789                return false;
    1790            }
    1791            if (!this.axisOffset.equals(that.axisOffset)) {
    1792                return false;
    1793            }
    1794            if (!PaintUtilities.equal(this.axisLabelPaint, that.axisLabelPaint)) {
    1795                return false;
    1796            }
    1797            if (!PaintUtilities.equal(this.tickLabelPaint, that.tickLabelPaint)) {
    1798                return false;
    1799            }
    1800            if (!PaintUtilities.equal(this.itemLabelPaint, that.itemLabelPaint)) {
    1801                return false;
    1802            }
    1803            if (this.shadowVisible != that.shadowVisible) {
    1804                return false;
    1805            }
    1806            if (!PaintUtilities.equal(this.shadowPaint, that.shadowPaint)) {
    1807                return false;
    1808            }
    1809            if (!this.barPainter.equals(that.barPainter)) {
    1810                return false;
    1811            }
    1812            if (!this.xyBarPainter.equals(that.xyBarPainter)) {
    1813                return false;
    1814            }
    1815            if (!PaintUtilities.equal(this.thermometerPaint,
    1816                    that.thermometerPaint)) {
    1817                return false;
    1818            }
    1819            if (!PaintUtilities.equal(this.wallPaint, that.wallPaint)) {
    1820                return false;
    1821            }
    1822            if (!PaintUtilities.equal(this.errorIndicatorPaint,
    1823                    that.errorIndicatorPaint)) {
    1824                return false;
    1825            }
    1826            if (!PaintUtilities.equal(this.gridBandPaint, that.gridBandPaint)) {
    1827                return false;
    1828            }
    1829            if (!PaintUtilities.equal(this.gridBandAlternatePaint,
    1830                    that.gridBandAlternatePaint)) {
    1831                return false;
    1832            }
    1833            return true;
    1834        }
    1835
    1836        /**
    1837         * Returns a clone of this theme.
    1838         *
    1839         * @return A clone.
    1840         *
    1841         * @throws CloneNotSupportedException if the theme cannot be cloned.
    1842         */
    1843        public Object clone() throws CloneNotSupportedException {
    1844            return super.clone();
    1845        }
    1846
    1847        /**
    1848         * Provides serialization support.
    1849         *
    1850         * @param stream  the output stream (<code>null</code> not permitted).
    1851         *
    1852         * @throws IOException  if there is an I/O error.
    1853         */
    1854        private void writeObject(ObjectOutputStream stream) throws IOException {
    1855            stream.defaultWriteObject();
    1856            SerialUtilities.writePaint(this.titlePaint, stream);
    1857            SerialUtilities.writePaint(this.subtitlePaint, stream);
    1858            SerialUtilities.writePaint(this.chartBackgroundPaint, stream);
    1859            SerialUtilities.writePaint(this.legendBackgroundPaint, stream);
    1860            SerialUtilities.writePaint(this.legendItemPaint, stream);
    1861            SerialUtilities.writePaint(this.plotBackgroundPaint, stream);
    1862            SerialUtilities.writePaint(this.plotOutlinePaint, stream);
    1863            SerialUtilities.writePaint(this.labelLinkPaint, stream);
    1864            SerialUtilities.writePaint(this.baselinePaint, stream);
    1865            SerialUtilities.writePaint(this.domainGridlinePaint, stream);
    1866            SerialUtilities.writePaint(this.rangeGridlinePaint, stream);
    1867            SerialUtilities.writePaint(this.crosshairPaint, stream);
    1868            SerialUtilities.writePaint(this.axisLabelPaint, stream);
    1869            SerialUtilities.writePaint(this.tickLabelPaint, stream);
    1870            SerialUtilities.writePaint(this.itemLabelPaint, stream);
    1871            SerialUtilities.writePaint(this.shadowPaint, stream);
    1872            SerialUtilities.writePaint(this.thermometerPaint, stream);
    1873            SerialUtilities.writePaint(this.wallPaint, stream);
    1874            SerialUtilities.writePaint(this.errorIndicatorPaint, stream);
    1875            SerialUtilities.writePaint(this.gridBandPaint, stream);
    1876            SerialUtilities.writePaint(this.gridBandAlternatePaint, stream);
    1877        }
    1878
    1879        /**
    1880         * Provides serialization support.
    1881         *
    1882         * @param stream  the input stream (<code>null</code> not permitted).
    1883         *
    1884         * @throws IOException  if there is an I/O error.
    1885         * @throws ClassNotFoundException  if there is a classpath problem.
    1886         */
    1887        private void readObject(ObjectInputStream stream)
    1888            throws IOException, ClassNotFoundException {
    1889            stream.defaultReadObject();
    1890            this.titlePaint = SerialUtilities.readPaint(stream);
    1891            this.subtitlePaint = SerialUtilities.readPaint(stream);
    1892            this.chartBackgroundPaint = SerialUtilities.readPaint(stream);
    1893            this.legendBackgroundPaint = SerialUtilities.readPaint(stream);
    1894            this.legendItemPaint = SerialUtilities.readPaint(stream);
    1895            this.plotBackgroundPaint = SerialUtilities.readPaint(stream);
    1896            this.plotOutlinePaint = SerialUtilities.readPaint(stream);
    1897            this.labelLinkPaint = SerialUtilities.readPaint(stream);
    1898            this.baselinePaint = SerialUtilities.readPaint(stream);
    1899            this.domainGridlinePaint = SerialUtilities.readPaint(stream);
    1900            this.rangeGridlinePaint = SerialUtilities.readPaint(stream);
    1901            this.crosshairPaint = SerialUtilities.readPaint(stream);
    1902            this.axisLabelPaint = SerialUtilities.readPaint(stream);
    1903            this.tickLabelPaint = SerialUtilities.readPaint(stream);
    1904            this.itemLabelPaint = SerialUtilities.readPaint(stream);
    1905            this.shadowPaint = SerialUtilities.readPaint(stream);
    1906            this.thermometerPaint = SerialUtilities.readPaint(stream);
    1907            this.wallPaint = SerialUtilities.readPaint(stream);
    1908            this.errorIndicatorPaint = SerialUtilities.readPaint(stream);
    1909            this.gridBandPaint = SerialUtilities.readPaint(stream);
    1910            this.gridBandAlternatePaint = SerialUtilities.readPaint(stream);
    1911        }
    1912
    1913    }