001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, 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-2005, 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.2 2005/12/01 20:33:26 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 * 060 */ 061 062 package org.jfree.chart.renderer.category; 063 064 import java.awt.Graphics2D; 065 import java.awt.Paint; 066 import java.awt.Stroke; 067 import java.awt.geom.Rectangle2D; 068 import java.io.Serializable; 069 070 import org.jfree.chart.axis.CategoryAxis; 071 import org.jfree.chart.axis.ValueAxis; 072 import org.jfree.chart.entity.CategoryItemEntity; 073 import org.jfree.chart.entity.EntityCollection; 074 import org.jfree.chart.labels.CategoryItemLabelGenerator; 075 import org.jfree.chart.labels.CategoryToolTipGenerator; 076 import org.jfree.chart.plot.CategoryPlot; 077 import org.jfree.chart.plot.PlotOrientation; 078 import org.jfree.data.category.CategoryDataset; 079 import org.jfree.data.category.IntervalCategoryDataset; 080 import org.jfree.ui.RectangleEdge; 081 import org.jfree.util.PublicCloneable; 082 083 /** 084 * A renderer that handles the drawing of bars for a bar plot where 085 * each bar has a high and low value. 086 * <p> 087 * For use with the {@link CategoryPlot} class. 088 * 089 * @author Jeremy Bowman 090 */ 091 public class IntervalBarRenderer extends BarRenderer 092 implements CategoryItemRenderer, 093 Cloneable, 094 PublicCloneable, 095 Serializable { 096 097 /** For serialization. */ 098 private static final long serialVersionUID = -5068857361615528725L; 099 100 /** 101 * Constructs a new renderer. 102 */ 103 public IntervalBarRenderer() { 104 super(); 105 } 106 107 /** 108 * Draws the bar for a single (series, category) data item. 109 * 110 * @param g2 the graphics device. 111 * @param state the renderer state. 112 * @param dataArea the data area. 113 * @param plot the plot. 114 * @param domainAxis the domain axis. 115 * @param rangeAxis the range axis. 116 * @param dataset the dataset. 117 * @param row the row index (zero-based). 118 * @param column the column index (zero-based). 119 * @param pass the pass index. 120 */ 121 public void drawItem(Graphics2D g2, 122 CategoryItemRendererState state, 123 Rectangle2D dataArea, 124 CategoryPlot plot, 125 CategoryAxis domainAxis, 126 ValueAxis rangeAxis, 127 CategoryDataset dataset, 128 int row, 129 int column, 130 int pass) { 131 132 if (dataset instanceof IntervalCategoryDataset) { 133 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset; 134 drawInterval( 135 g2, state, dataArea, plot, domainAxis, rangeAxis, 136 d, row, column 137 ); 138 } 139 else { 140 super.drawItem( 141 g2, state, dataArea, plot, domainAxis, rangeAxis, 142 dataset, row, column, pass 143 ); 144 } 145 146 } 147 148 /** 149 * Draws a single interval. 150 * 151 * @param g2 the graphics device. 152 * @param state the renderer state. 153 * @param dataArea the data plot area. 154 * @param plot the plot. 155 * @param domainAxis the domain axis. 156 * @param rangeAxis the range axis. 157 * @param dataset the data. 158 * @param row the row index (zero-based). 159 * @param column the column index (zero-based). 160 */ 161 protected void drawInterval(Graphics2D g2, 162 CategoryItemRendererState state, 163 Rectangle2D dataArea, 164 CategoryPlot plot, 165 CategoryAxis domainAxis, 166 ValueAxis rangeAxis, 167 IntervalCategoryDataset dataset, 168 int row, 169 int column) { 170 171 int seriesCount = getRowCount(); 172 int categoryCount = getColumnCount(); 173 174 PlotOrientation orientation = plot.getOrientation(); 175 176 double rectX = 0.0; 177 double rectY = 0.0; 178 179 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); 180 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); 181 182 // Y0 183 Number value0 = dataset.getEndValue(row, column); 184 if (value0 == null) { 185 return; 186 } 187 double java2dValue0 = rangeAxis.valueToJava2D( 188 value0.doubleValue(), dataArea, rangeAxisLocation 189 ); 190 191 // Y1 192 Number value1 = dataset.getStartValue(row, column); 193 if (value1 == null) { 194 return; 195 } 196 double java2dValue1 = rangeAxis.valueToJava2D( 197 value1.doubleValue(), dataArea, rangeAxisLocation 198 ); 199 200 if (java2dValue1 < java2dValue0) { 201 double temp = java2dValue1; 202 java2dValue1 = java2dValue0; 203 java2dValue0 = temp; 204 Number tempNum = value1; 205 value1 = value0; 206 value0 = tempNum; 207 } 208 209 // BAR WIDTH 210 double rectWidth = state.getBarWidth(); 211 212 // BAR HEIGHT 213 double rectHeight = Math.abs(java2dValue1 - java2dValue0); 214 215 if (orientation == PlotOrientation.HORIZONTAL) { 216 // BAR Y 217 rectY = domainAxis.getCategoryStart( 218 column, getColumnCount(), dataArea, domainAxisLocation 219 ); 220 if (seriesCount > 1) { 221 double seriesGap = dataArea.getHeight() * getItemMargin() 222 / (categoryCount * (seriesCount - 1)); 223 rectY = rectY + row * (state.getBarWidth() + seriesGap); 224 } 225 else { 226 rectY = rectY + row * state.getBarWidth(); 227 } 228 229 rectX = java2dValue0; 230 231 rectHeight = state.getBarWidth(); 232 rectWidth = Math.abs(java2dValue1 - java2dValue0); 233 234 } 235 else if (orientation == PlotOrientation.VERTICAL) { 236 // BAR X 237 rectX = domainAxis.getCategoryStart( 238 column, getColumnCount(), dataArea, domainAxisLocation 239 ); 240 241 if (seriesCount > 1) { 242 double seriesGap = dataArea.getWidth() * getItemMargin() 243 / (categoryCount * (seriesCount - 1)); 244 rectX = rectX + row * (state.getBarWidth() + seriesGap); 245 } 246 else { 247 rectX = rectX + row * state.getBarWidth(); 248 } 249 250 rectY = java2dValue0; 251 252 } 253 Rectangle2D bar = new Rectangle2D.Double( 254 rectX, rectY, rectWidth, rectHeight 255 ); 256 Paint seriesPaint = getItemPaint(row, column); 257 g2.setPaint(seriesPaint); 258 g2.fill(bar); 259 260 // draw the outline... 261 if (state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 262 Stroke stroke = getItemOutlineStroke(row, column); 263 Paint paint = getItemOutlinePaint(row, column); 264 if (stroke != null && paint != null) { 265 g2.setStroke(stroke); 266 g2.setPaint(paint); 267 g2.draw(bar); 268 } 269 } 270 271 CategoryItemLabelGenerator generator 272 = getItemLabelGenerator(row, column); 273 if (generator != null && isItemLabelVisible(row, column)) { 274 drawItemLabel( 275 g2, dataset, row, column, plot, generator, bar, false 276 ); 277 } 278 279 // collect entity and tool tip information... 280 if (state.getInfo() != null) { 281 EntityCollection entities = state.getEntityCollection(); 282 if (entities != null) { 283 String tip = null; 284 CategoryToolTipGenerator tipster 285 = getToolTipGenerator(row, column); 286 if (tipster != null) { 287 tip = tipster.generateToolTip(dataset, row, column); 288 } 289 String url = null; 290 if (getItemURLGenerator(row, column) != null) { 291 url = getItemURLGenerator(row, column).generateURL( 292 dataset, row, column 293 ); 294 } 295 CategoryItemEntity entity = new CategoryItemEntity( 296 bar, tip, url, dataset, row, 297 dataset.getColumnKey(column), column 298 ); 299 entities.add(entity); 300 } 301 } 302 303 } 304 305 }