KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > axis > Axis


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  * Axis.java
28  * ---------
29  * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
30  *
31  * Original Author: David Gilbert (for Object Refinery Limited);
32  * Contributor(s): Bill Kelemen; Nicolas Brodu
33  *
34  * $Id: Axis.java,v 1.11 2005/06/01 09:36:19 mungady Exp $
35  *
36  * Changes (from 21-Aug-2001)
37  * --------------------------
38  * 21-Aug-2001 : Added standard header, fixed DOS encoding problem (DG);
39  * 18-Sep-2001 : Updated header (DG);
40  * 07-Nov-2001 : Allow null axis labels (DG);
41  * : Added default font values (DG);
42  * 13-Nov-2001 : Modified the setPlot() method to check compatibility between
43  * the axis and the plot (DG);
44  * 30-Nov-2001 : Changed default font from "Arial" --> "SansSerif" (DG);
45  * 06-Dec-2001 : Allow null in setPlot() method (BK);
46  * 06-Mar-2002 : Added AxisConstants interface (DG);
47  * 23-Apr-2002 : Added a visible property. Moved drawVerticalString to
48  * RefineryUtilities. Added fixedDimension property for use in
49  * combined plots (DG);
50  * 25-Jun-2002 : Removed unnecessary imports (DG);
51  * 05-Sep-2002 : Added attribute for tick mark paint (DG);
52  * 18-Sep-2002 : Fixed errors reported by Checkstyle (DG);
53  * 07-Nov-2002 : Added attributes to control the inside and outside length of
54  * the tick marks (DG);
55  * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG);
56  * 18-Nov-2002 : Added axis location to refreshTicks() parameters (DG);
57  * 15-Jan-2003 : Removed monolithic constructor (DG);
58  * 17-Jan-2003 : Moved plot classes to separate package (DG);
59  * 26-Mar-2003 : Implemented Serializable (DG);
60  * 03-Jul-2003 : Modified reserveSpace method (DG);
61  * 13-Aug-2003 : Implemented Cloneable (DG);
62  * 11-Sep-2003 : Took care of listeners while cloning (NB);
63  * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG);
64  * 06-Nov-2003 : Modified refreshTicks() signature (DG);
65  * 06-Jan-2004 : Added axis line attributes (DG);
66  * 16-Mar-2004 : Added plot state to draw() method (DG);
67  * 07-Apr-2004 : Modified text bounds calculation (DG);
68  * 18-May-2004 : Eliminated AxisConstants.java (DG);
69  * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities -->
70  * TextUtilities (DG);
71  * 04-Oct-2004 : Modified getLabelEnclosure() method to treat an empty String
72  * the same way as a null string - see bug 1026521 (DG);
73  * 21-Apr-2005 : Replaced Insets with RectangleInsets (DG);
74  * 26-Apr-2005 : Removed LOGGER (DG);
75  * 01-Jun-2005 : Added hasListener() method for unit testing (DG);
76  *
77  */

78
79 package org.jfree.chart.axis;
80
81 import java.awt.BasicStroke JavaDoc;
82 import java.awt.Color JavaDoc;
83 import java.awt.Font JavaDoc;
84 import java.awt.FontMetrics JavaDoc;
85 import java.awt.Graphics2D JavaDoc;
86 import java.awt.Paint JavaDoc;
87 import java.awt.Shape JavaDoc;
88 import java.awt.Stroke JavaDoc;
89 import java.awt.geom.AffineTransform JavaDoc;
90 import java.awt.geom.Line2D JavaDoc;
91 import java.awt.geom.Rectangle2D JavaDoc;
92 import java.io.IOException JavaDoc;
93 import java.io.ObjectInputStream JavaDoc;
94 import java.io.ObjectOutputStream JavaDoc;
95 import java.io.Serializable JavaDoc;
96 import java.util.Arrays JavaDoc;
97 import java.util.EventListener JavaDoc;
98 import java.util.List JavaDoc;
99
100 import javax.swing.event.EventListenerList JavaDoc;
101
102 import org.jfree.chart.event.AxisChangeEvent;
103 import org.jfree.chart.event.AxisChangeListener;
104 import org.jfree.chart.plot.Plot;
105 import org.jfree.chart.plot.PlotRenderingInfo;
106 import org.jfree.io.SerialUtilities;
107 import org.jfree.text.TextUtilities;
108 import org.jfree.ui.RectangleEdge;
109 import org.jfree.ui.RectangleInsets;
110 import org.jfree.ui.TextAnchor;
111 import org.jfree.util.ObjectUtilities;
112
113 /**
114  * The base class for all axes in JFreeChart. Subclasses are divided into
115  * those that display values ({@link ValueAxis}) and those that display
116  * categories ({@link CategoryAxis}).
117  */

