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: * XYImageAnnotation.java 29: * ---------------------- 30: * (C) Copyright 2003-2006, by Object Refinery Limited and Contributors. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): Mike Harris; 34: * 35: * $Id: XYImageAnnotation.java,v 1.8.2.2 2006/12/01 15:57:33 mungady Exp $ 36: * 37: * Changes: 38: * -------- 39: * 01-Dec-2003 : Version 1 (DG); 40: * 21-Jan-2004 : Update for renamed method in ValueAxis (DG); 41: * 18-May-2004 : Fixed bug with plot orientation (DG); 42: * 29-Sep-2004 : Now extends AbstractXYAnnotation, with modified draw() 43: * method signature and updated equals() method (DG); 44: * ------------- JFREECHART 1.0.x --------------------------------------------- 45: * 01-Dec-2006 : Added anchor attribute (see patch 1584860 from 46: * Mike Harris) (DG); 47: */ 48: 49: package org.jfree.chart.annotations; 50: 51: import java.awt.Graphics2D; 52: import java.awt.Image; 53: import java.awt.geom.Point2D; 54: import java.awt.geom.Rectangle2D; 55: import java.io.IOException; 56: import java.io.ObjectInputStream; 57: import java.io.ObjectOutputStream; 58: import java.io.Serializable; 59: 60: import org.jfree.chart.axis.AxisLocation; 61: import org.jfree.chart.axis.ValueAxis; 62: import org.jfree.chart.plot.Plot; 63: import org.jfree.chart.plot.PlotOrientation; 64: import org.jfree.chart.plot.PlotRenderingInfo; 65: import org.jfree.chart.plot.XYPlot; 66: import org.jfree.ui.RectangleAnchor; 67: import org.jfree.ui.RectangleEdge; 68: import org.jfree.util.ObjectUtilities; 69: import org.jfree.util.PublicCloneable; 70: 71: /** 72: * An annotation that allows an image to be placed at some location on 73: * an {@link XYPlot}. 74: * 75: * TODO: implement serialization properly (image is not serializable). 76: */ 77: public class XYImageAnnotation extends AbstractXYAnnotation 78: implements Cloneable, PublicCloneable, 79: Serializable { 80: 81: /** For serialization. */ 82: private static final long serialVersionUID = -4364694501921559958L; 83: 84: /** The x-coordinate (in data space). */ 85: private double x; 86: 87: /** The y-coordinate (in data space). */ 88: private double y; 89: 90: /** The image. */ 91: private transient Image image; 92: 93: /** 94: * The image anchor point. 95: * 96: * @since 1.0.4 97: */ 98: private RectangleAnchor anchor; 99: 100: /** 101: * Creates a new annotation to be displayed at the specified (x, y) 102: * location. 103: * 104: * @param x the x-coordinate (in data space). 105: * @param y the y-coordinate (in data space). 106: * @param image the image (<code>null</code> not permitted). 107: */ 108: public XYImageAnnotation(double x, double y, Image image) { 109: this(x, y, image, RectangleAnchor.CENTER); 110: } 111: 112: /** 113: * Creates a new annotation to be displayed at the specified (x, y) 114: * location. 115: * 116: * @param x the x-coordinate (in data space). 117: * @param y the y-coordinate (in data space). 118: * @param image the image (<code>null</code> not permitted). 119: * @param anchor the image anchor (<code>null</code> not permitted). 120: * 121: * @since 1.0.4 122: */ 123: public XYImageAnnotation(double x, double y, Image image, 124: RectangleAnchor anchor) { 125: if (image == null) { 126: throw new IllegalArgumentException("Null 'image' argument."); 127: } 128: if (anchor == null) { 129: throw new IllegalArgumentException("Null 'anchor' argument."); 130: } 131: this.x = x; 132: this.y = y; 133: this.image = image; 134: this.anchor = anchor; 135: } 136: 137: /** 138: * Returns the x-coordinate (in data space) for the annotation. 139: * 140: * @return The x-coordinate. 141: * 142: * @since 1.0.4 143: */ 144: public double getX() { 145: return this.x; 146: } 147: 148: /** 149: * Returns the y-coordinate (in data space) for the annotation. 150: * 151: * @return The y-coordinate. 152: * 153: * @since 1.0.4 154: */ 155: public double getY() { 156: return this.y; 157: } 158: 159: /** 160: * Returns the image for the annotation. 161: * 162: * @return The image. 163: * 164: * @since 1.0.4 165: */ 166: public Image getImage() { 167: return this.image; 168: } 169: 170: /** 171: * Returns the image anchor for the annotation. 172: * 173: * @return The image anchor. 174: * 175: * @since 1.0.4 176: */ 177: public RectangleAnchor getImageAnchor() { 178: return this.anchor; 179: } 180: 181: /** 182: * Draws the annotation. This method is called by the drawing code in the 183: * {@link XYPlot} class, you don't normally need to call this method 184: * directly. 185: * 186: * @param g2 the graphics device. 187: * @param plot the plot. 188: * @param dataArea the data area. 189: * @param domainAxis the domain axis. 190: * @param rangeAxis the range axis. 191: * @param rendererIndex the renderer index. 192: * @param info if supplied, this info object will be populated with 193: * entity information. 194: */ 195: public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, 196: ValueAxis domainAxis, ValueAxis rangeAxis, 197: int rendererIndex, 198: PlotRenderingInfo info) { 199: 200: PlotOrientation orientation = plot.getOrientation(); 201: AxisLocation domainAxisLocation = plot.getDomainAxisLocation(); 202: AxisLocation rangeAxisLocation = plot.getRangeAxisLocation(); 203: RectangleEdge domainEdge 204: = Plot.resolveDomainAxisLocation(domainAxisLocation, orientation); 205: RectangleEdge rangeEdge 206: = Plot.resolveRangeAxisLocation(rangeAxisLocation, orientation); 207: float j2DX 208: = (float) domainAxis.valueToJava2D(this.x, dataArea, domainEdge); 209: float j2DY 210: = (float) rangeAxis.valueToJava2D(this.y, dataArea, rangeEdge); 211: float xx = 0.0f; 212: float yy = 0.0f; 213: if (orientation == PlotOrientation.HORIZONTAL) { 214: xx = j2DY; 215: yy = j2DX; 216: } 217: else if (orientation == PlotOrientation.VERTICAL) { 218: xx = j2DX; 219: yy = j2DY; 220: } 221: int w = this.image.getWidth(null); 222: int h = this.image.getHeight(null); 223: 224: Rectangle2D imageRect = new Rectangle2D.Double(0, 0, w, h); 225: Point2D anchorPoint = (Point2D) RectangleAnchor.coordinates(imageRect, 226: this.anchor); 227: xx = xx - (float) anchorPoint.getX(); 228: yy = yy - (float) anchorPoint.getY(); 229: g2.drawImage(this.image, (int) xx, (int) yy, null); 230: 231: String toolTip = getToolTipText(); 232: String url = getURL(); 233: if (toolTip != null || url != null) { 234: addEntity(info, new Rectangle2D.Float(xx, yy, w, h), rendererIndex, 235: toolTip, url); 236: } 237: } 238: 239: /** 240: * Tests this object for equality with an arbitrary object. 241: * 242: * @param obj the object (<code>null</code> permitted). 243: * 244: * @return A boolean. 245: */ 246: public boolean equals(Object obj) { 247: if (obj == this) { 248: return true; 249: } 250: // now try to reject equality... 251: if (!super.equals(obj)) { 252: return false; 253: } 254: if (!(obj instanceof XYImageAnnotation)) { 255: return false; 256: } 257: XYImageAnnotation that = (XYImageAnnotation) obj; 258: if (this.x != that.x) { 259: return false; 260: } 261: if (this.y != that.y) { 262: return false; 263: } 264: if (!ObjectUtilities.equal(this.image, that.image)) { 265: return false; 266: } 267: if (!this.anchor.equals(that.anchor)) { 268: return false; 269: } 270: // seems to be the same... 271: return true; 272: } 273: 274: /** 275: * Returns a hash code for this object. 276: * 277: * @return A hash code. 278: */ 279: public int hashCode() { 280: return this.image.hashCode(); 281: } 282: 283: /** 284: * Returns a clone of the annotation. 285: * 286: * @return A clone. 287: * 288: * @throws CloneNotSupportedException if the annotation can't be cloned. 289: */ 290: public Object clone() throws CloneNotSupportedException { 291: return super.clone(); 292: } 293: 294: /** 295: * Provides serialization support. 296: * 297: * @param stream the output stream. 298: * 299: * @throws IOException if there is an I/O error. 300: */ 301: private void writeObject(ObjectOutputStream stream) throws IOException { 302: stream.defaultWriteObject(); 303: //SerialUtilities.writeImage(this.image, stream); 304: } 305: 306: /** 307: * Provides serialization support. 308: * 309: * @param stream the input stream. 310: * 311: * @throws IOException if there is an I/O error. 312: * @throws ClassNotFoundException if there is a classpath problem. 313: */ 314: private void readObject(ObjectInputStream stream) 315: throws IOException, ClassNotFoundException { 316: stream.defaultReadObject(); 317: //this.image = SerialUtilities.readImage(stream); 318: } 319: 320: 321: }