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