118 public abstract class Axis implements Cloneable JavaDoc, Serializable JavaDoc {
119
120     /** For serialization. */
121     private static final long serialVersionUID = 7719289504573298271L;
122     
123     /** The default axis visibility. */
124     public static final boolean DEFAULT_AXIS_VISIBLE = true;
125
126     /** The default axis label font. */
127     public static final Font JavaDoc DEFAULT_AXIS_LABEL_FONT
128         = new Font JavaDoc("SansSerif", Font.PLAIN, 12);
129
130     /** The default axis label paint. */
131     public static final Paint JavaDoc DEFAULT_AXIS_LABEL_PAINT = Color.black;
132
133     /** The default axis label insets. */
134     public static final RectangleInsets DEFAULT_AXIS_LABEL_INSETS
135         = new RectangleInsets(3.0, 3.0, 3.0, 3.0);
136
137     /** The default axis line paint. */
138     public static final Paint JavaDoc DEFAULT_AXIS_LINE_PAINT = Color.gray;
139     
140     /** The default axis line stroke. */
141     public static final Stroke JavaDoc DEFAULT_AXIS_LINE_STROKE = new BasicStroke JavaDoc(1.0f);
142
143     /** The default tick labels visibility. */
144     public static final boolean DEFAULT_TICK_LABELS_VISIBLE = true;
145
146     /** The default tick label font. */
147     public static final Font JavaDoc DEFAULT_TICK_LABEL_FONT
148         = new Font JavaDoc("SansSerif", Font.PLAIN, 10);
149
150     /** The default tick label paint. */
151     public static final Paint JavaDoc DEFAULT_TICK_LABEL_PAINT = Color.black;
152
153     /** The default tick label insets. */
154     public static final RectangleInsets DEFAULT_TICK_LABEL_INSETS
155         = new RectangleInsets(2.0, 4.0, 2.0, 4.0);
156
157     /** The default tick marks visible. */
158     public static final boolean DEFAULT_TICK_MARKS_VISIBLE = true;
159
160     /** The default tick stroke. */
161     public static final Stroke JavaDoc DEFAULT_TICK_MARK_STROKE = new BasicStroke JavaDoc(1);
162
163     /** The default tick paint. */
164     public static final Paint JavaDoc DEFAULT_TICK_MARK_PAINT = Color.gray;
165
166     /** The default tick mark inside length. */
167     public static final float DEFAULT_TICK_MARK_INSIDE_LENGTH = 0.0f;
168
169     /** The default tick mark outside length. */
170     public static final float DEFAULT_TICK_MARK_OUTSIDE_LENGTH = 2.0f;
171
172     /** A flag indicating whether or not the axis is visible. */
173     private boolean visible;
174
175     /** The label for the axis. */
176     private String JavaDoc label;
177
178     /** The font for displaying the axis label. */
179     private Font JavaDoc labelFont;
180
181     /** The paint for drawing the axis label. */
182     private transient Paint JavaDoc labelPaint;
183
184     /** The insets for the axis label. */
185     private RectangleInsets labelInsets;
186
187     /** The label angle. */
188     private double labelAngle;
189
190     /** A flag that controls whether or not the axis line is visible. */
191     private boolean axisLineVisible;
192
193     /** The stroke used for the axis line. */
194     private transient Stroke JavaDoc axisLineStroke;
195     
196     /** The paint used for the axis line. */
197     private transient Paint JavaDoc axisLinePaint;
198     
199     /**
200      * A flag that indicates whether or not tick labels are visible for the
201      * axis.
202      */

203     private boolean tickLabelsVisible;
204
205     /** The font used to display the tick labels. */
206     private Font JavaDoc tickLabelFont;
207
208     /** The color used to display the tick labels. */
209     private transient Paint JavaDoc tickLabelPaint;
210
211     /** The blank space around each tick label. */
212     private RectangleInsets tickLabelInsets;
213
214     /**
215      * A flag that indicates whether or not tick marks are visible for the
216      * axis.
217      */

218     private boolean tickMarksVisible;
219
220     /** The length of the tick mark inside the data area (zero permitted). */
221     private float tickMarkInsideLength;
222
223     /** The length of the tick mark outside the data area (zero permitted). */
224     private float tickMarkOutsideLength;
225
226     /** The stroke used to draw tick marks. */
227     private transient Stroke JavaDoc tickMarkStroke;
228
229     /** The paint used to draw tick marks. */
230     private transient Paint JavaDoc tickMarkPaint;
231
232     /** The fixed (horizontal or vertical) dimension for the axis. */
233     private double fixedDimension;
234
235     /**
236      * A reference back to the plot that the axis is assigned to (can be
237      * <code>null</code>).
238      */

239     private transient Plot plot;
240
241     /** Storage for registered listeners. */
242     private transient EventListenerList JavaDoc listenerList;
243
244     /**
245      * Constructs an axis, using default values where necessary.
246      *
247      * @param label the axis label (<code>null</code> permitted).
248      */

249     protected Axis(String JavaDoc label) {
250
251         this.label = label;
252         this.visible = DEFAULT_AXIS_VISIBLE;
253         this.labelFont = DEFAULT_AXIS_LABEL_FONT;
254         this.labelPaint = DEFAULT_AXIS_LABEL_PAINT;
255         this.labelInsets = DEFAULT_AXIS_LABEL_INSETS;
256         this.labelAngle = 0.0;
257         
258         this.axisLineVisible = true;
259         this.axisLinePaint = DEFAULT_AXIS_LINE_PAINT;
260         this.axisLineStroke = DEFAULT_AXIS_LINE_STROKE;
261         
262         this.tickLabelsVisible = DEFAULT_TICK_LABELS_VISIBLE;
263         this.tickLabelFont = DEFAULT_TICK_LABEL_FONT;
264         this.tickLabelPaint = DEFAULT_TICK_LABEL_PAINT;
265         this.tickLabelInsets = DEFAULT_TICK_LABEL_INSETS;
266         
267         this.tickMarksVisible = DEFAULT_TICK_MARKS_VISIBLE;
268         this.tickMarkStroke = DEFAULT_TICK_MARK_STROKE;
269         this.tickMarkPaint = DEFAULT_TICK_MARK_PAINT;
270         this.tickMarkInsideLength = DEFAULT_TICK_MARK_INSIDE_LENGTH;
271         this.tickMarkOutsideLength = DEFAULT_TICK_MARK_OUTSIDE_LENGTH;
272
273         this.plot = null;
274
275         this.listenerList = new EventListenerList JavaDoc();
276
277     }
278
279     /**
280      * Returns <code>true</code> if the axis is visible, and
281      * <code>false</code> otherwise.
282      *
283      * @return A boolean.
284      */

285     public boolean isVisible() {
286         return this.visible;
287     }
288
289     /**
290      * Sets a flag that controls whether or not the axis is visible and sends
291      * an {@link AxisChangeEvent} to all registered listeners.
292      *
293      * @param flag the flag.
294      */

295     public void setVisible(boolean flag) {
296         if (flag != this.visible) {
297             this.visible = flag;
298             notifyListeners(new AxisChangeEvent(this));
299         }
300     }
301
302     /**
303      * Returns the label for the axis.
304      *
305      * @return The label for the axis (<code>null</code> possible).
306      */

307     public String JavaDoc getLabel() {
308         return this.label;
309     }
310
311     /**
312      * Sets the label for the axis and sends an {@link AxisChangeEvent} to all
313      * registered listeners.
314      *
315      * @param label the new label (<code>null</code> permitted).
316      */

317     public void setLabel(String JavaDoc label) {
318         
319         String JavaDoc existing = this.label;
320         if (existing != null) {
321             if (!existing.equals(label)) {
322                 this.label = label;
323                 notifyListeners(new AxisChangeEvent(this));
324             }
325         }
326         else {
327             if (label != null) {
328                 this.label = label;
329                 notifyListeners(new AxisChangeEvent(this));
330             }
331         }
332
333     }
334
335     /**
336      * Returns the font for the axis label.
337      *
338      * @return The font (never <code>null</code>).
339      */

340     public Font JavaDoc getLabelFont() {
341         return this.labelFont;
342     }
343
344     /**
345      * Sets the font for the axis label and sends an {@link AxisChangeEvent}
346      * to all registered listeners.
347      *
348      * @param font the font (<code>null</code> not permitted).
349      */

350     public void setLabelFont(Font JavaDoc font) {
351         if (font == null) {
352             throw new IllegalArgumentException JavaDoc("Null 'font' argument.");
353         }
354         if (!this.labelFont.equals(font)) {
355             this.labelFont = font;
356             notifyListeners(new AxisChangeEvent(this));
357         }
358     }
359
360     /**
361      * Returns the color/shade used to draw the axis label.
362      *
363      * @return The paint (never <code>null</code>).
364      */

365     public Paint JavaDoc getLabelPaint() {
366         return this.labelPaint;
367     }
368
369     /**
370      * Sets the paint used to draw the axis label and sends an
371      * {@link AxisChangeEvent} to all registered listeners.
372      *
373      * @param paint the paint (<code>null</code> not permitted).
374      */

375     public void setLabelPaint(Paint JavaDoc paint) {
376         if (paint == null) {
377             throw new IllegalArgumentException JavaDoc("Null 'paint' argument.");
378         }
379         this.labelPaint = paint;
380         notifyListeners(new AxisChangeEvent(this));
381     }
382
383     /**
384      * Returns the insets for the label (that is, the amount of blank space
385      * that should be left around the label).
386      *
387      * @return The label insets (never <code>null</code>).
388      */

389     public RectangleInsets getLabelInsets() {
390         return this.labelInsets;
391     }
392
393     /**
394      * Sets the insets for the axis label, and sends an {@link AxisChangeEvent}
395      * to all registered listeners.
396      *
397      * @param insets the insets (<code>null</code> not permitted).
398      */

399     public void setLabelInsets(RectangleInsets insets) {
400         if (insets == null) {
401             throw new IllegalArgumentException JavaDoc("Null 'insets' argument.");
402         }
403         if (!insets.equals(this.labelInsets)) {
404             this.labelInsets = insets;
405             notifyListeners(new AxisChangeEvent(this));
406         }
407     }
408
409     /**
410      * Returns the angle of the axis label.
411      *
412      * @return The angle (in radians).
413      */

414     public double getLabelAngle() {
415         return this.labelAngle;
416     }
417
418     /**
419      * Sets the angle for the label and sends an {@link AxisChangeEvent} to all
420      * registered listeners.
421      *
422      * @param angle the angle (in radians).
423      */

424     public void setLabelAngle(double angle) {
425         this.labelAngle = angle;
426         notifyListeners(new AxisChangeEvent(this));
427     }
428
429     /**
430      * A flag that controls whether or not the axis line is drawn.
431      *
432      * @return A boolean.
433      */

434     public boolean isAxisLineVisible() {
435         return this.axisLineVisible;
436     }
437     
438     /**
439      * Sets a flag that controls whether or not the axis line is visible and
440      * sends an {@link AxisChangeEvent} to all registered listeners.
441      *
442      * @param visible the flag.
443      */

444     public void setAxisLineVisible(boolean visible) {
445         this.axisLineVisible = visible;
446         notifyListeners(new AxisChangeEvent(this));
447     }
448     
449     /**
450      * Returns the paint used to draw the axis line.
451      *
452      * @return The paint (never <code>null</code>).
453      */

454     public Paint JavaDoc getAxisLinePaint() {
455         return this.axisLinePaint;
456     }
457     
458     /**
459      * Sets the paint used to draw the axis line and sends an
460      * {@link AxisChangeEvent} to all registered listeners.
461      *
462      * @param paint the paint (<code>null</code> not permitted).
463      */

464     public void setAxisLinePaint(Paint JavaDoc paint) {
465         if (paint == null) {
466             throw new IllegalArgumentException JavaDoc("Null 'paint' argument.");
467         }
468         this.axisLinePaint = paint;
469         notifyListeners(new AxisChangeEvent(this));
470     }
471     
472     /**
473      * Returns the stroke used to draw the axis line.
474      *
475      * @return The stroke (never <code>null</code>).
476      */

477     public Stroke JavaDoc getAxisLineStroke() {
478         return this.axisLineStroke;
479     }
480     
481     /**
482      * Sets the stroke used to draw the axis line and sends an
483      * {@link AxisChangeEvent} to all registered listeners.
484      *
485      * @param stroke the stroke (<code>null</code> not permitted).
486      */

487     public void setAxisLineStroke(Stroke JavaDoc stroke) {
488         if (stroke == null) {
489             throw new IllegalArgumentException JavaDoc("Null 'stroke' argument.");
490         }
491         this.axisLineStroke = stroke;
492         notifyListeners(new AxisChangeEvent(this));
493     }
494     
495     /**
496      * Returns a flag indicating whether or not the tick labels are visible.
497      *
498      * @return The flag.
499      */

500     public boolean isTickLabelsVisible() {
501         return this.tickLabelsVisible;
502     }
503
504     /**
505      * Sets the flag that determines whether or not the tick labels are
506      * visible and sends an {@link AxisChangeEvent} to all registered
507      * listeners.
508      *
509      * @param flag the flag.
510      */

511     public void setTickLabelsVisible(boolean flag) {
512
513         if (flag != this.tickLabelsVisible) {
514             this.tickLabelsVisible = flag;
515             notifyListeners(new AxisChangeEvent(this));
516         }
517
518     }
519
520     /**
521      * Returns the font used for the tick labels (if showing).
522      *
523      * @return The font (never <code>null</code>).
524      */

525     public Font JavaDoc getTickLabelFont() {
526         return this.tickLabelFont;
527     }
528
529     /**
530      * Sets the font for the tick labels and sends an {@link AxisChangeEvent}
531      * to all registered listeners.
532      *
533      * @param font the font (<code>null</code> not allowed).
534      */

535     public void setTickLabelFont(Font JavaDoc font) {
536
537         // check arguments...
538
if (font == null) {
539             throw new IllegalArgumentException JavaDoc("Null 'font' argument.");
540         }
541
542         // apply change if necessary...
543
if (!this.tickLabelFont.equals(font)) {
544             this.tickLabelFont = font;
545             notifyListeners(new AxisChangeEvent(this));
546         }
547
548     }
549
550     /**
551      * Returns the color/shade used for the tick labels.
552      *
553      * @return The paint used for the tick labels.
554      */

555     public Paint JavaDoc getTickLabelPaint() {
556         return this.tickLabelPaint;
557     }
558
559     /**
560      * Sets the paint used to draw tick labels (if they are showing) and
561      * sends an {@link AxisChangeEvent} to all registered listeners.
562      *
563      * @param paint the paint (<code>null</code> not permitted).
564      */

565     public void setTickLabelPaint(Paint JavaDoc paint) {
566         if (paint == null) {
567             throw new IllegalArgumentException JavaDoc("Null 'paint' argument.");
568         }
569         this.tickLabelPaint = paint;
570         notifyListeners(new AxisChangeEvent(this));
571     }
572
573     /**
574      * Returns the insets for the tick labels.
575      *
576      * @return The insets (never <code>null</code>).
577      */

578     public RectangleInsets getTickLabelInsets() {
579         return this.tickLabelInsets;
580     }
581
582     /**
583      * Sets the insets for the tick labels and sends an {@link AxisChangeEvent}
584      * to all registered listeners.
585      *
586      * @param insets the insets (<code>null</code> not permitted).
587      */

588     public void setTickLabelInsets(RectangleInsets insets) {
589         if (insets == null) {
590             throw new IllegalArgumentException JavaDoc("Null 'insets' argument.");
591         }
592         if (!this.tickLabelInsets.equals(insets)) {
593             this.tickLabelInsets = insets;
594             notifyListeners(new AxisChangeEvent(this));
595         }
596     }
597
598     /**
599      * Returns the flag that indicates whether or not the tick marks are
600      * showing.
601      *
602      * @return The flag that indicates whether or not the tick marks are
603      * showing.
604      */

605     public boolean isTickMarksVisible() {
606         return this.tickMarksVisible;
607     }
608
609     /**
610      * Sets the flag that indicates whether or not the tick marks are showing
611      * and sends an {@link AxisChangeEvent} to all registered listeners.
612      *
613      * @param flag the flag.
614      */

615     public void setTickMarksVisible(boolean flag) {
616         if (flag != this.tickMarksVisible) {
617             this.tickMarksVisible = flag;
618             notifyListeners(new AxisChangeEvent(this));
619         }
620     }
621
622     /**
623      * Returns the inside length of the tick marks.
624      *
625      * @return The length.
626      */

627     public float getTickMarkInsideLength() {
628         return this.tickMarkInsideLength;
629     }
630
631     /**
632      * Sets the inside length of the tick marks and sends
633      * an {@link AxisChangeEvent} to all registered listeners.
634      *
635      * @param length the new length.
636      */

637     public void setTickMarkInsideLength(float length) {
638         this.tickMarkInsideLength = length;
639         notifyListeners(new AxisChangeEvent(this));
640     }
641
642     /**
643      * Returns the outside length of the tick marks.
644      *
645      * @return The length.
646      */

647     public float getTickMarkOutsideLength() {
648         return this.tickMarkOutsideLength;
649     }
650
651     /**
652      * Sets the outside length of the tick marks and sends
653      * an {@link AxisChangeEvent} to all registered listeners.
654      *
655      * @param length the new length.
656      */

657     public void setTickMarkOutsideLength(float length) {
658         this.tickMarkOutsideLength = length;
659         notifyListeners(new AxisChangeEvent(this));
660     }
661
662     /**
663      * Returns the stroke used to draw tick marks.
664      *
665      * @return The stroke (never <code>null</code>).
666      */

667     public Stroke JavaDoc getTickMarkStroke() {
668         return this.tickMarkStroke;
669     }
670
671     /**
672      * Sets the stroke used to draw tick marks and sends
673      * an {@link AxisChangeEvent} to all registered listeners.
674      *
675      * @param stroke the stroke (<code>null</code> not permitted).
676      */

677     public void setTickMarkStroke(Stroke JavaDoc stroke) {
678         if (stroke == null) {
679             throw new IllegalArgumentException JavaDoc("Null 'stroke' argument.");
680         }
681         if (!this.tickMarkStroke.equals(stroke)) {
682             this.tickMarkStroke = stroke;
683             notifyListeners(new AxisChangeEvent(this));
684         }
685     }
686
687     /**
688      * Returns the paint used to draw tick marks (if they are showing).
689      *
690      * @return The paint (never <code>null</code>).
691      */

692     public Paint JavaDoc getTickMarkPaint() {
693         return this.tickMarkPaint;
694     }
695
696     /**
697      * Sets the paint used to draw tick marks and sends an
698      * {@link AxisChangeEvent} to all registered listeners.
699      *
700      * @param paint the paint (<code>null</code> not permitted).
701      */

702     public void setTickMarkPaint(Paint JavaDoc paint) {
703         if (paint == null) {
704             throw new IllegalArgumentException JavaDoc("Null 'paint' argument.");
705         }
706         this.tickMarkPaint = paint;
707         notifyListeners(new AxisChangeEvent(this));
708     }
709
710     /**
711      * Returns the plot that the axis is assigned to. This method will return
712      * <code>null</code> if the axis is not currently assigned to a plot.
713      *
714      * @return The plot that the axis is assigned to (possibly
715      * <code>null</code>).
716      */

717     public Plot getPlot() {
718         return this.plot;
719     }
720
721     /**
722      * Sets a reference to the plot that the axis is assigned to.
723      * <P>
724      * This method is used internally, you shouldn't need to call it yourself.
725      *
726      * @param plot the plot.
727      */

728     public void setPlot(Plot plot) {
729         this.plot = plot;
730         configure();
731     }
732
733     /**
734      * Returns the fixed dimension for the axis.
735      *
736      * @return The fixed dimension.
737      */

738     public double getFixedDimension() {
739         return this.fixedDimension;
740     }
741
742     /**
743      * Sets the fixed dimension for the axis.
744      * <P>
745      * This is used when combining more than one plot on a chart. In this case,
746      * there may be several axes that need to have the same height or width so
747      * that they are aligned. This method is used to fix a dimension for the
748      * axis (the context determines whether the dimension is horizontal or
749      * vertical).
750      *
751      * @param dimension the fixed dimension.
752      */

753     public void setFixedDimension(double dimension) {
754         this.fixedDimension = dimension;
755     }
756
757     /**
758      * Configures the axis to work with the current plot. Override this method
759      * to perform any special processing (such as auto-rescaling).
760      */

761     public abstract void configure();
762
763     /**
764      * Estimates the space (height or width) required to draw the axis.
765      *
766      * @param g2 the graphics device.
767      * @param plot the plot that the axis belongs to.
768      * @param plotArea the area within which the plot (including axes) should
769      * be drawn.
770      * @param edge the axis location.
771      * @param space space already reserved.
772      *
773      * @return The space required to draw the axis (including pre-reserved
774      * space).
775      */

776     public abstract AxisSpace reserveSpace(Graphics2D JavaDoc g2, Plot plot,
777                                            Rectangle2D JavaDoc plotArea,
778                                            RectangleEdge edge,
779                                            AxisSpace space);
780
781     /**
782      * Draws the axis on a Java 2D graphics device (such as the screen or a
783      * printer).
784      *
785      * @param g2 the graphics device (<code>null</code> not permitted).
786      * @param cursor the cursor location (determines where to draw the axis).
787      * @param plotArea the area within which the axes and plot should be drawn.
788      * @param dataArea the area within which the data should be drawn.
789      * @param edge the axis location (<code>null</code> not permitted).
790      * @param plotState collects information about the plot
791      * (<code>null</code> permitted).
792      *
793      * @return The axis state (never <code>null</code>).
794      */

795     public abstract AxisState draw(Graphics2D JavaDoc g2,
796                                    double cursor,
797                                    Rectangle2D JavaDoc plotArea,
798                                    Rectangle2D JavaDoc dataArea,
799                                    RectangleEdge edge,
800                                    PlotRenderingInfo plotState);
801
802     /**
803      * Calculates the positions of the ticks for the axis, storing the results
804      * in the tick list (ready for drawing).
805      *
806      * @param g2 the graphics device.
807      * @param state the axis state.
808      * @param dataArea the area inside the axes.
809      * @param edge the edge on which the axis is located.
810      *
811      * @return The list of ticks.
812      */

813     public abstract List JavaDoc refreshTicks(Graphics2D JavaDoc g2,
814                                       AxisState state,
815                                       Rectangle2D JavaDoc dataArea,
816                                       RectangleEdge edge);
817
818     /**
819      * Registers an object for notification of changes to the axis.
820      *
821      * @param listener the object that is being registered.
822      */

823     public void addChangeListener(AxisChangeListener listener) {
824         this.listenerList.add(AxisChangeListener.class, listener);
825     }
826
827     /**
828      * Deregisters an object for notification of changes to the axis.
829      *
830      * @param listener the object to deregister.
831      */

832     public void removeChangeListener(AxisChangeListener listener) {
833         this.listenerList.remove(AxisChangeListener.class, listener);
834     }
835
836     /**
837      * Returns <code>true</code> if the specified object is registered with
838      * the dataset as a listener. Most applications won't need to call this
839      * method, it exists mainly for use by unit testing code.
840      *
841      * @param listener the listener.
842      *
843      * @return A boolean.
844      */

845     public boolean hasListener(EventListener JavaDoc listener) {
846         List JavaDoc list = Arrays.asList(this.listenerList.getListenerList());
847         return list.contains(listener);
848     }
849     
850     /**
851      * Notifies all registered listeners that the axis has changed.
852      * The AxisChangeEvent provides information about the change.
853      *
854      * @param event information about the change to the axis.
855      */

856     protected void notifyListeners(AxisChangeEvent event) {
857
858         Object JavaDoc[] listeners = this.listenerList.getListenerList();
859         for (int i = listeners.length - 2; i >= 0; i -= 2) {
860             if (listeners[i] == AxisChangeListener.class) {
861                 ((AxisChangeListener) listeners[i + 1]).axisChanged(event);
862             }
863         }
864
865     }
866
867     /**
868      * Returns a rectangle that encloses the axis label. This is typically
869      * used for layout purposes (it gives the maximum dimensions of the label).
870      *
871      * @param g2 the graphics device.
872      * @param edge the edge of the plot area along which the axis is measuring.
873      *
874      * @return The enclosing rectangle.
875      */

876     protected Rectangle2D JavaDoc getLabelEnclosure(Graphics2D JavaDoc g2, RectangleEdge edge) {
877
878         Rectangle2D JavaDoc result = new Rectangle2D.Double JavaDoc();
879         String JavaDoc axisLabel = getLabel();
880         if (axisLabel != null && !axisLabel.equals("")) {
881             FontMetrics JavaDoc fm = g2.getFontMetrics(getLabelFont());
882             Rectangle2D JavaDoc bounds = TextUtilities.getTextBounds(axisLabel, g2, fm);
883             RectangleInsets insets = getLabelInsets();
884             bounds = insets.createOutsetRectangle(bounds);
885             double angle = getLabelAngle();
886             if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) {
887                 angle = angle - Math.PI / 2.0;
888             }
889             double x = bounds.getCenterX();
890             double y = bounds.getCenterY();
891             AffineTransform JavaDoc transformer
892                 = AffineTransform.getRotateInstance(angle, x, y);
893             Shape JavaDoc labelBounds = transformer.createTransformedShape(bounds);
894             result = labelBounds.getBounds2D();
895         }
896
897         return result;
898
899     }
900
901     /**
902      * Draws the axis label.
903      *
904      * @param label the label text.
905      * @param g2 the graphics device.
906      * @param plotArea the plot area.
907      * @param dataArea the area inside the axes.
908      * @param edge the location of the axis.
909      * @param state the axis state (<code>null</code> not permitted).
910      *
911      * @return Information about the axis.
912      */

