Source for org.jfree.chart.renderer.category.IntervalBarRenderer

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it
  10:  * under the terms of the GNU Lesser General Public License as published by
  11:  * the Free Software Foundation; either version 2.1 of the License, or
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  22:  * USA.
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  25:  * in the United States and other countries.]
  26:  *
  27:  * ------------------------
  28:  * IntervalBarRenderer.java
  29:  * ------------------------
  30:  * (C) Copyright 2002-2008, by Jeremy Bowman.
  31:  *
  32:  * Original Author:  Jeremy Bowman;
  33:  * Contributor(s):   David Gilbert (for Object Refinery Limited);
  34:  *                   Christian W. Zuckschwerdt;
  35:  *
  36:  * Changes
  37:  * -------
  38:  * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG);
  39:  * 11-May-2002 : Use CategoryPlot.getLabelsVisible() (JB);
  40:  * 29-May-2002 : Added constructors (DG);
  41:  * 26-Jun-2002 : Added axis to initialise method (DG);
  42:  * 20-Sep-2002 : Added basic support for chart entities (DG);
  43:  * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and
  44:  *               CategoryToolTipGenerator interface (DG);
  45:  * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
  46:  * 25-Mar-2003 : Implemented Serializable (DG);
  47:  * 30-Jul-2003 : Modified entity constructor (CZ);
  48:  * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
  49:  * 08-Sep-2003 : Added checks for null values (DG);
  50:  * 07-Oct-2003 : Added renderer state (DG);
  51:  * 21-Oct-2003 : Bar width moved into renderer state (DG);
  52:  * 23-Dec-2003 : Removed the deprecated MultiIntervalCategoryDataset
  53:  *               interface (DG);
  54:  * 05-Nov-2004 : Modified drawItem() signature (DG);
  55:  * 20-Apr-2005 : Renamed CategoryLabelGenerator
  56:  *               --> CategoryItemLabelGenerator (DG);
  57:  * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
  58:  *
  59:  */
  60: 
  61: package org.jfree.chart.renderer.category;
  62: 
  63: import java.awt.Graphics2D;
  64: import java.awt.Paint;
  65: import java.awt.Stroke;
  66: import java.awt.geom.Rectangle2D;
  67: import java.io.Serializable;
  68: 
  69: import org.jfree.chart.axis.CategoryAxis;
  70: import org.jfree.chart.axis.ValueAxis;
  71: import org.jfree.chart.entity.EntityCollection;
  72: import org.jfree.chart.labels.CategoryItemLabelGenerator;
  73: import org.jfree.chart.plot.CategoryPlot;
  74: import org.jfree.chart.plot.PlotOrientation;
  75: import org.jfree.data.category.CategoryDataset;
  76: import org.jfree.data.category.IntervalCategoryDataset;
  77: import org.jfree.ui.RectangleEdge;
  78: import org.jfree.util.PublicCloneable;
  79: 
  80: /**
  81:  * A renderer that handles the drawing of bars for a bar plot where
  82:  * each bar has a high and low value.
  83:  * <p>
  84:  * For use with the {@link CategoryPlot} class.
  85:  */
  86: public class IntervalBarRenderer extends BarRenderer
  87:         implements CategoryItemRenderer, Cloneable, PublicCloneable,
  88:                    Serializable {
  89: 
  90:     /** For serialization. */
  91:     private static final long serialVersionUID = -5068857361615528725L;
  92: 
  93:     /**
  94:      * Constructs a new renderer.
  95:      */
  96:     public IntervalBarRenderer() {
  97:         super();
  98:     }
  99: 
 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: }