KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > xy > XYBarRenderer


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2006, 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  * XYBarRenderer.java
29  * ------------------
30  * (C) Copyright 2001-2006, by Object Refinery Limited.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): Richard Atkinson;
34  * Christian W. Zuckschwerdt;
35  * Bill Kelemen;
36  *
37  * $Id: XYBarRenderer.java,v 1.14.2.7 2006/08/24 09:39:09 mungady Exp $
38  *
39  * Changes
40  * -------
41  * 13-Dec-2001 : Version 1, makes VerticalXYBarPlot class redundant (DG);
42  * 23-Jan-2002 : Added DrawInfo parameter to drawItem() method (DG);
43  * 09-Apr-2002 : Removed the translated zero from the drawItem method. Override
44  * the initialise() method to calculate it (DG);
45  * 24-May-2002 : Incorporated tooltips into chart entities (DG);
46  * 25-Jun-2002 : Removed redundant import (DG);
47  * 05-Aug-2002 : Small modification to drawItem method to support URLs for HTML
48  * image maps (RA);
49  * 25-Mar-2003 : Implemented Serializable (DG);
50  * 01-May-2003 : Modified drawItem() method signature (DG);
51  * 30-Jul-2003 : Modified entity constructor (CZ);
52  * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
53  * 24-Aug-2003 : Added null checks in drawItem (BK);
54  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
55  * 07-Oct-2003 : Added renderer state (DG);
56  * 05-Dec-2003 : Changed call to obtain outline paint (DG);
57  * 10-Feb-2004 : Added state class, updated drawItem() method to make
58  * cut-and-paste overriding easier, and replaced property change
59  * with RendererChangeEvent (DG);
60  * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG);
61  * 26-Apr-2004 : Added gradient paint transformer (DG);
62  * 19-May-2004 : Fixed bug (879709) with bar zero value for secondary axis (DG);
63  * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
64  * getYValue() (DG);
65  * 01-Sep-2004 : Added a flag to control whether or not the bar outlines are
66  * drawn (DG);
67  * 03-Sep-2004 : Added option to use y-interval from dataset to determine the
68  * length of the bars (DG);
69  * 08-Sep-2004 : Added equals() method and updated clone() method (DG);
70  * 26-Jan-2005 : Added override for getLegendItem() method (DG);
71  * 20-Apr-2005 : Use generators for label tooltips and URLs (DG);
72  * 19-May-2005 : Added minimal item label implementation - needs improving (DG);
73  * 14-Oct-2005 : Fixed rendering problem with inverted axes (DG);
74  * ------------- JFREECHART 1.0.0 ---------------------------------------------
75  * 21-Jun-2006 : Improved item label handling - see bug 1501768 (DG);
76  * 24-Aug-2006 : Added crosshair support (DG);
77  *
78  */

79
80 package org.jfree.chart.renderer.xy;
81
82 import java.awt.Font JavaDoc;
83 import java.awt.GradientPaint JavaDoc;
84 import java.awt.Graphics2D JavaDoc;
85 import java.awt.Paint JavaDoc;
86 import java.awt.Shape JavaDoc;
87 import java.awt.Stroke JavaDoc;
88 import java.awt.geom.Point2D JavaDoc;
89 import java.awt.geom.Rectangle2D JavaDoc;
90 import java.io.IOException JavaDoc;
91 import java.io.ObjectInputStream JavaDoc;
92 import java.io.ObjectOutputStream JavaDoc;
93 import java.io.Serializable JavaDoc;
94
95 import org.jfree.chart.LegendItem;
96 import org.jfree.chart.axis.ValueAxis;
97 import org.jfree.chart.entity.EntityCollection;
98 import org.jfree.chart.entity.XYItemEntity;
99 import org.jfree.chart.event.RendererChangeEvent;
100 import org.jfree.chart.labels.ItemLabelAnchor;
101 import org.jfree.chart.labels.ItemLabelPosition;
102 import org.jfree.chart.labels.XYItemLabelGenerator;
103 import org.jfree.chart.labels.XYSeriesLabelGenerator;
104 import org.jfree.chart.labels.XYToolTipGenerator;
105 import org.jfree.chart.plot.CrosshairState;
106 import org.jfree.chart.plot.PlotOrientation;
107 import org.jfree.chart.plot.PlotRenderingInfo;
108 import org.jfree.chart.plot.XYPlot;
109 import org.jfree.data.Range;
110 import org.jfree.data.general.DatasetUtilities;
111 import org.jfree.data.xy.IntervalXYDataset;
112 import org.jfree.data.xy.XYDataset;
113 import org.jfree.io.SerialUtilities;
114 import org.jfree.text.TextUtilities;
115 import org.jfree.ui.GradientPaintTransformer;
116 import org.jfree.ui.RectangleEdge;
117 import org.jfree.ui.StandardGradientPaintTransformer;
118 import org.jfree.util.ObjectUtilities;
119 import org.jfree.util.PublicCloneable;
120 import org.jfree.util.ShapeUtilities;
121
122 /**
123  * A renderer that draws bars on an {@link XYPlot} (requires an
124  * {@link IntervalXYDataset}).
125  */

