KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > demo > ExtendedStackedBarRenderer


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  * ExtendedStackedBarRenderer.java
24  * -------------------------------
25  * (C) Copyright 2003, by Object Refinery Limited and Contributors.
26  *
27  * Original Author: David Gilbert (for Object Refinery Limited);
28  * Contributor(s): -;
29  *
30  * $Id: ExtendedStackedBarRenderer.java,v 1.2 2003/11/28 10:57:36 mungady Exp $
31  *
32  * Changes
33  * -------
34  * 27-Nov-2003 : Version 1 (DG);
35  *
36  */

37
38 package org.jfree.chart.demo;
39
40 import java.awt.Color JavaDoc;
41 import java.awt.Font JavaDoc;
42 import java.awt.Graphics2D JavaDoc;
43 import java.awt.Paint JavaDoc;
44 import java.awt.geom.Rectangle2D JavaDoc;
45
46 import org.jfree.chart.axis.CategoryAxis;
47 import org.jfree.chart.axis.ValueAxis;
48 import org.jfree.chart.entity.CategoryItemEntity;
49 import org.jfree.chart.entity.EntityCollection;
50 import org.jfree.chart.labels.CategoryItemLabelGenerator;
51 import org.jfree.chart.plot.CategoryPlot;
52 import org.jfree.chart.plot.PlotOrientation;
53 import org.jfree.chart.renderer.CategoryItemRendererState;
54 import org.jfree.chart.renderer.StackedBarRenderer;
55 import org.jfree.data.CategoryDataset;
56 import org.jfree.ui.RectangleEdge;
57 import org.jfree.ui.RefineryUtilities;
58 import org.jfree.ui.TextAnchor;
59
60 /**
61  * An extension of the {@link StackedBarRenderer} that can draw positive and negative totals at
62  * the top and bottom of the stacked bars.
63  */

64 public class ExtendedStackedBarRenderer extends StackedBarRenderer {
65
66     /** Show positive label? */
67     private boolean showPositiveTotal = true;
68     
69     /** Show negative label? */
70     private boolean showNegativeTotal = true;
71     
72     /** Font for labels. */
73     private Font JavaDoc totalLabelFont = new Font JavaDoc("SansSerif", Font.PLAIN, 10);
74     
75     /**
76      * Creates a new renderer.
77      */

78     public ExtendedStackedBarRenderer() {
79         super();
80     }
81     
82     // ****************************************************************************
83
// * COMMERCIAL SUPPORT / JFREECHART DEVELOPER GUIDE *
84
// * Please note that commercial support and documentation is available from: *
85
// * *
86
// * http://www.object-refinery.com/jfreechart/support.html *
87
// * *
88
// * This is not only a great service for developers, but is a VERY IMPORTANT *
89
// * source of funding for the JFreeChart project. Please support us so that *
90
// * we can continue developing free software. *
91
// ****************************************************************************
92

93     /**
94      * Draws a stacked bar for a specific item.
95      *
96      * @param g2 the graphics device.
97      * @param state the renderer state.
98      * @param dataArea the plot area.
99      * @param plot the plot.
100      * @param domainAxis the domain (category) axis.
101      * @param rangeAxis the range (value) axis.
102      * @param dataset the data.
103      * @param row the row index (zero-based).
104      * @param column the column index (zero-based).
105      */

106     public void drawItem(Graphics2D JavaDoc g2,
107                          CategoryItemRendererState state,
108                          Rectangle2D JavaDoc dataArea,
109                          CategoryPlot plot,
110                          CategoryAxis domainAxis,
111                          ValueAxis rangeAxis,
112                          CategoryDataset dataset,
113                          int row,
114                          int column) {
115      
116         // nothing is drawn for null values...
117
Number JavaDoc dataValue = dataset.getValue(row, column);
118         if (dataValue == null) {
119             return;
120         }
121         
122         double value = dataValue.doubleValue();
123         
124         PlotOrientation orientation = plot.getOrientation();
125         double barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(), dataArea,
126                                                     plot.getDomainAxisEdge())
127                                                     - state.getBarWidth() / 2.0;
128
129         double positiveBase = 0.0;
130         double negativeBase = 0.0;
131
132         for (int i = 0; i < row; i++) {
133             Number JavaDoc v = dataset.getValue(i, column);
134             if (v != null) {
135                 double d = v.doubleValue();
136                 if (d > 0) {
137                     positiveBase = positiveBase + d;
138                 }
139                 else {
140                     negativeBase = negativeBase + d;
141                 }
142             }
143         }
144
145         double translatedBase;
146         double translatedValue;
147         RectangleEdge location = plot.getRangeAxisEdge();
148         if (value > 0.0) {
149             translatedBase = rangeAxis.translateValueToJava2D(positiveBase, dataArea, location);
150             translatedValue = rangeAxis.translateValueToJava2D(positiveBase + value, dataArea,
151                                                                location);
152         }
153         else {
154             translatedBase = rangeAxis.translateValueToJava2D(negativeBase, dataArea, location);
155             translatedValue = rangeAxis.translateValueToJava2D(negativeBase + value, dataArea,
156                                                                location);
157         }
158         double barL0 = Math.min(translatedBase, translatedValue);
159         double barLength = Math.max(Math.abs(translatedValue - translatedBase),
160                                     getMinimumBarLength());
161
162         Rectangle2D JavaDoc bar = null;
163         if (orientation == PlotOrientation.HORIZONTAL) {
164             bar = new Rectangle2D.Double JavaDoc(barL0, barW0, barLength, state.getBarWidth());
165         }
166         else {
167             bar = new Rectangle2D.Double JavaDoc(barW0, barL0, state.getBarWidth(), barLength);
168         }
169         Paint JavaDoc seriesPaint = getItemPaint(row, column);
170         g2.setPaint(seriesPaint);
171         g2.fill(bar);
172         if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
173             g2.setStroke(getItemStroke(row, column));
174             g2.setPaint(getItemOutlinePaint(row, column));
175             g2.draw(bar);
176         }
177
178         CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column);
179         if (generator != null && isItemLabelVisible(row, column)) {
180             drawItemLabel(g2, dataset, row, column, plot, generator, bar, (value < 0.0));
181         }
182         
183         if (value > 0.0) {
184             if (this.showPositiveTotal) {
185                 if (isLastPositiveItem(dataset, row, column)) {
186                     g2.setPaint(Color.black);
187                     g2.setFont(this.totalLabelFont);
188                     double total = calculateSumOfPositiveValuesForCategory(dataset, column);
189                     RefineryUtilities.drawRotatedString(String.valueOf(total), g2,
190                                                         (float) bar.getCenterX(),
191                                                         (float) (bar.getMinY() - 4.0),
192                                                         TextAnchor.BOTTOM_CENTER,
193                                                         TextAnchor.BOTTOM_CENTER,
194                                                         0.0);
195                 }
196             }
197         }
198         else {
199             if (this.showNegativeTotal) {
200                 if (isLastNegativeItem(dataset, row, column)) {
201                     g2.setPaint(Color.black);
202                     g2.setFont(this.totalLabelFont);
203                     double total = calculateSumOfNegativeValuesForCategory(dataset, column);
204                     RefineryUtilities.drawRotatedString(String.valueOf(total), g2,
205                                                         (float) bar.getCenterX(),
206                                                         (float) (bar.getMaxY() + 4.0),
207                                                         TextAnchor.TOP_CENTER,
208                                                         TextAnchor.TOP_CENTER,
209                                                         0.0);
210                 }
211             }
212         }
213                 
214         // collect entity and tool tip information...
215
if (state.getInfo() != null) {
216             EntityCollection entities = state.getInfo().getOwner().getEntityCollection();
217             if (entities != null) {
218                 String JavaDoc tip = null;
219                 if (generator != null) {
220                     tip = generator.generateToolTip(dataset, row, column);
221                 }
222                 String JavaDoc url = null;
223                 if (getItemURLGenerator(row, column) != null) {
224                     url = getItemURLGenerator(row, column).generateURL(dataset, row, column);
225                 }
226                 CategoryItemEntity entity = new CategoryItemEntity(
227                     bar, tip, url, dataset, row, dataset.getColumnKey(column), column
228                 );
229                 entities.addEntity(entity);
230             }
231         }
232         
233     }
234
235     /**
236      * Returns true if the specified item is the last positive value for that category.
237      *
238      * @param dataset the dataset.
239      * @param row the row (series).
240      * @param column the column (category).
241      *
242      * @return a boolean.
243      */

