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