001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2014, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * ------------------------ 028 * IntervalBarRenderer.java 029 * ------------------------ 030 * (C) Copyright 2002-2014, 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, 2791407); 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 * 16-May-2009 : The findRangeBounds() method needs to include the dataset 063 * interval (DG); 064 * 19-May-2009 : Fixed FindBugs warnings, patch by Michal Wozniak (DG); 065 * 30-Oct-2011 : Fixed alignment when setMaximumBarWidth is applied (DG); 066 */ 067 068package org.jfree.chart.renderer.category; 069 070import java.awt.Graphics2D; 071import java.awt.geom.Rectangle2D; 072 073import org.jfree.chart.axis.CategoryAxis; 074import org.jfree.chart.axis.ValueAxis; 075import org.jfree.chart.entity.EntityCollection; 076import org.jfree.chart.labels.CategoryItemLabelGenerator; 077import org.jfree.chart.plot.CategoryPlot; 078import org.jfree.chart.plot.PlotOrientation; 079import org.jfree.data.Range; 080import org.jfree.data.category.CategoryDataset; 081import org.jfree.data.category.IntervalCategoryDataset; 082import org.jfree.ui.RectangleEdge; 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. This renderer is for use with the 087 * {@link CategoryPlot} class. The example shown here is generated by the 088 * <code>IntervalBarChartDemo1.java</code> program included in the JFreeChart 089 * Demo Collection: 090 * <br><br> 091 * <img src="../../../../../images/IntervalBarRendererSample.png" 092 * alt="IntervalBarRendererSample.png"> 093 */ 094public class IntervalBarRenderer extends BarRenderer { 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 * Returns the range of values from the specified dataset. For this 108 * renderer, this is equivalent to calling 109 * <code>findRangeBounds(dataset, true)</code>. 110 * 111 * @param dataset the dataset (<code>null</code> permitted). 112 * 113 * @return The range (or <code>null</code> if the dataset is 114 * <code>null</code> or empty). 115 */ 116 @Override 117 public Range findRangeBounds(CategoryDataset dataset) { 118 return findRangeBounds(dataset, true); 119 } 120 121 /** 122 * Draws the bar for a single (series, category) data item. 123 * 124 * @param g2 the graphics device. 125 * @param state the renderer state. 126 * @param dataArea the data area. 127 * @param plot the plot. 128 * @param domainAxis the domain axis. 129 * @param rangeAxis the range axis. 130 * @param dataset the dataset. 131 * @param row the row index (zero-based). 132 * @param column the column index (zero-based). 133 * @param pass the pass index. 134 */ 135 @Override 136 public void drawItem(Graphics2D g2, CategoryItemRendererState state, 137 Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, 138 ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, 139 int pass) { 140 141 if (dataset instanceof IntervalCategoryDataset) { 142 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset; 143 drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis, 144 d, row, column); 145 } 146 else { 147 super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis, 148 dataset, row, column, pass); 149 } 150 151 } 152 153 /** 154 * Draws a single interval. 155 * 156 * @param g2 the graphics device. 157 * @param state the renderer state. 158 * @param dataArea the data plot area. 159 * @param plot the plot. 160 * @param domainAxis the domain axis. 161 * @param rangeAxis the range axis. 162 * @param dataset the data. 163 * @param row the row index (zero-based). 164 * @param column the column index (zero-based). 165 */ 166 protected void drawInterval(Graphics2D g2, 167 CategoryItemRendererState state, 168 Rectangle2D dataArea, 169 CategoryPlot plot, 170 CategoryAxis domainAxis, 171 ValueAxis rangeAxis, 172 IntervalCategoryDataset dataset, 173 int row, 174 int column) { 175 176 int visibleRow = state.getVisibleSeriesIndex(row); 177 if (visibleRow < 0) { 178 return; 179 } 180 181 PlotOrientation orientation = plot.getOrientation(); 182 double rectX = 0.0; 183 double rectY = 0.0; 184 185 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); 186 187 // Y0 188 Number value0 = dataset.getEndValue(row, column); 189 if (value0 == null) { 190 return; 191 } 192 double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(), 193 dataArea, rangeAxisLocation); 194 195 // Y1 196 Number value1 = dataset.getStartValue(row, column); 197 if (value1 == null) { 198 return; 199 } 200 double java2dValue1 = rangeAxis.valueToJava2D( 201 value1.doubleValue(), dataArea, rangeAxisLocation); 202 203 if (java2dValue1 < java2dValue0) { 204 double temp = java2dValue1; 205 java2dValue1 = java2dValue0; 206 java2dValue0 = temp; 207 } 208 209 // BAR WIDTH 210 double rectWidth = state.getBarWidth(); 211 212 // BAR HEIGHT 213 double rectHeight = Math.abs(java2dValue1 - java2dValue0); 214 215 RectangleEdge barBase = RectangleEdge.LEFT; 216 if (orientation == PlotOrientation.HORIZONTAL) { 217 // BAR Y 218 rectX = java2dValue0; 219 rectY = calculateBarW0(getPlot(), orientation, dataArea, 220 domainAxis, state, visibleRow, column); 221 rectHeight = state.getBarWidth(); 222 rectWidth = Math.abs(java2dValue1 - java2dValue0); 223 barBase = RectangleEdge.LEFT; 224 } 225 else if (orientation == PlotOrientation.VERTICAL) { 226 // BAR X 227 rectX = calculateBarW0(getPlot(), orientation, dataArea, 228 domainAxis, state, visibleRow, column); 229 rectY = java2dValue0; 230 barBase = RectangleEdge.BOTTOM; 231 } 232 Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth, 233 rectHeight); 234 BarPainter painter = getBarPainter(); 235 if (getShadowsVisible()) { 236 painter.paintBarShadow(g2, this, row, column, bar, barBase, false); 237 } 238 getBarPainter().paintBar(g2, this, row, column, bar, barBase); 239 240 CategoryItemLabelGenerator generator = getItemLabelGenerator(row, 241 column); 242 if (generator != null && isItemLabelVisible(row, column)) { 243 drawItemLabel(g2, dataset, row, column, plot, generator, bar, 244 false); 245 } 246 247 // add an item entity, if this information is being collected 248 EntityCollection entities = state.getEntityCollection(); 249 if (entities != null) { 250 addItemEntity(entities, dataset, row, column, bar); 251 } 252 253 } 254 255 /** 256 * Tests this renderer for equality with an arbitrary object. 257 * 258 * @param obj the object (<code>null</code> permitted). 259 * 260 * @return A boolean. 261 */ 262 @Override 263 public boolean equals(Object obj) { 264 if (obj == this) { 265 return true; 266 } 267 if (!(obj instanceof IntervalBarRenderer)) { 268 return false; 269 } 270 // there are no fields to check 271 return super.equals(obj); 272 } 273 274}