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