KickJava   Java API By Example, From Geeks To Geeks.

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


1 /* ======================================
2  * JFreeChart : a free Java chart library
3  * ======================================
4  *
5  * Project Info: http://www.jfree.org/jfreechart/index.html
6  * Project Lead: David Gilbert (david.gilbert@object-refinery.com);
7  *
8  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License along with this
19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * ------------------
23  * AbstractTitle.java
24  * ------------------
25  * (C) Copyright 2000-2003, by David Berry and Contributors.
26  *
27  * Original Author: David Berry;
28  * Contributor(s): David Gilbert (for Object Refinery Limited);
29  * Nicolas Brodu;
30  *
31  * $Id: AbstractTitle.java,v 1.8 2003/11/03 14:24:59 mungady Exp $
32  *
33  * Changes (from 21-Aug-2001)
34  * --------------------------
35  * 21-Aug-2001 : Added standard header (DG);
36  * 18-Sep-2001 : Updated header (DG);
37  * 14-Nov-2001 : Package com.jrefinery.common.ui.* changed to com.jrefinery.ui.* (DG);
38  * 07-Feb-2002 : Changed blank space around title from Insets --> Spacer, to allow for relative
39  * or absolute spacing (DG);
40  * 25-Jun-2002 : Removed unnecessary imports (DG);
41  * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
42  * 14-Oct-2002 : Changed the event listener storage structure (DG);
43  * 11-Sep-2003 : Took care of listeners while cloning (NB);
44  * 22-Sep-2003 : Spacer cannot be null. Added nullpointer checks for this (TM).
45  */

46
47 package org.jfree.chart;
48
49 import java.awt.Graphics2D JavaDoc;
50 import java.awt.geom.Rectangle2D JavaDoc;
51 import java.io.IOException JavaDoc;
52 import java.io.ObjectInputStream JavaDoc;
53 import java.io.ObjectOutputStream JavaDoc;
54 import java.io.Serializable JavaDoc;
55
56 import javax.swing.event.EventListenerList JavaDoc;
57
58 import org.jfree.chart.event.TitleChangeEvent;
59 import org.jfree.chart.event.TitleChangeListener;
60 import org.jfree.util.ObjectUtils;
61
62 /**
63  * The base class for all chart titles.
64  * <P>
65  * A chart can have multiple titles, appearing at the top, bottom, left or
66  * right of the chart (defined by the constants TOP, BOTTOM, LEFT and RIGHT ---
67  * we also use the constants NORTH, SOUTH, EAST and WEST to remain consistent
68  * with java.awt.BorderLayout, as most developers will be familiar with that
69  * class).
70  * <P>
71  * Concrete implementations of this class will render text, images, and hence
72  * do the actual work of drawing titles.
73  *
74  * @author David Berry
75  */

