KickJava   Java API By Example, From Geeks To Geeks.

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


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
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------
28  * SymbolAxis.java
29  * ---------------
30  * (C) Copyright 2002-2005, by Object Refinery Limited and Contributors.
31  *
32  * Original Author: Anthony Boulestreau;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  *
36  * Changes (from 23-Jun-2001)
37  * --------------------------
38  * 29-Mar-2002 : First version (AB);
39  * 19-Apr-2002 : Updated formatting and import statements (DG);
40  * 21-Jun-2002 : Make change to use the class TickUnit - remove valueToString()
41  * method and add SymbolicTickUnit (AB);
42  * 25-Jun-2002 : Removed redundant code (DG);
43  * 25-Jul-2002 : Changed order of parameters in ValueAxis constructor (DG);
44  * 05-Sep-2002 : Updated constructor to reflect changes in the Axis class (DG);
45  * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG);
46  * 14-Feb-2003 : Added back missing constructor code (DG);
47  * 26-Mar-2003 : Implemented Serializable (DG);
48  * 14-May-2003 : Renamed HorizontalSymbolicAxis --> SymbolicAxis and merged in
49  * VerticalSymbolicAxis (DG);
50  * 12-Aug-2003 : Fixed bug where refreshTicks() method has different signature
51  * to super class (DG);
52  * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG);
53  * 02-Nov-2003 : Added code to avoid overlapping labels (MR);
54  * 07-Nov-2003 : Modified to use new tick classes (DG);
55  * 18-Nov-2003 : Fixed bug where symbols are not being displayed on the
56  * axis (DG);
57  * 24-Nov-2003 : Added fix for gridlines on zooming (bug id 834643) (DG);
58  * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
59  * 11-Mar-2004 : Modified the way the background grid color is being drawn, see
60  * this thread:
61  * http://www.jfree.org/phpBB2/viewtopic.php?p=22973 (DG);
62  * 16-Mar-2004 : Added plotState to draw() method (DG);
63  * 07-Apr-2004 : Modified string bounds calculation (DG);
64  * 28-Mar-2005 : Renamed autoRangeIncludesZero() --> getAutoRangeIncludesZero()
65  * and autoRangeStickyZero() --> getAutoRangeStickyZero() (DG);
66  * 05-Jul-2005 : Fixed signature on refreshTicks() method - see bug report
67  * 1232264 (DG);
68  * 06-Jul-2005 : Renamed SymbolicAxis --> SymbolAxis, added equals() method,
69  * renamed getSymbolicValue() --> getSymbols(), renamed
70  * symbolicGridPaint --> gridBandPaint, fixed serialization of
71  * gridBandPaint, renamed symbolicGridLinesVisible -->
72  * gridBandsVisible, eliminated symbolicGridLineList (DG);
73  *
74  */

75
76 package org.jfree.chart.axis;
77
78 import java.awt.BasicStroke JavaDoc;
79 import java.awt.Color JavaDoc;
80 import java.awt.Font JavaDoc;
81 import java.awt.Graphics2D JavaDoc;
82 import java.awt.Paint JavaDoc;
83 import java.awt.Shape JavaDoc;
84 import java.awt.geom.Rectangle2D JavaDoc;
85 import java.io.IOException JavaDoc;
86 import java.io.ObjectInputStream JavaDoc;
87 import java.io.ObjectOutputStream JavaDoc;
88 import java.io.Serializable JavaDoc;
89 import java.text.NumberFormat JavaDoc;
90 import java.util.Arrays JavaDoc;
91 import java.util.Iterator JavaDoc;
92 import java.util.List JavaDoc;
93
94 import org.jfree.chart.event.AxisChangeEvent;
95 import org.jfree.chart.plot.Plot;
96 import org.jfree.chart.plot.PlotRenderingInfo;
97 import org.jfree.chart.plot.ValueAxisPlot;
98 import org.jfree.data.Range;
99 import org.jfree.io.SerialUtilities;
100 import org.jfree.text.TextUtilities;
101 import org.jfree.ui.RectangleEdge;
102 import org.jfree.ui.TextAnchor;
103 import org.jfree.util.PaintUtilities;
104
105 /**
106  * A standard linear value axis that replaces integer values with symbols.
107  *
108  * @author Anthony Boulestreau
109  */

