001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2008, 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-2008, 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.EntityCollection; 072 import org.jfree.chart.labels.CategoryItemLabelGenerator; 073 import org.jfree.chart.plot.CategoryPlot; 074 import org.jfree.chart.plot.PlotOrientation; 075 import org.jfree.data.category.CategoryDataset; 076 import org.jfree.data.category.IntervalCategoryDataset; 077 import org.jfree.ui.RectangleEdge; 078 import org.jfree.util.PublicCloneable; 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. 083 * <p> 084 * For use with the {@link CategoryPlot} class. 085 */ 086 public class IntervalBarRenderer extends BarRenderer 087 implements CategoryItemRenderer, Cloneable, PublicCloneable, 088 Serializable { 089 090 /** For serialization. */ 091 private static final long serialVersionUID = -5068857361615528725L; 092 093 /** 094 * Constructs a new renderer. 095 */ 096 public IntervalBarRenderer() { 097 super(); 098 } 099 100 /** 101 * Draws the bar for a single (series, category) data item. 102 * 103 * @param g2 the graphics device. 104 * @param state the renderer state. 105 * @param dataArea the data area. 106 * @param plot the plot. 107 * @param domainAxis the domain axis. 108 * @param rangeAxis the range axis. 109 * @param dataset the dataset. 110 * @param row the row index (zero-based). 111 * @param column the column index (zero-based). 112 * @param pass the pass index. 113 */ 114 public void drawItem(Graphics2D g2, 115 CategoryItemRendererState state, 116 Rectangle2D dataArea, 117 CategoryPlot plot, 118 CategoryAxis domainAxis, 119 ValueAxis rangeAxis, 120 CategoryDataset dataset, 121 int row, 122 int column, 123 int pass) { 124 125 if (dataset instanceof IntervalCategoryDataset) { 126 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset; 127 drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis, 128 d, row, column); 129 } 130 else { 131 super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis, 132 dataset, row, column, pass); 133 } 134 135 } 136 137 /** 138 * Draws a single interval. 139 * 140 * @param g2 the graphics device. 141 * @param state the renderer state. 142 * @param dataArea the data plot area. 143 * @param plot the plot. 144 * @param domainAxis the domain axis. 145 * @param rangeAxis the range axis. 146 * @param dataset the data. 147 * @param row the row index (zero-based). 148 * @param column the column index (zero-based). 149 */ 150 protected void drawInterval(Graphics2D g2, 151 CategoryItemRendererState state, 152 Rectangle2D dataArea, 153 CategoryPlot plot, 154 CategoryAxis domainAxis, 155 ValueAxis rangeAxis, 156 IntervalCategoryDataset dataset, 157 int row, 158 int column) { 159 160 int seriesCount = getRowCount(); 161 int categoryCount = getColumnCount(); 162 163 PlotOrientation orientation = plot.getOrientation(); 164 165 double rectX = 0.0; 166 double rectY = 0.0; 167 168 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); 169 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); 170 171 // Y0 172 Number value0 = dataset.getEndValue(row, column); 173 if (value0 == null) { 174 return; 175 } 176 double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(), 177 dataArea, rangeAxisLocation); 178 179 // Y1 180 Number value1 = dataset.getStartValue(row, column); 181 if (value1 == null) { 182 return; 183 } 184 double java2dValue1 = rangeAxis.valueToJava2D( 185 value1.doubleValue(), dataArea, rangeAxisLocation); 186 187 if (java2dValue1 < java2dValue0) { 188 double temp = java2dValue1; 189 java2dValue1 = java2dValue0; 190 java2dValue0 = temp; 191 Number tempNum = value1; 192 value1 = value0; 193 value0 = tempNum; 194 } 195 196 // BAR WIDTH 197 double rectWidth = state.getBarWidth(); 198 199 // BAR HEIGHT 200 double rectHeight = Math.abs(java2dValue1 - java2dValue0); 201 202 if (orientation == PlotOrientation.HORIZONTAL) { 203 // BAR Y 204 rectY = domainAxis.getCategoryStart(column, getColumnCount(), 205 dataArea, domainAxisLocation); 206 if (seriesCount > 1) { 207 double seriesGap = dataArea.getHeight() * getItemMargin() 208 / (categoryCount * (seriesCount - 1)); 209 rectY = rectY + row * (state.getBarWidth() + seriesGap); 210 } 211 else { 212 rectY = rectY + row * state.getBarWidth(); 213 } 214 215 rectX = java2dValue0; 216 217 rectHeight = state.getBarWidth(); 218 rectWidth = Math.abs(java2dValue1 - java2dValue0); 219 220 } 221 else if (orientation == PlotOrientation.VERTICAL) { 222 // BAR X 223 rectX = domainAxis.getCategoryStart(column, getColumnCount(), 224 dataArea, domainAxisLocation); 225 226 if (seriesCount > 1) { 227 double seriesGap = dataArea.getWidth() * getItemMargin() 228 / (categoryCount * (seriesCount - 1)); 229 rectX = rectX + row * (state.getBarWidth() + seriesGap); 230 } 231 else { 232 rectX = rectX + row * state.getBarWidth(); 233 } 234 235 rectY = java2dValue0; 236 237 } 238 Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth, 239 rectHeight); 240 Paint seriesPaint = getItemPaint(row, column); 241 g2.setPaint(seriesPaint); 242 g2.fill(bar); 243 244 // draw the outline... 245 if (state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 246 Stroke stroke = getItemOutlineStroke(row, column); 247 Paint paint = getItemOutlinePaint(row, column); 248 if (stroke != null && paint != null) { 249 g2.setStroke(stroke); 250 g2.setPaint(paint); 251 g2.draw(bar); 252 } 253 } 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 }