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: notifyListeners(new RendererChangeEvent(this)); 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: notifyListeners(new RendererChangeEvent(this)); 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. 148: * 149: * @param paint the paint. 150: */ 151: public void setWallPaint(Paint paint) { 152: this.wallPaint = paint; 153: notifyListeners(new RendererChangeEvent(this)); 154: } 155: 156: /** 157: * Returns the number of passes through the data that the renderer requires 158: * in order to draw the chart. Most charts will require a single pass, 159: * but some require two passes. 160: * 161: * @return The pass count. 162: */ 163: public int getPassCount() { 164: return 3; 165: } 166: 167: /** 168: * Returns <code>true</code> if the specified pass involves drawing lines. 169: * 170: * @param pass the pass. 171: * 172: * @return A boolean. 173: */ 174: protected boolean isLinePass(int pass) { 175: return pass == 0 || pass == 1; 176: } 177: 178: /** 179: * Returns <code>true</code> if the specified pass involves drawing items. 180: * 181: * @param pass the pass. 182: * 183: * @return A boolean. 184: */ 185: protected boolean isItemPass(int pass) { 186: return pass == 2; 187: } 188: 189: /** 190: * Returns <code>true</code> if the specified pass involves drawing shadows. 191: * 192: * @param pass the pass. 193: * 194: * @return A boolean. 195: */ 196: protected boolean isShadowPass (int pass) { 197: return pass == 0; 198: } 199: 200: /** 201: * Overrides the method in the subclass to draw a shadow in the first pass. 202: * 203: * @param g2 the graphics device. 204: * @param pass the pass. 205: * @param series the series index (zero-based). 206: * @param item the item index (zero-based). 207: * @param shape the shape. 208: */ 209: protected void drawFirstPassShape(Graphics2D g2, 210: int pass, 211: int series, 212: int item, 213: Shape shape) { 214: if (isShadowPass(pass)) { 215: if (getWallPaint() != null) { 216: g2.setStroke(getItemStroke(series, item)); 217: g2.setPaint(getWallPaint()); 218: g2.translate(getXOffset(), getYOffset()); 219: g2.draw(shape); 220: g2.translate(-getXOffset(), -getYOffset()); 221: } 222: } 223: else { 224: // now draw the real shape 225: super.drawFirstPassShape(g2, pass, series, item, shape); 226: } 227: } 228: 229: /** 230: * Tests this renderer for equality with an arbitrary object. 231: * 232: * @param obj the object (<code>null</code> permitted). 233: * 234: * @return A boolean. 235: */ 236: public boolean equals(Object obj) { 237: if (obj == this) { 238: return true; 239: } 240: if (!(obj instanceof XYLine3DRenderer)) { 241: return false; 242: } 243: XYLine3DRenderer that = (XYLine3DRenderer) obj; 244: if (this.xOffset != that.xOffset) { 245: return false; 246: } 247: if (this.yOffset != that.yOffset) { 248: return false; 249: } 250: if (!PaintUtilities.equal(this.wallPaint, that.wallPaint)) { 251: return false; 252: } 253: return super.equals(obj); 254: } 255: 256: /** 257: * Provides serialization support. 258: * 259: * @param stream the input stream. 260: * 261: * @throws IOException if there is an I/O error. 262: * @throws ClassNotFoundException if there is a classpath problem. 263: */ 264: private void readObject(ObjectInputStream stream) 265: throws IOException, ClassNotFoundException { 266: stream.defaultReadObject(); 267: this.wallPaint = SerialUtilities.readPaint(stream); 268: } 269: 270: /** 271: * Provides serialization support. 272: * 273: * @param stream the output stream. 274: * 275: * @throws IOException if there is an I/O error. 276: */ 277: private void writeObject(ObjectOutputStream stream) throws IOException { 278: stream.defaultWriteObject(); 279: SerialUtilities.writePaint(this.wallPaint, stream); 280: } 281: 282: }