Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, 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-2007, by Roger Studner and Contributors. 31: * 32: * Original Author: Roger Studner; 33: * Contributor(s): David Gilbert (for Object Refinery Limited); 34: * Matthias Rose; 35: * Gerald Struck (fix for bug 1569094); 36: * 37: * Changes 38: * ------- 39: * 13-May-2002 : Version 1, contributed by Roger Studner (DG); 40: * 25-Jun-2002 : Updated import statements (DG); 41: * 22-Jul-2002 : Added check for null data items (DG); 42: * 25-Mar-2003 : Implemented Serializable (DG); 43: * 01-May-2003 : Modified drawItem() method signature (DG); 44: * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG); 45: * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG); 46: * 28-Oct-2003 : Added tooltips, code contributed by Matthias Rose 47: * (RFE 824857) (DG); 48: * 10-Feb-2004 : Removed working line (use line from state object instead) (DG); 49: * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState. Renamed 50: * XYToolTipGenerator --> XYItemLabelGenerator (DG); 51: * 19-Jan-2005 : Now accesses only primitives from dataset (DG); 52: * 15-Mar-2005 : Fix silly bug in drawItem() method (DG); 53: * 19-Sep-2005 : Extend XYLineAndShapeRenderer (fixes legend shapes), added 54: * support for series visibility, and use getDefaultEntityRadius() 55: * for entity hotspot size (DG); 56: * ------------- JFREECHART 1.0.x --------------------------------------------- 57: * 15-Jun-2006 : Added basic support for item labels (DG); 58: * 11-Oct-2006 : Fixed rendering with horizontal orientation (see bug 1569094), 59: * thanks to Gerald Struck (DG); 60: * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG); 61: * 62: */ 63: 64: package org.jfree.chart.renderer.xy; 65: 66: import java.awt.Graphics2D; 67: import java.awt.Paint; 68: import java.awt.Shape; 69: import java.awt.Stroke; 70: import java.awt.geom.Line2D; 71: import java.awt.geom.Rectangle2D; 72: import java.io.Serializable; 73: 74: import org.jfree.chart.axis.ValueAxis; 75: import org.jfree.chart.entity.EntityCollection; 76: import org.jfree.chart.entity.XYItemEntity; 77: import org.jfree.chart.labels.XYToolTipGenerator; 78: import org.jfree.chart.plot.CrosshairState; 79: import org.jfree.chart.plot.PlotOrientation; 80: import org.jfree.chart.plot.PlotRenderingInfo; 81: import org.jfree.chart.plot.XYPlot; 82: import org.jfree.chart.urls.XYURLGenerator; 83: import org.jfree.data.xy.XYDataset; 84: import org.jfree.ui.RectangleEdge; 85: import org.jfree.util.PublicCloneable; 86: 87: /** 88: * Line/Step item renderer for an {@link XYPlot}. This class draws lines 89: * between data points, only allowing horizontal or vertical lines (steps). 90: */ 91: public class XYStepRenderer extends XYLineAndShapeRenderer 92: implements XYItemRenderer, 93: Cloneable, 94: PublicCloneable, 95: Serializable { 96: 97: /** For serialization. */ 98: private static final long serialVersionUID = -8918141928884796108L; 99: 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: }