001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2005, 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, 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.1 2005/10/25 20:56:21 mungady Exp $
036 *
037 * Changes
038 * -------
039 * 14-Jan-2005 : Added standard header (DG);
040 */
041
042 package org.jfree.chart.renderer.xy;
043
044 import java.awt.Color;
045 import java.awt.Graphics2D;
046 import java.awt.Paint;
047 import java.awt.Shape;
048 import java.io.Serializable;
049
050 import org.jfree.chart.Effect3D;
051 import org.jfree.chart.event.RendererChangeEvent;
052
053 /**
054 * A XYLineAndShapeRenderer that adds a shadow line to the graph
055 * to emulate a 3D-effect.
056 */
057 public class XYLine3DRenderer extends XYLineAndShapeRenderer
058 implements Effect3D, Serializable {
059
060 /** For serialization. */
061 private static final long serialVersionUID = 588933208243446087L;
062
063 /** The default x-offset for the 3D effect. */
064 public static final double DEFAULT_X_OFFSET = 12.0;
065
066 /** The default y-offset for the 3D effect. */
067 public static final double DEFAULT_Y_OFFSET = 8.0;
068
069 /** The default wall paint. */
070 public static final Paint DEFAULT_WALL_PAINT = new Color(0xDD, 0xDD, 0xDD);
071
072 /** The size of x-offset for the 3D effect. */
073 private double xOffset;
074
075 /** The size of y-offset for the 3D effect. */
076 private double yOffset;
077
078 /** The paint used to shade the left and lower 3D wall. */
079 private transient Paint wallPaint;
080
081 /**
082 * Creates a new renderer.
083 */
084 public XYLine3DRenderer() {
085 this.wallPaint = DEFAULT_WALL_PAINT;
086 this.xOffset = DEFAULT_X_OFFSET;
087 this.yOffset = DEFAULT_Y_OFFSET;
088 }
089
090 /**
091 * Returns the x-offset for the 3D effect.
092 *
093 * @return The 3D effect.
094 */
095 public double getXOffset() {
096 return this.xOffset;
097 }
098
099 /**
100 * Returns the y-offset for the 3D effect.
101 *
102 * @return The 3D effect.
103 */
104 public double getYOffset() {
105 return this.yOffset;
106 }
107
108 /**
109 * Sets the x-offset and sends a {@link RendererChangeEvent} to all
110 * registered listeners.
111 *
112 * @param xOffset the x-offset.
113 */
114 public void setXOffset(double xOffset) {
115 this.xOffset = xOffset;
116 notifyListeners(new RendererChangeEvent(this));
117 }
118
119 /**
120 * Sets the y-offset and sends a {@link RendererChangeEvent} to all
121 * registered listeners.
122 *
123 * @param yOffset the y-offset.
124 */
125 public void setYOffset(double yOffset) {
126 this.yOffset = yOffset;
127 notifyListeners(new RendererChangeEvent(this));
128 }
129
130 /**
131 * Returns the paint used to highlight the left and bottom wall in the plot
132 * background.
133 *
134 * @return The paint.
135 */
136 public Paint getWallPaint() {
137 return this.wallPaint;
138 }
139
140 /**
141 * Sets the paint used to hightlight the left and bottom walls in the plot
142 * background.
143 *
144 * @param paint the paint.
145 */
146 public void setWallPaint(Paint paint) {
147 this.wallPaint = paint;
148 notifyListeners(new RendererChangeEvent(this));
149 }
150
151 /**
152 * Returns the number of passes through the data that the renderer requires
153 * in order to draw the chart. Most charts will require a single pass,
154 * but some require two passes.
155 *
156 * @return The pass count.
157 */
158 public int getPassCount() {
159 return 3;
160 }
161
162 /**
163 * Returns <code>true</code> if the specified pass involves drawing lines.
164 *
165 * @param pass the pass.
166 *
167 * @return A boolean.
168 */
169 protected boolean isLinePass(int pass) {
170 return pass == 0 || pass == 1;
171 }
172
173 /**
174 * Returns <code>true</code> if the specified pass involves drawing items.
175 *
176 * @param pass the pass.
177 *
178 * @return A boolean.
179 */
180 protected boolean isItemPass(int pass) {
181 return pass == 2;
182 }
183
184 /**
185 * Returns <code>true</code> if the specified pass involves drawing shadows.
186 *
187 * @param pass the pass.
188 *
189 * @return A boolean.
190 */
191 protected boolean isShadowPass (int pass) {
192 return pass == 0;
193 }
194
195 /**
196 * Overrides the method in the subclass to draw a shadow in the first pass.
197 *
198 * @param g2 the graphics device.
199 * @param pass the pass.
200 * @param series the series index (zero-based).
201 * @param item the item index (zero-based).
202 * @param shape the shape.
203 */
204 protected void drawFirstPassShape(Graphics2D g2,
205 int pass,
206 int series,
207 int item,
208 Shape shape) {
209 if (isShadowPass(pass)) {
210 if (getWallPaint() != null) {
211 g2.setStroke(getItemStroke(series, item));
212 g2.setPaint(getWallPaint());
213 g2.translate(getXOffset(), getYOffset());
214 g2.draw(shape);
215 g2.translate(-getXOffset(), -getYOffset());
216 }
217 }
218 else {
219 // now draw the real shape
220 super.drawFirstPassShape(g2, pass, series, item, shape);
221 }
222 }
223
224 }