001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2009, 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-2009, by Jeremy Bowman.
031 *
032 * Original Author: Jeremy Bowman;
033 * Contributor(s): David Gilbert (for Object Refinery Limited);
034 * Christian W. Zuckschwerdt;
035 * Peter Kolb (patch 2497611);
036 *
037 * Changes
038 * -------
039 * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG);
040 * 11-May-2002 : Use CategoryPlot.getLabelsVisible() (JB);
041 * 29-May-2002 : Added constructors (DG);
042 * 26-Jun-2002 : Added axis to initialise method (DG);
043 * 20-Sep-2002 : Added basic support for chart entities (DG);
044 * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and
045 * CategoryToolTipGenerator interface (DG);
046 * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
047 * 25-Mar-2003 : Implemented Serializable (DG);
048 * 30-Jul-2003 : Modified entity constructor (CZ);
049 * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
050 * 08-Sep-2003 : Added checks for null values (DG);
051 * 07-Oct-2003 : Added renderer state (DG);
052 * 21-Oct-2003 : Bar width moved into renderer state (DG);
053 * 23-Dec-2003 : Removed the deprecated MultiIntervalCategoryDataset
054 * interface (DG);
055 * 05-Nov-2004 : Modified drawItem() signature (DG);
056 * 20-Apr-2005 : Renamed CategoryLabelGenerator
057 * --> CategoryItemLabelGenerator (DG);
058 * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
059 * 24-Jun-2008 : Added new barPainter mechanism (DG);
060 * 07-Oct-2008 : Override equals() method to fix minor bug (DG);
061 * 14-Jan-2009 : Added support for seriesVisible flags (PK);
062 *
063 */
064
065 package org.jfree.chart.renderer.category;
066
067 import java.awt.Graphics2D;
068 import java.awt.geom.Rectangle2D;
069
070 import org.jfree.chart.axis.CategoryAxis;
071 import org.jfree.chart.axis.ValueAxis;
072 import org.jfree.chart.entity.EntityCollection;
073 import org.jfree.chart.labels.CategoryItemLabelGenerator;
074 import org.jfree.chart.plot.CategoryPlot;
075 import org.jfree.chart.plot.PlotOrientation;
076 import org.jfree.data.category.CategoryDataset;
077 import org.jfree.data.category.IntervalCategoryDataset;
078 import org.jfree.ui.RectangleEdge;
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. This renderer is for use with the
083 * {@link CategoryPlot} class. The example shown here is generated by the
084 * <code>IntervalBarChartDemo1.java</code> program included in the JFreeChart
085 * Demo Collection:
086 * <br><br>
087 * <img src="../../../../../images/IntervalBarRendererSample.png"
088 * alt="IntervalBarRendererSample.png" />
089 */
090 public class IntervalBarRenderer extends BarRenderer {
091
092 /** For serialization. */
093 private static final long serialVersionUID = -5068857361615528725L;
094
095 /**
096 * Constructs a new renderer.
097 */
098 public IntervalBarRenderer() {
099 super();
100 }
101
102 /**
103 * Draws the bar for a single (series, category) data item.
104 *
105 * @param g2 the graphics device.
106 * @param state the renderer state.
107 * @param dataArea the data area.
108 * @param plot the plot.
109 * @param domainAxis the domain axis.
110 * @param rangeAxis the range axis.
111 * @param dataset the dataset.
112 * @param row the row index (zero-based).
113 * @param column the column index (zero-based).
114 * @param pass the pass index.
115 */
116 public void drawItem(Graphics2D g2,
117 CategoryItemRendererState state,
118 Rectangle2D dataArea,
119 CategoryPlot plot,
120 CategoryAxis domainAxis,
121 ValueAxis rangeAxis,
122 CategoryDataset dataset,
123 int row,
124 int column,
125 int pass) {
126
127 if (dataset instanceof IntervalCategoryDataset) {
128 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
129 drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis,
130 d, row, column);
131 }
132 else {
133 super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
134 dataset, row, column, pass);
135 }
136
137 }
138
139 /**
140 * Draws a single interval.
141 *
142 * @param g2 the graphics device.
143 * @param state the renderer state.
144 * @param dataArea the data plot area.
145 * @param plot the plot.
146 * @param domainAxis the domain axis.
147 * @param rangeAxis the range axis.
148 * @param dataset the data.
149 * @param row the row index (zero-based).
150 * @param column the column index (zero-based).
151 */
152 protected void drawInterval(Graphics2D g2,
153 CategoryItemRendererState state,
154 Rectangle2D dataArea,
155 CategoryPlot plot,
156 CategoryAxis domainAxis,
157 ValueAxis rangeAxis,
158 IntervalCategoryDataset dataset,
159 int row,
160 int column) {
161
162 int visibleRow = state.getVisibleSeriesIndex(row);
163 if (visibleRow < 0) {
164 return;
165 }
166 int seriesCount = state.getVisibleSeriesCount() >= 0
167 ? state.getVisibleSeriesCount() : getRowCount();
168
169 int categoryCount = getColumnCount();
170
171 PlotOrientation orientation = plot.getOrientation();
172
173 double rectX = 0.0;
174 double rectY = 0.0;
175
176 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
177 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
178
179 // Y0
180 Number value0 = dataset.getEndValue(row, column);
181 if (value0 == null) {
182 return;
183 }
184 double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(),
185 dataArea, rangeAxisLocation);
186
187 // Y1
188 Number value1 = dataset.getStartValue(row, column);
189 if (value1 == null) {
190 return;
191 }
192 double java2dValue1 = rangeAxis.valueToJava2D(
193 value1.doubleValue(), dataArea, rangeAxisLocation);
194
195 if (java2dValue1 < java2dValue0) {
196 double temp = java2dValue1;
197 java2dValue1 = java2dValue0;
198 java2dValue0 = temp;
199 Number tempNum = value1;
200 value1 = value0;
201 value0 = tempNum;
202 }
203
204 // BAR WIDTH
205 double rectWidth = state.getBarWidth();
206
207 // BAR HEIGHT
208 double rectHeight = Math.abs(java2dValue1 - java2dValue0);
209
210 RectangleEdge barBase = RectangleEdge.LEFT;
211 if (orientation == PlotOrientation.HORIZONTAL) {
212 // BAR Y
213 rectY = domainAxis.getCategoryStart(column, getColumnCount(),
214 dataArea, domainAxisLocation);
215 if (seriesCount > 1) {
216 double seriesGap = dataArea.getHeight() * getItemMargin()
217 / (categoryCount * (seriesCount - 1));
218 rectY = rectY + visibleRow * (state.getBarWidth() + seriesGap);
219 }
220 else {
221 rectY = rectY + visibleRow * state.getBarWidth();
222 }
223
224 rectX = java2dValue0;
225
226 rectHeight = state.getBarWidth();
227 rectWidth = Math.abs(java2dValue1 - java2dValue0);
228 barBase = RectangleEdge.LEFT;
229 }
230 else if (orientation == PlotOrientation.VERTICAL) {
231 // BAR X
232 rectX = domainAxis.getCategoryStart(column, getColumnCount(),
233 dataArea, domainAxisLocation);
234
235 if (seriesCount > 1) {
236 double seriesGap = dataArea.getWidth() * getItemMargin()
237 / (categoryCount * (seriesCount - 1));
238 rectX = rectX + visibleRow * (state.getBarWidth() + seriesGap);
239 }
240 else {
241 rectX = rectX + visibleRow * state.getBarWidth();
242 }
243
244 rectY = java2dValue0;
245 barBase = RectangleEdge.BOTTOM;
246 }
247 Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
248 rectHeight);
249 BarPainter painter = getBarPainter();
250 if (getShadowsVisible()) {
251 painter.paintBarShadow(g2, this, row, column, bar, barBase, false);
252 }
253 getBarPainter().paintBar(g2, this, row, column, bar, barBase);
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 /**
271 * Tests this renderer for equality with an arbitrary object.
272 *
273 * @param obj the object (<code>null</code> permitted).
274 *
275 * @return A boolean.
276 */
277 public boolean equals(Object obj) {
278 if (obj == this) {
279 return true;
280 }
281 if (!(obj instanceof IntervalBarRenderer)) {
282 return false;
283 }
284 // there are no fields to check
285 return super.equals(obj);
286 }
287
288 }