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-2007, 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-2007, 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.CategoryItemEntity;
  72: import org.jfree.chart.entity.EntityCollection;
  73: import org.jfree.chart.labels.CategoryItemLabelGenerator;
  74: import org.jfree.chart.labels.CategoryToolTipGenerator;
  75: import org.jfree.chart.plot.CategoryPlot;
  76: import org.jfree.chart.plot.PlotOrientation;
  77: import org.jfree.data.category.CategoryDataset;
  78: import org.jfree.data.category.IntervalCategoryDataset;
  79: import org.jfree.ui.RectangleEdge;
  80: import org.jfree.util.PublicCloneable;
  81: 
  82: /**
  83:  * A renderer that handles the drawing of bars for a bar plot where
  84:  * each bar has a high and low value.
  85:  * <p>
  86:  * For use with the {@link CategoryPlot} class.
  87:  */
  88: public class IntervalBarRenderer extends BarRenderer
  89:                                  implements CategoryItemRenderer, 
  90:                                             Cloneable, 
  91:                                             PublicCloneable, 
  92:                                             Serializable {
  93: 
  94:     /** For serialization. */
  95:     private static final long serialVersionUID = -5068857361615528725L;
  96:     
  97:     /**
  98:      * Constructs a new renderer.
  99:      */
 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: }