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