KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > category > LevelRenderer


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  * LevelRenderer.java
29  * ------------------
30  * (C) Copyright 2004, 2006, by Object Refinery Limited.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): -;
34  *
35  * $Id: LevelRenderer.java,v 1.7.2.3 2006/01/23 09:53:58 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 09-Jan-2004 : Version 1 (DG);
40  * 05-Nov-2004 : Modified drawItem() signature (DG);
41  * 20-Apr-2005 : Renamed CategoryLabelGenerator
42  * --> CategoryItemLabelGenerator (DG);
43  * ------------- JFREECHART 1.0.0 ---------------------------------------------
44  * 23-Jan-2006 : Renamed getMaxItemWidth() --> getMaximumItemWidth() (DG);
45  *
46  */

47
48 package org.jfree.chart.renderer.category;
49
50 import java.awt.Graphics2D JavaDoc;
51 import java.awt.Paint JavaDoc;
52 import java.awt.Stroke JavaDoc;
53 import java.awt.geom.Line2D JavaDoc;
54 import java.awt.geom.Rectangle2D JavaDoc;
55 import java.io.Serializable JavaDoc;
56
57 import org.jfree.chart.axis.CategoryAxis;
58 import org.jfree.chart.axis.ValueAxis;
59 import org.jfree.chart.entity.CategoryItemEntity;
60 import org.jfree.chart.entity.EntityCollection;
61 import org.jfree.chart.event.RendererChangeEvent;
62 import org.jfree.chart.labels.CategoryItemLabelGenerator;
63 import org.jfree.chart.labels.CategoryToolTipGenerator;
64 import org.jfree.chart.plot.CategoryPlot;
65 import org.jfree.chart.plot.PlotOrientation;
66 import org.jfree.chart.plot.PlotRenderingInfo;
67 import org.jfree.data.category.CategoryDataset;
68 import org.jfree.ui.RectangleEdge;
69 import org.jfree.util.PublicCloneable;
70
71 /**
72  * A {@link CategoryItemRenderer} that draws individual data items as
73  * horizontal lines, spaced in the same way as bars in a bar chart.
74  */

