KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > JFreeChart


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this library; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
24  * in the United States and other countries.]
25  *
26  * ---------------
27  * JFreeChart.java
28  * ---------------
29  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
30  *
31  * Original Author: David Gilbert (for Object Refinery Limited);
32  * Contributor(s): Andrzej Porebski;
33  * David Li;
34  * Wolfgang Irler;
35  * Christian W. Zuckschwerdt;
36  * Klaus Rheinwald;
37  * Nicolas Brodu;
38  *
39  * $Id: JFreeChart.java,v 1.34 2005/05/20 15:10:40 mungady Exp $
40  *
41  * Changes (from 20-Jun-2001)
42  * --------------------------
43  * 20-Jun-2001 : Modifications submitted by Andrzej Porebski for legend
44  * placement;
45  * 21-Jun-2001 : Removed JFreeChart parameter from Plot constructors (DG);
46  * 22-Jun-2001 : Multiple titles added (original code by David Berry, with
47  * reworkings by DG);
48  * 18-Sep-2001 : Updated header (DG);
49  * 15-Oct-2001 : Moved data source classes into new package
50  * com.jrefinery.data.* (DG);
51  * 18-Oct-2001 : New factory method for creating VerticalXYBarChart (DG);
52  * 19-Oct-2001 : Moved series paint and stroke methods to the Plot class (DG);
53  * Moved static chart creation methods to new ChartFactory
54  * class (DG);
55  * 22-Oct-2001 : Renamed DataSource.java --> Dataset.java etc. (DG);
56  * Fixed bug where chart isn't registered with the dataset (DG);
57  * 07-Nov-2001 : Fixed bug where null title in constructor causes
58  * exception (DG);
59  * Tidied up event notification code (DG);
60  * 17-Nov-2001 : Added getLegendItemCount() method (DG);
61  * 21-Nov-2001 : Set clipping in draw method to ensure that nothing gets drawn
62  * outside the chart area (DG);
63  * 11-Dec-2001 : Added the createBufferedImage() method, taken from the
64  * JFreeChartServletDemo class (DG);
65  * 13-Dec-2001 : Added tooltips (DG);
66  * 16-Jan-2002 : Added handleClick() method (DG);
67  * 22-Jan-2002 : Fixed bug correlating legend labels with pie data (DG);
68  * 05-Feb-2002 : Removed redundant tooltips code (DG);
69  * 19-Feb-2002 : Added accessor methods for the backgroundImage and
70  * backgroundImageAlpha attributes (DG);
71  * 21-Feb-2002 : Added static fields for INFO, COPYRIGHT, LICENCE, CONTRIBUTORS
72  * and LIBRARIES. These can be used to display information about
73  * JFreeChart (DG);
74  * 06-Mar-2002 : Moved constants to JFreeChartConstants interface (DG);
75  * 18-Apr-2002 : PieDataset is no longer sorted (oldman);
76  * 23-Apr-2002 : Moved dataset to the Plot class (DG);
77  * 13-Jun-2002 : Added an extra draw() method (DG);
78  * 25-Jun-2002 : Implemented the Drawable interface and removed redundant
79  * imports (DG);
80  * 26-Jun-2002 : Added another createBufferedImage() method (DG);
81  * 18-Sep-2002 : Fixed issues reported by Checkstyle (DG);
82  * 23-Sep-2002 : Added new contributor (DG);
83  * 28-Oct-2002 : Created main title and subtitle list to replace existing title
84  * list (DG);
85  * 08-Jan-2003 : Added contributor (DG);
86  * 17-Jan-2003 : Added new constructor (DG);
87  * 22-Jan-2003 : Added ChartColor class by Cameron Riley, and background image
88  * alignment code by Christian W. Zuckschwerdt (DG);
89  * 11-Feb-2003 : Added flag to allow suppression of chart change events, based
90  * on a suggestion by Klaus Rheinwald (DG);
91  * 04-Mar-2003 : Added small fix for suppressed chart change events (see bug id
92  * 690865) (DG);
93  * 10-Mar-2003 : Added Benoit Xhenseval to contributors (DG);
94  * 26-Mar-2003 : Implemented Serializable (DG);
95  * 15-Jul-2003 : Added an optional border for the chart (DG);
96  * 11-Sep-2003 : Took care of listeners while cloning (NB);
97  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
98  * 22-Sep-2003 : Added nullpointer checks.
99  * 25-Sep-2003 : Added nullpointer checks too (NB).
100  * 03-Dec-2003 : Legends are now registered by this class instead of using the
101  * old constructor way (TM);
102  * 03-Dec-2003 : Added anchorPoint to draw() method (DG);
103  * 08-Jan-2004 : Reworked title code, introducing line wrapping (DG);
104  * 09-Feb-2004 : Created additional createBufferedImage() method (DG);
105  * 05-Apr-2004 : Added new createBufferedImage() method (DG);
106  * 27-May-2004 : Moved constants from JFreeChartConstants.java back to this
107  * class (DG);
108  * 25-Nov-2004 : Updates for changes to Title class (DG);
109  * 06-Jan-2005 : Change lookup for default background color (DG);
110  * 31-Jan-2005 : Added Don Elliott to contributors (DG);
111  * 02-Feb-2005 : Added clearSubtitles() method (DG);
112  * 03-Feb-2005 : Added Mofeed Shahin to contributors (DG);
113  * 08-Feb-2005 : Updated for RectangleConstraint changes (DG);
114  * 28-Mar-2005 : Renamed Legend --> OldLegend (DG);
115  * 12-Apr-2005 : Added methods to access legend(s) in subtitle list (DG);
116  * 13-Apr-2005 : Added removeLegend() and removeSubtitle() methods (DG);
117  * 20-Apr-2005 : Modified to collect chart entities from titles and
118  * subtitles (DG);
119  * 26-Apr-2005 : Removed LOGGER (DG);
120  *
121  */

