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