76 public abstract class AbstractTitle extends Object JavaDoc implements Cloneable JavaDoc, Serializable JavaDoc {
77
78     /** Useful constant for the title position (also used for vertical alignment). */
79     public static final int TOP = 0;
80
81     /** Useful constant for the title position (also used for vertical alignment). */
82     public static final int BOTTOM = 1;
83
84     /** Useful constant for the title position (also used for horizontal alignment). */
85     public static final int RIGHT = 2;
86
87     /** Useful constant for the title position (also used for horizontal alignment). */
88     public static final int LEFT = 3;
89
90     /** Useful constant for the title position. */
91     public static final int NORTH = 0;
92
93     /** Useful constant for the title position. */
94     public static final int SOUTH = 1;
95
96     /** Useful constant for the title position. */
97     public static final int EAST = 2;
98
99     /** Useful constant for the title position. */
100     public static final int WEST = 3;
101
102     /** Useful constant for the title alignment (horizontal or vertical). */
103     public static final int CENTER = 4;
104
105     /** Useful constant for the title alignment (horizontal or vertical). */
106     public static final int MIDDLE = 4;
107
108     /** The default title position. */
109     public static final int DEFAULT_POSITION = AbstractTitle.TOP;
110
111     /** The default horizontal alignment. */
112     public static final int DEFAULT_HORIZONTAL_ALIGNMENT = AbstractTitle.CENTER;
113
114     /** The default vertical alignment. */
115     public static final int DEFAULT_VERTICAL_ALIGNMENT = AbstractTitle.MIDDLE;
116
117     /** Default title spacer. */
118     public static final Spacer DEFAULT_SPACER = new Spacer(Spacer.RELATIVE, 0.01, 0.30, 0.01, 0.15);
119
120     /**
121      * The position of the title (use the constants NORTH, SOUTH, EAST and
122      * WEST, or if you prefer you can also use TOP, BOTTOM, LEFT and RIGHT).
123      */

124     private int position;
125
126     /** The horizontal alignment of the title. */
127     private int horizontalAlignment;
128
129     /** The vertical alignment of the title. */
130     private int verticalAlignment;
131
132     /** The amount of blank space to leave around the title. */
133     private Spacer spacer;
134
135     /** Storage for registered change listeners. */
136     private transient EventListenerList JavaDoc listenerList;
137
138     /** A flag that can be used to temporarily disable the listener mechanism. */
139     private boolean notify;
140
141     /**
142      * Creates a new title, using default attributes where necessary.
143      */

144     protected AbstractTitle() {
145
146         this(AbstractTitle.DEFAULT_POSITION,
147             AbstractTitle.DEFAULT_HORIZONTAL_ALIGNMENT,
148             AbstractTitle.DEFAULT_VERTICAL_ALIGNMENT,
149             AbstractTitle.DEFAULT_SPACER);
150
151     }
152
153     /**
154      * Creates a new title, using default attributes where necessary.
155      *
156      * @param position the relative position of the title (TOP, BOTTOM, RIGHT and LEFT).
157      * @param horizontalAlignment the horizontal alignment of the title (LEFT, CENTER or RIGHT).
158      * @param verticalAlignment the vertical alignment of the title (TOP, MIDDLE or BOTTOM).
159      */

160     protected AbstractTitle(int position, int horizontalAlignment, int verticalAlignment) {
161
162         this(position,
163             horizontalAlignment, verticalAlignment,
164             AbstractTitle.DEFAULT_SPACER);
165
166     }
167
168     /**
169      * Constructs a new AbstractTitle.
170      * <P>
171      * This class defines constants for the valid position and alignment values
172      * --- an IllegalArgumentException will be thrown if invalid values are
173      * passed to this constructor.
174      *
175      * @param position the relative position of the title (TOP, BOTTOM, RIGHT and LEFT).
176      * @param horizontalAlignment the horizontal alignment of the title (LEFT, CENTER or RIGHT).
177      * @param verticalAlignment the vertical alignment of the title (TOP, MIDDLE or BOTTOM).
178      * @param spacer the amount of space to leave around the outside of the title.
179      */

180     protected AbstractTitle(int position,
181                             int horizontalAlignment, int verticalAlignment,
182                             Spacer spacer) {
183
184         // check arguments...
185
if (!isValidPosition(position)) {
186             throw new IllegalArgumentException JavaDoc("AbstractTitle(): invalid position.");
187         }
188
189         if (!AbstractTitle.isValidHorizontalAlignment(horizontalAlignment)) {
190             throw new IllegalArgumentException JavaDoc("AbstractTitle(): invalid horizontal alignment.");
191         }
192
193         if (!AbstractTitle.isValidVerticalAlignment(verticalAlignment)) {
194             throw new IllegalArgumentException JavaDoc("AbstractTitle(): invalid vertical alignment.");
195         }
196         if (spacer == null) {
197             throw new NullPointerException JavaDoc("AbstractTitle(..): Spacer is null.");
198         }
199
200         // initialise...
201
this.position = position;
202         this.horizontalAlignment = horizontalAlignment;
203         this.verticalAlignment = verticalAlignment;
204         this.spacer = spacer;
205         this.listenerList = new EventListenerList JavaDoc();
206         this.notify = true;
207
208     }
209
210     /**
211      * Returns the relative position of the title---represented by one of four
212      * integer constants defined in this class: TOP, BOTTOM, RIGHT or LEFT (or
213      * the equivalent NORTH, SOUTH, EAST and WEST).
214      *
215      * @return The title position.
216      */

217     public int getPosition() {
218         return this.position;
219     }
220
221     /**
222      * Sets the position for the title.
223      *
224      * @param position the relative position of the title (use one of the constants TOP, BOTTOM,
225      * RIGHT and LEFT, or the equivalent NORTH, SOUTH, EAST and WEST).
226      */

227     public void setPosition(int position) {
228
229         if (this.position != position) {
230             // check that the position is valid
231
if (!isValidPosition(position)) {
232                 throw new IllegalArgumentException JavaDoc("AbstractTitle(): invalid position.");
233             }
234             this.position = position;
235             notifyListeners(new TitleChangeEvent(this));
236         }
237     }
238
239     /**
240      * Returns the horizontal alignment of the title. The constants LEFT,
241      * CENTER and RIGHT (defined in this class) are used.
242      *
243      * @return the horizontal alignment of the title (LEFT, CENTER or RIGHT).
244      */

245     public int getHorizontalAlignment() {
246         return this.horizontalAlignment;
247     }
248
249     /**
250      * Sets the horizontal alignment for the title, and notifies any registered
251      * listeners of the change. The constants LEFT, CENTER and RIGHT (defined
252      * in this class) can be used to specify the alignment.
253      *
254      * @param alignment the new horizontal alignment (LEFT, CENTER or RIGHT).
255      */

256     public void setHorizontalAlignment(int alignment) {
257         if (this.horizontalAlignment != alignment) {
258             if (!AbstractTitle.isValidHorizontalAlignment(horizontalAlignment)) {
259                 throw new IllegalArgumentException JavaDoc(
260                     "AbstractTitle.setHorizontalAlignment(): invalid horizontal alignment.");
261             }
262             this.horizontalAlignment = alignment;
263             notifyListeners(new TitleChangeEvent(this));
264         }
265     }
266
267     /**
268      * Returns the vertical alignment of the title. The constants TOP, MIDDLE
269      * and BOTTOM (defined in this class) are used.
270      *
271      * @return the vertical alignment of the title (TOP, MIDDLE or BOTTOM).
272      */

273     public int getVerticalAlignment() {
274         return this.verticalAlignment;
275     }
276
277     /**
278      * Sets the vertical alignment for the title, and notifies any registered
279      * listeners of the change.
280      * The constants TOP, MIDDLE and BOTTOM (defined in this class) can be used
281      * to specify the alignment.
282      *
283      * @param alignment the new vertical alignment (TOP, MIDDLE or BOTTOM).
284      */

285     public void setVerticalAlignment(int alignment) {
286         if (this.verticalAlignment != alignment) {
287             if (!AbstractTitle.isValidVerticalAlignment(verticalAlignment)) {
288                 throw new IllegalArgumentException JavaDoc(
289                     "AbstractTitle.setVerticalAlignment(): invalid vertical alignment.");
290             }
291             this.verticalAlignment = alignment;
292             notifyListeners(new TitleChangeEvent(this));
293         }
294     }
295
296     /**
297      * Returns the spacer (determines the blank space around the edges) for
298      * this title.
299      *
300      * @return the spacer for this title.
301      */

302     public Spacer getSpacer() {
303         return this.spacer;
304     }
305
306     /**
307      * Sets the spacer for the title, and notifies registered listeners of the
308      * change.
309      *
310      * @param spacer the new spacer.
311      */

312     public void setSpacer(Spacer spacer) {
313
314         if (spacer == null) {
315             throw new NullPointerException JavaDoc("AbstractTitle.setSpacer(..): Null argument.");
316         }
317         if (!this.spacer.equals(spacer)) {
318             this.spacer = spacer;
319             notifyListeners(new TitleChangeEvent(this));
320         }
321
322     }
323
324     /**
325      * Returns the flag that indicates whether or not the notification mechanism is enabled.
326      *
327      * @return the flag.
328      */

329     public boolean getNotify() {
330         return this.notify;
331     }
332
333     /**
334      * Sets the flag that indicates whether or not the notification mechanism
335      * is enabled. There are certain situations (such as cloning) where you
336      * want to turn notification off temporarily.
337      *
338      * @param flag the new value of the flag.
339      */

340     public void setNotify(boolean flag) {
341         this.notify = flag;
342     }
343
344     /**
345      * Returns true if the title can assume the specified location, and false otherwise.
346      *
347      * @param position the position.
348      *
349      * @return <code>true</code> if the title can assume the specified position.
350      */

351     public abstract boolean isValidPosition(int position);
352
353     /**
354      * Returns the preferred width of the title. When a title is displayed at
355      * the left or right of a chart, the chart will attempt to give the title
356      * enough space for it's preferred width.
357      *
358      * @param g2 the graphics device.
359      *
360      * @return the preferred width of the title.
361      */

362     public abstract double getPreferredWidth(Graphics2D JavaDoc g2);
363
364     /**
365      * Returns the preferred height of the title. When a title is displayed at
366      * the top or bottom of a chart, the chart will attempt to give the title
367      * enough space for it's preferred height.
368      *
369      * @param g2 the graphics device.
370      *
371      * @return the preferred height of the title.
372      */

373     public abstract double getPreferredHeight(Graphics2D JavaDoc g2);
374
375     /**
376      * Draws the title on a Java 2D graphics device (such as the screen or a printer).
377      *
378      * @param g2 the graphics device.
379      * @param titleArea the area for drawing the title.
380      */

381     public abstract void draw(Graphics2D JavaDoc g2, Rectangle2D JavaDoc titleArea);
382
383     /**
384      * Returns a clone of the title.
385      * <P>
386      * One situation when this is useful is when editing the title properties -
387      * you can edit a clone, and then it is easier to cancel the changes if
388      * necessary.
389      *
390      * @return a clone of the title.
391      *
392      */

393     public Object JavaDoc clone() {
394
395         AbstractTitle duplicate = null;
396
397         try {
398             duplicate = (AbstractTitle) super.clone();
399         }
400         catch (CloneNotSupportedException JavaDoc e) {
401             // this should never happen because Cloneable is implemented
402
throw new RuntimeException JavaDoc("AbstractTitle.clone()");
403         }
404
405         duplicate.listenerList = new EventListenerList JavaDoc();
406
407         // Spacer is immutable => same reference in clone OK
408
return duplicate;
409     }
410
411     /**
412      * Registers an object for notification of changes to the title.
413      *
414      * @param listener the object that is being registered.
415      */

416     public void addChangeListener(TitleChangeListener listener) {
417         this.listenerList.add(TitleChangeListener.class, listener);
418     }
419
420     /**
421      * Unregisters an object for notification of changes to the chart title.
422      *
423      * @param listener the object that is being unregistered.
424      */

425     public void removeChangeListener(TitleChangeListener listener) {
426         this.listenerList.remove(TitleChangeListener.class, listener);
427     }
428
429     /**
430      * Notifies all registered listeners that the chart title has changed in some way.
431      *
432      * @param event an object that contains information about the change to the title.
433      */

434     protected void notifyListeners(TitleChangeEvent event) {
435
436         if (this.notify) {
437
438             Object JavaDoc[] listeners = this.listenerList.getListenerList();
439             for (int i = listeners.length - 2; i >= 0; i -= 2) {
440                 if (listeners[i] == TitleChangeListener.class) {
441                     ((TitleChangeListener) listeners[i + 1]).titleChanged(event);
442                 }
443             }
444         }
445
446     }
447
448     /**
449      * Utility method for checking a horizontal alignment code.
450      *
451      * @param code the alignment code.
452      *
453      * @return <code>true</code> if alignment is <code>LEFT|MIDDLE|RIGHT</code>.
454      */

455     protected static boolean isValidHorizontalAlignment(int code) {
456
457         switch (code) {
458             case AbstractTitle.LEFT:
459                 return true;
460             case AbstractTitle.MIDDLE:
461                 return true;
462             case AbstractTitle.RIGHT:
463                 return true;
464             default:
465                 return false;
466         }
467
468     }
469
470     /**
471      * Utility method for checking a vertical alignment code.
472      *
473      * @param code the alignment code.
474      *
475      * @return <code>true</code>, if alignment is <code>TOP|MIDDLE|BOTTOM</code>.
476      */

477     protected static boolean isValidVerticalAlignment(int code) {
478
479         switch (code) {
480             case AbstractTitle.TOP:
481                 return true;
482             case AbstractTitle.MIDDLE:
483                 return true;
484             case AbstractTitle.BOTTOM:
485                 return true;
486             default:
487                 return false;
488         }
489
490     }
491
492     /**
493      * Tests an object for equality with this title.
494      *
495      * @param obj the object.
496      *
497      * @return <code>true</code> or <code>false</code>.
498      */

499     public boolean equals(Object JavaDoc obj) {
500
501         if (obj == null) {
502             return false;
503         }
504
505         if (obj == this) {
506             return true;
507         }
508
509         if (obj instanceof AbstractTitle) {
510
511             AbstractTitle t = (AbstractTitle) obj;
512
513             if (this.position != t.position) {
514                 return false;
515             }
516             if (this.horizontalAlignment != t.horizontalAlignment) {
517                 return false;
518             }
519             if (this.verticalAlignment != t.verticalAlignment) {
520                 return false;
521             }
522             if (ObjectUtils.equal(this.spacer, t.spacer) == false) {
523                 return false;
524             }
525             if (this.notify != t.notify) {
526                 return false;
527             }
528
529             return true;
530
531         }
532
533         return false;
534
535     }
536
537     /**
538      * Provides serialization support.
539      *
540      * @param stream the output stream.
541      *
542      * @throws IOException if there is an I/O error.
543      */

544     private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
545         stream.defaultWriteObject();
546     }
547
548     /**
549      * Provides serialization support.
550      *
551      * @param stream the input stream.
552      *
553      * @throws IOException if there is an I/O error.
554      * @throws ClassNotFoundException if there is a classpath problem.
555      */

556     private void readObject(ObjectInputStream JavaDoc stream) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
557         stream.defaultReadObject();
558         this.listenerList = new EventListenerList JavaDoc();
559     }
560
561 }
562
Popular Tags