001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * ------------------- 028 * XYStepRenderer.java 029 * ------------------- 030 * (C) Copyright 2002-2007, by Roger Studner and Contributors. 031 * 032 * Original Author: Roger Studner; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * Matthias Rose; 035 * Gerald Struck (fix for bug 1569094); 036 * 037 * $Id: XYStepRenderer.java,v 1.7.2.6 2007/02/06 16:29:11 mungady Exp $ 038 * 039 * Changes 040 * ------- 041 * 13-May-2002 : Version 1, contributed by Roger Studner (DG); 042 * 25-Jun-2002 : Updated import statements (DG); 043 * 22-Jul-2002 : Added check for null data items (DG); 044 * 25-Mar-2003 : Implemented Serializable (DG); 045 * 01-May-2003 : Modified drawItem() method signature (DG); 046 * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG); 047 * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG); 048 * 28-Oct-2003 : Added tooltips, code contributed by Matthias Rose 049 * (RFE 824857) (DG); 050 * 10-Feb-2004 : Removed working line (use line from state object instead) (DG); 051 * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState. Renamed 052 * XYToolTipGenerator --> XYItemLabelGenerator (DG); 053 * 19-Jan-2005 : Now accesses only primitives from dataset (DG); 054 * 15-Mar-2005 : Fix silly bug in drawItem() method (DG); 055 * 19-Sep-2005 : Extend XYLineAndShapeRenderer (fixes legend shapes), added 056 * support for series visibility, and use getDefaultEntityRadius() 057 * for entity hotspot size (DG); 058 * ------------- JFREECHART 1.0.x --------------------------------------------- 059 * 15-Jun-2006 : Added basic support for item labels (DG); 060 * 11-Oct-2006 : Fixed rendering with horizontal orientation (see bug 1569094), 061 * thanks to Gerald Struck (DG); 062 * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG); 063 * 064 */ 065 066 package org.jfree.chart.renderer.xy; 067 068 import java.awt.Graphics2D; 069 import java.awt.Paint; 070 import java.awt.Shape; 071 import java.awt.Stroke; 072 import java.awt.geom.Line2D; 073 import java.awt.geom.Rectangle2D; 074 import java.io.Serializable; 075 076 import org.jfree.chart.axis.ValueAxis; 077 import org.jfree.chart.entity.EntityCollection; 078 import org.jfree.chart.entity.XYItemEntity; 079 import org.jfree.chart.labels.XYToolTipGenerator; 080 import org.jfree.chart.plot.CrosshairState; 081 import org.jfree.chart.plot.PlotOrientation; 082 import org.jfree.chart.plot.PlotRenderingInfo; 083 import org.jfree.chart.plot.XYPlot; 084 import org.jfree.chart.urls.XYURLGenerator; 085 import org.jfree.data.xy.XYDataset; 086 import org.jfree.ui.RectangleEdge; 087 import org.jfree.util.PublicCloneable; 088 089 /** 090 * Line/Step item renderer for an {@link XYPlot}. This class draws lines 091 * between data points, only allowing horizontal or vertical lines (steps). 092 */ 093 public class XYStepRenderer extends XYLineAndShapeRenderer 094 implements XYItemRenderer, 095 Cloneable, 096 PublicCloneable, 097 Serializable { 098 099 /** 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 }