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