122
123 package org.jfree.chart;
124
125 import java.awt.AlphaComposite JavaDoc;
126 import java.awt.BasicStroke JavaDoc;
127 import java.awt.Color JavaDoc;
128 import java.awt.Composite JavaDoc;
129 import java.awt.Font JavaDoc;
130 import java.awt.Graphics2D JavaDoc;
131 import java.awt.Image JavaDoc;
132 import java.awt.Paint JavaDoc;
133 import java.awt.RenderingHints JavaDoc;
134 import java.awt.Shape JavaDoc;
135 import java.awt.Stroke JavaDoc;
136 import java.awt.geom.AffineTransform JavaDoc;
137 import java.awt.geom.Point2D JavaDoc;
138 import java.awt.geom.Rectangle2D JavaDoc;
139 import java.awt.image.BufferedImage JavaDoc;
140 import java.io.IOException JavaDoc;
141 import java.io.ObjectInputStream JavaDoc;
142 import java.io.ObjectOutputStream JavaDoc;
143 import java.io.Serializable JavaDoc;
144 import java.net.URL JavaDoc;
145 import java.util.ArrayList JavaDoc;
146 import java.util.Arrays JavaDoc;
147 import java.util.Iterator JavaDoc;
148 import java.util.List JavaDoc;
149 import java.util.ResourceBundle JavaDoc;
150
151 import javax.swing.ImageIcon JavaDoc;
152 import javax.swing.UIManager JavaDoc;
153 import javax.swing.event.EventListenerList JavaDoc;
154
155 import org.jfree.JCommon;
156 import org.jfree.chart.block.BlockBorder;
157 import org.jfree.chart.block.BlockParams;
158 import org.jfree.chart.block.EntityBlockResult;
159 import org.jfree.chart.block.LengthConstraintType;
160 import org.jfree.chart.block.RectangleConstraint;
161 import org.jfree.chart.entity.EntityCollection;
162 import org.jfree.chart.event.ChartChangeEvent;
163 import org.jfree.chart.event.ChartChangeListener;
164 import org.jfree.chart.event.ChartProgressEvent;
165 import org.jfree.chart.event.ChartProgressListener;
166 import org.jfree.chart.event.LegendChangeEvent;
167 import org.jfree.chart.event.LegendChangeListener;
168 import org.jfree.chart.event.PlotChangeEvent;
169 import org.jfree.chart.event.PlotChangeListener;
170 import org.jfree.chart.event.TitleChangeEvent;
171 import org.jfree.chart.event.TitleChangeListener;
172 import org.jfree.chart.plot.CategoryPlot;
173 import org.jfree.chart.plot.Plot;
174 import org.jfree.chart.plot.PlotRenderingInfo;
175 import org.jfree.chart.plot.XYPlot;
176 import org.jfree.chart.title.LegendTitle;
177 import org.jfree.chart.title.TextTitle;
178 import org.jfree.chart.title.Title;
179 import org.jfree.data.Range;
180 import org.jfree.io.SerialUtilities;
181 import org.jfree.ui.Align;
182 import org.jfree.ui.Drawable;
183 import org.jfree.ui.HorizontalAlignment;
184 import org.jfree.ui.RectangleEdge;
185 import org.jfree.ui.RectangleInsets;
186 import org.jfree.ui.Size2D;
187 import org.jfree.ui.VerticalAlignment;
188 import org.jfree.ui.about.Contributor;
189 import org.jfree.ui.about.Licences;
190 import org.jfree.ui.about.ProjectInfo;
191 import org.jfree.util.ObjectUtilities;
192
193 /**
194  * A chart class implemented using the Java 2D APIs. The current version
195  * supports bar charts, line charts, pie charts and xy plots (including time
196  * series data).
197  * <P>
198  * JFreeChart coordinates several objects to achieve its aim of being able to
199  * draw a chart on a Java 2D graphics device: a list of {@link Title} objects,
200  * a {@link OldLegend}, a {@link Plot} and a
201  * {@link org.jfree.data.general.Dataset} (the plot in turn manages a
202  * horizontal axis and a vertical axis).
203  * <P>
204  * You should use a {@link ChartPanel} to display a chart in a GUI.
205  * <P>
206  * The {@link ChartFactory} class contains static methods for creating
207  * 'ready-made' charts.
208  *
209  * @see ChartPanel
210  * @see ChartFactory
211  * @see Title
212  * @see OldLegend
213  * @see Plot
214  *
215  */