75 public class LevelRenderer extends AbstractCategoryItemRenderer
76                            implements Cloneable JavaDoc, PublicCloneable, Serializable JavaDoc {
77
78     /** For serialization. */
79     private static final long serialVersionUID = -8204856624355025117L;
80     
81     /** The default item margin percentage. */
82     public static final double DEFAULT_ITEM_MARGIN = 0.20;
83
84     /** The margin between items within a category. */
85     private double itemMargin;
86
87     /** The maximum item width as a percentage of the available space. */
88     private double maxItemWidth;
89     
90     /**
91      * Creates a new renderer with default settings.
92      */

93     public LevelRenderer() {
94         super();
95         this.itemMargin = DEFAULT_ITEM_MARGIN;
96         this.maxItemWidth = 1.0; // 100 percent, so it will not apply unless
97
// changed
98
}
99
100     /**
101      * Returns the item margin.
102      *
103      * @return The margin.
104      */

105     public double getItemMargin() {
106         return this.itemMargin;
107     }
108
109     /**
110      * Sets the item margin. The value is expressed as a percentage of the
111      * available width for plotting all the bars, with the resulting amount to
112      * be distributed between all the bars evenly.
113      *
114      * @param percent the new margin.
115      */

116     public void setItemMargin(double percent) {
117         this.itemMargin = percent;
118         notifyListeners(new RendererChangeEvent(this));
119     }
120     
121     /**
122      * Returns the maximum width, as a percentage of the available drawing
123      * space.
124      *
125      * @return The maximum width.
126      *
127      * @deprecated Use {@link #getMaximumItemWidth()} instead.
128      */

129     public double getMaxItemWidth() {
130         return this.maxItemWidth;
131     }
132     
133     /**
134      * Sets the maximum item width, which is specified as a percentage of the
135      * available space for all items, and sends a {@link RendererChangeEvent}
136      * to all registered listeners.
137      *
138      * @param percent the percent.
139      *
140      * @deprecated Use {@link #setMaximumItemWidth(double)} instead.
141      */

142     public void setMaxItemWidth(double percent) {
143         this.maxItemWidth = percent;
144         notifyListeners(new RendererChangeEvent(this));
145     }
146
147     /**
148      * Returns the maximum width, as a percentage of the available drawing
149      * space.
150      *
151      * @return The maximum width.
152      */

153     public double getMaximumItemWidth() {
154         return getMaxItemWidth();
155     }
156     
157     /**
158      * Sets the maximum item width, which is specified as a percentage of the
159      * available space for all items, and sends a {@link RendererChangeEvent}
160      * to all registered listeners.
161      *
162      * @param percent the percent.
163      */

164     public void setMaximumItemWidth(double percent) {
165         setMaxItemWidth(percent);
166     }
167
168     /**
169      * Initialises the renderer and returns a state object that will be passed
170      * to subsequent calls to the drawItem method.
171      * <p>
172      * This method gets called once at the start of the process of drawing a
173      * chart.
174      *
175      * @param g2 the graphics device.
176      * @param dataArea the area in which the data is to be plotted.
177      * @param plot the plot.
178      * @param rendererIndex the renderer index.
179      * @param info collects chart rendering information for return to caller.
180      *
181      * @return The renderer state.
182      *
183      */

184     public CategoryItemRendererState initialise(Graphics2D JavaDoc g2,
185                                                 Rectangle2D JavaDoc dataArea,
186                                                 CategoryPlot plot,
187                                                 int rendererIndex,
188                                                 PlotRenderingInfo info) {
189
190         CategoryItemRendererState state = super.initialise(g2, dataArea, plot,
191                 rendererIndex, info);
192         calculateItemWidth(plot, dataArea, rendererIndex, state);
193         return state;
194         
195     }
196     
197     /**
198      * Calculates the bar width and stores it in the renderer state.
199      *
200      * @param plot the plot.
201      * @param dataArea the data area.
202      * @param rendererIndex the renderer index.
203      * @param state the renderer state.
204      */

205     protected void calculateItemWidth(CategoryPlot plot,
206                                       Rectangle2D JavaDoc dataArea,
207                                       int rendererIndex,
208                                       CategoryItemRendererState state) {
209                                          
210         CategoryAxis domainAxis = getDomainAxis(plot, rendererIndex);
211         CategoryDataset dataset = plot.getDataset(rendererIndex);
212         if (dataset != null) {
213             int columns = dataset.getColumnCount();
214             int rows = dataset.getRowCount();
215             double space = 0.0;
216             PlotOrientation orientation = plot.getOrientation();
217             if (orientation == PlotOrientation.HORIZONTAL) {
218                 space = dataArea.getHeight();
219             }
220             else if (orientation == PlotOrientation.VERTICAL) {
221                 space = dataArea.getWidth();
222             }
223             double maxWidth = space * getMaxItemWidth();
224             double categoryMargin = 0.0;
225             double currentItemMargin = 0.0;
226             if (columns > 1) {
227                 categoryMargin = domainAxis.getCategoryMargin();
228             }
229             if (rows > 1) {
230                 currentItemMargin = getItemMargin();
231             }
232             double used = space * (1 - domainAxis.getLowerMargin()
233                                      - domainAxis.getUpperMargin()
234                                      - categoryMargin - currentItemMargin);
235             if ((rows * columns) > 0) {
236                 state.setBarWidth(Math.min(used / (rows * columns), maxWidth));
237             }
238             else {
239                 state.setBarWidth(Math.min(used, maxWidth));
240             }
241         }
242     }
243
244     /**
245      * Calculates the coordinate of the first "side" of a bar. This will be
246      * the minimum x-coordinate for a vertical bar, and the minimum
247      * y-coordinate for a horizontal bar.
248      *
249      * @param plot the plot.
250      * @param orientation the plot orientation.
251      * @param dataArea the data area.
252      * @param domainAxis the domain axis.
253      * @param state the renderer state (has the bar width precalculated).
254      * @param row the row index.
255      * @param column the column index.
256      *
257      * @return The coordinate.
258      */

259     protected double calculateBarW0(CategoryPlot plot,
260                                     PlotOrientation orientation,
261                                     Rectangle2D JavaDoc dataArea,
262                                     CategoryAxis domainAxis,
263                                     CategoryItemRendererState state,
264                                     int row,
265                                     int column) {
266         // calculate bar width...
267
double space = 0.0;
268         if (orientation == PlotOrientation.HORIZONTAL) {
269             space = dataArea.getHeight();
270         }
271         else {
272             space = dataArea.getWidth();
273         }
274         double barW0 = domainAxis.getCategoryStart(column, getColumnCount(),
275                 dataArea, plot.getDomainAxisEdge());
276         int seriesCount = getRowCount();
277         int categoryCount = getColumnCount();
278         if (seriesCount > 1) {
279             double seriesGap = space * getItemMargin()
280                     / (categoryCount * (seriesCount - 1));
281             double seriesW = calculateSeriesWidth(space, domainAxis,
282                     categoryCount, seriesCount);
283             barW0 = barW0 + row * (seriesW + seriesGap)
284                           + (seriesW / 2.0) - (state.getBarWidth() / 2.0);
285         }
286         else {
287             barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(),
288                     dataArea, plot.getDomainAxisEdge()) - state.getBarWidth()
289                     / 2.0;
290         }
291         return barW0;
292     }
293     
294     /**
295      * Draws the bar for a single (series, category) data item.
296      *
297      * @param g2 the graphics device.
298      * @param state the renderer state.
299      * @param dataArea the data area.
300      * @param plot the plot.
301      * @param domainAxis the domain axis.
302      * @param rangeAxis the range axis.
303      * @param dataset the dataset.
304      * @param row the row index (zero-based).
305      * @param column the column index (zero-based).
306      * @param pass the pass index.
307      */

