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