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