913     protected AxisState drawLabel(String JavaDoc label,
914                                   Graphics2D JavaDoc g2,
915                                   Rectangle2D JavaDoc plotArea,
916                                   Rectangle2D JavaDoc dataArea,
917                                   RectangleEdge edge,
918                                   AxisState state) {
919
920         // it is unlikely that 'state' will be null, but check anyway...
921
if (state == null) {
922             throw new IllegalArgumentException JavaDoc("Null 'state' argument.");
923         }
924         
925         if ((label == null) || (label.equals(""))) {
926             return state;
927         }
928
929         Font JavaDoc font = getLabelFont();
930         RectangleInsets insets = getLabelInsets();
931         g2.setFont(font);
932         g2.setPaint(getLabelPaint());
933         FontMetrics JavaDoc fm = g2.getFontMetrics();
934         Rectangle2D JavaDoc labelBounds = TextUtilities.getTextBounds(label, g2, fm);
935
936         if (edge == RectangleEdge.TOP) {
937
938             AffineTransform JavaDoc t = AffineTransform.getRotateInstance(
939                 getLabelAngle(),
940                 labelBounds.getCenterX(), labelBounds.getCenterY()
941             );
942             Shape JavaDoc rotatedLabelBounds = t.createTransformedShape(labelBounds);
943             labelBounds = rotatedLabelBounds.getBounds2D();
944             double labelx = dataArea.getCenterX();
945             double labely = state.getCursor()
946                             - insets.getBottom()
947                             - labelBounds.getHeight() / 2.0;
948             TextUtilities.drawRotatedString(
949                 label, g2, (float) labelx, (float) labely,
950                 TextAnchor.CENTER, getLabelAngle(), TextAnchor.CENTER
951             );
952             state.cursorUp(
953                 insets.getTop() + labelBounds.getHeight() + insets.getBottom()
954             );
955
956         }
957         else if (edge == RectangleEdge.BOTTOM) {
958
959             AffineTransform JavaDoc t = AffineTransform.getRotateInstance(
960                 getLabelAngle(),
961                 labelBounds.getCenterX(), labelBounds.getCenterY()
962             );
963             Shape JavaDoc rotatedLabelBounds = t.createTransformedShape(labelBounds);
964             labelBounds = rotatedLabelBounds.getBounds2D();
965             double labelx = dataArea.getCenterX();
966             double labely = state.getCursor()
967                             + insets.getTop() + labelBounds.getHeight() / 2.0;
968             TextUtilities.drawRotatedString(
969                 label, g2, (float) labelx, (float) labely,
970                 TextAnchor.CENTER, getLabelAngle(), TextAnchor.CENTER
971             );
972             state.cursorDown(
973                 insets.getTop() + labelBounds.getHeight() + insets.getBottom()
974             );
975
976         }
977         else if (edge == RectangleEdge.LEFT) {
978
979             AffineTransform JavaDoc t = AffineTransform.getRotateInstance(
980                 getLabelAngle() - Math.PI / 2.0,
981                 labelBounds.getCenterX(), labelBounds.getCenterY()
982             );
983             Shape JavaDoc rotatedLabelBounds = t.createTransformedShape(labelBounds);
984             labelBounds = rotatedLabelBounds.getBounds2D();
985             double labelx = state.getCursor()
986                             - insets.getRight() - labelBounds.getWidth() / 2.0;
987             double labely = dataArea.getCenterY();
988             TextUtilities.drawRotatedString(
989                 label, g2, (float) labelx, (float) labely, TextAnchor.CENTER,
990                 getLabelAngle() - Math.PI / 2.0, TextAnchor.CENTER
991             );
992             state.cursorLeft(
993                 insets.getLeft() + labelBounds.getWidth() + insets.getRight()
994             );
995         }
996         else if (edge == RectangleEdge.RIGHT) {
997
998             AffineTransform JavaDoc t = AffineTransform.getRotateInstance(
999                 getLabelAngle() + Math.PI / 2.0,
1000                labelBounds.getCenterX(), labelBounds.getCenterY()
1001            );
1002            Shape JavaDoc rotatedLabelBounds = t.createTransformedShape(labelBounds);
1003            labelBounds = rotatedLabelBounds.getBounds2D();
1004            double labelx = state.getCursor()
1005                            + insets.getLeft() + labelBounds.getWidth() / 2.0;
1006            double labely = dataArea.getY() + dataArea.getHeight() / 2.0;
1007            TextUtilities.drawRotatedString(
1008                label, g2, (float) labelx, (float) labely, TextAnchor.CENTER,
1009                getLabelAngle() + Math.PI / 2.0, TextAnchor.CENTER
1010            );
1011            state.cursorRight(
1012                insets.getLeft() + labelBounds.getWidth() + insets.getRight()
1013            );
1014
1015        }
1016
1017        return state;
1018
1019    }
1020
1021    /**
1022     * Draws an axis line at the current cursor position and edge.
1023     *
1024     * @param g2 the graphics device.
1025     * @param cursor the cursor position.
1026     * @param dataArea the data area.
1027     * @param edge the edge.
1028     */