126 public class XYBarRenderer extends AbstractXYItemRenderer
127         implements XYItemRenderer, Cloneable JavaDoc, PublicCloneable, Serializable JavaDoc {
128     
129     /** For serialization. */
130     private static final long serialVersionUID = 770559577251370036L;
131
132     /**
133      * The state class used by this renderer.
134      */

135     protected class XYBarRendererState extends XYItemRendererState {
136         
137         /** Base for bars against the range axis, in Java 2D space. */
138         private double g2Base;
139         
140         /**
141          * Creates a new state object.
142          *
143          * @param info the plot rendering info.
144          */

145         public XYBarRendererState(PlotRenderingInfo info) {
146             super(info);
147         }
148         
149         /**
150          * Returns the base (range) value in Java 2D space.
151          *
152          * @return The base value.
153          */

154         public double getG2Base() {
155             return this.g2Base;
156         }
157         
158         /**
159          * Sets the range axis base in Java2D space.
160          *
161          * @param value the value.
162          */

163         public void setG2Base(double value) {
164             this.g2Base = value;
165         }
166     }
167
168     /** The default base value for the bars. */
169     private double base;
170     
171     /**
172      * A flag that controls whether the bars use the y-interval supplied by the
173      * dataset.
174      */

175     private boolean useYInterval;
176     
177     /** Percentage margin (to reduce the width of bars). */
178     private double margin;
179
180     /** A flag that controls whether or not bar outlines are drawn. */
181     private boolean drawBarOutline;
182     
183     /**
184      * An optional class used to transform gradient paint objects to fit each
185      * bar.
186      */

187     private GradientPaintTransformer gradientPaintTransformer;
188     
189     /**
190      * The shape used to represent a bar in each legend item (this should never
191      * be <code>null</code>).
192      */

193     private transient Shape JavaDoc legendBar;
194     
195     /**
196      * The fallback position if a positive item label doesn't fit inside the
197      * bar.
198      */

199     private ItemLabelPosition positiveItemLabelPositionFallback;
200     
201     /**
202      * The fallback position if a negative item label doesn't fit inside the
203      * bar.
204      */

205     private ItemLabelPosition negativeItemLabelPositionFallback;
206
207     /**
208      * The default constructor.
209      */

210     public XYBarRenderer() {
211         this(0.0);
212     }
213
214     /**
215      * Constructs a new renderer.
216      *
217      * @param margin the percentage amount to trim from the width of each bar.
218      */

219     public XYBarRenderer(double margin) {
220         super();
221         this.margin = margin;
222         this.base = 0.0;
223         this.useYInterval = false;
224         this.gradientPaintTransformer = new StandardGradientPaintTransformer();
225         this.drawBarOutline = true;
226         this.legendBar = new Rectangle2D.Double JavaDoc(-3.0, -5.0, 6.0, 10.0);
227     }
228     
229     /**
230      * Returns the base value for the bars.
231      *
232      * @return The base value for the bars.
233      */

234     public double getBase() {
235         return this.base;
236     }
237     
238     /**
239      * Sets the base value for the bars and sends a {@link RendererChangeEvent}
240      * to all registered listeners. The base value is not used if the dataset's
241      * y-interval is being used to determine the bar length.
242      *
243      * @param base the new base value.
244      */

245     public void setBase(double base) {
246         this.base = base;
247         notifyListeners(new RendererChangeEvent(this));
248     }
249     
250     /**
251      * Returns a flag that determines whether the y-interval from the dataset is
252      * used to calculate the length of each bar.
253      *
254      * @return A boolean.
255      */

256     public boolean getUseYInterval() {
257         return this.useYInterval;
258     }
259     
260     /**
261      * Sets the flag that determines whether the y-interval from the dataset is
262      * used to calculate the length of each bar, and sends a
263      * {@link RendererChangeEvent} to all registered listeners..
264      *
265      * @param use the flag.
266      */

267     public void setUseYInterval(boolean use) {
268         this.useYInterval = use;
269         notifyListeners(new RendererChangeEvent(this));
270     }
271
272     /**
273      * Returns the margin which is a percentage amount by which the bars are
274      * trimmed.
275      *
276      * @return The margin.
277      */

278     public double getMargin() {
279         return this.margin;
280     }
281     
282     /**
283      * Sets the percentage amount by which the bars are trimmed and sends a
284      * {@link RendererChangeEvent} to all registered listeners.
285      *
286      * @param margin the new margin.
287      */

288     public void setMargin(double margin) {
289         this.margin = margin;
290         notifyListeners(new RendererChangeEvent(this));
291     }
292
293     /**
294      * Returns a flag that controls whether or not bar outlines are drawn.
295      *
296      * @return A boolean.
297      */

298     public boolean isDrawBarOutline() {
299         return this.drawBarOutline;
300     }
301     
302     /**
303      * Sets the flag that controls whether or not bar outlines are drawn and
304      * sends a {@link RendererChangeEvent} to all registered listeners.
305      *
306      * @param draw the flag.
307      */

308     public void setDrawBarOutline(boolean draw) {
309         this.drawBarOutline = draw;
310         notifyListeners(new RendererChangeEvent(this));
311     }
312     
313     /**
314      * Returns the gradient paint transformer (an object used to transform
315      * gradient paint objects to fit each bar.
316      *
317      * @return A transformer (<code>null</code> possible).
318      */

319     public GradientPaintTransformer getGradientPaintTransformer() {
320         return this.gradientPaintTransformer;
321     }
322     
323     /**
324      * Sets the gradient paint transformer and sends a
325      * {@link RendererChangeEvent} to all registered listeners.
326      *
327      * @param transformer the transformer (<code>null</code> permitted).
328      */

329     public void setGradientPaintTransformer(
330             GradientPaintTransformer transformer) {
331         this.gradientPaintTransformer = transformer;
332         notifyListeners(new RendererChangeEvent(this));
333     }
334      
335     /**
336      * Returns the shape used to represent bars in each legend item.
337      *
338      * @return The shape used to represent bars in each legend item (never
339      * <code>null</code>).
340      */

341     public Shape JavaDoc getLegendBar() {
342         return this.legendBar;
343     }
344     
345     /**
346      * Sets the shape used to represent bars in each legend item.
347      *
348      * @param bar the bar shape (<code>null</code> not permitted).
349      */

350     public void setLegendBar(Shape JavaDoc bar) {
351         if (bar == null) {
352             throw new IllegalArgumentException JavaDoc("Null 'bar' argument.");
353         }
354         this.legendBar = bar;
355         notifyListeners(new RendererChangeEvent(this));
356     }
357     
358     /**
359      * Returns the fallback position for positive item labels that don't fit
360      * within a bar.
361      *
362      * @return The fallback position (<code>null</code> possible).
363      *
364      * @since 1.0.2
365      */

366     public ItemLabelPosition getPositiveItemLabelPositionFallback() {
367         return this.positiveItemLabelPositionFallback;
368     }
369     
370     /**
371      * Sets the fallback position for positive item labels that don't fit
372      * within a bar, and sends a {@link RendererChangeEvent} to all registered
373      * listeners.
374      *
375      * @param position the position (<code>null</code> permitted).
376      *
377      * @since 1.0.2
378      */

379     public void setPositiveItemLabelPositionFallback(
380             ItemLabelPosition position) {
381         this.positiveItemLabelPositionFallback = position;
382         notifyListeners(new RendererChangeEvent(this));
383     }
384     
385     /**
386      * Returns the fallback position for negative item labels that don't fit
387      * within a bar.
388      *
389      * @return The fallback position (<code>null</code> possible).
390      *
391      * @since 1.0.2
392      */

393     public ItemLabelPosition getNegativeItemLabelPositionFallback() {
394         return this.negativeItemLabelPositionFallback;
395     }
396     
397     /**
398      * Sets the fallback position for negative item labels that don't fit
399      * within a bar, and sends a {@link RendererChangeEvent} to all registered
400      * listeners.
401      *
402      * @param position the position (<code>null</code> permitted).
403      *
404      * @since 1.0.2
405      */

406     public void setNegativeItemLabelPositionFallback(
407             ItemLabelPosition position) {
408         this.negativeItemLabelPositionFallback = position;
409         notifyListeners(new RendererChangeEvent(this));
410     }
411
412     /**
413      * Initialises the renderer and returns a state object that should be
414      * passed to all subsequent calls to the drawItem() method. Here we
415      * calculate the Java2D y-coordinate for zero, since all the bars have
416      * their bases fixed at zero.
417      *
418      * @param g2 the graphics device.
419      * @param dataArea the area inside the axes.
420      * @param plot the plot.
421      * @param dataset the data.
422      * @param info an optional info collection object to return data back to
423      * the caller.
424      *
425      * @return A state object.
426      */

427     public XYItemRendererState initialise(Graphics2D JavaDoc g2, Rectangle2D JavaDoc dataArea,
428             XYPlot plot, XYDataset dataset, PlotRenderingInfo info) {
429
430         XYBarRendererState state = new XYBarRendererState(info);
431         ValueAxis rangeAxis
432             = plot.getRangeAxisForDataset(plot.indexOf(dataset));
433         state.setG2Base(rangeAxis.valueToJava2D(this.base, dataArea,
434                 plot.getRangeAxisEdge()));
435         return state;
436
437     }
438
439     /**
440      * Returns a default legend item for the specified series. Subclasses
441      * should override this method to generate customised items.
442      *
443      * @param datasetIndex the dataset index (zero-based).
444      * @param series the series index (zero-based).
445      *
446      * @return A legend item for the series.
447      */

448     public LegendItem getLegendItem(int datasetIndex, int series) {
449         LegendItem result = null;
450         XYPlot xyplot = getPlot();
451         if (xyplot != null) {
452             XYDataset dataset = xyplot.getDataset(datasetIndex);
453             if (dataset != null) {
454                 XYSeriesLabelGenerator lg = getLegendItemLabelGenerator();
455                 String JavaDoc label = lg.generateLabel(dataset, series);
456                 String JavaDoc description = label;
457                 String JavaDoc toolTipText = null;
458                 if (getLegendItemToolTipGenerator() != null) {
459                     toolTipText = getLegendItemToolTipGenerator().generateLabel(
460                             dataset, series);
461                 }
462                 String JavaDoc urlText = null;
463                 if (getLegendItemURLGenerator() != null) {
464                     urlText = getLegendItemURLGenerator().generateLabel(
465                             dataset, series);
466                 }
467                 Shape JavaDoc shape = this.legendBar;
468                 Paint JavaDoc paint = getSeriesPaint(series);
469                 Paint JavaDoc outlinePaint = getSeriesOutlinePaint(series);
470                 Stroke JavaDoc outlineStroke = getSeriesOutlineStroke(series);
471                 result = new LegendItem(label, description, toolTipText,
472                         urlText, shape, paint, outlineStroke, outlinePaint);
473             }
474         }
475         return result;
476     }
477     
478     /**
479      * Draws the visual representation of a single data item.
480      *
481      * @param g2 the graphics device.
482      * @param state the renderer state.
483      * @param dataArea the area within which the plot is being drawn.
484      * @param info collects information about the drawing.
485      * @param plot the plot (can be used to obtain standard color
486      * information etc).
487      * @param domainAxis the domain axis.
488      * @param rangeAxis the range axis.
489      * @param dataset the dataset.
490      * @param series the series index (zero-based).
491      * @param item the item index (zero-based).
492      * @param crosshairState crosshair information for the plot
493      * (<code>null</code> permitted).
494      * @param pass the pass index.
495      */

496     public void drawItem(Graphics2D JavaDoc g2,
497                          XYItemRendererState state,
498                          Rectangle2D JavaDoc dataArea,
499                          PlotRenderingInfo info,
500                          XYPlot plot,
501                          ValueAxis domainAxis,
502                          ValueAxis rangeAxis,
503                          XYDataset dataset,
504                          int series,
505                          int item,
506                          CrosshairState crosshairState,
507                          int pass) {
508
509         if (!getItemVisible(series, item)) {
510             return;
511         }
512         IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset;
513
514         double value0;
515         double value1;
516         if (this.useYInterval) {
517             value0 = intervalDataset.getStartYValue(series, item);
518             value1 = intervalDataset.getEndYValue(series, item);
519         }
520         else {
521             value0 = this.base;
522             value1 = intervalDataset.getYValue(series, item);
523         }
524         if (Double.isNaN(value0) || Double.isNaN(value1)) {
525             return;
526         }
527
528         double translatedValue0 = rangeAxis.valueToJava2D(value0, dataArea,
529                 plot.getRangeAxisEdge());
530         double translatedValue1 = rangeAxis.valueToJava2D(value1, dataArea,
531                 plot.getRangeAxisEdge());
532
533         RectangleEdge location = plot.getDomainAxisEdge();
534         double startX = intervalDataset.getStartXValue(series, item);
535         if (Double.isNaN(startX)) {
536             return;
537         }
538         double translatedStartX = domainAxis.valueToJava2D(startX, dataArea,
539                 location);
540
541         double endX = intervalDataset.getEndXValue(series, item);
542         if (Double.isNaN(endX)) {
543             return;
544         }
545         double translatedEndX = domainAxis.valueToJava2D(endX, dataArea,
546                 location);
547
548         double translatedWidth = Math.max(1, Math.abs(translatedEndX
549                 - translatedStartX));
550         double translatedHeight = Math.abs(translatedValue1 - translatedValue0);
551
552         if (getMargin() > 0.0) {
553             double cut = translatedWidth * getMargin();
554             translatedWidth = translatedWidth - cut;
555             translatedStartX = translatedStartX + cut / 2;
556         }
557
558         Rectangle2D JavaDoc bar = null;
559         PlotOrientation orientation = plot.getOrientation();
560         if (orientation == PlotOrientation.HORIZONTAL) {
561             bar = new Rectangle2D.Double JavaDoc(
562                 Math.min(translatedValue0, translatedValue1),
563                 Math.min(translatedStartX, translatedEndX),
564                 translatedHeight, translatedWidth);
565         }
566         else if (orientation == PlotOrientation.VERTICAL) {
567             bar = new Rectangle2D.Double JavaDoc(
568                 Math.min(translatedStartX, translatedEndX),
569                 Math.min(translatedValue0, translatedValue1),
570                 translatedWidth, translatedHeight);
571         }
572
573         Paint JavaDoc itemPaint = getItemPaint(series, item);
574         if (getGradientPaintTransformer()
575                 != null && itemPaint instanceof GradientPaint JavaDoc) {
576             GradientPaint JavaDoc gp = (GradientPaint JavaDoc) itemPaint;
577             itemPaint = getGradientPaintTransformer().transform(gp, bar);
578         }
579         g2.setPaint(itemPaint);
580         g2.fill(bar);
581         if (isDrawBarOutline()
582                 && Math.abs(translatedEndX - translatedStartX) > 3) {
583             Stroke JavaDoc stroke = getItemOutlineStroke(series, item);
584             Paint JavaDoc paint = getItemOutlinePaint(series, item);
585             if (stroke != null && paint != null) {
586                 g2.setStroke(stroke);
587                 g2.setPaint(paint);
588                 g2.draw(bar);
589             }
590         }
591         
592         if (isItemLabelVisible(series, item)) {
593             XYItemLabelGenerator generator = getItemLabelGenerator(series,
594                     item);
595             drawItemLabel(g2, dataset, series, item, plot, generator, bar,
596                     value1 < 0.0);
597         }
598
599         // update the crosshair point
600
double x1 = (startX + endX) / 2.0;
601         double y1 = dataset.getYValue(series, item);
602         double transX1 = domainAxis.valueToJava2D(x1, dataArea, location);
603         double transY1 = rangeAxis.valueToJava2D(y1, dataArea,
604                 plot.getRangeAxisEdge());
605         updateCrosshairValues(crosshairState, x1, y1, transX1, transY1,
606                 plot.getOrientation());
607
608         // add an entity for the item...
609
if (info != null) {
610             EntityCollection entities = info.getOwner().getEntityCollection();
611             if (entities != null) {
612                 String JavaDoc tip = null;
613                 XYToolTipGenerator generator
614                     = getToolTipGenerator(series, item);
615                 if (generator != null) {
616                     tip = generator.generateToolTip(dataset, series, item);
617                 }
618                 String JavaDoc url = null;
619                 if (getURLGenerator() != null) {
620                     url = getURLGenerator().generateURL(dataset, series, item);
621                 }
622                 XYItemEntity entity = new XYItemEntity(bar, dataset, series,
623                         item, tip, url);
624                 entities.add(entity);
625             }
626         }
627
628     }
629
630     /**
631      * Draws an item label. This method is overridden so that the bar can be
632      * used to calculate the label anchor point.
633      *
634      * @param g2 the graphics device.
635      * @param dataset the dataset.
636      * @param series the series index.
637      * @param item the item index.
638      * @param plot the plot.
639      * @param generator the label generator.
640      * @param bar the bar.
641      * @param negative a flag indicating a negative value.
642      */

643     protected void drawItemLabel(Graphics2D JavaDoc g2, XYDataset dataset,
644             int series, int item, XYPlot plot, XYItemLabelGenerator generator,
645             Rectangle2D JavaDoc bar, boolean negative) {
646                                      
647         String JavaDoc label = generator.generateLabel(dataset, series, item);
648         if (label == null) {
649             return; // nothing to do
650
}
651         
652         Font JavaDoc labelFont = getItemLabelFont(series, item);
653         g2.setFont(labelFont);
654         Paint JavaDoc paint = getItemLabelPaint(series, item);
655         g2.setPaint(paint);
656
657         // find out where to place the label...
658
ItemLabelPosition position = null;
659         if (!negative) {
660             position = getPositiveItemLabelPosition(series, item);
661         }
662         else {
663             position = getNegativeItemLabelPosition(series, item);
664         }
665
666         // work out the label anchor point...
667
Point2D JavaDoc anchorPoint = calculateLabelAnchorPoint(
668                 position.getItemLabelAnchor(), bar, plot.getOrientation());
669         
670         if (isInternalAnchor(position.getItemLabelAnchor())) {
671             Shape JavaDoc bounds = TextUtilities.calculateRotatedStringBounds(label,
672                     g2, (float) anchorPoint.getX(), (float) anchorPoint.getY(),
673                     position.getTextAnchor(), position.getAngle(),
674                     position.getRotationAnchor());
675             
676             if (bounds != null) {
677                 if (!bar.contains(bounds.getBounds2D())) {
678                     if (!negative) {
679                         position = getPositiveItemLabelPositionFallback();
680                     }
681                     else {
682                         position = getNegativeItemLabelPositionFallback();
683                     }
684                     if (position != null) {
685                         anchorPoint = calculateLabelAnchorPoint(
686                                 position.getItemLabelAnchor(), bar,
687                                 plot.getOrientation());
688                     }
689                 }
690             }
691         
692         }
693         
694         if (position != null) {
695             TextUtilities.drawRotatedString(label, g2,
696                     (float) anchorPoint.getX(), (float) anchorPoint.getY(),
697                     position.getTextAnchor(), position.getAngle(),
698                     position.getRotationAnchor());
699         }
700     }
701
702     /**
703      * Calculates the item label anchor point.
704      *
705      * @param anchor the anchor.
706      * @param bar the bar.
707      * @param orientation the plot orientation.
708      *
709      * @return The anchor point.
710      */

711     private Point2D JavaDoc calculateLabelAnchorPoint(ItemLabelAnchor anchor,
712             Rectangle2D JavaDoc bar, PlotOrientation orientation) {
713
714         Point2D JavaDoc result = null;
715         double offset = getItemLabelAnchorOffset();
716         double x0 = bar.getX() - offset;
717         double x1 = bar.getX();
718         double x2 = bar.getX() + offset;
719         double x3 = bar.getCenterX();
720         double x4 = bar.getMaxX() - offset;
721         double x5 = bar.getMaxX();
722         double x6 = bar.getMaxX() + offset;
723
724         double y0 = bar.getMaxY() + offset;
725         double y1 = bar.getMaxY();
726         double y2 = bar.getMaxY() - offset;
727         double y3 = bar.getCenterY();
728         double y4 = bar.getMinY() + offset;
729         double y5 = bar.getMinY();
730         double y6 = bar.getMinY() - offset;
731
732         if (anchor == ItemLabelAnchor.CENTER) {
733             result = new Point2D.Double JavaDoc(x3, y3);
734         }
735         else if (anchor == ItemLabelAnchor.INSIDE1) {
736             result = new Point2D.Double JavaDoc(x4, y4);
737         }
738         else if (anchor == ItemLabelAnchor.INSIDE2) {
739             result = new Point2D.Double JavaDoc(x4, y4);
740         }
741         else if (anchor == ItemLabelAnchor.INSIDE3) {
742             result = new Point2D.Double JavaDoc(x4, y3);
743         }
744         else if (anchor == ItemLabelAnchor.INSIDE4) {
745             result = new Point2D.Double JavaDoc(x4, y2);
746         }
747         else if (anchor == ItemLabelAnchor.INSIDE5) {
748             result = new Point2D.Double JavaDoc(x4, y2);
749         }
750         else if (anchor == ItemLabelAnchor.INSIDE6) {
751             result = new Point2D.Double JavaDoc(x3, y2);
752         }
753         else if (anchor == ItemLabelAnchor.INSIDE7) {
754             result = new Point2D.Double JavaDoc(x2, y2);
755         }
756         else if (anchor == ItemLabelAnchor.INSIDE8) {
757             result = new Point2D.Double JavaDoc(x2, y2);
758         }
759         else if (anchor == ItemLabelAnchor.INSIDE9) {
760             result = new Point2D.Double JavaDoc(x2, y3);
761         }
762         else if (anchor == ItemLabelAnchor.INSIDE10) {
763             result = new Point2D.Double JavaDoc(x2, y4);
764         }
765         else if (anchor == ItemLabelAnchor.INSIDE11) {
766             result = new Point2D.Double JavaDoc(x2, y4);
767         }
768         else if (anchor == ItemLabelAnchor.INSIDE12) {
769             result = new Point2D.Double JavaDoc(x3, y4);
770         }
771         else if (anchor == ItemLabelAnchor.OUTSIDE1) {
772             result = new Point2D.Double JavaDoc(x5, y6);
773         }
774         else if (anchor == ItemLabelAnchor.OUTSIDE2) {
775             result = new Point2D.Double JavaDoc(x6, y5);
776         }
777         else if (anchor == ItemLabelAnchor.OUTSIDE3) {
778             result = new Point2D.Double JavaDoc(x6, y3);
779         }
780         else if (anchor == ItemLabelAnchor.OUTSIDE4) {
781             result = new Point2D.Double JavaDoc(x6, y1);
782         }
783         else if (anchor == ItemLabelAnchor.OUTSIDE5) {
784             result = new Point2D.Double JavaDoc(x5, y0);
785         }
786         else if (anchor == ItemLabelAnchor.OUTSIDE6) {
787             result = new Point2D.Double JavaDoc(x3, y0);
788         }
789         else if (anchor == ItemLabelAnchor.OUTSIDE7) {
790             result = new Point2D.Double JavaDoc(x1, y0);
791         }
792         else if (anchor == ItemLabelAnchor.OUTSIDE8) {
793             result = new Point2D.Double JavaDoc(x0, y1);
794         }
795         else if (anchor == ItemLabelAnchor.OUTSIDE9) {
796             result = new Point2D.Double JavaDoc(x0, y3);
797         }
798         else if (anchor == ItemLabelAnchor.OUTSIDE10) {
799             result = new Point2D.Double JavaDoc(x0, y5);
800         }
801         else if (anchor == ItemLabelAnchor.OUTSIDE11) {
802             result = new Point2D.Double JavaDoc(x1, y6);
803         }
804         else if (anchor == ItemLabelAnchor.OUTSIDE12) {
805             result = new Point2D.Double JavaDoc(x3, y6);
806         }
807
808         return result;
809
810     }
811
812     /**
813      * Returns <code>true</code> if the specified anchor point is inside a bar.
814      *
815      * @param anchor the anchor point.
816      *
817      * @return A boolean.
818      */

819     private boolean isInternalAnchor(ItemLabelAnchor anchor) {
820         return anchor == ItemLabelAnchor.CENTER
821                || anchor == ItemLabelAnchor.INSIDE1
822                || anchor == ItemLabelAnchor.INSIDE2
823                || anchor == ItemLabelAnchor.INSIDE3
824                || anchor == ItemLabelAnchor.INSIDE4
825                || anchor == ItemLabelAnchor.INSIDE5
826                || anchor == ItemLabelAnchor.INSIDE6
827                || anchor == ItemLabelAnchor.INSIDE7
828                || anchor == ItemLabelAnchor.INSIDE8
829                || anchor == ItemLabelAnchor.INSIDE9
830                || anchor == ItemLabelAnchor.INSIDE10
831                || anchor == ItemLabelAnchor.INSIDE11
832                || anchor == ItemLabelAnchor.INSIDE12;
833     }
834     
835     /**
836      * Returns the lower and upper bounds (range) of the x-values in the
837      * specified dataset. Since this renderer uses the x-interval in the
838      * dataset, this is taken into account for the range.
839      *
840      * @param dataset the dataset (<code>null</code> permitted).
841      *
842      * @return The range (<code>null</code> if the dataset is
843      * <code>null</code> or empty).
844      */

845     public Range findDomainBounds(XYDataset dataset) {
846         if (dataset != null) {
847             return DatasetUtilities.findDomainBounds(dataset, true);
848         }
849         else {
850             return null;
851         }
852     }
853
854     /**
855      * Returns a clone of the renderer.
856      *
857      * @return A clone.
858      *
859      * @throws CloneNotSupportedException if the renderer cannot be cloned.
860      */

861     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
862         XYBarRenderer result = (XYBarRenderer) super.clone();
863         if (this.gradientPaintTransformer != null) {
864             result.gradientPaintTransformer = (GradientPaintTransformer)
865                 ObjectUtilities.clone(this.gradientPaintTransformer);
866         }
867         return result;
868     }
869
870     /**
871      * Tests this renderer for equality with an arbitrary object.
872      *
873      * @param obj the object to test against (<code>null</code> permitted).
874      *
875      * @return A boolean.
876      */

