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