244     private boolean isLastPositiveItem(CategoryDataset dataset, int row, int column) {
245         boolean result = true;
246         Number JavaDoc dataValue = dataset.getValue(row, column);
247         if (dataValue == null) {
248             return false; // value is null
249
}
250         for (int r = row + 1; r < dataset.getRowCount(); r++) {
251             dataValue = dataset.getValue(r, column);
252             if (dataValue != null) {
253                 result = result && (dataValue.doubleValue() <= 0.0);
254             }
255         }
256         return result;
257     }
258
259     /**
260      * Returns true if the specified item is the last negative value for that category.
261      *
262      * @param dataset the dataset.
263      * @param row the row (series).
264      * @param column the column (category).
265      *
266      * @return a boolean.
267      */

268     private boolean isLastNegativeItem(CategoryDataset dataset, int row, int column) {
269         boolean result = true;
270         Number JavaDoc dataValue = dataset.getValue(row, column);
271         if (dataValue == null) {
272             return false; // value is null
273
}
274         for (int r = row + 1; r < dataset.getRowCount(); r++) {
275             dataValue = dataset.getValue(r, column);
276             if (dataValue != null) {
277                 result = result && (dataValue.doubleValue() >= 0.0);
278             }
279         }
280         return result;
281     }
282
283     /**
284      * Calculates the sum of the positive values within a category.
285      *
286      * @param dataset the dataset.
287      * @param column the column (category).
288      *
289      * @return the sum of the positive values.
290      */

291     private double calculateSumOfPositiveValuesForCategory(CategoryDataset dataset, int column) {
292         double result = 0.0;
293         for (int r = 0; r < dataset.getRowCount(); r++) {
294             Number JavaDoc dataValue = dataset.getValue(r, column);
295             if (dataValue != null) {
296                 double v = dataValue.doubleValue();
297                 if (v > 0.0) {
298                     result = result + v;
299                 }
300             }
301         }
302         return result;
303     }
304
305     /**
306      * Calculates the sum of the negative values within a category.
307      *
308      * @param dataset the dataset.
309      * @param column the column (category).
310      *
311      * @return the sum of the negative values.
312      */

313     private double calculateSumOfNegativeValuesForCategory(CategoryDataset dataset, int column) {
314         double result = 0.0;
315         for (int r = 0; r < dataset.getRowCount(); r++) {
316             Number JavaDoc dataValue = dataset.getValue(r, column);
317             if (dataValue != null) {
318                 double v = dataValue.doubleValue();
319                 if (v < 0.0) {
320                     result = result + v;
321                 }
322             }
323         }
324         return result;
325     }
326     
327 }
328
Popular Tags