001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * -------------------------
028 * XYDrawableAnnotation.java
029 * -------------------------
030 * (C) Copyright 2003-2007, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * $Id: XYDrawableAnnotation.java,v 1.6.2.2 2007/03/06 16:12:18 mungady Exp $
036 *
037 * Changes:
038 * --------
039 * 21-May-2003 : Version 1 (DG);
040 * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
041 * 30-Sep-2004 : Added support for tool tips and URLs (DG);
042 *
043 */
044
045 package org.jfree.chart.annotations;
046
047 import java.awt.Graphics2D;
048 import java.awt.geom.Rectangle2D;
049 import java.io.Serializable;
050
051 import org.jfree.chart.axis.ValueAxis;
052 import org.jfree.chart.plot.Plot;
053 import org.jfree.chart.plot.PlotOrientation;
054 import org.jfree.chart.plot.PlotRenderingInfo;
055 import org.jfree.chart.plot.XYPlot;
056 import org.jfree.ui.Drawable;
057 import org.jfree.ui.RectangleEdge;
058 import org.jfree.util.ObjectUtilities;
059 import org.jfree.util.PublicCloneable;
060
061 /**
062 * A general annotation that can be placed on an {@link XYPlot}.
063 */
064 public class XYDrawableAnnotation extends AbstractXYAnnotation
065 implements Cloneable, PublicCloneable,
066 Serializable {
067
068 /** For serialization. */
069 private static final long serialVersionUID = -6540812859722691020L;
070
071 /** The x-coordinate. */
072 private double x;
073
074 /** The y-coordinate. */
075 private double y;
076
077 /** The width. */
078 private double width;
079
080 /** The height. */
081 private double height;
082
083 /** The drawable object. */
084 private Drawable drawable;
085
086 /**
087 * Creates a new annotation to be displayed within the given area.
088 *
089 * @param x the x-coordinate for the area.
090 * @param y the y-coordinate for the area.
091 * @param width the width of the area.
092 * @param height the height of the area.
093 * @param drawable the drawable object (<code>null</code> not permitted).
094 */
095 public XYDrawableAnnotation(double x, double y, double width, double height,
096 Drawable drawable) {
097
098 if (drawable == null) {
099 throw new IllegalArgumentException("Null 'drawable' argument.");
100 }
101 this.x = x;
102 this.y = y;
103 this.width = width;
104 this.height = height;
105 this.drawable = drawable;
106
107 }
108
109 /**
110 * Draws the annotation.
111 *
112 * @param g2 the graphics device.
113 * @param plot the plot.
114 * @param dataArea the data area.
115 * @param domainAxis the domain axis.
116 * @param rangeAxis the range axis.
117 * @param rendererIndex the renderer index.
118 * @param info if supplied, this info object will be populated with
119 * entity information.
120 */
121 public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea,
122 ValueAxis domainAxis, ValueAxis rangeAxis,
123 int rendererIndex,
124 PlotRenderingInfo info) {
125
126 PlotOrientation orientation = plot.getOrientation();
127 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
128 plot.getDomainAxisLocation(), orientation);
129 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
130 plot.getRangeAxisLocation(), orientation);
131 float j2DX = (float) domainAxis.valueToJava2D(this.x, dataArea,
132 domainEdge);
133 float j2DY = (float) rangeAxis.valueToJava2D(this.y, dataArea,
134 rangeEdge);
135 Rectangle2D area = new Rectangle2D.Double(j2DX - this.width / 2.0,
136 j2DY - this.height / 2.0, this.width, this.height);
137 this.drawable.draw(g2, area);
138 String toolTip = getToolTipText();
139 String url = getURL();
140 if (toolTip != null || url != null) {
141 addEntity(info, area, rendererIndex, toolTip, url);
142 }
143
144 }
145
146 /**
147 * Tests this annotation for equality with an arbitrary object.
148 *
149 * @param obj the object to test against.
150 *
151 * @return <code>true</code> or <code>false</code>.
152 */
153 public boolean equals(Object obj) {
154
155 if (obj == this) { // simple case
156 return true;
157 }
158 // now try to reject equality...
159 if (!super.equals(obj)) {
160 return false;
161 }
162 if (!(obj instanceof XYDrawableAnnotation)) {
163 return false;
164 }
165 XYDrawableAnnotation that = (XYDrawableAnnotation) obj;
166 if (this.x != that.x) {
167 return false;
168 }
169 if (this.y != that.y) {
170 return false;
171 }
172 if (this.width != that.width) {
173 return false;
174 }
175 if (this.height != that.height) {
176 return false;
177 }
178 if (!ObjectUtilities.equal(this.drawable, that.drawable)) {
179 return false;
180 }
181 // seem to be the same...
182 return true;
183
184 }
185
186 /**
187 * Returns a hash code.
188 *
189 * @return A hash code.
190 */
191 public int hashCode() {
192 int result;
193 long temp;
194 temp = Double.doubleToLongBits(this.x);
195 result = (int) (temp ^ (temp >>> 32));
196 temp = Double.doubleToLongBits(this.y);
197 result = 29 * result + (int) (temp ^ (temp >>> 32));
198 temp = Double.doubleToLongBits(this.width);
199 result = 29 * result + (int) (temp ^ (temp >>> 32));
200 temp = Double.doubleToLongBits(this.height);
201 result = 29 * result + (int) (temp ^ (temp >>> 32));
202 return result;
203 }
204
205 /**
206 * Returns a clone of the annotation.
207 *
208 * @return A clone.
209 *
210 * @throws CloneNotSupportedException if the annotation can't be cloned.
211 */
212 public Object clone() throws CloneNotSupportedException {
213 return super.clone();
214 }
215
216 }