KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > LayeredBarRenderer


1 /* ======================================
2  * JFreeChart : a free Java chart library
3  * ======================================
4  *
5  * Project Info: http://www.jfree.org/jfreechart/index.html
6  * Project Lead: David Gilbert (david.gilbert@object-refinery.com);
7  *
8  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License along with this
19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * -----------------------
23  * LayeredBarRenderer.java
24  * -----------------------
25  * (C) Copyright 2003, by Arnaud Lelievre and Contributors.
26  *
27  * Original Author: Arnaud Lelievre (for Garden);
28  * Contributor(s): -;
29  *
30  *
31  * Changes
32  * -------
33  * 28-Aug-2003 : Version 1 (AL);
34  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
35  * 07-Oct-2003 : Added renderer state (DG);
36  * 21-Oct-2003 : Bar width moved to renderer state (DG);
37  *
38  */

39
40 package org.jfree.chart.renderer;
41
42 import java.awt.Graphics2D JavaDoc;
43 import java.awt.Paint JavaDoc;
44 import java.awt.Stroke JavaDoc;
45 import java.awt.geom.Rectangle2D JavaDoc;
46
47 import org.jfree.chart.axis.CategoryAxis;
48 import org.jfree.chart.axis.ValueAxis;
49 import org.jfree.chart.entity.CategoryItemEntity;
50 import org.jfree.chart.entity.EntityCollection;
51 import org.jfree.chart.labels.CategoryItemLabelGenerator;
52 import org.jfree.chart.plot.CategoryPlot;
53 import org.jfree.chart.plot.PlotOrientation;
54 import org.jfree.data.CategoryDataset;
55 import org.jfree.ui.RectangleEdge;
56 import org.jfree.util.ObjectList;
57
58 /**
59  * A {@link CategoryItemRenderer} that represents data using bars which are superimposed.
60  *
61  * @author Arnaud Lelievre
62  */

