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