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: * StandardDialFrame.java 29: * ---------------------- 30: * (C) Copyright 2006, 2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * Changes 36: * ------- 37: * 03-Nov-2006 : Version 1 (DG); 38: * 08-Mar-2007 : Fix in hashCode() (DG); 39: * 29-Oct-2007 : Renamed StandardDialFrame (DG); 40: * 41: */ 42: 43: package org.jfree.chart.plot.dial; 44: 45: import java.awt.BasicStroke; 46: import java.awt.Color; 47: import java.awt.Graphics2D; 48: import java.awt.Paint; 49: import java.awt.Shape; 50: import java.awt.Stroke; 51: import java.awt.geom.Area; 52: import java.awt.geom.Ellipse2D; 53: import java.awt.geom.Rectangle2D; 54: import java.io.IOException; 55: import java.io.ObjectInputStream; 56: import java.io.ObjectOutputStream; 57: import java.io.Serializable; 58: 59: import org.jfree.chart.HashUtilities; 60: import org.jfree.io.SerialUtilities; 61: import org.jfree.util.PaintUtilities; 62: import org.jfree.util.PublicCloneable; 63: 64: /** 65: * A simple circular frame for the {@link DialPlot} class. 66: */ 67: public class StandardDialFrame extends AbstractDialLayer implements DialFrame, 68: Cloneable, PublicCloneable, Serializable { 69: 70: /** For serialization. */ 71: static final long serialVersionUID = 1016585407507121596L; 72: 73: /** The outer radius, relative to the framing rectangle. */ 74: private double radius; 75: 76: /** 77: * The color used for the front of the panel. This field is transient 78: * because it requires special handling for serialization. 79: */ 80: private transient Paint backgroundPaint; 81: 82: /** 83: * The color used for the border around the window. This field is transient 84: * because it requires special handling for serialization. 85: */ 86: private transient Paint foregroundPaint; 87: 88: /** 89: * The stroke for drawing the frame outline. This field is transient 90: * because it requires special handling for serialization. 91: */ 92: private transient Stroke stroke; 93: 94: /** 95: * Creates a new instance of <code>StandardDialFrame</code>. 96: */ 97: public StandardDialFrame() { 98: this.backgroundPaint = Color.gray; 99: this.foregroundPaint = Color.black; 100: this.stroke = new BasicStroke(2.0f); 101: this.radius = 0.95; 102: } 103: 104: /** 105: * Returns the radius, relative to the framing rectangle. 106: * 107: * @return The radius. 108: * 109: * @see #setRadius(double) 110: */ 111: public double getRadius() { 112: return this.radius; 113: } 114: 115: /** 116: * Sets the radius and sends a {@link DialLayerChangeEvent} to all 117: * registered listeners. 118: * 119: * @param radius the radius (must be positive). 120: * 121: * @see #getRadius() 122: */ 123: public void setRadius(double radius) { 124: if (radius <= 0) { 125: throw new IllegalArgumentException( 126: "The 'radius' must be positive."); 127: } 128: this.radius = radius; 129: notifyListeners(new DialLayerChangeEvent(this)); 130: } 131: 132: /** 133: * Returns the background paint. 134: * 135: * @return The background paint (never <code>null</code>). 136: * 137: * @see #setBackgroundPaint(Paint) 138: */ 139: public Paint getBackgroundPaint() { 140: return this.backgroundPaint; 141: } 142: 143: /** 144: * Sets the background paint and sends a {@link DialLayerChangeEvent} to 145: * all registered listeners. 146: * 147: * @param paint the paint (<code>null</code> not permitted). 148: * 149: * @see #getBackgroundPaint() 150: */ 151: public void setBackgroundPaint(Paint paint) { 152: if (paint == null) { 153: throw new IllegalArgumentException("Null 'paint' argument."); 154: } 155: this.backgroundPaint = paint; 156: notifyListeners(new DialLayerChangeEvent(this)); 157: } 158: 159: /** 160: * Returns the foreground paint. 161: * 162: * @return The foreground paint (never <code>null</code>). 163: * 164: * @see #setForegroundPaint(Paint) 165: */ 166: public Paint getForegroundPaint() { 167: return this.foregroundPaint; 168: } 169: 170: /** 171: * Sets the foreground paint and sends a {@link DialLayerChangeEvent} to 172: * all registered listeners. 173: * 174: * @param paint the paint (<code>null</code> not permitted). 175: * 176: * @see #getForegroundPaint() 177: */ 178: public void setForegroundPaint(Paint paint) { 179: if (paint == null) { 180: throw new IllegalArgumentException("Null 'paint' argument."); 181: } 182: this.foregroundPaint = paint; 183: notifyListeners(new DialLayerChangeEvent(this)); 184: } 185: 186: /** 187: * Returns the stroke for the frame. 188: * 189: * @return The stroke (never <code>null</code>). 190: * 191: * @see #setStroke(Stroke) 192: */ 193: public Stroke getStroke() { 194: return this.stroke; 195: } 196: 197: /** 198: * Sets the stroke and sends a {@link DialLayerChangeEvent} to all 199: * registered listeners. 200: * 201: * @param stroke the stroke (<code>null</code> not permitted). 202: * 203: * @see #getStroke() 204: */ 205: public void setStroke(Stroke stroke) { 206: if (stroke == null) { 207: throw new IllegalArgumentException("Null 'stroke' argument."); 208: } 209: this.stroke = stroke; 210: notifyListeners(new DialLayerChangeEvent(this)); 211: } 212: 213: /** 214: * Returns the shape for the window for this dial. Some dial layers will 215: * request that their drawing be clipped within this window. 216: * 217: * @param frame the reference frame (<code>null</code> not permitted). 218: * 219: * @return The shape of the dial's window. 220: */ 221: public Shape getWindow(Rectangle2D frame) { 222: Rectangle2D f = DialPlot.rectangleByRadius(frame, this.radius, 223: this.radius); 224: return new Ellipse2D.Double(f.getX(), f.getY(), f.getWidth(), 225: f.getHeight()); 226: } 227: 228: /** 229: * Returns <code>false</code> to indicate that this dial layer is not 230: * clipped to the dial window. 231: * 232: * @return A boolean. 233: */ 234: public boolean isClippedToWindow() { 235: return false; 236: } 237: 238: /** 239: * Draws the frame. This method is called by the {@link DialPlot} class, 240: * you shouldn't need to call it directly. 241: * 242: * @param g2 the graphics target (<code>null</code> not permitted). 243: * @param plot the plot (<code>null</code> not permitted). 244: * @param frame the frame (<code>null</code> not permitted). 245: * @param view the view (<code>null</code> not permitted). 246: */ 247: public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame, 248: Rectangle2D view) { 249: 250: Shape window = getWindow(frame); 251: 252: Rectangle2D f = DialPlot.rectangleByRadius(frame, this.radius + 0.02, 253: this.radius + 0.02); 254: Ellipse2D e = new Ellipse2D.Double(f.getX(), f.getY(), f.getWidth(), 255: f.getHeight()); 256: 257: Area area = new Area(e); 258: Area area2 = new Area(window); 259: area.subtract(area2); 260: g2.setPaint(this.backgroundPaint); 261: g2.fill(area); 262: 263: g2.setStroke(this.stroke); 264: g2.setPaint(this.foregroundPaint); 265: g2.draw(window); 266: g2.draw(e); 267: } 268: 269: /** 270: * Tests this instance for equality with an arbitrary object. 271: * 272: * @param obj the object (<code>null</code> permitted). 273: * 274: * @return A boolean. 275: */ 276: public boolean equals(Object obj) { 277: if (obj == this) { 278: return true; 279: } 280: if (!(obj instanceof StandardDialFrame)) { 281: return false; 282: } 283: StandardDialFrame that = (StandardDialFrame) obj; 284: if (!PaintUtilities.equal(this.backgroundPaint, that.backgroundPaint)) { 285: return false; 286: } 287: if (!PaintUtilities.equal(this.foregroundPaint, that.foregroundPaint)) { 288: return false; 289: } 290: if (this.radius != that.radius) { 291: return false; 292: } 293: if (!this.stroke.equals(that.stroke)) { 294: return false; 295: } 296: return super.equals(obj); 297: } 298: 299: /** 300: * Returns a hash code for this instance. 301: * 302: * @return The hash code. 303: */ 304: public int hashCode() { 305: int result = 193; 306: long temp = Double.doubleToLongBits(this.radius); 307: result = 37 * result + (int) (temp ^ (temp >>> 32)); 308: result = 37 * result + HashUtilities.hashCodeForPaint( 309: this.backgroundPaint); 310: result = 37 * result + HashUtilities.hashCodeForPaint( 311: this.foregroundPaint); 312: result = 37 * result + this.stroke.hashCode(); 313: return result; 314: } 315: 316: /** 317: * Returns a clone of this instance. 318: * 319: * @return A clone. 320: * 321: * @throws CloneNotSupportedException if any of the frame's attributes 322: * cannot be cloned. 323: */ 324: public Object clone() throws CloneNotSupportedException { 325: return super.clone(); 326: } 327: 328: /** 329: * Provides serialization support. 330: * 331: * @param stream the output stream. 332: * 333: * @throws IOException if there is an I/O error. 334: */ 335: private void writeObject(ObjectOutputStream stream) throws IOException { 336: stream.defaultWriteObject(); 337: SerialUtilities.writePaint(this.backgroundPaint, stream); 338: SerialUtilities.writePaint(this.foregroundPaint, stream); 339: SerialUtilities.writeStroke(this.stroke, stream); 340: } 341: 342: /** 343: * Provides serialization support. 344: * 345: * @param stream the input stream. 346: * 347: * @throws IOException if there is an I/O error. 348: * @throws ClassNotFoundException if there is a classpath problem. 349: */ 350: private void readObject(ObjectInputStream stream) 351: throws IOException, ClassNotFoundException { 352: stream.defaultReadObject(); 353: this.backgroundPaint = SerialUtilities.readPaint(stream); 354: this.foregroundPaint = SerialUtilities.readPaint(stream); 355: this.stroke = SerialUtilities.readStroke(stream); 356: } 357: 358: }