63 public class LayeredBarRenderer extends BarRenderer {
64
65     /** A list of the width of each series bar. */
66     protected ObjectList seriesBarWidthList;
67
68     /**
69      * Default constructor.
70      */

71     public LayeredBarRenderer() {
72         super();
73         this.seriesBarWidthList = new ObjectList();
74
75     }
76
77     /**
78      * Calculates the bar width and stores it in the renderer state.
79      *
80      * @param plot the plot.
81      * @param dataArea the data area.
82      * @param rendererIndex the renderer index.
83      * @param state the renderer state.
84      */

85     protected void calculateBarWidth(CategoryPlot plot,
86                                      Rectangle2D JavaDoc dataArea,
87                                      Integer JavaDoc rendererIndex,
88                                      CategoryItemRendererState state) {
89
90         // calculate the bar width
91
CategoryAxis domainAxis = getDomainAxis(plot, rendererIndex);
92         CategoryDataset dataset = getDataset(plot, rendererIndex);
93         if (dataset != null) {
94             int columns = dataset.getColumnCount();
95             int rows = dataset.getRowCount();
96             double space = 0.0;
97             PlotOrientation orientation = plot.getOrientation();
98             if (orientation == PlotOrientation.HORIZONTAL) {
99                 space = dataArea.getHeight();
100             }
101             else if (orientation == PlotOrientation.VERTICAL) {
102                 space = dataArea.getWidth();
103             }
104             double categoryMargin = 0.0;
105             double currentItemMargin = 0.0;
106             if (columns > 1) {
107                 categoryMargin = domainAxis.getCategoryMargin();
108             }
109             if (rows > 1) {
110                 currentItemMargin = getItemMargin();
111             }
112             double used = space * (1 - domainAxis.getLowerMargin() - domainAxis.getUpperMargin()
113                                      - categoryMargin - currentItemMargin);
114             if ((rows * columns) > 0) {
115                 state.setBarWidth(used / (dataset.getColumnCount()));
116             }
117             else {
118                 state.setBarWidth(used);
119             }
120         }
121     }
122
123     /**
124      * Draws the bar for one item in the dataset.
125      *
126      * @param g2 the graphics device.
127      * @param state the renderer state.
128      * @param dataArea the plot area.
129      * @param plot the plot.
130      * @param domainAxis the domain (category) axis.
131      * @param rangeAxis the range (value) axis.
132      * @param data the data.
133      * @param row the row index (zero-based).
134      * @param column the column index (zero-based).
135      */

136     public void drawItem(Graphics2D JavaDoc g2,
137                          CategoryItemRendererState state,
138                          Rectangle2D JavaDoc dataArea,
139                          CategoryPlot plot,
140                          CategoryAxis domainAxis,
141                          ValueAxis rangeAxis,
142                          CategoryDataset data,
143                          int row,
144                          int column) {
145
146         PlotOrientation orientation = plot.getOrientation();
147         if (orientation == PlotOrientation.HORIZONTAL) {
148             drawHorizontalItem(g2, state, dataArea,
149                                plot, domainAxis, rangeAxis, data, row, column);
150         }
151         else if (orientation == PlotOrientation.VERTICAL) {
152             drawVerticalItem(g2, state, dataArea,
153                              plot, domainAxis, rangeAxis, data, row, column);
154         }
155
156     }
157
158     /**
159      * Draws the bar for a single (series, category) data item.
160      *
161      * @param g2 the graphics device.
162      * @param state the renderer state.
163      * @param dataArea the data area.
164      * @param plot the plot.
165      * @param domainAxis the domain axis.
166      * @param rangeAxis the range axis.
167      * @param data the data.
168      * @param row the row index (zero-based).
169      * @param column the column index (zero-based).
170      */

171     protected void drawHorizontalItem(Graphics2D JavaDoc g2,
172                                       CategoryItemRendererState state,
173                                       Rectangle2D JavaDoc dataArea,
174                                       CategoryPlot plot,
175                                       CategoryAxis domainAxis,
176                                       ValueAxis rangeAxis,
177                                       CategoryDataset data,
178                                       int row,
179                                       int column) {
180
181         // nothing is drawn for null values...
182
Number JavaDoc dataValue = data.getValue(row, column);
183         if (dataValue == null) {
184             return;
185         }
186
187         // X
188
double value = dataValue.doubleValue();
189         double base = 0.0;
190         double lclip = getLowerClip();
191         double uclip = getUpperClip();
192         if (uclip <= 0.0) { // cases 1, 2, 3 and 4
193
if (value >= uclip) {
194                 return; // bar is not visible
195
}
196             base = uclip;
197             if (value <= lclip) {
198                 value = lclip;
199             }
200         }
201         else if (lclip <= 0.0) { // cases 5, 6, 7 and 8
202
if (value >= uclip) {
203                 value = uclip;
204             }
205             else {
206                 if (value <= lclip) {
207                     value = lclip;
208                 }
209             }
210         }
211         else { // cases 9, 10, 11 and 12
212
if (value <= lclip) {
213                 return; // bar is not visible
214
}
215             base = lclip;
216             if (value >= uclip) {
217                 value = uclip;
218             }
219         }
220
221         RectangleEdge edge = plot.getRangeAxisEdge();
222         double transX1 = rangeAxis.translateValueToJava2D(base, dataArea, edge);
223         double transX2 = rangeAxis.translateValueToJava2D(value, dataArea, edge);
224         double rectX = Math.min(transX1, transX2);
225         double rectWidth = Math.abs(transX2 - transX1);
226
227         // Y
228
double rectY = domainAxis.getCategoryStart(column, getColumnCount(), dataArea,
229                                                    plot.getDomainAxisEdge());
230
231         int seriesCount = getRowCount();
232
233         // draw the bar...
234
double shift = 0.0;
235         double rectHeight = 0.0;
236         if (getSeriesBarWidth(row, state) != state.getBarWidth()) {
237             rectHeight = getSeriesBarWidth(row, state) * state.getBarWidth();
238             rectY = rectY + (1 - getSeriesBarWidth(row, state)) * state.getBarWidth() / 2;
239         }
240         else {
241             rectHeight = state.getBarWidth();
242             if (seriesCount > 1) {
243                 shift = rectHeight * 0.20 / (seriesCount - 1);
244             }
245         }
246
247         Rectangle2D JavaDoc bar = new Rectangle2D.Double JavaDoc(rectX,
248                                                 (rectY + ((seriesCount - 1 - row) * shift)),
249                                                 rectWidth,
250                                                 (rectHeight - (seriesCount - 1 - row) * shift * 2));
251
252         g2.setPaint(getItemPaint(row, column));
253         g2.fill(bar);
254
255         // draw the outline...
256
if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
257             Stroke JavaDoc stroke = getItemOutlineStroke(row, column);
258             Paint JavaDoc paint = getItemOutlinePaint(row, column);
259             if (stroke != null && paint != null) {
260                 g2.setStroke(stroke);
261                 g2.setPaint(paint);
262                 g2.draw(bar);
263             }
264         }
265
266         CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column);
267         if (generator != null && isItemLabelVisible(row, column)) {
268             drawItemLabel(g2, data, row, column, plot, generator, bar, (transX1 > transX2));
269         }
270
271         // collect entity and tool tip information...
272
if (state.getInfo() != null) {
273             EntityCollection entities = state.getInfo().getOwner().getEntityCollection();
274             if (entities != null) {
275                 String JavaDoc tip = null;
276                 if (generator != null) {
277                     tip = generator.generateToolTip(data, row, column);
278                 }
279                 String JavaDoc url = null;
280                 if (getItemURLGenerator(row, column) != null) {
281                     url = getItemURLGenerator(row, column).generateURL(data, row, column);
282                 }
283                 CategoryItemEntity entity = new CategoryItemEntity(bar, tip, url, data, row,
284                                                                data.getColumnKey(column), column);
285                 entities.addEntity(entity);
286             }
287         }
288     }
289
290     /**
291      * Draws the bar for a single (series, category) data item.
292      *
293      * @param g2 the graphics device.
294      * @param state the renderer state.
295      * @param dataArea the data area.
296      * @param plot the plot.
297      * @param domainAxis the domain axis.
298      * @param rangeAxis the range axis.
299      * @param data the data.
300      * @param row the row index (zero-based).
301      * @param column the column index (zero-based).
302      */

