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