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 * Changes 038 * ------- 039 * 13-May-2002 : Version 1, contributed by Roger Studner (DG); 040 * 25-Jun-2002 : Updated import statements (DG); 041 * 22-Jul-2002 : Added check for null data items (DG); 042 * 25-Mar-2003 : Implemented Serializable (DG); 043 * 01-May-2003 : Modified drawItem() method signature (DG); 044 * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG); 045 * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG); 046 * 28-Oct-2003 : Added tooltips, code contributed by Matthias Rose 047 * (RFE 824857) (DG); 048 * 10-Feb-2004 : Removed working line (use line from state object instead) (DG); 049 * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState. Renamed 050 * XYToolTipGenerator --> XYItemLabelGenerator (DG); 051 * 19-Jan-2005 : Now accesses only primitives from dataset (DG); 052 * 15-Mar-2005 : Fix silly bug in drawItem() method (DG); 053 * 19-Sep-2005 : Extend XYLineAndShapeRenderer (fixes legend shapes), added 054 * support for series visibility, and use getDefaultEntityRadius() 055 * for entity hotspot size (DG); 056 * ------------- JFREECHART 1.0.x --------------------------------------------- 057 * 15-Jun-2006 : Added basic support for item labels (DG); 058 * 11-Oct-2006 : Fixed rendering with horizontal orientation (see bug 1569094), 059 * thanks to Gerald Struck (DG); 060 * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG); 061 * 062 */ 063 064 package org.jfree.chart.renderer.xy; 065 066 import java.awt.Graphics2D; 067 import java.awt.Paint; 068 import java.awt.Shape; 069 import java.awt.Stroke; 070 import java.awt.geom.Line2D; 071 import java.awt.geom.Rectangle2D; 072 import java.io.Serializable; 073 074 import org.jfree.chart.axis.ValueAxis; 075 import org.jfree.chart.entity.EntityCollection; 076 import org.jfree.chart.entity.XYItemEntity; 077 import org.jfree.chart.labels.XYToolTipGenerator; 078 import org.jfree.chart.plot.CrosshairState; 079 import org.jfree.chart.plot.PlotOrientation; 080 import org.jfree.chart.plot.PlotRenderingInfo; 081 import org.jfree.chart.plot.XYPlot; 082 import org.jfree.chart.urls.XYURLGenerator; 083 import org.jfree.data.xy.XYDataset; 084 import org.jfree.ui.RectangleEdge; 085 import org.jfree.util.PublicCloneable; 086 087 /** 088 * Line/Step item renderer for an {@link XYPlot}. This class draws lines 089 * between data points, only allowing horizontal or vertical lines (steps). 090 */ 091 public class XYStepRenderer extends XYLineAndShapeRenderer 092 implements XYItemRenderer, 093 Cloneable, 094 PublicCloneable, 095 Serializable { 096 097 /** For serialization. */ 098 private static final long serialVersionUID = -8918141928884796108L; 099 100 /** 101 * Constructs a new renderer with no tooltip or URL generation. 102 */ 103 public XYStepRenderer() { 104 this(null, null); 105 } 106 107 /** 108 * Constructs a new renderer with the specified tool tip and URL 109 * generators. 110 * 111 * @param toolTipGenerator the item label generator (<code>null</code> 112 * permitted). 113 * @param urlGenerator the URL generator (<code>null</code> permitted). 114 */ 115 public XYStepRenderer(XYToolTipGenerator toolTipGenerator, 116 XYURLGenerator urlGenerator) { 117 super(); 118 setBaseToolTipGenerator(toolTipGenerator); 119 setURLGenerator(urlGenerator); 120 setShapesVisible(false); 121 } 122 123 /** 124 * Draws the visual representation of a single data item. 125 * 126 * @param g2 the graphics device. 127 * @param state the renderer state. 128 * @param dataArea the area within which the data is being drawn. 129 * @param info collects information about the drawing. 130 * @param plot the plot (can be used to obtain standard color 131 * information etc). 132 * @param domainAxis the domain axis. 133 * @param rangeAxis the vertical axis. 134 * @param dataset the dataset. 135 * @param series the series index (zero-based). 136 * @param item the item index (zero-based). 137 * @param crosshairState crosshair information for the plot 138 * (<code>null</code> permitted). 139 * @param pass the pass index (ignored here). 140 */ 141 public void drawItem(Graphics2D g2, 142 XYItemRendererState state, 143 Rectangle2D dataArea, 144 PlotRenderingInfo info, 145 XYPlot plot, 146 ValueAxis domainAxis, 147 ValueAxis rangeAxis, 148 XYDataset dataset, 149 int series, 150 int item, 151 CrosshairState crosshairState, 152 int pass) { 153 154 // do nothing if item is not visible 155 if (!getItemVisible(series, item)) { 156 return; 157 } 158 159 PlotOrientation orientation = plot.getOrientation(); 160 161 Paint seriesPaint = getItemPaint(series, item); 162 Stroke seriesStroke = getItemStroke(series, item); 163 g2.setPaint(seriesPaint); 164 g2.setStroke(seriesStroke); 165 166 // get the data point... 167 double x1 = dataset.getXValue(series, item); 168 double y1 = dataset.getYValue(series, item); 169 if (Double.isNaN(y1)) { 170 return; 171 } 172 173 RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); 174 RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); 175 double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); 176 double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); 177 178 if (item > 0) { 179 // get the previous data point... 180 double x0 = dataset.getXValue(series, item - 1); 181 double y0 = dataset.getYValue(series, item - 1); 182 if (!Double.isNaN(y0)) { 183 double transX0 = domainAxis.valueToJava2D(x0, dataArea, 184 xAxisLocation); 185 double transY0 = rangeAxis.valueToJava2D(y0, dataArea, 186 yAxisLocation); 187 188 Line2D line = state.workingLine; 189 if (orientation == PlotOrientation.HORIZONTAL) { 190 if (transY0 == transY1) { //this represents the situation 191 // for drawing a horizontal bar. 192 line.setLine(transY0, transX0, transY1, transX1); 193 g2.draw(line); 194 } 195 else { //this handles the need to perform a 'step'. 196 line.setLine(transY0, transX0, transY0, transX1); 197 g2.draw(line); 198 line.setLine(transY0, transX1, transY1, transX1); 199 g2.draw(line); 200 } 201 } 202 else if (orientation == PlotOrientation.VERTICAL) { 203 if (transY0 == transY1) { // this represents the situation 204 // for drawing a horizontal bar. 205 line.setLine(transX0, transY0, transX1, transY1); 206 g2.draw(line); 207 } 208 else { //this handles the need to perform a 'step'. 209 line.setLine(transX0, transY0, transX1, transY0); 210 g2.draw(line); 211 line.setLine(transX1, transY0, transX1, transY1); 212 g2.draw(line); 213 } 214 } 215 216 } 217 } 218 219 // draw the item label if there is one... 220 if (isItemLabelVisible(series, item)) { 221 double xx = transX1; 222 double yy = transY1; 223 if (orientation == PlotOrientation.HORIZONTAL) { 224 xx = transY1; 225 yy = transX1; 226 } 227 drawItemLabel(g2, orientation, dataset, series, item, xx, yy, 228 (y1 < 0.0)); 229 } 230 231 int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); 232 int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); 233 updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, 234 rangeAxisIndex, transX1, transY1, orientation); 235 236 // collect entity and tool tip information... 237 if (state.getInfo() != null) { 238 EntityCollection entities = state.getEntityCollection(); 239 if (entities != null) { 240 int r = getDefaultEntityRadius(); 241 Shape shape = orientation == PlotOrientation.VERTICAL 242 ? new Rectangle2D.Double(transX1 - r, transY1 - r, 2 * r, 243 2 * r) 244 : new Rectangle2D.Double(transY1 - r, transX1 - r, 2 * r, 245 2 * r); 246 if (shape != null) { 247 String tip = null; 248 XYToolTipGenerator generator 249 = getToolTipGenerator(series, item); 250 if (generator != null) { 251 tip = generator.generateToolTip(dataset, series, item); 252 } 253 String url = null; 254 if (getURLGenerator() != null) { 255 url = getURLGenerator().generateURL(dataset, series, 256 item); 257 } 258 XYItemEntity entity = new XYItemEntity(shape, dataset, 259 series, item, tip, url); 260 entities.add(entity); 261 } 262 } 263 } 264 } 265 266 /** 267 * Returns a clone of the renderer. 268 * 269 * @return A clone. 270 * 271 * @throws CloneNotSupportedException if the renderer cannot be cloned. 272 */ 273 public Object clone() throws CloneNotSupportedException { 274 return super.clone(); 275 } 276 277 }