216 public class JFreeChart implements Drawable,
217                                    TitleChangeListener,
218                                    LegendChangeListener,
219                                    PlotChangeListener,
220                                    Serializable JavaDoc,
221                                    Cloneable JavaDoc {
222
223     /** For serialization. */
224     private static final long serialVersionUID = -3470703747817429120L;
225     
226     /** Information about the project. */
227     public static final ProjectInfo INFO = new JFreeChartInfo();
228
229     /** The default font for titles. */
230     public static final Font JavaDoc DEFAULT_TITLE_FONT
231         = new Font JavaDoc("SansSerif", Font.BOLD, 18);
232
233     /** The default background color. */
234     public static final Paint JavaDoc DEFAULT_BACKGROUND_PAINT
235         = UIManager.getColor("Panel.background");
236
237     /** The default background image. */
238     public static final Image JavaDoc DEFAULT_BACKGROUND_IMAGE = null;
239
240     /** The default background image alignment. */
241     public static final int DEFAULT_BACKGROUND_IMAGE_ALIGNMENT = Align.FIT;
242
243     /** The default background image alpha. */
244     public static final float DEFAULT_BACKGROUND_IMAGE_ALPHA = 0.5f;
245
246     /** Rendering hints that will be used for chart drawing. */
247     private transient RenderingHints JavaDoc renderingHints;
248
249     /** A flag that controls whether or not the chart border is drawn. */
250     private boolean borderVisible;
251
252     /** The stroke used to draw the chart border (if visible). */
253     private transient Stroke JavaDoc borderStroke;
254
255     /** The paint used to draw the chart border (if visible). */
256     private transient Paint JavaDoc borderPaint;
257
258     /** The chart title (optional). */
259     private TextTitle title;
260
261     /** The chart subtitles (zero, one or many). */
262     private List JavaDoc subtitles;
263
264     /** The chart legend. */
265     private OldLegend oldLegend;
266
267     /** Draws the visual representation of the data. */
268     private Plot plot;
269
270     /** Paint used to draw the background of the chart. */
271     private transient Paint JavaDoc backgroundPaint;
272
273     /** An optional background image for the chart. */
274     private transient Image JavaDoc backgroundImage; // todo: not serialized yet
275

276     /** The alignment for the background image. */
277     private int backgroundImageAlignment = Align.FIT;
278
279     /** The alpha transparency for the background image. */
280     private float backgroundImageAlpha = 0.5f;
281
282     /** Storage for registered change listeners. */
283     private transient EventListenerList JavaDoc changeListeners;
284
285     /** Storage for registered progress listeners. */
286     private transient EventListenerList JavaDoc progressListeners;
287
288     /**
289      * A flag that can be used to enable/disable notification of chart change
290      * events.
291      */

292     private boolean notify;
293     
294     /**
295      * Creates a new chart based on the supplied plot. The chart will have
296      * a legend added automatically, but no title (although you can easily add
297      * one later).
298      * <br><br>
299      * Note that the {@link ChartFactory} class contains a range
300      * of static methods that will return ready-made charts, and often this
301      * is a more convenient way to create charts than using this constructor.
302      *
303      * @param plot the plot (<code>null</code> not permitted).
304      */

305     public JFreeChart(Plot plot) {
306
307         this(
308             null, // title
309
null, // font
310
plot,
311             true // create legend
312
);
313
314     }
315
316     /**
317      * Creates a new chart with the given title and plot. A default font
318      * (@link DEFAULT_TITLE_FONT) is used for the title, and the chart will
319      * have a legend added automatically.
320      * <br><br>
321      * Note that the {@link ChartFactory} class contains a range
322      * of static methods that will return ready-made charts, and often this
323      * is a more convenient way to create charts than using this constructor.
324      *
325      * @param title the chart title (<code>null</code> permitted).
326      * @param plot the plot (<code>null</code> not permitted).
327      */

328     public JFreeChart(String JavaDoc title, Plot plot) {
329         this(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
330     }
331
332     /**
333      * Creates a new chart with the given title and plot. The
334      * <code>createLegend</code> argument specifies whether or not a legend
335      * should be added to the chart.
336      * <br><br>
337      * Note that the {@link ChartFactory} class contains a range
338      * of static methods that will return ready-made charts, and often this
339      * is a more convenient way to create charts than using this constructor.
340      *
341      * @param title the chart title (<code>null</code> permitted).
342      * @param titleFont the font for displaying the chart title
343      * (<code>null</code> permitted).
344      * @param plot controller of the visual representation of the data
345      * (<code>null</code> not permitted).
346      * @param createLegend a flag indicating whether or not a legend should
347      * be created for the chart.
348      */

349     public JFreeChart(String JavaDoc title, Font JavaDoc titleFont, Plot plot,
350                       boolean createLegend) {
351
352         if (plot == null) {
353             throw new NullPointerException JavaDoc("Null 'plot' argument.");
354         }
355
356         // create storage for listeners...
357
this.progressListeners = new EventListenerList JavaDoc();
358         this.changeListeners = new EventListenerList JavaDoc();
359         this.notify = true; // default is to notify listeners when the
360
// chart changes
361

362         this.renderingHints = new RenderingHints JavaDoc(
363             RenderingHints.KEY_ANTIALIASING,
364             RenderingHints.VALUE_ANTIALIAS_ON
365         );
366
367         this.borderVisible = false;
368         this.borderStroke = new BasicStroke JavaDoc(1.0f);
369         this.borderPaint = Color.black;
370
371         this.plot = plot;
372         plot.addChangeListener(this);
373
374         this.subtitles = new ArrayList JavaDoc();
375
376         // create a legend, if requested...
377
if (createLegend) {
378             LegendTitle legend = new LegendTitle(this.plot);
379             legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
380             legend.setBorder(new BlockBorder());
381             legend.setBackgroundPaint(Color.white);
382             legend.setPosition(RectangleEdge.BOTTOM);
383             this.subtitles.add(legend);
384         }
385
386         // add the chart title, if one has been specified...
387
if (title != null) {
388             if (titleFont == null) {
389                 titleFont = DEFAULT_TITLE_FONT;
390             }
391             this.title = new TextTitle(title, titleFont);
392             this.title.addChangeListener(this);
393         }
394
395         this.backgroundPaint = DEFAULT_BACKGROUND_PAINT;
396
397         this.backgroundImage = DEFAULT_BACKGROUND_IMAGE;
398         this.backgroundImageAlignment = DEFAULT_BACKGROUND_IMAGE_ALIGNMENT;
399         this.backgroundImageAlpha = DEFAULT_BACKGROUND_IMAGE_ALPHA;
400
401     }
402
403     /**
404      * Returns the collection of rendering hints for the chart.
405      *
406      * @return The rendering hints for the chart (never <code>null</code>).
407      */

408     public RenderingHints JavaDoc getRenderingHints() {
409         return this.renderingHints;
410     }
411
412     /**
413      * Sets the rendering hints for the chart. These will be added (using the
414      * Graphics2D.addRenderingHints() method) near the start of the
415      * JFreeChart.draw() method.
416      *
417      * @param renderingHints the rendering hints (<code>null</code> not
418      * permitted).
419      */

420     public void setRenderingHints(RenderingHints JavaDoc renderingHints) {
421         if (renderingHints == null) {
422             throw new NullPointerException JavaDoc("RenderingHints given are null");
423         }
424         this.renderingHints = renderingHints;
425         fireChartChanged();
426     }
427
428     /**
429      * Returns a flag that controls whether or not a border is drawn around the
430      * outside of the chart.
431      *
432      * @return A boolean.
433      */

434     public boolean isBorderVisible() {
435         return this.borderVisible;
436     }
437
438     /**
439      * Sets a flag that controls whether or not a border is drawn around the
440      * outside of the chart.
441      *
442      * @param visible the flag.
443      */

444     public void setBorderVisible(boolean visible) {
445         this.borderVisible = visible;
446         fireChartChanged();
447     }
448
449     /**
450      * Returns the stroke used to draw the chart border (if visible).
451      *
452      * @return The border stroke.
453      */

454     public Stroke JavaDoc getBorderStroke() {
455         return this.borderStroke;
456     }
457
458     /**
459      * Sets the stroke used to draw the chart border (if visible).
460      *
461      * @param stroke the stroke.
462      */

463     public void setBorderStroke(Stroke JavaDoc stroke) {
464         this.borderStroke = stroke;
465         fireChartChanged();
466     }
467
468     /**
469      * Returns the paint used to draw the chart border (if visible).
470      *
471      * @return The border paint.
472      */

473     public Paint JavaDoc getBorderPaint() {
474         return this.borderPaint;
475     }
476
477     /**
478      * Sets the paint used to draw the chart border (if visible).
479      *
480      * @param paint the paint.
481      */

482     public void setBorderPaint(Paint JavaDoc paint) {
483         this.borderPaint = paint;
484         fireChartChanged();
485     }
486
487     /**
488      * Returns the main chart title. Very often a chart will have just one
489      * title, so we make this case simple by providing accessor methods for
490      * the main title. However, multiple titles are supported - see the
491      * {@link #addSubtitle(Title)} method.
492      *
493      * @return The chart title (possibly <code>null</code>).
494      */

495     public TextTitle getTitle() {
496         return this.title;
497     }
498
499     /**
500      * Sets the main title for the chart and sends a {@link ChartChangeEvent}
501      * to all registered listeners. If you do not want a title for the
502      * chart, set it to <code>null</code>. If you want more than one title on
503      * a chart, use the {@link #addSubtitle(Title)} method.
504      *
505      * @param title the title (<code>null</code> permitted).
506      */

507     public void setTitle(TextTitle title) {
508         this.title = title;
509         fireChartChanged();
510     }
511
512     /**
513      * Sets the chart title and sends a {@link ChartChangeEvent} to all
514      * registered listeners. This is a convenience method that ends up calling
515      * the {@link #setTitle(TextTitle)} method. If there is an existing title,
516      * its text is updated, otherwise a new title using the default font is
517      * added to the chart. If <code>text</code> is <code>null</code> the chart
518      * title is set to <code>null</code>.
519      *
520      * @param text the title text (<code>null</code> permitted).
521      */

522     public void setTitle(String JavaDoc text) {
523         if (text != null) {
524             if (this.title == null) {
525                 setTitle(new TextTitle(text, JFreeChart.DEFAULT_TITLE_FONT));
526             }
527             else {
528                 this.title.setText(text);
529             }
530         }
531         else {
532             setTitle((TextTitle) null);
533         }
534     }
535
536     /**
537      * Returns the legend for the chart, if there is one. Note that a chart
538      * can have more than one legend - this method returns the first.
539      *
540      * @return The legend (possibly <code>null</code>).
541      */

542     public LegendTitle getLegend() {
543         return getLegend(0);
544     }
545     
546     /**
547      * Returns the nth legend for a chart, or <code>null</code>.
548      *
549      * @param index the legend index (zero-based).
550      *
551      * @return The legend (possibly <code>null</code>).
552      */

553     public LegendTitle getLegend(int index) {
554         int seen = 0;
555         Iterator JavaDoc iterator = this.subtitles.iterator();
556         while (iterator.hasNext()) {
557             Title subtitle = (Title) iterator.next();
558             if (subtitle instanceof LegendTitle) {
559                 if (seen == index) {
560                     return (LegendTitle) subtitle;
561                 }
562                 else {
563                     seen++;
564                 }
565             }
566         }
567         return null;
568     }
569     
570     /**
571      * Removes the first legend in the chart and sends a
572      * {@link ChartChangeEvent} to all registered listeners.
573      */

574     public void removeLegend() {
575         removeSubtitle(getLegend());
576     }
577     
578     /**
579      * Returns the list of subtitles for the chart.
580      *
581      * @return The subtitle list (possibly empty, but never <code>null</code>).
582      */

583     public List JavaDoc getSubtitles() {
584         return this.subtitles;
585     }
586
587     /**
588      * Sets the title list for the chart (completely replaces any existing
589      * titles).
590      *
591      * @param subtitles the new list of subtitles (<code>null</code> not
592      * permitted).
593      */

594     public void setSubtitles(List JavaDoc subtitles) {
595         if (subtitles == null) {
596             throw new NullPointerException JavaDoc("Null 'subtitles' argument.");
597         }
598         this.subtitles = subtitles;
599         fireChartChanged();
600     }
601
602     /**
603      * Returns the number of titles for the chart.
604      *
605      * @return The number of titles for the chart.
606      */

607     public int getSubtitleCount() {
608         return this.subtitles.size();
609     }
610
611     /**
612      * Returns a chart subtitle.
613      *
614      * @param index the index of the chart subtitle (zero based).
615      *
616      * @return A chart subtitle.
617      */

618     public Title getSubtitle(int index) {
619         if ((index < 0) || (index == getSubtitleCount())) {
620             throw new IllegalArgumentException JavaDoc("Index out of range.");
621         }
622         return (Title) this.subtitles.get(index);
623     }
624
625     /**
626      * Adds a chart subtitle, and notifies registered listeners that the chart
627      * has been modified.
628      *
629      * @param subtitle the subtitle (<code>null</code> not permitted).
630      */

631     public void addSubtitle(Title subtitle) {
632         if (subtitle == null) {
633             throw new IllegalArgumentException JavaDoc("Null 'subtitle' argument.");
634         }
635         this.subtitles.add(subtitle);
636         subtitle.addChangeListener(this);
637         fireChartChanged();
638     }
639     
640     /**
641      * Clears all subtitles from the chart and sends a {@link ChartChangeEvent}
642      * to all registered listeners.
643      */

644     public void clearSubtitles() {
645         Iterator JavaDoc iterator = this.subtitles.iterator();
646         while (iterator.hasNext()) {
647             Title t = (Title) iterator.next();
648             t.removeChangeListener(this);
649         }
650         this.subtitles.clear();
651         fireChartChanged();
652     }
653
654     /**
655      * Removes the specified subtitle and sends a {@link ChartChangeEvent} to
656      * all registered listeners.
657      *
658      * @param title the title.
659      */

660     public void removeSubtitle(Title title) {
661         this.subtitles.remove(title);
662         fireChartChanged();
663     }
664     
665     /**
666      * Returns the chart legend.
667      *
668      * @return The chart legend (possibly <code>null</code>).
669      */

670     public OldLegend getOldLegend() {
671         return this.oldLegend;
672     }
673
674     /**
675      * Sets the chart legend. Registered listeners are notified that the chart
676      * has been modified. The legends chart reference is updated.
677      *
678      * @param legend the new chart legend (<code>null</code> permitted).
679      */

680     public void setOldLegend(OldLegend legend) {
681
682         // if there is an existing legend, remove the chart from the list of
683
// change listeners...
684
OldLegend existing = this.oldLegend;
685         if (existing != null) {
686             existing.removeChangeListener(this);
687             existing.registerChart(null);
688         }
689
690         // set the new legend, and register the chart as a change listener...
691
this.oldLegend = legend;
692         if (legend != null) {
693             legend.registerChart(this);
694             legend.addChangeListener(this);
695         }
696
697         // notify chart change listeners...
698
fireChartChanged();
699
700     }
701
702     /**
703      * Returns the plot for the chart. The plot is a class responsible for
704      * coordinating the visual representation of the data, including the axes
705      * (if any).
706      *
707      * @return The plot.
708      */

709     public Plot getPlot() {
710         return this.plot;
711     }
712
713     /**
714      * Returns the plot cast as a {@link CategoryPlot}.
715      * <p>
716      * NOTE: if the plot is not an instance of {@link CategoryPlot}, then a
717      * <code>ClassCastException</code> is thrown.
718      *
719      * @return The plot.
720      */

721     public CategoryPlot getCategoryPlot() {
722         return (CategoryPlot) this.plot;
723     }
724
725     /**
726      * Returns the plot cast as an {@link XYPlot}.
727      * <p>
728      * NOTE: if the plot is not an instance of {@link XYPlot}, then a
729      * <code>ClassCastException</code> is thrown.
730      *
731      * @return The plot.
732      */

733     public XYPlot getXYPlot() {
734         return (XYPlot) this.plot;
735     }
736
737     /**
738      * Returns a flag that indicates whether or not anti-aliasing is used when
739      * the chart is drawn.
740      *
741      * @return The flag.
742      */

743     public boolean getAntiAlias() {
744         Object JavaDoc o = this.renderingHints.get(RenderingHints.KEY_ANTIALIASING);
745         if (o == null) {
746             return false;
747         }
748         return (o.equals(RenderingHints.VALUE_ANTIALIAS_ON));
749     }
750
751     /**
752      * Sets a flag that indicates whether or not anti-aliasing is used when the
753      * chart is drawn.
754      * <P>
755      * Anti-aliasing usually improves the appearance of charts, but is slower.
756      *
757      * @param flag the new value of the flag.
758      */

759     public void setAntiAlias(boolean flag) {
760
761         Object JavaDoc o = this.renderingHints.get(RenderingHints.KEY_ANTIALIASING);
762         if (o == null) {
763             o = RenderingHints.VALUE_ANTIALIAS_DEFAULT;
764         }
765         if (!flag && RenderingHints.VALUE_ANTIALIAS_OFF.equals(o)
766             || flag && RenderingHints.VALUE_ANTIALIAS_ON.equals(o)) {
767             // no change, do nothing
768
return;
769         }
770         if (flag) {
771             this.renderingHints.put(RenderingHints.KEY_ANTIALIASING,
772                                     RenderingHints.VALUE_ANTIALIAS_ON);
773         }
774         else {
775             this.renderingHints.put(RenderingHints.KEY_ANTIALIASING,
776                                     RenderingHints.VALUE_ANTIALIAS_OFF);
777         }
778         fireChartChanged();
779
780     }
781
782     /**
783      * Returns the paint used for the chart background.
784      *
785      * @return The paint (possibly <code>null</code>).
786      */

787     public Paint JavaDoc getBackgroundPaint() {
788         return this.backgroundPaint;
789     }
790
791     /**
792      * Sets the paint used to fill the chart background and sends a
793      * {@link ChartChangeEvent} to all registered listeners.
794      *
795      * @param paint the paint (<code>null</code> permitted).
796      */

797     public void setBackgroundPaint(Paint JavaDoc paint) {
798
799         if (this.backgroundPaint != null) {
800             if (!this.backgroundPaint.equals(paint)) {
801                 this.backgroundPaint = paint;
802                 fireChartChanged();
803             }
804         }
805         else {
806             if (paint != null) {
807                 this.backgroundPaint = paint;
808                 fireChartChanged();
809             }
810         }
811
812     }
813
814     /**
815      * Returns the background image for the chart, or <code>null</code> if
816      * there is no image.
817      *
818      * @return The image (possibly <code>null</code>).
819      */

820     public Image JavaDoc getBackgroundImage() {
821         return this.backgroundImage;
822     }
823
824     /**
825      * Sets the background image for the chart and sends a
826      * {@link ChartChangeEvent} to all registered listeners.
827      *
828      * @param image the image (<code>null</code> permitted).
829      */

830     public void setBackgroundImage(Image JavaDoc image) {
831
832         if (this.backgroundImage != null) {
833             if (!this.backgroundImage.equals(image)) {
834                 this.backgroundImage = image;
835                 fireChartChanged();
836             }
837         }
838         else {
839             if (image != null) {
840                 this.backgroundImage = image;
841                 fireChartChanged();
842             }
843         }
844
845     }
846
847     /**
848      * Returns the background image alignment. Alignment constants are defined
849      * in the <code>org.jfree.ui.Align</code> class in the JCommon class
850      * library.
851      *
852      * @return The alignment.
853      */

854     public int getBackgroundImageAlignment() {
855         return this.backgroundImageAlignment;
856     }
857
858     /**
859      * Sets the background alignment. Alignment options are defined by the
860      * {@link org.jfree.ui.Align} class.
861      *
862      * @param alignment the alignment.
863      */

864     public void setBackgroundImageAlignment(int alignment) {
865         if (this.backgroundImageAlignment != alignment) {
866             this.backgroundImageAlignment = alignment;
867             fireChartChanged();
868         }
869     }
870
871     /**
872      * Returns the alpha-transparency for the chart's background image.
873      *
874      * @return The alpha-transparency.
875      */

876     public float getBackgroundImageAlpha() {
877         return this.backgroundImageAlpha;
878     }
879
880     /**
881      * Sets the alpha-transparency for the chart's background image.
882      * Registered listeners are notified that the chart has been changed.
883      *
884      * @param alpha the alpha value.
885      */

886     public void setBackgroundImageAlpha(float alpha) {
887
888         if (this.backgroundImageAlpha != alpha) {
889             this.backgroundImageAlpha = alpha;
890             fireChartChanged();
891         }
892
893     }
894
895     /**
896      * Returns a flag that controls whether or not change events are sent to
897      * registered listeners.
898      *
899      * @return A boolean.
900      */

901     public boolean isNotify() {
902         return this.notify;
903     }
904
905     /**
906      * Sets a flag that controls whether or not listeners receive
907      * {@link ChartChangeEvent} notifications.
908      *
909      * @param notify a boolean.
910      */

911     public void setNotify(boolean notify) {
912         this.notify = notify;
913         // if the flag is being set to true, there may be queued up changes...
914
if (notify) {
915             notifyListeners(new ChartChangeEvent(this));
916         }
917     }
918
919     /**
920      * Draws the chart on a Java 2D graphics device (such as the screen or a
921      * printer).
922      * <P>
923      * This method is the focus of the entire JFreeChart library.
924      *
925      * @param g2 the graphics device.
926      * @param area the area within which the chart should be drawn.
927      */

928     public void draw(Graphics2D JavaDoc g2, Rectangle2D JavaDoc area) {
929         draw(g2, area, null, null);
930     }
931
932     /**
933      * Draws the chart on a Java 2D graphics device (such as the screen or a
934      * printer). This method is the focus of the entire JFreeChart library.
935      *
936      * @param g2 the graphics device.
937      * @param area the area within which the chart should be drawn.
938      * @param info records info about the drawing (null means collect no info).
939      */

940     public void draw(Graphics2D JavaDoc g2, Rectangle2D JavaDoc area, ChartRenderingInfo info) {
941         draw(g2, area, null, info);
942     }
943     
944     /**
945      * Draws the chart on a Java 2D graphics device (such as the screen or a
946      * printer).
947      * <P>
948      * This method is the focus of the entire JFreeChart library.
949      *
950      * @param g2 the graphics device.
951      * @param chartArea the area within which the chart should be drawn.
952      * @param anchor the anchor point (in Java2D space) for the chart
953      * (<code>null</code> permitted).
954      * @param info records info about the drawing (null means collect no info).
955      */

956     public void draw(Graphics2D JavaDoc g2,
957                      Rectangle2D JavaDoc chartArea, Point2D JavaDoc anchor,
958                      ChartRenderingInfo info) {
959
960         notifyListeners(
961             new ChartProgressEvent(
962                 this, this, ChartProgressEvent.DRAWING_STARTED, 0
963             )
964         );
965
966         // record the chart area, if info is requested...
967
if (info != null) {
968             info.clear();
969             info.setChartArea(chartArea);
970         }
971
972         // ensure no drawing occurs outside chart area...
973
Shape JavaDoc savedClip = g2.getClip();
974         g2.clip(chartArea);
975
976         g2.addRenderingHints(this.renderingHints);
977
978         // draw the chart background...
979
if (this.backgroundPaint != null) {
980             g2.setPaint(this.backgroundPaint);
981             g2.fill(chartArea);
982         }
983
984         if (this.backgroundImage != null) {
985             Composite JavaDoc originalComposite = g2.getComposite();
986             g2.setComposite(
987                 AlphaComposite.getInstance(
988                     AlphaComposite.SRC_OVER,
989                     this.backgroundImageAlpha
990                 )
991             );
992             Rectangle2D JavaDoc dest = new Rectangle2D.Double JavaDoc(
993                 0.0, 0.0, this.backgroundImage.getWidth(null),
994                 this.backgroundImage.getHeight(null)
995             );
996             Align.align(dest, chartArea, this.backgroundImageAlignment);
997             g2.drawImage(
998                 this.backgroundImage, (int) dest.getX(), (int) dest.getY(),
999                 (int) dest.getWidth(), (int) dest.getHeight(), null
1000            );
1001            g2.setComposite(originalComposite);
1002        }
1003
1004        if (isBorderVisible()) {
1005            Paint JavaDoc paint = getBorderPaint();
1006            Stroke JavaDoc stroke = getBorderStroke();
1007            if (paint != null && stroke != null) {
1008                Rectangle2D JavaDoc borderArea = new Rectangle2D.Double JavaDoc(
1009                    chartArea.getX(), chartArea.getY(),
1010                    chartArea.getWidth() - 1.0, chartArea.getHeight() - 1.0
1011                );
1012                g2.setPaint(paint);
1013                g2.setStroke(stroke);
1014                g2.draw(borderArea);
1015            }
1016        }
1017
1018        // draw the title and subtitles...
1019
Rectangle2D JavaDoc nonTitleArea = new Rectangle2D.Double JavaDoc();
1020        nonTitleArea.setRect(chartArea);
1021
1022        EntityCollection entities = null;
1023        if (info != null) {
1024            entities = info.getEntityCollection();
1025        }
1026        if (this.title != null) {
1027            EntityCollection e = drawTitle(
1028                this.title, g2, nonTitleArea, (entities != null)
1029            );
1030            if (e != null) {
1031                entities.addAll(e);
1032            }
1033        }
1034
1035        Iterator JavaDoc iterator = this.subtitles.iterator();
1036        while (iterator.hasNext()) {
1037            Title currentTitle = (Title) iterator.next();
1038            EntityCollection e = drawTitle(
1039                currentTitle, g2, nonTitleArea, (entities != null)
1040            );
1041            if (e != null) {
1042                entities.addAll(e);
1043            }
1044        }
1045
1046        // draw the legend - the draw method will return the remaining area
1047
// after the legend steals a chunk of the non-title area for itself
1048
Rectangle2D JavaDoc plotArea = nonTitleArea;
1049        if (this.oldLegend != null) {
1050            plotArea.setRect(this.oldLegend.draw(g2, nonTitleArea, info));
1051        }
1052
1053        // draw the plot (axes and data visualisation)
1054
PlotRenderingInfo plotInfo = null;
1055        if (info != null) {
1056            plotInfo = info.getPlotInfo();
1057        }
1058        this.plot.draw(g2, plotArea, anchor, null, plotInfo);
1059
1060        g2.setClip(savedClip);
1061
1062        notifyListeners(
1063            new ChartProgressEvent(
1064                this, this, ChartProgressEvent.DRAWING_FINISHED, 100
1065            )
1066        );
1067    }
1068
1069    /**
1070     * Creates a rectangle that is aligned to the frame.
1071     *
1072     * @param dimensions
1073     * @param frame
1074     * @param hAlign
1075     * @param vAlign
1076     *
1077     * @return A rectangle.
1078     */

1079    private Rectangle2D JavaDoc createAlignedRectangle2D(Size2D dimensions,
1080            Rectangle2D JavaDoc frame, HorizontalAlignment hAlign,
1081            VerticalAlignment vAlign) {
1082        double x = Double.NaN;
1083        double y = Double.NaN;
1084        if (hAlign == HorizontalAlignment.LEFT) {
1085            x = frame.getX();
1086        }
1087        else if (hAlign == HorizontalAlignment.CENTER) {
1088            x = frame.getCenterX() - (dimensions.width / 2.0);
1089        }
1090        else if (hAlign == HorizontalAlignment.RIGHT) {
1091            x = frame.getMaxX() - dimensions.width;
1092        }
1093        if (vAlign == VerticalAlignment.TOP) {
1094            y = frame.getY();
1095        }
1096        else if (vAlign == VerticalAlignment.CENTER) {
1097            y = frame.getCenterY() - (dimensions.height / 2.0);
1098        }
1099        else if (vAlign == VerticalAlignment.BOTTOM) {
1100            y = frame.getMaxY() - dimensions.height;
1101        }
1102        
1103        return new Rectangle2D.Double JavaDoc(
1104            x, y, dimensions.width, dimensions.height
1105        );
1106    }
1107    
1108    /**
1109     * Draws a title. The title should be drawn at the top, bottom, left or
1110     * right of the specified area, and the area should be updated to reflect
1111     * the amount of space used by the title.
1112     *
1113     * @param t the title (<code>null</code> not permitted).
1114     * @param g2 the graphics device (<code>null</code> not permitted).
1115     * @param area the chart area, excluding any existing titles
1116     * (<code>null</code> not permitted).
1117     * @param entities a flag that controls whether or not an entity
1118     * collection is returned for the title.
1119     *
1120     * @return An entity collection for the title (possibly <code>null</code>).
1121     */

1122    protected EntityCollection drawTitle(Title t, Graphics2D JavaDoc g2,
1123                                         Rectangle2D JavaDoc area, boolean entities) {
1124
1125        if (t == null) {
1126            throw new IllegalArgumentException JavaDoc("Null 't' argument.");
1127        }
1128        if (area == null) {
1129            throw new IllegalArgumentException JavaDoc("Null 'area' argument.");
1130        }
1131        Rectangle2D JavaDoc titleArea = new Rectangle2D.Double JavaDoc();
1132        RectangleEdge position = t.getPosition();
1133        double ww = area.getWidth();
1134        double hh = area.getHeight();
1135        RectangleConstraint constraint = new RectangleConstraint(
1136            ww, new Range(0.0, ww), LengthConstraintType.RANGE,
1137            hh, new Range(0.0, hh), LengthConstraintType.RANGE
1138        );
1139        Object JavaDoc retValue = null;
1140        BlockParams p = new BlockParams();
1141        p.setGenerateEntities(entities);
1142        if (position == RectangleEdge.TOP) {
1143            Size2D size = t.arrange(g2, constraint);
1144            titleArea = createAlignedRectangle2D(
1145                size, area, t.getHorizontalAlignment(), VerticalAlignment.TOP
1146            );
1147            retValue = t.draw(g2, titleArea, p);
1148            area.setRect(
1149                area.getX(),
1150                Math.min(area.getY() + size.height, area.getMaxY()),
1151                area.getWidth(), Math.max(area.getHeight() - size.height, 0)
1152            );
1153        }
1154        else if (position == RectangleEdge.BOTTOM) {
1155            Size2D size = t.arrange(g2, constraint);
1156            titleArea = createAlignedRectangle2D(
1157                size, area, t.getHorizontalAlignment(), VerticalAlignment.BOTTOM
1158            );
1159            retValue = t.draw(g2, titleArea, p);
1160            area.setRect(
1161                area.getX(), area.getY(),
1162                area.getWidth(), area.getHeight() - size.height
1163            );
1164        }
1165        else if (position == RectangleEdge.RIGHT) {
1166            Size2D size = t.arrange(g2, constraint);
1167            titleArea = createAlignedRectangle2D(
1168                size, area, HorizontalAlignment.RIGHT, t.getVerticalAlignment()
1169            );
1170            retValue = t.draw(g2, titleArea, p);
1171            area.setRect(
1172                area.getX(), area.getY(),
1173                area.getWidth() - size.width, area.getHeight()
1174            );
1175        }
1176
1177        else if (position == RectangleEdge.LEFT) {
1178            Size2D size = t.arrange(g2, constraint);
1179            titleArea = createAlignedRectangle2D(
1180                size, area, HorizontalAlignment.LEFT, t.getVerticalAlignment()
1181            );
1182            retValue = t.draw(g2, titleArea, p);
1183            area.setRect(
1184                area.getX() + size.width, area.getY(),
1185                area.getWidth() - size.width, area.getHeight()
1186            );
1187        }
1188        else {
1189            throw new RuntimeException JavaDoc("Unrecognised title position.");
1190        }
1191        EntityCollection result = null;
1192        if (retValue instanceof EntityBlockResult) {
1193            EntityBlockResult ebr = (EntityBlockResult) retValue;
1194            result = ebr.getEntityCollection();
1195        }
1196        return result;
1197    }
1198
1199    /**
1200     * Creates and returns a buffered image into which the chart has been drawn.
1201     *
1202     * @param width the width.
1203     * @param height the height.
1204     *
1205     * @return A buffered image.
1206     */

1207    public BufferedImage JavaDoc createBufferedImage(int width, int height) {
1208        return createBufferedImage(width, height, null);
1209    }
1210
1211    /**
1212     * Creates and returns a buffered image into which the chart has been drawn.
1213     *
1214     * @param width the width.
1215     * @param height the height.
1216     * @param info carries back chart state information (<code>null</code>
1217     * permitted).
1218     *
1219     * @return A buffered image.
1220     */

1221    public BufferedImage JavaDoc createBufferedImage(int width, int height,
1222                                             ChartRenderingInfo info) {
1223        return createBufferedImage(
1224            width, height, BufferedImage.TYPE_INT_RGB, info
1225        );
1226    }
1227
1228    /**
1229     * Creates and returns a buffered image into which the chart has been drawn.
1230     *
1231     * @param width the width.
1232     * @param height the height.
1233     * @param imageType the image type.
1234     * @param info carries back chart state information (<code>null</code>
1235     * permitted).
1236     *
1237     * @return A buffered image.
1238     */

1239    public BufferedImage JavaDoc createBufferedImage(int width, int height,
1240                                             int imageType,
1241                                             ChartRenderingInfo info) {
1242        BufferedImage JavaDoc image = new BufferedImage JavaDoc(width, height, imageType);
1243        Graphics2D JavaDoc g2 = image.createGraphics();
1244        draw(g2, new Rectangle2D.Double JavaDoc(0, 0, width, height), null, info);
1245        g2.dispose();
1246        return image;
1247    }
1248
1249    /**
1250     * Creates and returns a buffered image into which the chart has been drawn.
1251     *
1252     * @param imageWidth the image width.
1253     * @param imageHeight the image height.
1254     * @param drawWidth the width for drawing the chart (will be scaled to
1255     * fit image).
1256     * @param drawHeight the height for drawing the chart (will be scaled to
1257     * fit image).
1258     * @param info optional object for collection chart dimension and entity
1259     * information.
1260     *
1261     * @return A buffered image.
1262     */

1263    public BufferedImage JavaDoc createBufferedImage(int imageWidth,
1264                                             int imageHeight,
1265                                             double drawWidth,
1266                                             double drawHeight,
1267                                             ChartRenderingInfo info) {
1268
1269        BufferedImage JavaDoc image = new BufferedImage JavaDoc(
1270            imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB
1271        );
1272        Graphics2D JavaDoc g2 = image.createGraphics();
1273        double scaleX = imageWidth / drawWidth;
1274        double scaleY = imageHeight / drawHeight;
1275        AffineTransform JavaDoc st = AffineTransform.getScaleInstance(scaleX, scaleY);
1276        g2.transform(st);
1277        draw(
1278            g2, new Rectangle2D.Double JavaDoc(0, 0, drawWidth, drawHeight), null, info
1279        );
1280        g2.dispose();
1281        return image;
1282
1283    }
1284
1285    /**
1286     * Handles a 'click' on the chart.
1287     * <P>
1288     * JFreeChart is not a UI component, so some other object (e.g. ChartPanel)
1289     * needs to capture the click event and pass it onto the JFreeChart object.
1290     * If you are not using JFreeChart in a client application, then this
1291     * method is not required (and hopefully it doesn't get in the way).
1292     *
1293     * @param x x-coordinate of the click (in Java2D space).
1294     * @param y y-coordinate of the click (in Java2D space).
1295     * @param info contains chart dimension and entity information.
1296     */

1297    public void handleClick(int x, int y, ChartRenderingInfo info) {
1298
1299        // pass the click on to the plot...
1300
// rely on the plot to post a plot change event and redraw the chart...
1301
this.plot.handleClick(x, y, info.getPlotInfo());
1302
1303    }
1304
1305    /**
1306     * Registers an object for notification of changes to the chart.
1307     *
1308     * @param listener the listener (<code>null</code> not permitted).
1309     */

1310    public void addChangeListener(ChartChangeListener listener) {
1311        if (listener == null) {
1312            throw new IllegalArgumentException JavaDoc("Null 'listener' argument.");
1313        }
1314        this.changeListeners.add(ChartChangeListener.class, listener);
1315    }
1316
1317    /**
1318     * Deregisters an object for notification of changes to the chart.
1319     *
1320     * @param listener the listener (<code>null</code> not permitted)
1321     */

1322    public void removeChangeListener(ChartChangeListener listener) {
1323        if (listener == null) {
1324            throw new IllegalArgumentException JavaDoc("Null 'listener' argument.");
1325        }
1326        this.changeListeners.remove(ChartChangeListener.class, listener);
1327    }
1328
1329    /**
1330     * Sends a default {@link ChartChangeEvent} to all registered listeners.
1331     * <P>
1332     * This method is for convenience only.
1333     */

1334    public void fireChartChanged() {
1335        ChartChangeEvent event = new ChartChangeEvent(this);
1336        notifyListeners(event);
1337    }
1338
1339    /**
1340     * Sends a {@link ChartChangeEvent} to all registered listeners.
1341     *
1342     * @param event information about the event that triggered the
1343     * notification.
1344     */

1345    protected void notifyListeners(ChartChangeEvent event) {
1346        if (this.notify) {
1347            Object JavaDoc[] listeners = this.changeListeners.getListenerList();
1348            for (int i = listeners.length - 2; i >= 0; i -= 2) {
1349                if (listeners[i] == ChartChangeListener.class) {
1350                    ((ChartChangeListener) listeners[i + 1]).chartChanged(
1351                        event
1352                    );
1353                }
1354            }
1355        }
1356    }
1357
1358    /**
1359     * Registers an object for notification of progress events relating to the
1360     * chart.
1361     *
1362     * @param listener the object being registered.
1363     */

1364    public void addProgressListener(ChartProgressListener listener) {
1365        this.progressListeners.add(ChartProgressListener.class, listener);
1366    }
1367
1368    /**
1369     * Deregisters an object for notification of changes to the chart.
1370     *
1371     * @param listener the object being deregistered.
1372     */

1373    public void removeProgressListener(ChartProgressListener listener) {
1374        this.progressListeners.remove(ChartProgressListener.class, listener);
1375    }
1376
1377    /**
1378     * Sends a {@link ChartProgressEvent} to all registered listeners.
1379     *
1380     * @param event information about the event that triggered the
1381     * notification.
1382     */

1383    protected void notifyListeners(ChartProgressEvent event) {
1384
1385        Object JavaDoc[] listeners = this.progressListeners.getListenerList();
1386        for (int i = listeners.length - 2; i >= 0; i -= 2) {
1387            if (listeners[i] == ChartProgressListener.class) {
1388                ((ChartProgressListener) listeners[i + 1]).chartProgress(event);
1389            }
1390        }
1391
1392    }
1393
1394    /**
1395     * Receives notification that a chart title has changed, and passes this
1396     * on to registered listeners.
1397     *
1398     * @param event information about the chart title change.
1399     */

1400    public void titleChanged(TitleChangeEvent event) {
1401        event.setChart(this);
1402        notifyListeners(event);
1403    }
1404
1405    /**
1406     * Receives notification that the chart legend has changed, and passes this
1407     * on to registered listeners.
1408     *
1409     * @param event information about the chart legend change.
1410     */

1411    public void legendChanged(LegendChangeEvent event) {
1412        event.setChart(this);
1413        notifyListeners(event);
1414    }
1415
1416    /**
1417     * Receives notification that the plot has changed, and passes this on to
1418     * registered listeners.
1419     *
1420     * @param event information about the plot change.
1421     */

1422    public void plotChanged(PlotChangeEvent event) {
1423        event.setChart(this);
1424        notifyListeners(event);
1425    }
1426
1427    /**
1428     * Tests this chart for equality with another object.
1429     *
1430     * @param obj the object (<code>null</code> permitted).
1431     *
1432     * @return A boolean.
1433     */

1434    public boolean equals(Object JavaDoc obj) {
1435
1436        if (obj == this) {
1437            return true;
1438        }
1439
1440        if (!(obj instanceof JFreeChart)) {
1441            return false;
1442        }
1443
1444        JFreeChart that = (JFreeChart) obj;
1445        if (!ObjectUtilities.equal(this.title, that.title)) {
1446            return false;
1447        }
1448        if (!ObjectUtilities.equal(this.subtitles, that.subtitles)) {
1449            return false;
1450        }
1451        if (!ObjectUtilities.equal(this.oldLegend, that.oldLegend)) {
1452            return false;
1453        }
1454        if (!ObjectUtilities.equal(this.plot, that.plot)) {
1455            return false;
1456        }
1457        if (!ObjectUtilities.equal(
1458            this.backgroundPaint, that.backgroundPaint
1459        )) {
1460            return false;
1461        }
1462        if (!ObjectUtilities.equal(
1463            this.backgroundImage, that.backgroundImage
1464        )) {
1465            return false;
1466        }
1467        if (this.backgroundImageAlignment != that.backgroundImageAlignment) {
1468            return false;
1469        }
1470        if (this.backgroundImageAlpha != that.backgroundImageAlpha) {
1471            return false;
1472        }
1473        if (this.notify != that.notify) {
1474            return false;
1475        }
1476
1477        return true;
1478
1479    }
1480
1481    /**
1482     * Provides serialization support.
1483     *
1484     * @param stream the output stream.
1485     *
1486     * @throws IOException if there is an I/O error.
1487     */

1488    private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
1489        stream.defaultWriteObject();
1490        SerialUtilities.writeStroke(this.borderStroke, stream);
1491        SerialUtilities.writePaint(this.borderPaint, stream);
1492        SerialUtilities.writePaint(this.backgroundPaint, stream);
1493    }
1494
1495    /**
1496     * Provides serialization support.
1497     *
1498     * @param stream the input stream.
1499     *
1500     * @throws IOException if there is an I/O error.
1501     * @throws ClassNotFoundException if there is a classpath problem.
1502     */

1503    private void readObject(ObjectInputStream JavaDoc stream)
1504        throws IOException JavaDoc, ClassNotFoundException JavaDoc {
1505        stream.defaultReadObject();
1506        this.borderStroke = SerialUtilities.readStroke(stream);
1507        this.borderPaint = SerialUtilities.readPaint(stream);
1508        this.backgroundPaint = SerialUtilities.readPaint(stream);
1509        this.progressListeners = new EventListenerList JavaDoc();
1510        this.changeListeners = new EventListenerList JavaDoc();
1511        this.renderingHints = new RenderingHints JavaDoc(
1512            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
1513        );
1514
1515        // register as a listener with sub-components...
1516
if (this.title != null) {
1517            this.title.addChangeListener(this);
1518        }
1519
1520        for (int i = 0; i < getSubtitleCount(); i++) {
1521            getSubtitle(i).addChangeListener(this);
1522        }
1523
1524        if (this.oldLegend != null) {
1525            this.oldLegend.addChangeListener(this);
1526        }
1527
1528        //if (this.plot != null) {
1529
// the plot can never be null.
1530
this.plot.addChangeListener(this);
1531        //}
1532

1533    }
1534
1535    /**
1536     * Prints information about JFreeChart to standard output.
1537     *
1538     * @param args no arguments are honored.
1539     */

1540    public static void main(String JavaDoc[] args) {
1541        System.out.println(JFreeChart.INFO.toString());
1542    }
1543
1544    /**
1545     * Clones the object, and takes care of listeners.
1546     * Note: caller shall register its own listeners on cloned graph.
1547     *
1548     * @return A clone.
1549     *
1550     * @throws CloneNotSupportedException if the chart is not cloneable.
1551     */

1552    public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
1553        JFreeChart chart = (JFreeChart) super.clone();
1554
1555        chart.renderingHints = (RenderingHints JavaDoc) this.renderingHints.clone();
1556        // private boolean borderVisible;
1557
// private transient Stroke borderStroke;
1558
// private transient Paint borderPaint;
1559

1560        if (this.title != null) {
1561            chart.title = (TextTitle) this.title.clone();
1562            chart.title.addChangeListener(chart);
1563        }
1564
1565        chart.subtitles = new ArrayList JavaDoc();
1566        for (int i = 0; i < getSubtitleCount(); i++) {
1567            Title subtitle = (Title) getSubtitle(i).clone();
1568            chart.subtitles.add(subtitle);
1569            subtitle.addChangeListener(chart);
1570        }
1571
1572        if (this.oldLegend != null) {
1573            chart.oldLegend = (OldLegend) this.oldLegend.clone();
1574            chart.oldLegend.registerChart(chart);
1575            chart.oldLegend.addChangeListener(chart);
1576        }
1577
1578        if (this.plot != null) {
1579            chart.plot = (Plot) this.plot.clone();
1580            chart.plot.addChangeListener(chart);
1581        }
1582
1583        //private boolean antialias;
1584
//private transient Paint backgroundPaint;
1585
//private transient Image backgroundImage; // todo: not serialized yet
1586
//private int backgroundImageAlignment = Align.FIT;
1587
//private float backgroundImageAlpha = 0.5f;
1588

1589        chart.progressListeners = new EventListenerList JavaDoc();
1590        chart.changeListeners = new EventListenerList JavaDoc();
1591        //private boolean notify;
1592

1593        return chart;
1594    }
1595
1596}
1597
1598/**
1599 * Information about the JFreeChart project. One instance of this class is
1600 * assigned to <code>JFreeChart.INFO<code>.
1601 */

