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 }