308     public void drawItem(Graphics2D JavaDoc g2, CategoryItemRendererState state,
309             Rectangle2D JavaDoc dataArea, CategoryPlot plot, CategoryAxis domainAxis,
310             ValueAxis rangeAxis, CategoryDataset dataset, int row, int column,
311             int pass) {
312
313         // nothing is drawn for null values...
314
Number JavaDoc dataValue = dataset.getValue(row, column);
315         if (dataValue == null) {
316             return;
317         }
318         
319         double value = dataValue.doubleValue();
320         
321         PlotOrientation orientation = plot.getOrientation();
322         double barW0 = calculateBarW0(plot, orientation, dataArea, domainAxis,
323                 state, row, column);
324         RectangleEdge edge = plot.getRangeAxisEdge();
325         double barL = rangeAxis.valueToJava2D(value, dataArea, edge);
326
327         // draw the bar...
328
Line2D JavaDoc line = null;
329         double x = 0.0;
330         double y = 0.0;
331         if (orientation == PlotOrientation.HORIZONTAL) {
332             x = barL;
333             y = barW0 + state.getBarWidth() / 2.0;
334             line = new Line2D.Double JavaDoc(barL, barW0, barL,
335                     barW0 + state.getBarWidth());
336         }
337         else {
338             x = barW0 + state.getBarWidth() / 2.0;
339             y = barL;
340             line = new Line2D.Double JavaDoc(barW0, barL, barW0 + state.getBarWidth(),
341                     barL);
342         }
343         Stroke JavaDoc itemStroke = getItemStroke(row, column);
344         Paint JavaDoc itemPaint = getItemPaint(row, column);
345         g2.setStroke(itemStroke);
346         g2.setPaint(itemPaint);
347         g2.draw(line);
348
349         CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
350                 column);
351         if (generator != null && isItemLabelVisible(row, column)) {
352             drawItemLabel(g2, orientation, dataset, row, column, x, y,
353                     (value < 0.0));
354         }
355                 
356         // collect entity and tool tip information...
357
if (state.getInfo() != null) {
358             EntityCollection entities = state.getEntityCollection();
359             if (entities != null) {
360                 String JavaDoc tip = null;
361                 CategoryToolTipGenerator tipster = getToolTipGenerator(row,
362                         column);
363                 if (tipster != null) {
364                     tip = tipster.generateToolTip(dataset, row, column);
365                 }
366                 String JavaDoc url = null;
367                 if (getItemURLGenerator(row, column) != null) {
368                     url = getItemURLGenerator(row, column).generateURL(dataset,
369                             row, column);
370                 }
371                 CategoryItemEntity entity = new CategoryItemEntity(
372                         line.getBounds(), tip, url, dataset, row,
373                         dataset.getColumnKey(column), column);
374                 entities.add(entity);
375             }
376
377         }
378
379     }
380
381     /**
382      * Calculates the available space for each series.
383      *
384      * @param space the space along the entire axis (in Java2D units).
385      * @param axis the category axis.
386      * @param categories the number of categories.
387      * @param series the number of series.
388      *
389      * @return The width of one series.
390      */

391     protected double calculateSeriesWidth(double space, CategoryAxis axis,
392                                           int categories, int series) {
393         double factor = 1.0 - getItemMargin() - axis.getLowerMargin()
394                         - axis.getUpperMargin();
395         if (categories > 1) {
396             factor = factor - axis.getCategoryMargin();
397         }
398         return (space * factor) / (categories * series);
399     }
400     
401     /**
402      * Tests an object for equality with this instance.
403      *
404      * @param obj the object (<code>null</code> permitted).
405      *
406      * @return A boolean.
407      */

408     public boolean equals(Object JavaDoc obj) {
409         if (obj == this) {
410             return true;
411         }
412         if (!(obj instanceof LevelRenderer)) {
413             return false;
414         }
415         if (!super.equals(obj)) {
416             return false;
417         }
418         LevelRenderer that = (LevelRenderer) obj;
419         if (this.itemMargin != that.itemMargin) {
420             return false;
421         }
422         if (this.maxItemWidth != that.maxItemWidth) {
423             return false;
424         }
425         return true;
426     }
427
428 }
429
Popular Tags