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 }