001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, 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-2008, 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, Serializable {
064
065 /** For serialization. */
066 private static final long serialVersionUID = -6540812859722691020L;
067
068 /** The x-coordinate. */
069 private double x;
070
071 /** The y-coordinate. */
072 private double y;
073
074 /** The width. */
075 private double width;
076
077 /** The height. */
078 private double height;
079
080 /** The drawable object. */
081 private Drawable drawable;
082
083 /**
084 * Creates a new annotation to be displayed within the given area.
085 *
086 * @param x the x-coordinate for the area.
087 * @param y the y-coordinate for the area.
088 * @param width the width of the area.
089 * @param height the height of the area.
090 * @param drawable the drawable object (<code>null</code> not permitted).
091 */
092 public XYDrawableAnnotation(double x, double y, double width, double height,
093 Drawable drawable) {
094
095 if (drawable == null) {
096 throw new IllegalArgumentException("Null 'drawable' argument.");
097 }
098 this.x = x;
099 this.y = y;
100 this.width = width;
101 this.height = height;
102 this.drawable = drawable;
103
104 }
105
106 /**
107 * Draws the annotation.
108 *
109 * @param g2 the graphics device.
110 * @param plot the plot.
111 * @param dataArea the data area.
112 * @param domainAxis the domain axis.
113 * @param rangeAxis the range axis.
114 * @param rendererIndex the renderer index.
115 * @param info if supplied, this info object will be populated with
116 * entity information.
117 */
118 public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea,
119 ValueAxis domainAxis, ValueAxis rangeAxis,
120 int rendererIndex,
121 PlotRenderingInfo info) {
122
123 PlotOrientation orientation = plot.getOrientation();
124 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
125 plot.getDomainAxisLocation(), orientation);
126 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
127 plot.getRangeAxisLocation(), orientation);
128 float j2DX = (float) domainAxis.valueToJava2D(this.x, dataArea,
129 domainEdge);
130 float j2DY = (float) rangeAxis.valueToJava2D(this.y, dataArea,
131 rangeEdge);
132 Rectangle2D area = new Rectangle2D.Double(j2DX - this.width / 2.0,
133 j2DY - this.height / 2.0, this.width, this.height);
134 this.drawable.draw(g2, area);
135 String toolTip = getToolTipText();
136 String url = getURL();
137 if (toolTip != null || url != null) {
138 addEntity(info, area, rendererIndex, toolTip, url);
139 }
140
141 }
142
143 /**
144 * Tests this annotation for equality with an arbitrary object.
145 *
146 * @param obj the object to test against.
147 *
148 * @return <code>true</code> or <code>false</code>.
149 */
150 public boolean equals(Object obj) {
151
152 if (obj == this) { // simple case
153 return true;
154 }
155 // now try to reject equality...
156 if (!super.equals(obj)) {
157 return false;
158 }
159 if (!(obj instanceof XYDrawableAnnotation)) {
160 return false;
161 }
162 XYDrawableAnnotation that = (XYDrawableAnnotation) obj;
163 if (this.x != that.x) {
164 return false;
165 }
166 if (this.y != that.y) {
167 return false;
168 }
169 if (this.width != that.width) {
170 return false;
171 }
172 if (this.height != that.height) {
173 return false;
174 }
175 if (!ObjectUtilities.equal(this.drawable, that.drawable)) {
176 return false;
177 }
178 // seem to be the same...
179 return true;
180
181 }
182
183 /**
184 * Returns a hash code.
185 *
186 * @return A hash code.
187 */
188 public int hashCode() {
189 int result;
190 long temp;
191 temp = Double.doubleToLongBits(this.x);
192 result = (int) (temp ^ (temp >>> 32));
193 temp = Double.doubleToLongBits(this.y);
194 result = 29 * result + (int) (temp ^ (temp >>> 32));
195 temp = Double.doubleToLongBits(this.width);
196 result = 29 * result + (int) (temp ^ (temp >>> 32));
197 temp = Double.doubleToLongBits(this.height);
198 result = 29 * result + (int) (temp ^ (temp >>> 32));
199 return result;
200 }
201
202 /**
203 * Returns a clone of the annotation.
204 *
205 * @return A clone.
206 *
207 * @throws CloneNotSupportedException if the annotation can't be cloned.
208 */
209 public Object clone() throws CloneNotSupportedException {
210 return super.clone();
211 }
212
213 }