877     public boolean equals(Object JavaDoc obj) {
878         if (obj == this) {
879             return true;
880         }
881         if (!(obj instanceof XYBarRenderer)) {
882             return false;
883         }
884         if (!super.equals(obj)) {
885             return false;
886         }
887         XYBarRenderer that = (XYBarRenderer) obj;
888         if (this.base != that.base) {
889             return false;
890         }
891         if (this.drawBarOutline != that.drawBarOutline) {
892             return false;
893         }
894         if (this.margin != that.margin) {
895             return false;
896         }
897         if (this.useYInterval != that.useYInterval) {
898             return false;
899         }
900         if (!ObjectUtilities.equal(
901             this.gradientPaintTransformer, that.gradientPaintTransformer)
902         ) {
903             return false;
904         }
905         if (!ShapeUtilities.equal(this.legendBar, that.legendBar)) {
906             return false;
907         }
908         if (!ObjectUtilities.equal(this.positiveItemLabelPositionFallback,
909                 that.positiveItemLabelPositionFallback)) {
910             return false;
911         }
912         if (!ObjectUtilities.equal(this.negativeItemLabelPositionFallback,
913                 that.negativeItemLabelPositionFallback)) {
914             return false;
915         }
916         return true;
917     }
918     
919     /**
920      * Provides serialization support.
921      *
922      * @param stream the input stream.
923      *
924      * @throws IOException if there is an I/O error.
925      * @throws ClassNotFoundException if there is a classpath problem.
926      */

927     private void readObject(ObjectInputStream JavaDoc stream)
928             throws IOException JavaDoc, ClassNotFoundException JavaDoc {
929         stream.defaultReadObject();
930         this.legendBar = SerialUtilities.readShape(stream);
931     }
932     
933     /**
934      * Provides serialization support.
935      *
936      * @param stream the output stream.
937      *
938      * @throws IOException if there is an I/O error.
939      */

940     private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
941         stream.defaultWriteObject();
942         SerialUtilities.writeShape(this.legendBar, stream);
943     }
944
945 }
946
Popular Tags