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: * XYLine3DRenderer.java 29: * --------------------- 30: * (C) Copyright 2005, 2007, by Object Refinery Limited. 31: * 32: * Original Author: Thomas Morgner; 33: * Contributor(s): David Gilbert (for Object Refinery Limited); 34: * 35: * Changes 36: * ------- 37: * 14-Jan-2005 : Added standard header (DG); 38: * 01-May-2007 : Fixed equals() and serialization bugs (DG); 39: * 40: */ 41: 42: package org.jfree.chart.renderer.xy; 43: 44: import java.awt.Color; 45: import java.awt.Graphics2D; 46: import java.awt.Paint; 47: import java.awt.Shape; 48: import java.io.IOException; 49: import java.io.ObjectInputStream; 50: import java.io.ObjectOutputStream; 51: import java.io.Serializable; 52: 53: import org.jfree.chart.Effect3D; 54: import org.jfree.chart.event.RendererChangeEvent; 55: import org.jfree.io.SerialUtilities; 56: import org.jfree.util.PaintUtilities; 57: 58: /** 59: * A XYLineAndShapeRenderer that adds a shadow line to the graph 60: * to emulate a 3D-effect. 61: */ 62: public class XYLine3DRenderer extends XYLineAndShapeRenderer 63: implements Effect3D, Serializable { 64: 65: /** For serialization. */ 66: private static final long serialVersionUID = 588933208243446087L; 67: 68: /** The default x-offset for the 3D effect. */ 69: public static final double DEFAULT_X_OFFSET = 12.0; 70: 71: /** The default y-offset for the 3D effect. */ 72: public static final double DEFAULT_Y_OFFSET = 8.0; 73: 74: /** The default wall paint. */ 75: public static final Paint DEFAULT_WALL_PAINT = new Color(0xDD, 0xDD, 0xDD); 76: 77: /** The size of x-offset for the 3D effect. */ 78: private double xOffset; 79: 80: /** The size of y-offset for the 3D effect. */ 81: private double yOffset; 82: 83: /** The paint used to shade the left and lower 3D wall. */ 84: private transient Paint wallPaint; 85: 86: /** 87: * Creates a new renderer. 88: */ 89: public XYLine3DRenderer() { 90: this.wallPaint = DEFAULT_WALL_PAINT; 91: this.xOffset = DEFAULT_X_OFFSET; 92: this.yOffset = DEFAULT_Y_OFFSET; 93: } 94: 95: /** 96: * Returns the x-offset for the 3D effect. 97: * 98: * @return The 3D effect. 99: */ 100: public double getXOffset() { 101: return this.xOffset; 102: } 103: 104: /** 105: * Returns the y-offset for the 3D effect. 106: * 107: * @return The 3D effect. 108: */ 109: public double getYOffset() { 110: return this.yOffset; 111: } 112: 113: /** 114: * Sets the x-offset and sends a {@link RendererChangeEvent} to all 115: * registered listeners. 116: * 117: * @param xOffset the x-offset. 118: */ 119: public void setXOffset(double xOffset) { 120: this.xOffset = xOffset; 121: fireChangeEvent(); 122: } 123: 124: /** 125: * Sets the y-offset and sends a {@link RendererChangeEvent} to all 126: * registered listeners. 127: * 128: * @param yOffset the y-offset. 129: */ 130: public void setYOffset(double yOffset) { 131: this.yOffset = yOffset; 132: fireChangeEvent(); 133: } 134: 135: /** 136: * Returns the paint used to highlight the left and bottom wall in the plot 137: * background. 138: * 139: * @return The paint. 140: */ 141: public Paint getWallPaint() { 142: return this.wallPaint; 143: } 144: 145: /** 146: * Sets the paint used to hightlight the left and bottom walls in the plot 147: * background and sends a {@link RendererChangeEvent} to all registered 148: * listeners. 149: * 150: * @param paint the paint. 151: */ 152: public void setWallPaint(Paint paint) { 153: this.wallPaint = paint; 154: fireChangeEvent(); 155: } 156: 157: /** 158: * Returns the number of passes through the data that the renderer requires 159: * in order to draw the chart. Most charts will require a single pass, 160: * but some require two passes. 161: * 162: * @return The pass count. 163: */ 164: public int getPassCount() { 165: return 3; 166: } 167: 168: /** 169: * Returns <code>true</code> if the specified pass involves drawing lines. 170: * 171: * @param pass the pass. 172: * 173: * @return A boolean. 174: */ 175: protected boolean isLinePass(int pass) { 176: return pass == 0 || pass == 1; 177: } 178: 179: /** 180: * Returns <code>true</code> if the specified pass involves drawing items. 181: * 182: * @param pass the pass. 183: * 184: * @return A boolean. 185: */ 186: protected boolean isItemPass(int pass) { 187: return pass == 2; 188: } 189: 190: /** 191: * Returns <code>true</code> if the specified pass involves drawing shadows. 192: * 193: * @param pass the pass. 194: * 195: * @return A boolean. 196: */ 197: protected boolean isShadowPass (int pass) { 198: return pass == 0; 199: } 200: 201: /** 202: * Overrides the method in the subclass to draw a shadow in the first pass. 203: * 204: * @param g2 the graphics device. 205: * @param pass the pass. 206: * @param series the series index (zero-based). 207: * @param item the item index (zero-based). 208: * @param shape the shape. 209: */ 210: protected void drawFirstPassShape(Graphics2D g2, 211: int pass, 212: int series, 213: int item, 214: Shape shape) { 215: if (isShadowPass(pass)) { 216: if (getWallPaint() != null) { 217: g2.setStroke(getItemStroke(series, item)); 218: g2.setPaint(getWallPaint()); 219: g2.translate(getXOffset(), getYOffset()); 220: g2.draw(shape); 221: g2.translate(-getXOffset(), -getYOffset()); 222: } 223: } 224: else { 225: // now draw the real shape 226: super.drawFirstPassShape(g2, pass, series, item, shape); 227: } 228: } 229: 230: /** 231: * Tests this renderer for equality with an arbitrary object. 232: * 233: * @param obj the object (<code>null</code> permitted). 234: * 235: * @return A boolean. 236: */ 237: public boolean equals(Object obj) { 238: if (obj == this) { 239: return true; 240: } 241: if (!(obj instanceof XYLine3DRenderer)) { 242: return false; 243: } 244: XYLine3DRenderer that = (XYLine3DRenderer) obj; 245: if (this.xOffset != that.xOffset) { 246: return false; 247: } 248: if (this.yOffset != that.yOffset) { 249: return false; 250: } 251: if (!PaintUtilities.equal(this.wallPaint, that.wallPaint)) { 252: return false; 253: } 254: return super.equals(obj); 255: } 256: 257: /** 258: * Provides serialization support. 259: * 260: * @param stream the input stream. 261: * 262: * @throws IOException if there is an I/O error. 263: * @throws ClassNotFoundException if there is a classpath problem. 264: */ 265: private void readObject(ObjectInputStream stream) 266: throws IOException, ClassNotFoundException { 267: stream.defaultReadObject(); 268: this.wallPaint = SerialUtilities.readPaint(stream); 269: } 270: 271: /** 272: * Provides serialization support. 273: * 274: * @param stream the output stream. 275: * 276: * @throws IOException if there is an I/O error. 277: */ 278: private void writeObject(ObjectOutputStream stream) throws IOException { 279: stream.defaultWriteObject(); 280: SerialUtilities.writePaint(this.wallPaint, stream); 281: } 282: 283: }