Source for org.jfree.chart.renderer.xy.XYStepRenderer

   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:  * XYStepRenderer.java
  29:  * -------------------
  30:  * (C) Copyright 2002-2007, by Roger Studner and Contributors.
  31:  *
  32:  * Original Author:  Roger Studner;
  33:  * Contributor(s):   David Gilbert (for Object Refinery Limited);
  34:  *                   Matthias Rose;
  35:  *                   Gerald Struck (fix for bug 1569094);
  36:  *
  37:  * $Id: XYStepRenderer.java,v 1.7.2.6 2007/02/06 16:29:11 mungady Exp $
  38:  *
  39:  * Changes
  40:  * -------
  41:  * 13-May-2002 : Version 1, contributed by Roger Studner (DG);
  42:  * 25-Jun-2002 : Updated import statements (DG);
  43:  * 22-Jul-2002 : Added check for null data items (DG);
  44:  * 25-Mar-2003 : Implemented Serializable (DG);
  45:  * 01-May-2003 : Modified drawItem() method signature (DG);
  46:  * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
  47:  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
  48:  * 28-Oct-2003 : Added tooltips, code contributed by Matthias Rose 
  49:  *               (RFE 824857) (DG);
  50:  * 10-Feb-2004 : Removed working line (use line from state object instead) (DG);
  51:  * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState.  Renamed 
  52:  *               XYToolTipGenerator --> XYItemLabelGenerator (DG);
  53:  * 19-Jan-2005 : Now accesses only primitives from dataset (DG);
  54:  * 15-Mar-2005 : Fix silly bug in drawItem() method (DG);
  55:  * 19-Sep-2005 : Extend XYLineAndShapeRenderer (fixes legend shapes), added 
  56:  *               support for series visibility, and use getDefaultEntityRadius() 
  57:  *               for entity hotspot size (DG);
  58:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  59:  * 15-Jun-2006 : Added basic support for item labels (DG);
  60:  * 11-Oct-2006 : Fixed rendering with horizontal orientation (see bug 1569094),
  61:  *               thanks to Gerald Struck (DG);
  62:  * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG);
  63:  *
  64:  */
  65: 
  66: package org.jfree.chart.renderer.xy;
  67: 
  68: import java.awt.Graphics2D;
  69: import java.awt.Paint;
  70: import java.awt.Shape;
  71: import java.awt.Stroke;
  72: import java.awt.geom.Line2D;
  73: import java.awt.geom.Rectangle2D;
  74: import java.io.Serializable;
  75: 
  76: import org.jfree.chart.axis.ValueAxis;
  77: import org.jfree.chart.entity.EntityCollection;
  78: import org.jfree.chart.entity.XYItemEntity;
  79: import org.jfree.chart.labels.XYToolTipGenerator;
  80: import org.jfree.chart.plot.CrosshairState;
  81: import org.jfree.chart.plot.PlotOrientation;
  82: import org.jfree.chart.plot.PlotRenderingInfo;
  83: import org.jfree.chart.plot.XYPlot;
  84: import org.jfree.chart.urls.XYURLGenerator;
  85: import org.jfree.data.xy.XYDataset;
  86: import org.jfree.ui.RectangleEdge;
  87: import org.jfree.util.PublicCloneable;
  88: 
  89: /**
  90:  * Line/Step item renderer for an {@link XYPlot}.  This class draws lines 
  91:  * between data points, only allowing horizontal or vertical lines (steps).
  92:  */
  93: public class XYStepRenderer extends XYLineAndShapeRenderer 
  94:                             implements XYItemRenderer, 
  95:                                        Cloneable,
  96:                                        PublicCloneable,
  97:                                        Serializable {
  98: 
  99:     /** For serialization. */
 100:     private static final long serialVersionUID = -8918141928884796108L;
 101:     
 102:     /**
 103:      * Constructs a new renderer with no tooltip or URL generation.
 104:      */
 105:     public XYStepRenderer() {
 106:         this(null, null);
 107:     }
 108: 
 109:     /**
 110:      * Constructs a new renderer with the specified tool tip and URL 
 111:      * generators.
 112:      *
 113:      * @param toolTipGenerator  the item label generator (<code>null</code> 
 114:      *     permitted).
 115:      * @param urlGenerator  the URL generator (<code>null</code> permitted).
 116:      */
 117:     public XYStepRenderer(XYToolTipGenerator toolTipGenerator,
 118:                           XYURLGenerator urlGenerator) {
 119:         super();
 120:         setBaseToolTipGenerator(toolTipGenerator);
 121:         setURLGenerator(urlGenerator);
 122:         setShapesVisible(false);
 123:     }
 124: 
 125:     /**
 126:      * Draws the visual representation of a single data item.
 127:      *
 128:      * @param g2  the graphics device.
 129:      * @param state  the renderer state.
 130:      * @param dataArea  the area within which the data is being drawn.
 131:      * @param info  collects information about the drawing.
 132:      * @param plot  the plot (can be used to obtain standard color 
 133:      *              information etc).
 134:      * @param domainAxis  the domain axis.
 135:      * @param rangeAxis  the vertical axis.
 136:      * @param dataset  the dataset.
 137:      * @param series  the series index (zero-based).
 138:      * @param item  the item index (zero-based).
 139:      * @param crosshairState  crosshair information for the plot 
 140:      *                        (<code>null</code> permitted).
 141:      * @param pass  the pass index (ignored here).
 142:      */
 143:     public void drawItem(Graphics2D g2, 
 144:                          XYItemRendererState state,
 145:                          Rectangle2D dataArea, 
 146:                          PlotRenderingInfo info,
 147:                          XYPlot plot, 
 148:                          ValueAxis domainAxis, 
 149:                          ValueAxis rangeAxis,
 150:                          XYDataset dataset, 
 151:                          int series, 
 152:                          int item,
 153:                          CrosshairState crosshairState, 
 154:                          int pass) {
 155: 
 156:         // do nothing if item is not visible
 157:         if (!getItemVisible(series, item)) {
 158:             return;   
 159:         }
 160: 
 161:         PlotOrientation orientation = plot.getOrientation();
 162:         
 163:         Paint seriesPaint = getItemPaint(series, item);
 164:         Stroke seriesStroke = getItemStroke(series, item);
 165:         g2.setPaint(seriesPaint);
 166:         g2.setStroke(seriesStroke);
 167: 
 168:         // get the data point...
 169:         double x1 = dataset.getXValue(series, item);
 170:         double y1 = dataset.getYValue(series, item);
 171:         if (Double.isNaN(y1)) {
 172:             return;
 173:         }
 174: 
 175:         RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
 176:         RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
 177:         double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
 178:         double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
 179: 
 180:         if (item > 0) {
 181:             // get the previous data point...
 182:             double x0 = dataset.getXValue(series, item - 1);
 183:             double y0 = dataset.getYValue(series, item - 1);
 184:             if (!Double.isNaN(y0)) {
 185:                 double transX0 = domainAxis.valueToJava2D(x0, dataArea, 
 186:                         xAxisLocation);
 187:                 double transY0 = rangeAxis.valueToJava2D(y0, dataArea, 
 188:                         yAxisLocation);
 189: 
 190:                 Line2D line = state.workingLine;
 191:                 if (orientation == PlotOrientation.HORIZONTAL) {
 192:                     if (transY0 == transY1) { //this represents the situation 
 193:                                               // for drawing a horizontal bar.
 194:                         line.setLine(transY0, transX0, transY1, transX1);
 195:                         g2.draw(line);
 196:                     }
 197:                     else {  //this handles the need to perform a 'step'.
 198:                         line.setLine(transY0, transX0, transY0, transX1);
 199:                         g2.draw(line);
 200:                         line.setLine(transY0, transX1, transY1, transX1);
 201:                         g2.draw(line);
 202:                     }
 203:                 }
 204:                 else if (orientation == PlotOrientation.VERTICAL) {
 205:                     if (transY0 == transY1) { // this represents the situation 
 206:                                               // for drawing a horizontal bar.
 207:                         line.setLine(transX0, transY0, transX1, transY1);
 208:                         g2.draw(line);
 209:                     }
 210:                     else {  //this handles the need to perform a 'step'.
 211:                         line.setLine(transX0, transY0, transX1, transY0);
 212:                         g2.draw(line);
 213:                         line.setLine(transX1, transY0, transX1, transY1);
 214:                         g2.draw(line);
 215:                     }
 216:                 }
 217: 
 218:             }
 219:         }
 220: 
 221:         // draw the item label if there is one...
 222:         if (isItemLabelVisible(series, item)) {
 223:             double xx = transX1;
 224:             double yy = transY1;
 225:             if (orientation == PlotOrientation.HORIZONTAL) {
 226:                 xx = transY1;
 227:                 yy = transX1;
 228:             }          
 229:             drawItemLabel(g2, orientation, dataset, series, item, xx, yy, 
 230:                     (y1 < 0.0));
 231:         }
 232: 
 233:         int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
 234:         int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
 235:         updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, 
 236:                 rangeAxisIndex, transX1, transY1, orientation);
 237:         
 238:         // collect entity and tool tip information...
 239:         if (state.getInfo() != null) {
 240:             EntityCollection entities = state.getEntityCollection();
 241:             if (entities != null) {
 242:                 int r = getDefaultEntityRadius();
 243:                 Shape shape = orientation == PlotOrientation.VERTICAL
 244:                     ? new Rectangle2D.Double(transX1 - r, transY1 - r, 2 * r, 
 245:                             2 * r)
 246:                     : new Rectangle2D.Double(transY1 - r, transX1 - r, 2 * r, 
 247:                             2 * r);           
 248:                 if (shape != null) {
 249:                     String tip = null;
 250:                     XYToolTipGenerator generator 
 251:                         = getToolTipGenerator(series, item);
 252:                     if (generator != null) {
 253:                         tip = generator.generateToolTip(dataset, series, item);
 254:                     }
 255:                     String url = null;
 256:                     if (getURLGenerator() != null) {
 257:                         url = getURLGenerator().generateURL(dataset, series, 
 258:                                 item);
 259:                     }
 260:                     XYItemEntity entity = new XYItemEntity(shape, dataset, 
 261:                             series, item, tip, url);
 262:                     entities.add(entity);
 263:                 }
 264:             }
 265:         }
 266:     }
 267: 
 268:     /**
 269:      * Returns a clone of the renderer.
 270:      * 
 271:      * @return A clone.
 272:      * 
 273:      * @throws CloneNotSupportedException  if the renderer cannot be cloned.
 274:      */
 275:     public Object clone() throws CloneNotSupportedException {
 276:         return super.clone();
 277:     }
 278: 
 279: }