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-2005, 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-2005, by Jeremy Bowman.
  31:  *
  32:  * Original Author:  Jeremy Bowman;
  33:  * Contributor(s):   David Gilbert (for Object Refinery Limited);
  34:  *                   Christian W. Zuckschwerdt;
  35:  *
  36:  * $Id: IntervalBarRenderer.java,v 1.6.2.2 2005/12/01 20:33:26 mungady Exp $
  37:  *
  38:  * Changes
  39:  * -------
  40:  * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG);
  41:  * 11-May-2002 : Use CategoryPlot.getLabelsVisible() (JB);
  42:  * 29-May-2002 : Added constructors (DG);
  43:  * 26-Jun-2002 : Added axis to initialise method (DG);
  44:  * 20-Sep-2002 : Added basic support for chart entities (DG);
  45:  * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and 
  46:  *               CategoryToolTipGenerator interface (DG);
  47:  * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
  48:  * 25-Mar-2003 : Implemented Serializable (DG);
  49:  * 30-Jul-2003 : Modified entity constructor (CZ);
  50:  * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
  51:  * 08-Sep-2003 : Added checks for null values (DG);
  52:  * 07-Oct-2003 : Added renderer state (DG);
  53:  * 21-Oct-2003 : Bar width moved into renderer state (DG);
  54:  * 23-Dec-2003 : Removed the deprecated MultiIntervalCategoryDataset 
  55:  *               interface (DG);
  56:  * 05-Nov-2004 : Modified drawItem() signature (DG);
  57:  * 20-Apr-2005 : Renamed CategoryLabelGenerator 
  58:  *               --> CategoryItemLabelGenerator (DG);
  59:  * 
  60:  */
  61: 
  62: package org.jfree.chart.renderer.category;
  63: 
  64: import java.awt.Graphics2D;
  65: import java.awt.Paint;
  66: import java.awt.Stroke;
  67: import java.awt.geom.Rectangle2D;
  68: import java.io.Serializable;
  69: 
  70: import org.jfree.chart.axis.CategoryAxis;
  71: import org.jfree.chart.axis.ValueAxis;
  72: import org.jfree.chart.entity.CategoryItemEntity;
  73: import org.jfree.chart.entity.EntityCollection;
  74: import org.jfree.chart.labels.CategoryItemLabelGenerator;
  75: import org.jfree.chart.labels.CategoryToolTipGenerator;
  76: import org.jfree.chart.plot.CategoryPlot;
  77: import org.jfree.chart.plot.PlotOrientation;
  78: import org.jfree.data.category.CategoryDataset;
  79: import org.jfree.data.category.IntervalCategoryDataset;
  80: import org.jfree.ui.RectangleEdge;
  81: import org.jfree.util.PublicCloneable;
  82: 
  83: /**
  84:  * A renderer that handles the drawing of bars for a bar plot where
  85:  * each bar has a high and low value.
  86:  * <p>
  87:  * For use with the {@link CategoryPlot} class.
  88:  *
  89:  * @author Jeremy Bowman
  90:  */
  91: public class IntervalBarRenderer extends BarRenderer
  92:                                  implements CategoryItemRenderer, 
  93:                                             Cloneable, 
  94:                                             PublicCloneable, 
  95:                                             Serializable {
  96: 
  97:     /** For serialization. */
  98:     private static final long serialVersionUID = -5068857361615528725L;
  99:     
 100:     /**
 101:      * Constructs a new renderer.
 102:      */
 103:     public IntervalBarRenderer() {
 104:         super();
 105:     }
 106: 
 107:     /**
 108:      * Draws the bar for a single (series, category) data item.
 109:      *
 110:      * @param g2  the graphics device.
 111:      * @param state  the renderer state.
 112:      * @param dataArea  the data area.
 113:      * @param plot  the plot.
 114:      * @param domainAxis  the domain axis.
 115:      * @param rangeAxis  the range axis.
 116:      * @param dataset  the dataset.
 117:      * @param row  the row index (zero-based).
 118:      * @param column  the column index (zero-based).
 119:      * @param pass  the pass index.
 120:      */
 121:     public void drawItem(Graphics2D g2,
 122:                          CategoryItemRendererState state,
 123:                          Rectangle2D dataArea,
 124:                          CategoryPlot plot,
 125:                          CategoryAxis domainAxis,
 126:                          ValueAxis rangeAxis,
 127:                          CategoryDataset dataset,
 128:                          int row,
 129:                          int column,
 130:                          int pass) {
 131: 
 132:          if (dataset instanceof IntervalCategoryDataset) {
 133:              IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
 134:              drawInterval(
 135:                  g2, state, dataArea, plot, domainAxis, rangeAxis, 
 136:                  d, row, column
 137:              );
 138:          }
 139:          else {
 140:              super.drawItem(
 141:                  g2, state, dataArea, plot, domainAxis, rangeAxis, 
 142:                  dataset, row, column, pass
 143:              );
 144:          } 
 145:          
 146:      }
 147:                           
 148:      /**
 149:       * Draws a single interval.
 150:       *
 151:       * @param g2  the graphics device.
 152:       * @param state  the renderer state.
 153:       * @param dataArea  the data plot area.
 154:       * @param plot  the plot.
 155:       * @param domainAxis  the domain axis.
 156:       * @param rangeAxis  the range axis.
 157:       * @param dataset  the data.
 158:       * @param row  the row index (zero-based).
 159:       * @param column  the column index (zero-based).
 160:       */
 161:      protected void drawInterval(Graphics2D g2,
 162:                                  CategoryItemRendererState state,
 163:                                  Rectangle2D dataArea,
 164:                                  CategoryPlot plot,
 165:                                  CategoryAxis domainAxis,
 166:                                  ValueAxis rangeAxis,
 167:                                  IntervalCategoryDataset dataset,
 168:                                  int row,
 169:                                  int column) {
 170: 
 171:         int seriesCount = getRowCount();
 172:         int categoryCount = getColumnCount();
 173: 
 174:         PlotOrientation orientation = plot.getOrientation();
 175:         
 176:         double rectX = 0.0;
 177:         double rectY = 0.0;
 178: 
 179:         RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
 180:         RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
 181:         
 182:         // Y0
 183:         Number value0 = dataset.getEndValue(row, column);
 184:         if (value0 == null) {
 185:             return;
 186:         }
 187:         double java2dValue0 = rangeAxis.valueToJava2D(
 188:             value0.doubleValue(), dataArea, rangeAxisLocation
 189:         );
 190: 
 191:         // Y1
 192:         Number value1 = dataset.getStartValue(row, column);
 193:         if (value1 == null) {
 194:             return;
 195:         }
 196:         double java2dValue1 = rangeAxis.valueToJava2D(
 197:             value1.doubleValue(), dataArea, rangeAxisLocation
 198:         );
 199: 
 200:         if (java2dValue1 < java2dValue0) {
 201:             double temp = java2dValue1;
 202:             java2dValue1 = java2dValue0;
 203:             java2dValue0 = temp;
 204:             Number tempNum = value1;
 205:             value1 = value0;
 206:             value0 = tempNum;
 207:         }
 208: 
 209:         // BAR WIDTH
 210:         double rectWidth = state.getBarWidth();
 211: 
 212:         // BAR HEIGHT
 213:         double rectHeight = Math.abs(java2dValue1 - java2dValue0);
 214: 
 215:         if (orientation == PlotOrientation.HORIZONTAL) {
 216:             // BAR Y
 217:             rectY = domainAxis.getCategoryStart(
 218:                 column, getColumnCount(), dataArea, domainAxisLocation
 219:             );
 220:             if (seriesCount > 1) {
 221:                 double seriesGap = dataArea.getHeight() * getItemMargin()
 222:                                    / (categoryCount * (seriesCount - 1));
 223:                 rectY = rectY + row * (state.getBarWidth() + seriesGap);
 224:             }
 225:             else {
 226:                 rectY = rectY + row * state.getBarWidth();
 227:             }
 228:             
 229:             rectX = java2dValue0;
 230: 
 231:             rectHeight = state.getBarWidth();
 232:             rectWidth = Math.abs(java2dValue1 - java2dValue0);
 233: 
 234:         }
 235:         else if (orientation == PlotOrientation.VERTICAL) {
 236:             // BAR X
 237:             rectX = domainAxis.getCategoryStart(
 238:                 column, getColumnCount(), dataArea, domainAxisLocation
 239:             );
 240: 
 241:             if (seriesCount > 1) {
 242:                 double seriesGap = dataArea.getWidth() * getItemMargin()
 243:                                    / (categoryCount * (seriesCount - 1));
 244:                 rectX = rectX + row * (state.getBarWidth() + seriesGap);
 245:             }
 246:             else {
 247:                 rectX = rectX + row * state.getBarWidth();
 248:             }
 249: 
 250:             rectY = java2dValue0;
 251: 
 252:         }
 253:         Rectangle2D bar = new Rectangle2D.Double(
 254:             rectX, rectY, rectWidth, rectHeight
 255:         );
 256:         Paint seriesPaint = getItemPaint(row, column);
 257:         g2.setPaint(seriesPaint);
 258:         g2.fill(bar);
 259:         
 260:         // draw the outline...
 261:         if (state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
 262:             Stroke stroke = getItemOutlineStroke(row, column);
 263:             Paint paint = getItemOutlinePaint(row, column);
 264:             if (stroke != null && paint != null) {
 265:                 g2.setStroke(stroke);
 266:                 g2.setPaint(paint);
 267:                 g2.draw(bar);
 268:             }
 269:         }
 270:         
 271:         CategoryItemLabelGenerator generator 
 272:             = getItemLabelGenerator(row, column);
 273:         if (generator != null && isItemLabelVisible(row, column)) {
 274:             drawItemLabel(
 275:                 g2, dataset, row, column, plot, generator, bar, false
 276:             );
 277:         }        
 278: 
 279:         // collect entity and tool tip information...
 280:         if (state.getInfo() != null) {
 281:             EntityCollection entities = state.getEntityCollection();
 282:             if (entities != null) {
 283:                 String tip = null;
 284:                 CategoryToolTipGenerator tipster 
 285:                     = getToolTipGenerator(row, column);
 286:                 if (tipster != null) {
 287:                     tip = tipster.generateToolTip(dataset, row, column);
 288:                 }
 289:                 String url = null;
 290:                 if (getItemURLGenerator(row, column) != null) {
 291:                     url = getItemURLGenerator(row, column).generateURL(
 292:                         dataset, row, column
 293:                     );
 294:                 }
 295:                 CategoryItemEntity entity = new CategoryItemEntity(
 296:                     bar, tip, url, dataset, row, 
 297:                     dataset.getColumnKey(column), column
 298:                 );
 299:                 entities.add(entity);
 300:             }
 301:         }
 302: 
 303:     }
 304: 
 305: }