303     protected void drawVerticalItem(Graphics2D JavaDoc g2,
304                                     CategoryItemRendererState state,
305                                     Rectangle2D JavaDoc dataArea,
306                                     CategoryPlot plot,
307                                     CategoryAxis domainAxis,
308                                     ValueAxis rangeAxis,
309                                     CategoryDataset data,
310                                     int row,
311                                     int column) {
312
313         // nothing is drawn for null values...
314
Number JavaDoc dataValue = data.getValue(row, column);
315         if (dataValue == null) {
316             return;
317         }
318
319         // BAR X
320
double rectX = domainAxis.getCategoryStart(column, getColumnCount(), dataArea,
321                                                    plot.getDomainAxisEdge());
322
323         int seriesCount = getRowCount();
324
325         // BAR Y
326
double value = dataValue.doubleValue();
327         double base = 0.0;
328         double lclip = getLowerClip();
329         double uclip = getUpperClip();
330
331         if (uclip <= 0.0) { // cases 1, 2, 3 and 4
332
if (value >= uclip) {
333                 return; // bar is not visible
334
}
335             base = uclip;
336             if (value <= lclip) {
337                 value = lclip;
338             }
339         }
340         else if (lclip <= 0.0) { // cases 5, 6, 7 and 8
341
if (value >= uclip) {
342                 value = uclip;
343             }
344             else {
345                 if (value <= lclip) {
346                     value = lclip;
347                 }
348             }
349         }
350         else { // cases 9, 10, 11 and 12
351
if (value <= lclip) {
352                 return; // bar is not visible
353
}
354             base = getLowerClip();
355             if (value >= uclip) {
356                value = uclip;
357             }
358         }
359
360         RectangleEdge edge = plot.getRangeAxisEdge();
361         double transY1 = rangeAxis.translateValueToJava2D(base, dataArea, edge);
362         double transY2 = rangeAxis.translateValueToJava2D(value, dataArea, edge);
363         double rectY = Math.min(transY2, transY1);
364
365         double rectWidth = state.getBarWidth();
366         double rectHeight = Math.abs(transY2 - transY1);
367
368         // draw the bar...
369
double shift = 0.0;
370         rectWidth = 0.0;
371         if (getSeriesBarWidth(row, state) != state.getBarWidth()) {
372             rectWidth = getSeriesBarWidth(row, state) * state.getBarWidth();
373             rectX = rectX + (1 - getSeriesBarWidth(row, state)) * state.getBarWidth() / 2;
374         } else {
375             rectWidth = state.getBarWidth();
376             if (seriesCount > 1) {
377                 // needs to be improved !!!
378
shift = rectWidth * 0.20 / (seriesCount - 1);
379             }
380         }
381
382         Rectangle2D JavaDoc bar = new Rectangle2D.Double JavaDoc(
383                                                 (rectX + ((seriesCount - 1 - row) * shift)),
384                                                 rectY,
385                                                 (rectWidth - (seriesCount - 1 - row) * shift * 2),
386                                                 rectHeight);
387         g2.setPaint(getItemPaint(row, column));
388         g2.fill(bar);
389
390         // draw the outline...
391
if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
392             Stroke JavaDoc stroke = getItemOutlineStroke(row, column);
393             Paint JavaDoc paint = getItemOutlinePaint(row, column);
394             if (stroke != null && paint != null) {
395                 g2.setStroke(stroke);
396                 g2.setPaint(paint);
397                 g2.draw(bar);
398             }
399         }
400
401         // draw the item labels if there are any...
402
double transX1 = rangeAxis.translateValueToJava2D(base, dataArea, edge);
403         double transX2 = rangeAxis.translateValueToJava2D(value, dataArea, edge);
404
405         CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column);
406         if (generator != null && isItemLabelVisible(row, column)) {
407             drawItemLabel(g2, data, row, column, plot, generator, bar, (transX1 > transX2));
408         }
409
410         // collect entity and tool tip information...
411
if (state.getInfo() != null) {
412             EntityCollection entities = state.getInfo().getOwner().getEntityCollection();
413             if (entities != null) {
414                 String JavaDoc tip = null;
415                 if (generator != null) {
416                     tip = generator.generateToolTip(data, row, column);
417                 }
418                 String JavaDoc url = null;
419                 if (getItemURLGenerator(row, column) != null) {
420                     url = getItemURLGenerator(row, column).generateURL(data, row, column);
421                 }
422                 CategoryItemEntity entity = new CategoryItemEntity(bar, tip, url, data, row,
423                                                     data.getColumnKey(column), column);
424                 entities.addEntity(entity);
425             }
426         }
427     }
428
429     /**
430      * Returns the bar width for a series.
431      *
432      * @param series the series index (zero based).
433      * @param state the renderer state.
434      *
435      * @return The width for the series (1.0=100%, it is the maximum).
436      */

437     public double getSeriesBarWidth(int series, CategoryItemRendererState state) {
438
439         if (this.seriesBarWidthList.get(series) != null) {
440             return ((Number JavaDoc) this.seriesBarWidthList.get(series)).doubleValue();
441         }
442         else {
443             return state.getBarWidth();
444         }
445     }
446
447     /**
448      * Sets the width of the bars of a series.
449      *
450      * @param series the series index (zero based).
451      * @param width the width of the series bar in percentage (1.0=100%, it is the maximum).
452      */

453     public void setSeriesBarWidth(int series, double width) {
454         this.seriesBarWidthList.set(series, new Double JavaDoc(width));
455     }
456
457 }
458
Popular Tags