001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * ------------------------
028 * IntervalBarRenderer.java
029 * ------------------------
030 * (C) Copyright 2002-2007, by Jeremy Bowman.
031 *
032 * Original Author: Jeremy Bowman;
033 * Contributor(s): David Gilbert (for Object Refinery Limited);
034 * Christian W. Zuckschwerdt;
035 *
036 * $Id: IntervalBarRenderer.java,v 1.6.2.3 2007/02/02 15:52:07 mungady Exp $
037 *
038 * Changes
039 * -------
040 * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG);
041 * 11-May-2002 : Use CategoryPlot.getLabelsVisible() (JB);
042 * 29-May-2002 : Added constructors (DG);
043 * 26-Jun-2002 : Added axis to initialise method (DG);
044 * 20-Sep-2002 : Added basic support for chart entities (DG);
045 * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and
046 * CategoryToolTipGenerator interface (DG);
047 * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
048 * 25-Mar-2003 : Implemented Serializable (DG);
049 * 30-Jul-2003 : Modified entity constructor (CZ);
050 * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
051 * 08-Sep-2003 : Added checks for null values (DG);
052 * 07-Oct-2003 : Added renderer state (DG);
053 * 21-Oct-2003 : Bar width moved into renderer state (DG);
054 * 23-Dec-2003 : Removed the deprecated MultiIntervalCategoryDataset
055 * interface (DG);
056 * 05-Nov-2004 : Modified drawItem() signature (DG);
057 * 20-Apr-2005 : Renamed CategoryLabelGenerator
058 * --> CategoryItemLabelGenerator (DG);
059 * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
060 *
061 */
062
063 package org.jfree.chart.renderer.category;
064
065 import java.awt.Graphics2D;
066 import java.awt.Paint;
067 import java.awt.Stroke;
068 import java.awt.geom.Rectangle2D;
069 import java.io.Serializable;
070
071 import org.jfree.chart.axis.CategoryAxis;
072 import org.jfree.chart.axis.ValueAxis;
073 import org.jfree.chart.entity.CategoryItemEntity;
074 import org.jfree.chart.entity.EntityCollection;
075 import org.jfree.chart.labels.CategoryItemLabelGenerator;
076 import org.jfree.chart.labels.CategoryToolTipGenerator;
077 import org.jfree.chart.plot.CategoryPlot;
078 import org.jfree.chart.plot.PlotOrientation;
079 import org.jfree.data.category.CategoryDataset;
080 import org.jfree.data.category.IntervalCategoryDataset;
081 import org.jfree.ui.RectangleEdge;
082 import org.jfree.util.PublicCloneable;
083
084 /**
085 * A renderer that handles the drawing of bars for a bar plot where
086 * each bar has a high and low value.
087 * <p>
088 * For use with the {@link CategoryPlot} class.
089 */
090 public class IntervalBarRenderer extends BarRenderer
091 implements CategoryItemRenderer,
092 Cloneable,
093 PublicCloneable,
094 Serializable {
095
096 /** For serialization. */
097 private static final long serialVersionUID = -5068857361615528725L;
098
099 /**
100 * Constructs a new renderer.
101 */
102 public IntervalBarRenderer() {
103 super();
104 }
105
106 /**
107 * Draws the bar for a single (series, category) data item.
108 *
109 * @param g2 the graphics device.
110 * @param state the renderer state.
111 * @param dataArea the data area.
112 * @param plot the plot.
113 * @param domainAxis the domain axis.
114 * @param rangeAxis the range axis.
115 * @param dataset the dataset.
116 * @param row the row index (zero-based).
117 * @param column the column index (zero-based).
118 * @param pass the pass index.
119 */
120 public void drawItem(Graphics2D g2,
121 CategoryItemRendererState state,
122 Rectangle2D dataArea,
123 CategoryPlot plot,
124 CategoryAxis domainAxis,
125 ValueAxis rangeAxis,
126 CategoryDataset dataset,
127 int row,
128 int column,
129 int pass) {
130
131 if (dataset instanceof IntervalCategoryDataset) {
132 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
133 drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis,
134 d, row, column);
135 }
136 else {
137 super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
138 dataset, row, column, pass);
139 }
140
141 }
142
143 /**
144 * Draws a single interval.
145 *
146 * @param g2 the graphics device.
147 * @param state the renderer state.
148 * @param dataArea the data plot area.
149 * @param plot the plot.
150 * @param domainAxis the domain axis.
151 * @param rangeAxis the range axis.
152 * @param dataset the data.
153 * @param row the row index (zero-based).
154 * @param column the column index (zero-based).
155 */
156 protected void drawInterval(Graphics2D g2,
157 CategoryItemRendererState state,
158 Rectangle2D dataArea,
159 CategoryPlot plot,
160 CategoryAxis domainAxis,
161 ValueAxis rangeAxis,
162 IntervalCategoryDataset dataset,
163 int row,
164 int column) {
165
166 int seriesCount = getRowCount();
167 int categoryCount = getColumnCount();
168
169 PlotOrientation orientation = plot.getOrientation();
170
171 double rectX = 0.0;
172 double rectY = 0.0;
173
174 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
175 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
176
177 // Y0
178 Number value0 = dataset.getEndValue(row, column);
179 if (value0 == null) {
180 return;
181 }
182 double java2dValue0 = rangeAxis.valueToJava2D(
183 value0.doubleValue(), dataArea, rangeAxisLocation
184 );
185
186 // Y1
187 Number value1 = dataset.getStartValue(row, column);
188 if (value1 == null) {
189 return;
190 }
191 double java2dValue1 = rangeAxis.valueToJava2D(
192 value1.doubleValue(), dataArea, rangeAxisLocation);
193
194 if (java2dValue1 < java2dValue0) {
195 double temp = java2dValue1;
196 java2dValue1 = java2dValue0;
197 java2dValue0 = temp;
198 Number tempNum = value1;
199 value1 = value0;
200 value0 = tempNum;
201 }
202
203 // BAR WIDTH
204 double rectWidth = state.getBarWidth();
205
206 // BAR HEIGHT
207 double rectHeight = Math.abs(java2dValue1 - java2dValue0);
208
209 if (orientation == PlotOrientation.HORIZONTAL) {
210 // BAR Y
211 rectY = domainAxis.getCategoryStart(
212 column, getColumnCount(), dataArea, domainAxisLocation
213 );
214 if (seriesCount > 1) {
215 double seriesGap = dataArea.getHeight() * getItemMargin()
216 / (categoryCount * (seriesCount - 1));
217 rectY = rectY + row * (state.getBarWidth() + seriesGap);
218 }
219 else {
220 rectY = rectY + row * state.getBarWidth();
221 }
222
223 rectX = java2dValue0;
224
225 rectHeight = state.getBarWidth();
226 rectWidth = Math.abs(java2dValue1 - java2dValue0);
227
228 }
229 else if (orientation == PlotOrientation.VERTICAL) {
230 // BAR X
231 rectX = domainAxis.getCategoryStart(
232 column, getColumnCount(), dataArea, domainAxisLocation
233 );
234
235 if (seriesCount > 1) {
236 double seriesGap = dataArea.getWidth() * getItemMargin()
237 / (categoryCount * (seriesCount - 1));
238 rectX = rectX + row * (state.getBarWidth() + seriesGap);
239 }
240 else {
241 rectX = rectX + row * state.getBarWidth();
242 }
243
244 rectY = java2dValue0;
245
246 }
247 Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
248 rectHeight);
249 Paint seriesPaint = getItemPaint(row, column);
250 g2.setPaint(seriesPaint);
251 g2.fill(bar);
252
253 // draw the outline...
254 if (state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
255 Stroke stroke = getItemOutlineStroke(row, column);
256 Paint paint = getItemOutlinePaint(row, column);
257 if (stroke != null && paint != null) {
258 g2.setStroke(stroke);
259 g2.setPaint(paint);
260 g2.draw(bar);
261 }
262 }
263
264 CategoryItemLabelGenerator generator
265 = getItemLabelGenerator(row, column);
266 if (generator != null && isItemLabelVisible(row, column)) {
267 drawItemLabel(g2, dataset, row, column, plot, generator, bar,
268 false);
269 }
270
271 // collect entity and tool tip information...
272 if (state.getInfo() != null) {
273 EntityCollection entities = state.getEntityCollection();
274 if (entities != null) {
275 String tip = null;
276 CategoryToolTipGenerator tipster
277 = getToolTipGenerator(row, column);
278 if (tipster != null) {
279 tip = tipster.generateToolTip(dataset, row, column);
280 }
281 String url = null;
282 if (getItemURLGenerator(row, column) != null) {
283 url = getItemURLGenerator(row, column).generateURL(
284 dataset, row, column);
285 }
286 CategoryItemEntity entity = new CategoryItemEntity(bar, tip,
287 url, dataset, row, dataset.getColumnKey(column),
288 column);
289 entities.add(entity);
290 }
291 }
292
293 }
294
295 }