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: * XYLine3DRenderer.java
029: * ---------------------
030: * (C) Copyright 2005, 2007, by Object Refinery Limited.
031: *
032: * Original Author: Thomas Morgner;
033: * Contributor(s): David Gilbert (for Object Refinery Limited);
034: *
035: * $Id: XYLine3DRenderer.java,v 1.4.2.2 2007/05/01 16:08:40 mungady Exp $
036: *
037: * Changes
038: * -------
039: * 14-Jan-2005 : Added standard header (DG);
040: * 01-May-2007 : Fixed equals() and serialization bugs (DG);
041: *
042: */
043:
044: package org.jfree.chart.renderer.xy;
045:
046: import java.awt.Color;
047: import java.awt.Graphics2D;
048: import java.awt.Paint;
049: import java.awt.Shape;
050: import java.io.IOException;
051: import java.io.ObjectInputStream;
052: import java.io.ObjectOutputStream;
053: import java.io.Serializable;
054:
055: import org.jfree.chart.Effect3D;
056: import org.jfree.chart.event.RendererChangeEvent;
057: import org.jfree.io.SerialUtilities;
058: import org.jfree.util.PaintUtilities;
059:
060: /**
061: * A XYLineAndShapeRenderer that adds a shadow line to the graph
062: * to emulate a 3D-effect.
063: */
064: public class XYLine3DRenderer extends XYLineAndShapeRenderer implements
065: Effect3D, Serializable {
066:
067: /** For serialization. */
068: private static final long serialVersionUID = 588933208243446087L;
069:
070: /** The default x-offset for the 3D effect. */
071: public static final double DEFAULT_X_OFFSET = 12.0;
072:
073: /** The default y-offset for the 3D effect. */
074: public static final double DEFAULT_Y_OFFSET = 8.0;
075:
076: /** The default wall paint. */
077: public static final Paint DEFAULT_WALL_PAINT = new Color(0xDD,
078: 0xDD, 0xDD);
079:
080: /** The size of x-offset for the 3D effect. */
081: private double xOffset;
082:
083: /** The size of y-offset for the 3D effect. */
084: private double yOffset;
085:
086: /** The paint used to shade the left and lower 3D wall. */
087: private transient Paint wallPaint;
088:
089: /**
090: * Creates a new renderer.
091: */
092: public XYLine3DRenderer() {
093: this .wallPaint = DEFAULT_WALL_PAINT;
094: this .xOffset = DEFAULT_X_OFFSET;
095: this .yOffset = DEFAULT_Y_OFFSET;
096: }
097:
098: /**
099: * Returns the x-offset for the 3D effect.
100: *
101: * @return The 3D effect.
102: */
103: public double getXOffset() {
104: return this .xOffset;
105: }
106:
107: /**
108: * Returns the y-offset for the 3D effect.
109: *
110: * @return The 3D effect.
111: */
112: public double getYOffset() {
113: return this .yOffset;
114: }
115:
116: /**
117: * Sets the x-offset and sends a {@link RendererChangeEvent} to all
118: * registered listeners.
119: *
120: * @param xOffset the x-offset.
121: */
122: public void setXOffset(double xOffset) {
123: this .xOffset = xOffset;
124: notifyListeners(new RendererChangeEvent(this ));
125: }
126:
127: /**
128: * Sets the y-offset and sends a {@link RendererChangeEvent} to all
129: * registered listeners.
130: *
131: * @param yOffset the y-offset.
132: */
133: public void setYOffset(double yOffset) {
134: this .yOffset = yOffset;
135: notifyListeners(new RendererChangeEvent(this ));
136: }
137:
138: /**
139: * Returns the paint used to highlight the left and bottom wall in the plot
140: * background.
141: *
142: * @return The paint.
143: */
144: public Paint getWallPaint() {
145: return this .wallPaint;
146: }
147:
148: /**
149: * Sets the paint used to hightlight the left and bottom walls in the plot
150: * background.
151: *
152: * @param paint the paint.
153: */
154: public void setWallPaint(Paint paint) {
155: this .wallPaint = paint;
156: notifyListeners(new RendererChangeEvent(this ));
157: }
158:
159: /**
160: * Returns the number of passes through the data that the renderer requires
161: * in order to draw the chart. Most charts will require a single pass,
162: * but some require two passes.
163: *
164: * @return The pass count.
165: */
166: public int getPassCount() {
167: return 3;
168: }
169:
170: /**
171: * Returns <code>true</code> if the specified pass involves drawing lines.
172: *
173: * @param pass the pass.
174: *
175: * @return A boolean.
176: */
177: protected boolean isLinePass(int pass) {
178: return pass == 0 || pass == 1;
179: }
180:
181: /**
182: * Returns <code>true</code> if the specified pass involves drawing items.
183: *
184: * @param pass the pass.
185: *
186: * @return A boolean.
187: */
188: protected boolean isItemPass(int pass) {
189: return pass == 2;
190: }
191:
192: /**
193: * Returns <code>true</code> if the specified pass involves drawing shadows.
194: *
195: * @param pass the pass.
196: *
197: * @return A boolean.
198: */
199: protected boolean isShadowPass(int pass) {
200: return pass == 0;
201: }
202:
203: /**
204: * Overrides the method in the subclass to draw a shadow in the first pass.
205: *
206: * @param g2 the graphics device.
207: * @param pass the pass.
208: * @param series the series index (zero-based).
209: * @param item the item index (zero-based).
210: * @param shape the shape.
211: */
212: protected void drawFirstPassShape(Graphics2D g2, int pass,
213: int series, int item, 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: } else {
223: // now draw the real shape
224: super .drawFirstPassShape(g2, pass, series, item, shape);
225: }
226: }
227:
228: /**
229: * Tests this renderer for equality with an arbitrary object.
230: *
231: * @param obj the object (<code>null</code> permitted).
232: *
233: * @return A boolean.
234: */
235: public boolean equals(Object obj) {
236: if (obj == this ) {
237: return true;
238: }
239: if (!(obj instanceof XYLine3DRenderer)) {
240: return false;
241: }
242: XYLine3DRenderer that = (XYLine3DRenderer) obj;
243: if (this .xOffset != that.xOffset) {
244: return false;
245: }
246: if (this .yOffset != that.yOffset) {
247: return false;
248: }
249: if (!PaintUtilities.equal(this .wallPaint, that.wallPaint)) {
250: return false;
251: }
252: return super .equals(obj);
253: }
254:
255: /**
256: * Provides serialization support.
257: *
258: * @param stream the input stream.
259: *
260: * @throws IOException if there is an I/O error.
261: * @throws ClassNotFoundException if there is a classpath problem.
262: */
263: private void readObject(ObjectInputStream stream)
264: throws IOException, ClassNotFoundException {
265: stream.defaultReadObject();
266: this .wallPaint = SerialUtilities.readPaint(stream);
267: }
268:
269: /**
270: * Provides serialization support.
271: *
272: * @param stream the output stream.
273: *
274: * @throws IOException if there is an I/O error.
275: */
276: private void writeObject(ObjectOutputStream stream)
277: throws IOException {
278: stream.defaultWriteObject();
279: SerialUtilities.writePaint(this.wallPaint, stream);
280: }
281:
282: }
|