1602class JFreeChartInfo extends ProjectInfo {
1603
1604    /**
1605     * Default constructor.
1606     */

1607    public JFreeChartInfo() {
1608
1609        // get a locale-specific resource bundle...
1610
String JavaDoc baseResourceClass
1611            = "org.jfree.chart.resources.JFreeChartResources";
1612        ResourceBundle JavaDoc resources = ResourceBundle.getBundle(baseResourceClass);
1613
1614        setName(resources.getString("project.name"));
1615        setVersion(resources.getString("project.version"));
1616        setInfo(resources.getString("project.info"));
1617        setCopyright(resources.getString("project.copyright"));
1618        setLogo(null); // load only when required
1619
setLicenceName("LGPL");
1620        setLicenceText(Licences.getInstance().getLGPL());
1621
1622        setContributors(Arrays.asList(
1623            new Contributor[]{
1624                new Contributor("Eric Alexander", "-"),
1625                new Contributor(
1626                    "Richard Atkinson", "richard_c_atkinson@ntlworld.com"
1627                ),
1628                new Contributor("David Basten", "-"),
1629                new Contributor("David Berry", "-"),
1630                new Contributor("Anthony Boulestreau", "-"),
1631                new Contributor("Jeremy Bowman", "-"),
1632                new Contributor("Nicolas Brodu", "-"),
1633                new Contributor("David Browning", "-"),
1634                new Contributor("S???ren Caspersen", "-"),
1635                new Contributor("Chuanhao Chiu", "-"),
1636                new Contributor("Brian Cole", "-"),
1637                new Contributor("Pascal Collet", "-"),
1638                new Contributor("Martin Cordova", "-"),
1639                new Contributor("Paolo Cova", "-"),
1640                new Contributor("Mike Duffy", "-"),
1641                new Contributor("Don Elliott", "-"),
1642                new Contributor("Jonathan Gabbai", "-"),
1643                new Contributor(
1644                    "David Gilbert", "david.gilbert@object-refinery.com"
1645                ),
1646                new Contributor("Serge V. Grachov", "-"),
1647                new Contributor("Daniel Gredler", "-"),
1648                new Contributor("Hans-Jurgen Greiner", "-"),
1649                new Contributor("Joao Guilherme Del Valle", "-"),
1650                new Contributor("Aiman Han", "-"),
1651                new Contributor("Cameron Hayne", "-"),
1652                new Contributor("Jon Iles", "-"),
1653                new Contributor("Wolfgang Irler", "-"),
1654                new Contributor("Xun Kang", "-"),
1655                new Contributor("Bill Kelemen", "-"),
1656                new Contributor("Norbert Kiesel", "-"),
1657                new Contributor("Gideon Krause", "-"),
1658                new Contributor("Arnaud Lelievre", "-"),
1659                new Contributor("Wolfgang Lenhard", "-"),
1660                new Contributor("David Li", "-"),
1661                new Contributor("Tin Luu", "-"),
1662                new Contributor("Craig MacFarlane", "-"),
1663                new Contributor("Achilleus Mantzios", "-"),
1664                new Contributor("Thomas Meier", "-"),
1665                new Contributor("Jim Moore", "-"),
1666                new Contributor("Jonathan Nash", "-"),
1667                new Contributor("Barak Naveh", "-"),
1668                new Contributor("David M. O'Donnell", "-"),
1669                new Contributor("Krzysztof Paz", "-"),
1670                new Contributor("Tomer Peretz", "-"),
1671                new Contributor("Andrzej Porebski", "-"),
1672                new Contributor("Xavier Poinsard", "-"),
1673                new Contributor("Viktor Rajewski", "-"),
1674                new Contributor("Eduardo Ramalho", "-"),
1675                new Contributor("Michael Rauch", "-"),
1676                new Contributor("Cameron Riley", "-"),
1677                new Contributor("Dan Rivett", "d.rivett@ukonline.co.uk"),
1678                new Contributor("Scott Sams", "-"),
1679                new Contributor("Michel Santos", "-"),
1680                new Contributor("Thierry Saura", "-"),
1681                new Contributor("Andreas Schneider", "-"),
1682                new Contributor("Jean-Luc SCHWAB", "-"),
1683                new Contributor("Bryan Scott", "-"),
1684                new Contributor("Tobias Selb", "-"),
1685                new Contributor("Mofeed Shahin", "-"),
1686                new Contributor("Greg Steckman", "-"),
1687                new Contributor("Roger Studner", "-"),
1688                new Contributor("Irv Thomae", "-"),
1689                new Contributor("Eric Thomas", "-"),
1690                new Contributor("Rich Unger", "-"),
1691                new Contributor("Daniel van Enckevort", "-"),
1692                new Contributor("Laurence Vanhelsuwe", "-"),
1693                new Contributor("Sylvain Vieujot", "-"),
1694                new Contributor("Mark Watson", "www.markwatson.com"),
1695                new Contributor("Alex Weber", "-"),
1696                new Contributor("Matthew Wright", "-"),
1697                new Contributor("Benoit Xhenseval", "-"),
1698                new Contributor(
1699                    "Christian W. Zuckschwerdt",
1700                    "Christian.Zuckschwerdt@Informatik.Uni-Oldenburg.de"
1701                ),
1702                new Contributor("Hari", "-"),
1703                new Contributor("Sam (oldman)", "-"),
1704            }
1705        ));
1706
1707        addLibrary(JCommon.INFO);
1708
1709    }
1710
1711    /**
1712     * Returns the JFreeChart logo (a picture of a gorilla).
1713     *
1714     * @return The JFreeChart logo.
1715     */

1716    public Image JavaDoc getLogo() {
1717
1718        Image JavaDoc logo = super.getLogo();
1719        if (logo == null) {
1720            URL JavaDoc imageURL = ClassLoader.getSystemResource(
1721                "org/jfree/chart/gorilla.jpg"
1722            );
1723            if (imageURL != null) {
1724                ImageIcon JavaDoc temp = new ImageIcon JavaDoc(imageURL);
1725                    // use ImageIcon because it waits for the image to load...
1726
logo = temp.getImage();
1727                setLogo(logo);
1728            }
1729        }
1730        return logo;
1731
1732    }
1733
1734}
1735
Popular Tags