001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, 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-2008, by Jeremy Bowman.
031 *
032 * Original Author: Jeremy Bowman;
033 * Contributor(s): David Gilbert (for Object Refinery Limited);
034 * Christian W. Zuckschwerdt;
035 *
036 * Changes
037 * -------
038 * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG);
039 * 11-May-2002 : Use CategoryPlot.getLabelsVisible() (JB);
040 * 29-May-2002 : Added constructors (DG);
041 * 26-Jun-2002 : Added axis to initialise method (DG);
042 * 20-Sep-2002 : Added basic support for chart entities (DG);
043 * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and
044 * CategoryToolTipGenerator interface (DG);
045 * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
046 * 25-Mar-2003 : Implemented Serializable (DG);
047 * 30-Jul-2003 : Modified entity constructor (CZ);
048 * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
049 * 08-Sep-2003 : Added checks for null values (DG);
050 * 07-Oct-2003 : Added renderer state (DG);
051 * 21-Oct-2003 : Bar width moved into renderer state (DG);
052 * 23-Dec-2003 : Removed the deprecated MultiIntervalCategoryDataset
053 * interface (DG);
054 * 05-Nov-2004 : Modified drawItem() signature (DG);
055 * 20-Apr-2005 : Renamed CategoryLabelGenerator
056 * --> CategoryItemLabelGenerator (DG);
057 * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
058 *
059 */
060
061 package org.jfree.chart.renderer.category;
062
063 import java.awt.Graphics2D;
064 import java.awt.Paint;
065 import java.awt.Stroke;
066 import java.awt.geom.Rectangle2D;
067 import java.io.Serializable;
068
069 import org.jfree.chart.axis.CategoryAxis;
070 import org.jfree.chart.axis.ValueAxis;
071 import org.jfree.chart.entity.EntityCollection;
072 import org.jfree.chart.labels.CategoryItemLabelGenerator;
073 import org.jfree.chart.plot.CategoryPlot;
074 import org.jfree.chart.plot.PlotOrientation;
075 import org.jfree.data.category.CategoryDataset;
076 import org.jfree.data.category.IntervalCategoryDataset;
077 import org.jfree.ui.RectangleEdge;
078 import org.jfree.util.PublicCloneable;
079
080 /**
081 * A renderer that handles the drawing of bars for a bar plot where
082 * each bar has a high and low value.
083 * <p>
084 * For use with the {@link CategoryPlot} class.
085 */
086 public class IntervalBarRenderer extends BarRenderer
087 implements CategoryItemRenderer, Cloneable, PublicCloneable,
088 Serializable {
089
090 /** For serialization. */
091 private static final long serialVersionUID = -5068857361615528725L;
092
093 /**
094 * Constructs a new renderer.
095 */
096 public IntervalBarRenderer() {
097 super();
098 }
099
100 /**
101 * Draws the bar for a single (series, category) data item.
102 *
103 * @param g2 the graphics device.
104 * @param state the renderer state.
105 * @param dataArea the data area.
106 * @param plot the plot.
107 * @param domainAxis the domain axis.
108 * @param rangeAxis the range axis.
109 * @param dataset the dataset.
110 * @param row the row index (zero-based).
111 * @param column the column index (zero-based).
112 * @param pass the pass index.
113 */
114 public void drawItem(Graphics2D g2,
115 CategoryItemRendererState state,
116 Rectangle2D dataArea,
117 CategoryPlot plot,
118 CategoryAxis domainAxis,
119 ValueAxis rangeAxis,
120 CategoryDataset dataset,
121 int row,
122 int column,
123 int pass) {
124
125 if (dataset instanceof IntervalCategoryDataset) {
126 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
127 drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis,
128 d, row, column);
129 }
130 else {
131 super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
132 dataset, row, column, pass);
133 }
134
135 }
136
137 /**
138 * Draws a single interval.
139 *
140 * @param g2 the graphics device.
141 * @param state the renderer state.
142 * @param dataArea the data plot area.
143 * @param plot the plot.
144 * @param domainAxis the domain axis.
145 * @param rangeAxis the range axis.
146 * @param dataset the data.
147 * @param row the row index (zero-based).
148 * @param column the column index (zero-based).
149 */
150 protected void drawInterval(Graphics2D g2,
151 CategoryItemRendererState state,
152 Rectangle2D dataArea,
153 CategoryPlot plot,
154 CategoryAxis domainAxis,
155 ValueAxis rangeAxis,
156 IntervalCategoryDataset dataset,
157 int row,
158 int column) {
159
160 int seriesCount = getRowCount();
161 int categoryCount = getColumnCount();
162
163 PlotOrientation orientation = plot.getOrientation();
164
165 double rectX = 0.0;
166 double rectY = 0.0;
167
168 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
169 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
170
171 // Y0
172 Number value0 = dataset.getEndValue(row, column);
173 if (value0 == null) {
174 return;
175 }
176 double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(),
177 dataArea, rangeAxisLocation);
178
179 // Y1
180 Number value1 = dataset.getStartValue(row, column);
181 if (value1 == null) {
182 return;
183 }
184 double java2dValue1 = rangeAxis.valueToJava2D(
185 value1.doubleValue(), dataArea, rangeAxisLocation);
186
187 if (java2dValue1 < java2dValue0) {
188 double temp = java2dValue1;
189 java2dValue1 = java2dValue0;
190 java2dValue0 = temp;
191 Number tempNum = value1;
192 value1 = value0;
193 value0 = tempNum;
194 }
195
196 // BAR WIDTH
197 double rectWidth = state.getBarWidth();
198
199 // BAR HEIGHT
200 double rectHeight = Math.abs(java2dValue1 - java2dValue0);
201
202 if (orientation == PlotOrientation.HORIZONTAL) {
203 // BAR Y
204 rectY = domainAxis.getCategoryStart(column, getColumnCount(),
205 dataArea, domainAxisLocation);
206 if (seriesCount > 1) {
207 double seriesGap = dataArea.getHeight() * getItemMargin()
208 / (categoryCount * (seriesCount - 1));
209 rectY = rectY + row * (state.getBarWidth() + seriesGap);
210 }
211 else {
212 rectY = rectY + row * state.getBarWidth();
213 }
214
215 rectX = java2dValue0;
216
217 rectHeight = state.getBarWidth();
218 rectWidth = Math.abs(java2dValue1 - java2dValue0);
219
220 }
221 else if (orientation == PlotOrientation.VERTICAL) {
222 // BAR X
223 rectX = domainAxis.getCategoryStart(column, getColumnCount(),
224 dataArea, domainAxisLocation);
225
226 if (seriesCount > 1) {
227 double seriesGap = dataArea.getWidth() * getItemMargin()
228 / (categoryCount * (seriesCount - 1));
229 rectX = rectX + row * (state.getBarWidth() + seriesGap);
230 }
231 else {
232 rectX = rectX + row * state.getBarWidth();
233 }
234
235 rectY = java2dValue0;
236
237 }
238 Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
239 rectHeight);
240 Paint seriesPaint = getItemPaint(row, column);
241 g2.setPaint(seriesPaint);
242 g2.fill(bar);
243
244 // draw the outline...
245 if (state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
246 Stroke stroke = getItemOutlineStroke(row, column);
247 Paint paint = getItemOutlinePaint(row, column);
248 if (stroke != null && paint != null) {
249 g2.setStroke(stroke);
250 g2.setPaint(paint);
251 g2.draw(bar);
252 }
253 }
254
255 CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
256 column);
257 if (generator != null && isItemLabelVisible(row, column)) {
258 drawItemLabel(g2, dataset, row, column, plot, generator, bar,
259 false);
260 }
261
262 // add an item entity, if this information is being collected
263 EntityCollection entities = state.getEntityCollection();
264 if (entities != null) {
265 addItemEntity(entities, dataset, row, column, bar);
266 }
267
268 }
269
270 }