1029    protected void drawAxisLine(Graphics2D JavaDoc g2, double cursor,
1030            Rectangle2D JavaDoc dataArea, RectangleEdge edge) {
1031        
1032        Line2D JavaDoc axisLine = null;
1033        if (edge == RectangleEdge.TOP) {
1034            axisLine = new Line2D.Double JavaDoc(
1035                dataArea.getX(), cursor, dataArea.getMaxX(), cursor
1036            );
1037        }
1038        else if (edge == RectangleEdge.BOTTOM) {
1039            axisLine = new Line2D.Double JavaDoc(
1040                dataArea.getX(), cursor, dataArea.getMaxX(), cursor
1041            );
1042        }
1043        else if (edge == RectangleEdge.LEFT) {
1044            axisLine = new Line2D.Double JavaDoc(
1045                cursor, dataArea.getY(), cursor, dataArea.getMaxY()
1046            );
1047        }
1048        else if (edge == RectangleEdge.RIGHT) {
1049            axisLine = new Line2D.Double JavaDoc(
1050                cursor, dataArea.getY(), cursor, dataArea.getMaxY()
1051            );
1052        }
1053        g2.setPaint(this.axisLinePaint);
1054        g2.setStroke(this.axisLineStroke);
1055        g2.draw(axisLine);
1056        
1057    }
1058
1059    /**
1060     * Returns a clone of the axis.
1061     *
1062     * @return A clone.
1063     *
1064     * @throws CloneNotSupportedException if some component of the axis does
1065     * not support cloning.
1066     */