110 public class SymbolAxis extends NumberAxis implements Serializable JavaDoc {
111
112     /** For serialization. */
113     private static final long serialVersionUID = 7216330468770619716L;
114     
115     /** The default grid band paint. */
116     public static final Paint JavaDoc DEFAULT_GRID_BAND_PAINT
117         = new Color JavaDoc(232, 234, 232, 128);
118
119     /** The list of symbols to display instead of the numeric values. */
120     private List JavaDoc symbols;
121
122     /** The paint used to color the grid bands (if the bands are visible). */
123     private transient Paint JavaDoc gridBandPaint;
124
125     /** Flag that indicates whether or not grid bands are visible. */
126     private boolean gridBandsVisible;
127
128     /**
129      * Constructs a symbol axis, using default attribute values where
130      * necessary.
131      *
132      * @param label the axis label (null permitted).
133      * @param sv the list of symbols to display instead of the numeric
134      * values.
135      */

136     public SymbolAxis(String JavaDoc label, String JavaDoc[] sv) {
137         super(label);
138         this.symbols = Arrays.asList(sv);
139         this.gridBandsVisible = true;
140         this.gridBandPaint = DEFAULT_GRID_BAND_PAINT;
141
142         setAutoTickUnitSelection(false, false);
143         setAutoRangeStickyZero(false);
144
145     }
146
147     /**
148      * Returns an array of the symbols for the axis.
149      *
150      * @return The symbols.
151      */

152     public String JavaDoc[] getSymbols() {
153         String JavaDoc[] result = new String JavaDoc[this.symbols.size()];
154         result = (String JavaDoc[]) this.symbols.toArray(result);
155         return result;
156     }
157
158     /**
159      * Returns the paint used to color the grid bands.
160      *
161      * @return The grid band paint (never <code>null</code>).
162      *
163      * @see #isGridBandsVisible()
164      */

165     public Paint JavaDoc getGridBandPaint() {
166         return this.gridBandPaint;
167     }
168
169     /**
170      * Sets the grid band paint and sends an {@link AxisChangeEvent} to
171      * all registered listeners.
172      *
173      * @param paint the paint (<code>null</code> not permitted).
174      */

175     public void setGridBandPaint(Paint JavaDoc paint) {
176         if (paint == null) {
177             throw new IllegalArgumentException JavaDoc("Null 'paint' argument.");
178         }
179         this.gridBandPaint = paint;
180         notifyListeners(new AxisChangeEvent(this));
181     }
182     
183     /**
184      * Returns <code>true</code> if the grid bands are showing, and
185      * <code>false</code> otherwise.
186      *
187      * @return <code>true</code> if the grid bands are showing, and
188      * <code>false</code> otherwise.
189      */

190     public boolean isGridBandsVisible() {
191         return this.gridBandsVisible;
192     }
193
194     /**
195      * Sets the visibility of the grid bands and notifies registered
196      * listeners that the axis has been modified.
197      *
198      * @param flag the new setting.
199      */

200     public void setGridBandsVisible(boolean flag) {
201         if (this.gridBandsVisible != flag) {
202             this.gridBandsVisible = flag;
203             notifyListeners(new AxisChangeEvent(this));
204         }
205     }
206
207     /**
208      * This operation is not supported by this axis.
209      *
210      * @param g2 the graphics device.
211      * @param dataArea the area in which the plot and axes should be drawn.
212      * @param edge the edge along which the axis is drawn.
213      */

214     protected void selectAutoTickUnit(Graphics2D JavaDoc g2, Rectangle2D JavaDoc dataArea,
215                                       RectangleEdge edge) {
216         throw new UnsupportedOperationException JavaDoc();
217     }
218
219     /**
220      * Draws the axis on a Java 2D graphics device (such as the screen or a
221      * printer).
222      *
223      * @param g2 the graphics device (<code>null</code> not permitted).
224      * @param cursor the cursor location.
225      * @param plotArea the area within which the plot and axes should be drawn
226      * (<code>null</code> not permitted).
227      * @param dataArea the area within which the data should be drawn
228      * (<code>null</code> not permitted).
229      * @param edge the axis location (<code>null</code> not permitted).
230      * @param plotState collects information about the plot
231      * (<code>null</code> permitted).
232      *
233      * @return The axis state (never <code>null</code>).
234      */

235     public AxisState draw(Graphics2D JavaDoc g2,
236                           double cursor,
237                           Rectangle2D JavaDoc plotArea,
238                           Rectangle2D JavaDoc dataArea,
239                           RectangleEdge edge,
240                           PlotRenderingInfo plotState) {
241
242         AxisState info = new AxisState(cursor);
243         if (isVisible()) {
244             info = super.draw(g2, cursor, plotArea, dataArea, edge, plotState);
245         }
246         if (this.gridBandsVisible) {
247             drawGridBands(g2, plotArea, dataArea, edge, info.getTicks());
248         }
249         return info;
250
251     }
252
253     /**
254      * Draws the grid bands. Alternate bands are colored using
255      * <CODE>gridBandPaint<CODE> (<CODE>DEFAULT_GRID_BAND_PAINT</CODE> by
256      * default).
257      *
258      * @param g2 the graphics device.
259      * @param plotArea the area within which the chart should be drawn.
260      * @param dataArea the area within which the plot should be drawn (a
261      * subset of the drawArea).
262      * @param edge the axis location.
263      * @param ticks the ticks.
264      */

265     protected void drawGridBands(Graphics2D JavaDoc g2,
266                                  Rectangle2D JavaDoc plotArea,
267                                  Rectangle2D JavaDoc dataArea,
268                                  RectangleEdge edge,
269                                  List JavaDoc ticks) {
270
271         Shape JavaDoc savedClip = g2.getClip();
272         g2.clip(dataArea);
273         if (RectangleEdge.isTopOrBottom(edge)) {
274             drawGridBandsHorizontal(g2, plotArea, dataArea, true, ticks);
275         }
276         else if (RectangleEdge.isLeftOrRight(edge)) {
277             drawGridBandsVertical(g2, plotArea, dataArea, true, ticks);
278         }
279         g2.setClip(savedClip);
280
281     }
282
283     /**
284      * Draws the grid bands for the axis when it is at the top or bottom of
285      * the plot.
286      *
287      * @param g2 the graphics device.
288      * @param plotArea the area within which the chart should be drawn.
289      * @param dataArea the area within which the plot should be drawn
290      * (a subset of the drawArea).
291      * @param firstGridBandIsDark True: the first grid band takes the
292      * color of <CODE>gridBandPaint<CODE>.
293      * False: the second grid band takes the
294      * color of <CODE>gridBandPaint<CODE>.
295      * @param ticks the ticks.
296      */

297     protected void drawGridBandsHorizontal(Graphics2D JavaDoc g2,
298                                            Rectangle2D JavaDoc plotArea,
299                                            Rectangle2D JavaDoc dataArea,
300                                            boolean firstGridBandIsDark,
301                                            List JavaDoc ticks) {
302
303         boolean currentGridBandIsDark = firstGridBandIsDark;
304         double yy = dataArea.getY();
305         double xx1, xx2;
306
307         //gets the outline stroke width of the plot
308
double outlineStrokeWidth;
309         if (getPlot().getOutlineStroke() != null) {
310             outlineStrokeWidth
311                 = ((BasicStroke JavaDoc) getPlot().getOutlineStroke()).getLineWidth();
312         }
313         else {
314             outlineStrokeWidth = 1d;
315         }
316
317         Iterator JavaDoc iterator = ticks.iterator();
318         ValueTick tick;
319         Rectangle2D JavaDoc band;
320         while (iterator.hasNext()) {
321             tick = (ValueTick) iterator.next();
322             xx1 = valueToJava2D(
323                 tick.getValue() - 0.5d, dataArea, RectangleEdge.BOTTOM
324             );
325             xx2 = valueToJava2D(
326                 tick.getValue() + 0.5d, dataArea, RectangleEdge.BOTTOM
327             );
328             if (currentGridBandIsDark) {
329                 g2.setPaint(this.gridBandPaint);
330             }
331             else {
332                 g2.setPaint(Color.white);
333             }
334             band = new Rectangle2D.Double JavaDoc(xx1, yy + outlineStrokeWidth,
335                 xx2 - xx1, dataArea.getMaxY() - yy - outlineStrokeWidth);
336             g2.fill(band);
337             currentGridBandIsDark = !currentGridBandIsDark;
338         }
339         g2.setPaintMode();
340     }
341
342     /**
343      * Draws the grid bands for the axis when it is at the top or bottom of
344      * the plot.
345      *
346      * @param g2 the graphics device.
347      * @param drawArea the area within which the chart should be drawn.
348      * @param plotArea the area within which the plot should be drawn (a
349      * subset of the drawArea).
350      * @param firstGridBandIsDark True: the first grid band takes the
351      * color of <CODE>gridBandPaint<CODE>.
352      * False: the second grid band takes the
353      * color of <CODE>gridBandPaint<CODE>.
354      * @param ticks a list of ticks.
355      */

356     protected void drawGridBandsVertical(Graphics2D JavaDoc g2,
357                                          Rectangle2D JavaDoc drawArea,
358                                          Rectangle2D JavaDoc plotArea,
359                                          boolean firstGridBandIsDark,
360                                          List JavaDoc ticks) {
361
362         boolean currentGridBandIsDark = firstGridBandIsDark;
363         double xx = plotArea.getX();
364         double yy1, yy2;
365
366         //gets the outline stroke width of the plot
367
double outlineStrokeWidth;
368         if (getPlot().getOutlineStroke() != null) {
369             outlineStrokeWidth
370                 = ((BasicStroke JavaDoc) getPlot().getOutlineStroke()).getLineWidth();
371         }
372         else {
373             outlineStrokeWidth = 1d;
374         }
375
376         Iterator JavaDoc iterator = ticks.iterator();
377         ValueTick tick;
378         Rectangle2D JavaDoc band;
379         while (iterator.hasNext()) {
380             tick = (ValueTick) iterator.next();
381             yy1 = valueToJava2D(
382                 tick.getValue() + 0.5d, plotArea, RectangleEdge.LEFT
383             );
384             yy2 = valueToJava2D(
385                 tick.getValue() - 0.5d, plotArea, RectangleEdge.LEFT
386             );
387             if (currentGridBandIsDark) {
388                 g2.setPaint(this.gridBandPaint);
389             }
390             else {
391                 g2.setPaint(Color.white);
392             }
393             band = new Rectangle2D.Double JavaDoc(xx + outlineStrokeWidth,
394                 yy1, plotArea.getMaxX() - xx - outlineStrokeWidth, yy2 - yy1);
395             g2.fill(band);
396             currentGridBandIsDark = !currentGridBandIsDark;
397         }
398         g2.setPaintMode();
399     }
400
401     /**
402      * Rescales the axis to ensure that all data is visible.
403      */

404     protected void autoAdjustRange() {
405
406         Plot plot = getPlot();
407         if (plot == null) {
408             return; // no plot, no data
409
}
410
411         if (plot instanceof ValueAxisPlot) {
412
413             // ensure that all the symbols are displayed
414
double upper = this.symbols.size() - 1;
415             double lower = 0;
416             double range = upper - lower;
417
418             // ensure the autorange is at least <minRange> in size...
419
double minRange = getAutoRangeMinimumSize();
420             if (range < minRange) {
421                 upper = (upper + lower + minRange) / 2;
422                 lower = (upper + lower - minRange) / 2;
423             }
424
425             // this ensure that the grid bands will be displayed correctly.
426
double upperMargin = 0.5;
427             double lowerMargin = 0.5;
428
429             if (getAutoRangeIncludesZero()) {
430                 if (getAutoRangeStickyZero()) {
431                     if (upper <= 0.0) {
432                         upper = 0.0;
433                     }
434                     else {
435                         upper = upper + upperMargin;
436                     }
437                     if (lower >= 0.0) {
438                         lower = 0.0;
439                     }
440                     else {
441                         lower = lower - lowerMargin;
442                     }
443                 }
444                 else {
445                     upper = Math.max(0.0, upper + upperMargin);
446                     lower = Math.min(0.0, lower - lowerMargin);
447                 }
448             }
449             else {
450                 if (getAutoRangeStickyZero()) {
451                     if (upper <= 0.0) {
452                         upper = Math.min(0.0, upper + upperMargin);
453                     }
454                     else {
455                         upper = upper + upperMargin * range;
456                     }
457                     if (lower >= 0.0) {
458                         lower = Math.max(0.0, lower - lowerMargin);
459                     }
460                     else {
461                         lower = lower - lowerMargin;
462                     }
463                 }
464                 else {
465                     upper = upper + upperMargin;
466                     lower = lower - lowerMargin;
467                 }
468             }
469
470             setRange(new Range(lower, upper), false, false);
471
472         }
473
474     }
475
476     /**
477      * Calculates the positions of the tick labels for the axis, storing the
478      * results in the tick label list (ready for drawing).
479      *
480      * @param g2 the graphics device.
481      * @param state the axis state.
482      * @param dataArea the area in which the data should be drawn.
483      * @param edge the location of the axis.
484      *
485      * @return A list of ticks.
486      */

487     public List JavaDoc refreshTicks(Graphics2D JavaDoc g2,
488                              AxisState state,
489                              Rectangle2D JavaDoc dataArea,
490                              RectangleEdge edge) {
491         List JavaDoc ticks = null;
492         if (RectangleEdge.isTopOrBottom(edge)) {
493             ticks = refreshTicksHorizontal(g2, dataArea, edge);
494         }
495         else if (RectangleEdge.isLeftOrRight(edge)) {
496             ticks = refreshTicksVertical(g2, dataArea, edge);
497         }
498         return ticks;
499     }
500
501     /**
502      * Calculates the positions of the tick labels for the axis, storing the
503      * results in the tick label list (ready for drawing).
504      *
505      * @param g2 the graphics device.
506      * @param dataArea the area in which the data should be drawn.
507      * @param edge the location of the axis.
508      *
509      * @return The ticks.
510      */

511     protected List JavaDoc refreshTicksHorizontal(Graphics2D JavaDoc g2,
512                                           Rectangle2D JavaDoc dataArea,
513                                           RectangleEdge edge) {
514
515         List JavaDoc ticks = new java.util.ArrayList JavaDoc();
516
517         Font JavaDoc tickLabelFont = getTickLabelFont();
518         g2.setFont(tickLabelFont);
519
520         double size = getTickUnit().getSize();
521         int count = calculateVisibleTickCount();
522         double lowestTickValue = calculateLowestVisibleTickValue();
523
524         double previousDrawnTickLabelPos = 0.0;
525         double previousDrawnTickLabelLength = 0.0;
526
527         if (count <= ValueAxis.MAXIMUM_TICK_COUNT) {
528             for (int i = 0; i < count; i++) {
529                 double currentTickValue = lowestTickValue + (i * size);
530                 double xx = valueToJava2D(currentTickValue, dataArea, edge);
531                 String JavaDoc tickLabel;
532                 NumberFormat JavaDoc formatter = getNumberFormatOverride();
533                 if (formatter != null) {
534                     tickLabel = formatter.format(currentTickValue);
535                 }
536                 else {
537                     tickLabel = valueToString(currentTickValue);
538                 }
539                 
540                 // avoid to draw overlapping tick labels
541
Rectangle2D JavaDoc bounds = TextUtilities.getTextBounds(
542                     tickLabel, g2, g2.getFontMetrics()
543                 );
544                 double tickLabelLength = isVerticalTickLabels()
545                     ? bounds.getHeight() : bounds.getWidth();
546                 boolean tickLabelsOverlapping = false;
547                 if (i > 0) {
548                     double avgTickLabelLength = (previousDrawnTickLabelLength
549                         + tickLabelLength) / 2.0;
550                     if (Math.abs(xx - previousDrawnTickLabelPos)
551                             < avgTickLabelLength) {
552                         tickLabelsOverlapping = true;
553                     }
554                 }
555                 if (tickLabelsOverlapping) {
556                     tickLabel = ""; // don't draw this tick label
557
}
558                 else {
559                     // remember these values for next comparison
560
previousDrawnTickLabelPos = xx;
561                     previousDrawnTickLabelLength = tickLabelLength;
562                 }
563                 
564                 TextAnchor anchor = null;
565                 TextAnchor rotationAnchor = null;
566                 double angle = 0.0;
567                 if (isVerticalTickLabels()) {
568                     anchor = TextAnchor.CENTER_RIGHT;
569                     rotationAnchor = TextAnchor.CENTER_RIGHT;
570                     if (edge == RectangleEdge.TOP) {
571                         angle = Math.PI / 2.0;
572                     }
573                     else {
574                         angle = -Math.PI / 2.0;
575                     }
576                 }
577                 else {
578                     if (edge == RectangleEdge.TOP) {
579                         anchor = TextAnchor.BOTTOM_CENTER;
580                         rotationAnchor = TextAnchor.BOTTOM_CENTER;
581                     }
582                     else {
583                         anchor = TextAnchor.TOP_CENTER;
584                         rotationAnchor = TextAnchor.TOP_CENTER;
585                     }
586                 }
587                 Tick tick = new NumberTick(
588                     new Double JavaDoc(currentTickValue), tickLabel, anchor,
589                     rotationAnchor, angle
590                 );
591                 ticks.add(tick);
592             }
593         }
594         return ticks;
595
596     }
597
598     /**
599      * Calculates the positions of the tick labels for the axis, storing the
600      * results in the tick label list (ready for drawing).
601      *
602      * @param g2 the graphics device.
603      * @param dataArea the area in which the plot should be drawn.
604      * @param edge the location of the axis.
605      *
606      * @return The ticks.
607      */

608     protected List JavaDoc refreshTicksVertical(Graphics2D JavaDoc g2,
609                                         Rectangle2D JavaDoc dataArea,
610                                         RectangleEdge edge) {
611
612         List JavaDoc ticks = new java.util.ArrayList JavaDoc();
613
614         Font JavaDoc tickLabelFont = getTickLabelFont();
615         g2.setFont(tickLabelFont);
616
617         double size = getTickUnit().getSize();
618         int count = calculateVisibleTickCount();
619         double lowestTickValue = calculateLowestVisibleTickValue();
620
621         double previousDrawnTickLabelPos = 0.0;
622         double previousDrawnTickLabelLength = 0.0;
623
624         if (count <= ValueAxis.MAXIMUM_TICK_COUNT) {
625             for (int i = 0; i < count; i++) {
626                 double currentTickValue = lowestTickValue + (i * size);
627                 double yy = valueToJava2D(currentTickValue, dataArea, edge);
628                 String JavaDoc tickLabel;
629                 NumberFormat JavaDoc formatter = getNumberFormatOverride();
630                 if (formatter != null) {
631                     tickLabel = formatter.format(currentTickValue);
632                 }
633                 else {
634                     tickLabel = valueToString(currentTickValue);
635                 }
636
637                 // avoid to draw overlapping tick labels
638
Rectangle2D JavaDoc bounds = TextUtilities.getTextBounds(
639                     tickLabel, g2, g2.getFontMetrics()
640                 );
641                 double tickLabelLength = isVerticalTickLabels()
642                     ? bounds.getWidth() : bounds.getHeight();
643                 boolean tickLabelsOverlapping = false;
644                 if (i > 0) {
645                     double avgTickLabelLength =
646                         (previousDrawnTickLabelLength + tickLabelLength) / 2.0;
647                     if (Math.abs(yy - previousDrawnTickLabelPos)
648                             < avgTickLabelLength) {
649                         tickLabelsOverlapping = true;
650                     }
651                     if (tickLabelsOverlapping) {
652                         tickLabel = ""; // don't draw this tick label
653
}
654                     else {
655                         // remember these values for next comparison
656
previousDrawnTickLabelPos = yy;
657                         previousDrawnTickLabelLength = tickLabelLength;
658                     }
659                 }
660                 TextAnchor anchor = null;
661                 TextAnchor rotationAnchor = null;
662                 double angle = 0.0;
663                 if (isVerticalTickLabels()) {
664                     anchor = TextAnchor.BOTTOM_CENTER;
665                     rotationAnchor = TextAnchor.BOTTOM_CENTER;
666                     if (edge == RectangleEdge.LEFT) {
667                         angle = -Math.PI / 2.0;
668                     }
669                     else {
670                         angle = Math.PI / 2.0;
671                     }
672                 }
673                 else {
674                     if (edge == RectangleEdge.LEFT) {
675                         anchor = TextAnchor.CENTER_RIGHT;
676                         rotationAnchor = TextAnchor.CENTER_RIGHT;
677                     }
678                     else {
679                         anchor = TextAnchor.CENTER_LEFT;
680                         rotationAnchor = TextAnchor.CENTER_LEFT;
681                     }
682                 }
683                 Tick tick = new NumberTick(
684                     new Double JavaDoc(currentTickValue), tickLabel, anchor,
685                     rotationAnchor, angle
686                 );
687                 ticks.add(tick);
688             }
689         }
690         return ticks;
691         
692     }
693
694     /**
695      * Converts a value to a string, using the list of symbols.
696      *
697      * @param value value to convert.
698      *
699      * @return The symbol.
700      */

701     public String JavaDoc valueToString(double value) {
702         String JavaDoc strToReturn;
703         try {
704             strToReturn = (String JavaDoc) this.symbols.get((int) value);
705         }
706         catch (IndexOutOfBoundsException JavaDoc ex) {
707             strToReturn = "";
708         }
709         return strToReturn;
710     }
711
712     /**
713      * Tests this axis for equality with an arbitrary object.
714      *
715      * @param obj the object (<code>null</code> permitted).
716      *
717      * @return A boolean.
718      */

719     public boolean equals(Object JavaDoc obj) {
720         if (obj == this) {
721             return true;
722         }
723         if (!(obj instanceof SymbolAxis)) {
724             return false;
725         }
726         SymbolAxis that = (SymbolAxis) obj;
727         if (!this.symbols.equals(that.symbols)) {
728             return false;
729         }
730         if (this.gridBandsVisible != that.gridBandsVisible) {
731             return false;
732         }
733         if (!PaintUtilities.equal(this.gridBandPaint, that.gridBandPaint)) {
734             return false;
735         }
736         if (!super.equals(obj)) {
737             return false;
738         }
739         return true;
740     }
741     
742     /**
743      * Provides serialization support.
744      *
745      * @param stream the output stream.
746      *
747      * @throws IOException if there is an I/O error.
748      */

749     private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
750         stream.defaultWriteObject();
751         SerialUtilities.writePaint(this.gridBandPaint, stream);
752     }
753
754     /**
755      * Provides serialization support.
756      *
757      * @param stream the input stream.
758      *
759      * @throws IOException if there is an I/O error.
760      * @throws ClassNotFoundException if there is a classpath problem.
761      */

762     private void readObject(ObjectInputStream JavaDoc stream)
763         throws IOException JavaDoc, ClassNotFoundException JavaDoc {
764         stream.defaultReadObject();
765         this.gridBandPaint = SerialUtilities.readPaint(stream);
766     }
767
768 }
769
Popular Tags