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: * SimpleDialFrame.java
029: * --------------------
030: * (C) Copyright 2006, 2007, by Object Refinery Limited.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): -;
034: *
035: * $Id: SimpleDialFrame.java,v 1.1.2.3 2007/03/08 16:51:07 mungady Exp $
036: *
037: * Changes
038: * -------
039: * 03-Nov-2006 : Version 1 (DG);
040: * 08-Mar-2007 : Fix in hashCode() (DG);
041: *
042: */
043:
044: package org.jfree.experimental.chart.plot.dial;
045:
046: import java.awt.BasicStroke;
047: import java.awt.Color;
048: import java.awt.Graphics2D;
049: import java.awt.Paint;
050: import java.awt.Shape;
051: import java.awt.Stroke;
052: import java.awt.geom.Area;
053: import java.awt.geom.Ellipse2D;
054: import java.awt.geom.Rectangle2D;
055: import java.io.IOException;
056: import java.io.ObjectInputStream;
057: import java.io.ObjectOutputStream;
058: import java.io.Serializable;
059:
060: import org.jfree.chart.HashUtilities;
061: import org.jfree.io.SerialUtilities;
062: import org.jfree.util.PaintUtilities;
063: import org.jfree.util.PublicCloneable;
064:
065: /**
066: * A simple circular frame for the {@link DialPlot} class.
067: */
068: public class SimpleDialFrame extends AbstractDialLayer implements
069: DialFrame, Cloneable, PublicCloneable, Serializable {
070:
071: /** The outer radius, relative to the framing rectangle. */
072: private double radius;
073:
074: /**
075: * The color used for the front of the panel. This field is transient
076: * because it requires special handling for serialization.
077: */
078: private transient Paint backgroundPaint;
079:
080: /**
081: * The color used for the border around the window. This field is transient
082: * because it requires special handling for serialization.
083: */
084: private transient Paint foregroundPaint;
085:
086: /**
087: * The stroke for drawing the frame outline. This field is transient
088: * because it requires special handling for serialization.
089: */
090: private transient Stroke stroke;
091:
092: /**
093: * Creates a new instance of <code>SimpleDialFrame</code>.
094: */
095: public SimpleDialFrame() {
096: this .backgroundPaint = Color.gray;
097: this .foregroundPaint = Color.black;
098: this .stroke = new BasicStroke(2.0f);
099: this .radius = 0.95;
100: }
101:
102: /**
103: * Returns the radius, relative to the framing rectangle.
104: *
105: * @return The radius.
106: */
107: public double getRadius() {
108: return this .radius;
109: }
110:
111: /**
112: * Sets the radius.
113: *
114: * @param radius the radius.
115: */
116: public void setRadius(double radius) {
117: // TODO: validation
118: this .radius = radius;
119: notifyListeners(new DialLayerChangeEvent(this ));
120: }
121:
122: /**
123: * Returns the background paint.
124: *
125: * @return The background paint (never <code>null</code>).
126: *
127: * @see #setBackgroundPaint(Paint)
128: */
129: public Paint getBackgroundPaint() {
130: return this .backgroundPaint;
131: }
132:
133: /**
134: * Sets the background paint.
135: *
136: * @param paint the paint (<code>null</code> not permitted).
137: *
138: * @see #getBackgroundPaint()
139: */
140: public void setBackgroundPaint(Paint paint) {
141: if (paint == null) {
142: throw new IllegalArgumentException("Null 'paint' argument.");
143: }
144: this .backgroundPaint = paint;
145: notifyListeners(new DialLayerChangeEvent(this ));
146: }
147:
148: /**
149: * Returns the foreground paint.
150: *
151: * @return The foreground paint (never <code>null</code>).
152: *
153: * @see #setForegroundPaint(Paint)
154: */
155: public Paint getForegroundPaint() {
156: return this .foregroundPaint;
157: }
158:
159: /**
160: * Sets the foreground paint.
161: *
162: * @param paint the paint (<code>null</code> not permitted).
163: *
164: * @see #getForegroundPaint()
165: */
166: public void setForegroundPaint(Paint paint) {
167: if (paint == null) {
168: throw new IllegalArgumentException("Null 'paint' argument.");
169: }
170: this .foregroundPaint = paint;
171: notifyListeners(new DialLayerChangeEvent(this ));
172: }
173:
174: /**
175: * Returns the stroke for the frame.
176: *
177: * @return The stroke (never <code>null</code>).
178: *
179: * @see #setStroke(Stroke)
180: */
181: public Stroke getStroke() {
182: return this .stroke;
183: }
184:
185: /**
186: * Sets the stroke.
187: *
188: * @param stroke the stroke (<code>null</code> not permitted).
189: *
190: * @see #getStroke()
191: */
192: public void setStroke(Stroke stroke) {
193: if (stroke == null) {
194: throw new IllegalArgumentException(
195: "Null 'stroke' argument.");
196: }
197: this .stroke = stroke;
198: notifyListeners(new DialLayerChangeEvent(this ));
199: }
200:
201: /**
202: * Returns the shape for the window for this dial. Some dial layers will
203: * request that their drawing be clipped within this window.
204: *
205: * @param frame the reference frame (<code>null</code> not permitted).
206: *
207: * @return The shape of the dial's window.
208: */
209: public Shape getWindow(Rectangle2D frame) {
210: Rectangle2D f = DialPlot.rectangleByRadius(frame, this .radius,
211: this .radius);
212: return new Ellipse2D.Double(f.getX(), f.getY(), f.getWidth(), f
213: .getHeight());
214: }
215:
216: /**
217: * Returns <code>false</code> to indicate that this dial layer is not
218: * clipped to the dial window.
219: *
220: * @return A boolean.
221: */
222: public boolean isClippedToWindow() {
223: return false;
224: }
225:
226: /**
227: * Draws the frame. This method is called by the {@link DialPlot} class,
228: * you shouldn't need to call it directly.
229: *
230: * @param g2 the graphics target (<code>null</code> not permitted).
231: * @param plot the plot (<code>null</code> not permitted).
232: * @param frame the frame (<code>null</code> not permitted).
233: * @param view the view (<code>null</code> not permitted).
234: */
235: public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame,
236: Rectangle2D view) {
237:
238: Shape window = getWindow(frame);
239:
240: Rectangle2D f = DialPlot.rectangleByRadius(frame,
241: this .radius + 0.02, this .radius + 0.02);
242: Ellipse2D e = new Ellipse2D.Double(f.getX(), f.getY(), f
243: .getWidth(), f.getHeight());
244:
245: Area area = new Area(e);
246: Area area2 = new Area(window);
247: area.subtract(area2);
248: g2.setPaint(this .backgroundPaint);
249: g2.fill(area);
250:
251: g2.setStroke(this .stroke);
252: g2.setPaint(this .foregroundPaint);
253: g2.draw(window);
254: g2.draw(e);
255: }
256:
257: /**
258: * Tests this instance for equality with an arbitrary object.
259: *
260: * @param obj the object (<code>null</code> permitted).
261: *
262: * @return A boolean.
263: */
264: public boolean equals(Object obj) {
265: if (obj == this ) {
266: return true;
267: }
268: if (!(obj instanceof SimpleDialFrame)) {
269: return false;
270: }
271: SimpleDialFrame that = (SimpleDialFrame) obj;
272: if (!PaintUtilities.equal(this .backgroundPaint,
273: that.backgroundPaint)) {
274: return false;
275: }
276: if (!PaintUtilities.equal(this .foregroundPaint,
277: that.foregroundPaint)) {
278: return false;
279: }
280: if (this .radius != that.radius) {
281: return false;
282: }
283: if (!this .stroke.equals(that.stroke)) {
284: return false;
285: }
286: return true;
287: }
288:
289: /**
290: * Returns a hash code for this instance.
291: *
292: * @return The hash code.
293: */
294: public int hashCode() {
295: int result = 193;
296: long temp = Double.doubleToLongBits(this .radius);
297: result = 37 * result + (int) (temp ^ (temp >>> 32));
298: result = 37 * result
299: + HashUtilities.hashCodeForPaint(this .backgroundPaint);
300: result = 37 * result
301: + HashUtilities.hashCodeForPaint(this .foregroundPaint);
302: result = 37 * result + this .stroke.hashCode();
303: return result;
304: }
305:
306: /**
307: * Returns a clone of this instance.
308: *
309: * @return A clone.
310: *
311: * @throws CloneNotSupportedException if any of the frame's attributes
312: * cannot be cloned.
313: */
314: public Object clone() throws CloneNotSupportedException {
315: return super .clone();
316: }
317:
318: /**
319: * Provides serialization support.
320: *
321: * @param stream the output stream.
322: *
323: * @throws IOException if there is an I/O error.
324: */
325: private void writeObject(ObjectOutputStream stream)
326: throws IOException {
327: stream.defaultWriteObject();
328: SerialUtilities.writePaint(this .backgroundPaint, stream);
329: SerialUtilities.writePaint(this .foregroundPaint, stream);
330: SerialUtilities.writeStroke(this .stroke, stream);
331: }
332:
333: /**
334: * Provides serialization support.
335: *
336: * @param stream the input stream.
337: *
338: * @throws IOException if there is an I/O error.
339: * @throws ClassNotFoundException if there is a classpath problem.
340: */
341: private void readObject(ObjectInputStream stream)
342: throws IOException, ClassNotFoundException {
343: stream.defaultReadObject();
344: this.backgroundPaint = SerialUtilities.readPaint(stream);
345: this.foregroundPaint = SerialUtilities.readPaint(stream);
346: this.stroke = SerialUtilities.readStroke(stream);
347: }
348:
349: }
|