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 }