Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2006, 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: * XYBoxAnnotation.java 29: * -------------------- 30: * (C) Copyright 2005, 2006, by Object Refinery Limited and Contributors. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: XYBoxAnnotation.java,v 1.5.2.3 2006/08/02 11:49:10 mungady Exp $ 36: * 37: * Changes: 38: * -------- 39: * 19-Jan-2005 : Version 1 (DG); 40: * 06-Jun-2005 : Fixed equals() method to handle GradientPaint (DG); 41: * 42: */ 43: 44: package org.jfree.chart.annotations; 45: 46: import java.awt.BasicStroke; 47: import java.awt.Color; 48: import java.awt.Graphics2D; 49: import java.awt.Paint; 50: import java.awt.Stroke; 51: import java.awt.geom.Rectangle2D; 52: import java.io.IOException; 53: import java.io.ObjectInputStream; 54: import java.io.ObjectOutputStream; 55: import java.io.Serializable; 56: 57: import org.jfree.chart.axis.ValueAxis; 58: import org.jfree.chart.plot.Plot; 59: import org.jfree.chart.plot.PlotOrientation; 60: import org.jfree.chart.plot.PlotRenderingInfo; 61: import org.jfree.chart.plot.XYPlot; 62: import org.jfree.io.SerialUtilities; 63: import org.jfree.ui.RectangleEdge; 64: import org.jfree.util.ObjectUtilities; 65: import org.jfree.util.PaintUtilities; 66: import org.jfree.util.PublicCloneable; 67: 68: /** 69: * A box annotation that can be placed on an {@link XYPlot}. The 70: * box coordinates are specified in data space. 71: */ 72: public class XYBoxAnnotation extends AbstractXYAnnotation 73: implements Cloneable, 74: PublicCloneable, 75: Serializable { 76: 77: /** For serialization. */ 78: private static final long serialVersionUID = 6764703772526757457L; 79: 80: /** The lower x-coordinate. */ 81: private double x0; 82: 83: /** The lower y-coordinate. */ 84: private double y0; 85: 86: /** The upper x-coordinate. */ 87: private double x1; 88: 89: /** The upper y-coordinate. */ 90: private double y1; 91: 92: /** The stroke used to draw the box outline. */ 93: private transient Stroke stroke; 94: 95: /** The paint used to draw the box outline. */ 96: private transient Paint outlinePaint; 97: 98: /** The paint used to fill the box. */ 99: private transient Paint fillPaint; 100: 101: /** 102: * Creates a new annotation (where, by default, the box is drawn 103: * with a black outline). 104: * 105: * @param x0 the lower x-coordinate of the box (in data space). 106: * @param y0 the lower y-coordinate of the box (in data space). 107: * @param x1 the upper x-coordinate of the box (in data space). 108: * @param y1 the upper y-coordinate of the box (in data space). 109: */ 110: public XYBoxAnnotation(double x0, double y0, double x1, double y1) { 111: this(x0, y0, x1, y1, new BasicStroke(1.0f), Color.black); 112: } 113: 114: /** 115: * Creates a new annotation where the box is drawn as an outline using 116: * the specified <code>stroke</code> and <code>outlinePaint</code>. 117: * 118: * @param x0 the lower x-coordinate of the box (in data space). 119: * @param y0 the lower y-coordinate of the box (in data space). 120: * @param x1 the upper x-coordinate of the box (in data space). 121: * @param y1 the upper y-coordinate of the box (in data space). 122: * @param stroke the shape stroke (<code>null</code> permitted). 123: * @param outlinePaint the shape color (<code>null</code> permitted). 124: */ 125: public XYBoxAnnotation(double x0, double y0, double x1, double y1, 126: Stroke stroke, Paint outlinePaint) { 127: this(x0, y0, x1, y1, stroke, outlinePaint, null); 128: } 129: 130: /** 131: * Creates a new annotation. 132: * 133: * @param x0 the lower x-coordinate of the box (in data space). 134: * @param y0 the lower y-coordinate of the box (in data space). 135: * @param x1 the upper x-coordinate of the box (in data space). 136: * @param y1 the upper y-coordinate of the box (in data space). 137: * @param stroke the shape stroke (<code>null</code> permitted). 138: * @param outlinePaint the shape color (<code>null</code> permitted). 139: * @param fillPaint the paint used to fill the shape (<code>null</code> 140: * permitted). 141: */ 142: public XYBoxAnnotation(double x0, double y0, double x1, double y1, 143: Stroke stroke, Paint outlinePaint, Paint fillPaint) { 144: this.x0 = x0; 145: this.y0 = y0; 146: this.x1 = x1; 147: this.y1 = y1; 148: this.stroke = stroke; 149: this.outlinePaint = outlinePaint; 150: this.fillPaint = fillPaint; 151: } 152: 153: /** 154: * Draws the annotation. This method is usually called by the 155: * {@link XYPlot} class, you shouldn't need to call it directly. 156: * 157: * @param g2 the graphics device. 158: * @param plot the plot. 159: * @param dataArea the data area. 160: * @param domainAxis the domain axis. 161: * @param rangeAxis the range axis. 162: * @param rendererIndex the renderer index. 163: * @param info the plot rendering info. 164: */ 165: public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, 166: ValueAxis domainAxis, ValueAxis rangeAxis, 167: int rendererIndex, PlotRenderingInfo info) { 168: 169: PlotOrientation orientation = plot.getOrientation(); 170: RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( 171: plot.getDomainAxisLocation(), orientation); 172: RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( 173: plot.getRangeAxisLocation(), orientation); 174: 175: double transX0 = domainAxis.valueToJava2D(this.x0, dataArea, 176: domainEdge); 177: double transY0 = rangeAxis.valueToJava2D(this.y0, dataArea, rangeEdge); 178: double transX1 = domainAxis.valueToJava2D(this.x1, dataArea, 179: domainEdge); 180: double transY1 = rangeAxis.valueToJava2D(this.y1, dataArea, rangeEdge); 181: 182: Rectangle2D box = null; 183: if (orientation == PlotOrientation.HORIZONTAL) { 184: box = new Rectangle2D.Double(transY0, transX1, transY1 - transY0, 185: transX0 - transX1); 186: } 187: else if (orientation == PlotOrientation.VERTICAL) { 188: box = new Rectangle2D.Double(transX0, transY1, transX1 - transX0, 189: transY0 - transY1); 190: } 191: 192: if (this.fillPaint != null) { 193: g2.setPaint(this.fillPaint); 194: g2.fill(box); 195: } 196: 197: if (this.stroke != null && this.outlinePaint != null) { 198: g2.setPaint(this.outlinePaint); 199: g2.setStroke(this.stroke); 200: g2.draw(box); 201: } 202: addEntity(info, box, rendererIndex, getToolTipText(), getURL()); 203: 204: } 205: 206: /** 207: * Tests this annotation for equality with an arbitrary object. 208: * 209: * @param obj the object (<code>null</code> permitted). 210: * 211: * @return A boolean. 212: */ 213: public boolean equals(Object obj) { 214: if (obj == this) { 215: return true; 216: } 217: // now try to reject equality 218: if (!super.equals(obj)) { 219: return false; 220: } 221: if (!(obj instanceof XYBoxAnnotation)) { 222: return false; 223: } 224: XYBoxAnnotation that = (XYBoxAnnotation) obj; 225: if (!(this.x0 == that.x0)) { 226: return false; 227: } 228: if (!(this.y0 == that.y0)) { 229: return false; 230: } 231: if (!(this.x1 == that.x1)) { 232: return false; 233: } 234: if (!(this.y1 == that.y1)) { 235: return false; 236: } 237: if (!ObjectUtilities.equal(this.stroke, that.stroke)) { 238: return false; 239: } 240: if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) { 241: return false; 242: } 243: if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) { 244: return false; 245: } 246: // seem to be the same 247: return true; 248: } 249: 250: /** 251: * Returns a hash code. 252: * 253: * @return A hash code. 254: */ 255: public int hashCode() { 256: int result; 257: long temp; 258: temp = Double.doubleToLongBits(this.x0); 259: result = (int) (temp ^ (temp >>> 32)); 260: temp = Double.doubleToLongBits(this.x1); 261: result = 29 * result + (int) (temp ^ (temp >>> 32)); 262: temp = Double.doubleToLongBits(this.y0); 263: result = 29 * result + (int) (temp ^ (temp >>> 32)); 264: temp = Double.doubleToLongBits(this.y1); 265: result = 29 * result + (int) (temp ^ (temp >>> 32)); 266: return result; 267: } 268: 269: /** 270: * Returns a clone. 271: * 272: * @return A clone. 273: * 274: * @throws CloneNotSupportedException not thrown by this class, but may be 275: * by subclasses. 276: */ 277: public Object clone() throws CloneNotSupportedException { 278: return super.clone(); 279: } 280: 281: /** 282: * Provides serialization support. 283: * 284: * @param stream the output stream (<code>null</code> not permitted). 285: * 286: * @throws IOException if there is an I/O error. 287: */ 288: private void writeObject(ObjectOutputStream stream) throws IOException { 289: stream.defaultWriteObject(); 290: SerialUtilities.writeStroke(this.stroke, stream); 291: SerialUtilities.writePaint(this.outlinePaint, stream); 292: SerialUtilities.writePaint(this.fillPaint, stream); 293: } 294: 295: /** 296: * Provides serialization support. 297: * 298: * @param stream the input stream (<code>null</code> not permitted). 299: * 300: * @throws IOException if there is an I/O error. 301: * @throws ClassNotFoundException if there is a classpath problem. 302: */ 303: private void readObject(ObjectInputStream stream) 304: throws IOException, ClassNotFoundException { 305: 306: stream.defaultReadObject(); 307: this.stroke = SerialUtilities.readStroke(stream); 308: this.outlinePaint = SerialUtilities.readPaint(stream); 309: this.fillPaint = SerialUtilities.readPaint(stream); 310: } 311: 312: }