1067    public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
1068        Axis clone = (Axis) super.clone();
1069        // It's up to the plot which clones up to restore the correct references
1070
clone.plot = null;
1071        clone.listenerList = new EventListenerList JavaDoc();
1072        return clone;
1073    }
1074    
1075    /**
1076     * Tests this axis for equality with another object.
1077     *
1078     * @param obj the object (<code>null</code> permitted).
1079     *
1080     * @return <code>true</code> or <code>false</code>.
1081     */

1082    public boolean equals(Object JavaDoc obj) {
1083
1084        if (obj == this) {
1085            return true;
1086        }
1087
1088        if (!(obj instanceof Axis)) {
1089            return false;
1090        }
1091        Axis that = (Axis) obj;
1092
1093        if (this.visible != that.visible) {
1094            return false;
1095        }
1096
1097        if (!ObjectUtilities.equal(this.label, that.label)) {
1098            return false;
1099        }
1100        if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) {
1101            return false;
1102        }
1103        if (!ObjectUtilities.equal(this.labelPaint, that.labelPaint)) {
1104            return false;
1105        }
1106        if (!ObjectUtilities.equal(this.labelInsets, that.labelInsets)) {
1107            return false;
1108        }
1109        if (this.labelAngle != that.labelAngle) {
1110            return false;
1111        }
1112  
1113        if (this.axisLineVisible != that.axisLineVisible) {
1114            return false;
1115        }
1116        if (!ObjectUtilities.equal(this.axisLineStroke, that.axisLineStroke)) {
1117            return false;
1118        }
1119        if (!ObjectUtilities.equal(this.axisLinePaint, that.axisLinePaint)) {
1120            return false;
1121        }
1122         
1123        if (this.tickLabelsVisible != that.tickLabelsVisible) {
1124            return false;
1125        }
1126        if (!ObjectUtilities.equal(this.tickLabelFont, that.tickLabelFont)) {
1127            return false;
1128        }
1129        if (!ObjectUtilities.equal(this.tickLabelPaint, that.tickLabelPaint)) {
1130            return false;
1131        }
1132        if (!ObjectUtilities.equal(
1133            this.tickLabelInsets, that.tickLabelInsets
1134        )) {
1135            return false;
1136        }
1137        if (this.tickMarksVisible != that.tickMarksVisible) {
1138            return false;
1139        }
1140        if (this.tickMarkInsideLength != that.tickMarkInsideLength) {
1141            return false;
1142        }
1143                           
1144        if (this.tickMarkOutsideLength != that.tickMarkOutsideLength) {
1145            return false;
1146        }
1147                           
1148        if (!ObjectUtilities.equal(this.tickMarkPaint, that.tickMarkPaint)) {
1149            return false;
1150        }
1151        if (!ObjectUtilities.equal(this.tickMarkStroke, that.tickMarkStroke)) {
1152            return false;
1153        }
1154
1155        if (this.fixedDimension != that.fixedDimension) {
1156            return false;
1157        }
1158
1159        return true;
1160
1161    }
1162
1163    /**
1164     * Provides serialization support.
1165     *
1166     * @param stream the output stream.
1167     *
1168     * @throws IOException if there is an I/O error.
1169     */

