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