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 * Changes:
036 * --------
037 * 21-May-2003 : Version 1 (DG);
038 * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
039 * 30-Sep-2004 : Added support for tool tips and URLs (DG);
040 *
041 */
042
043 package org.jfree.chart.annotations;
044
045 import java.awt.Graphics2D;
046 import java.awt.geom.Rectangle2D;
047 import java.io.Serializable;
048
049 import org.jfree.chart.axis.ValueAxis;
050 import org.jfree.chart.plot.Plot;
051 import org.jfree.chart.plot.PlotOrientation;
052 import org.jfree.chart.plot.PlotRenderingInfo;
053 import org.jfree.chart.plot.XYPlot;
054 import org.jfree.ui.Drawable;
055 import org.jfree.ui.RectangleEdge;
056 import org.jfree.util.ObjectUtilities;
057 import org.jfree.util.PublicCloneable;
058
059 /**
060 * A general annotation that can be placed on an {@link XYPlot}.
061 */
062 public class XYDrawableAnnotation extends AbstractXYAnnotation
063 implements Cloneable, PublicCloneable,
064 Serializable {
065
066 /** For serialization. */
067 private static final long serialVersionUID = -6540812859722691020L;
068
069 /** The x-coordinate. */
070 private double x;
071
072 /** The y-coordinate. */
073 private double y;
074
075 /** The width. */
076 private double width;
077
078 /** The height. */
079 private double height;
080
081 /** The drawable object. */
082 private Drawable drawable;
083
084 /**
085 * Creates a new annotation to be displayed within the given area.
086 *
087 * @param x the x-coordinate for the area.
088 * @param y the y-coordinate for the area.
089 * @param width the width of the area.
090 * @param height the height of the area.
091 * @param drawable the drawable object (<code>null</code> not permitted).
092 */
093 public XYDrawableAnnotation(double x, double y, double width, double height,
094 Drawable drawable) {
095
096 if (drawable == null) {
097 throw new IllegalArgumentException("Null 'drawable' argument.");
098 }
099 this.x = x;
100 this.y = y;
101 this.width = width;
102 this.height = height;
103 this.drawable = drawable;
104
105 }
106
107 /**
108 * Draws the annotation.
109 *
110 * @param g2 the graphics device.
111 * @param plot the plot.
112 * @param dataArea the data area.
113 * @param domainAxis the domain axis.
114 * @param rangeAxis the range axis.
115 * @param rendererIndex the renderer index.
116 * @param info if supplied, this info object will be populated with
117 * entity information.
118 */
119 public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea,
120 ValueAxis domainAxis, ValueAxis rangeAxis,
121 int rendererIndex,
122 PlotRenderingInfo info) {
123
124 PlotOrientation orientation = plot.getOrientation();
125 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
126 plot.getDomainAxisLocation(), orientation);
127 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
128 plot.getRangeAxisLocation(), orientation);
129 float j2DX = (float) domainAxis.valueToJava2D(this.x, dataArea,
130 domainEdge);
131 float j2DY = (float) rangeAxis.valueToJava2D(this.y, dataArea,
132 rangeEdge);
133 Rectangle2D area = new Rectangle2D.Double(j2DX - this.width / 2.0,
134 j2DY - this.height / 2.0, this.width, this.height);
135 this.drawable.draw(g2, area);
136 String toolTip = getToolTipText();
137 String url = getURL();
138 if (toolTip != null || url != null) {
139 addEntity(info, area, rendererIndex, toolTip, url);
140 }
141
142 }
143
144 /**
145 * Tests this annotation for equality with an arbitrary object.
146 *
147 * @param obj the object to test against.
148 *
149 * @return <code>true</code> or <code>false</code>.
150 */
151 public boolean equals(Object obj) {
152
153 if (obj == this) { // simple case
154 return true;
155 }
156 // now try to reject equality...
157 if (!super.equals(obj)) {
158 return false;
159 }
160 if (!(obj instanceof XYDrawableAnnotation)) {
161 return false;
162 }
163 XYDrawableAnnotation that = (XYDrawableAnnotation) obj;
164 if (this.x != that.x) {
165 return false;
166 }
167 if (this.y != that.y) {
168 return false;
169 }
170 if (this.width != that.width) {
171 return false;
172 }
173 if (this.height != that.height) {
174 return false;
175 }
176 if (!ObjectUtilities.equal(this.drawable, that.drawable)) {
177 return false;
178 }
179 // seem to be the same...
180 return true;
181
182 }
183
184 /**
185 * Returns a hash code.
186 *
187 * @return A hash code.
188 */
189 public int hashCode() {
190 int result;
191 long temp;
192 temp = Double.doubleToLongBits(this.x);
193 result = (int) (temp ^ (temp >>> 32));
194 temp = Double.doubleToLongBits(this.y);
195 result = 29 * result + (int) (temp ^ (temp >>> 32));
196 temp = Double.doubleToLongBits(this.width);
197 result = 29 * result + (int) (temp ^ (temp >>> 32));
198 temp = Double.doubleToLongBits(this.height);
199 result = 29 * result + (int) (temp ^ (temp >>> 32));
200 return result;
201 }
202
203 /**
204 * Returns a clone of the annotation.
205 *
206 * @return A clone.
207 *
208 * @throws CloneNotSupportedException if the annotation can't be cloned.
209 */
210 public Object clone() throws CloneNotSupportedException {
211 return super.clone();
212 }
213
214 }