1170    private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
1171        stream.defaultWriteObject();
1172        SerialUtilities.writePaint(this.labelPaint, stream);
1173        SerialUtilities.writePaint(this.tickLabelPaint, stream);
1174        SerialUtilities.writeStroke(this.axisLineStroke, stream);
1175        SerialUtilities.writePaint(this.axisLinePaint, stream);
1176        SerialUtilities.writeStroke(this.tickMarkStroke, stream);
1177        SerialUtilities.writePaint(this.tickMarkPaint, stream);
1178    }
1179
1180    /**
1181     * Provides serialization support.
1182     *
1183     * @param stream the input stream.
1184     *
1185     * @throws IOException if there is an I/O error.
1186     * @throws ClassNotFoundException if there is a classpath problem.
1187     */

1188    private void readObject(ObjectInputStream JavaDoc stream)
1189        throws IOException JavaDoc, ClassNotFoundException JavaDoc {
1190        stream.defaultReadObject();
1191        this.labelPaint = SerialUtilities.readPaint(stream);
1192        this.tickLabelPaint = SerialUtilities.readPaint(stream);
1193        this.axisLineStroke = SerialUtilities.readStroke(stream);
1194        this.axisLinePaint = SerialUtilities.readPaint(stream);
1195        this.tickMarkStroke = SerialUtilities.readStroke(stream);
1196        this.tickMarkPaint = SerialUtilities.readPaint(stream);
1197        this.listenerList = new EventListenerList JavaDoc();
1198    }
1199
1200}
1201
Popular Tags