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
043package org.jfree.chart.annotations;
044
045import java.awt.Graphics2D;
046import java.awt.geom.Rectangle2D;
047import java.io.Serializable;
048
049import org.jfree.chart.axis.ValueAxis;
050import org.jfree.chart.plot.Plot;
051import org.jfree.chart.plot.PlotOrientation;
052import org.jfree.chart.plot.PlotRenderingInfo;
053import org.jfree.chart.plot.XYPlot;
054import org.jfree.ui.Drawable;
055import org.jfree.ui.RectangleEdge;
056import org.jfree.util.ObjectUtilities;
057import org.jfree.util.PublicCloneable;
058
059/**
060 * A general annotation that can be placed on an {@link XYPlot}.
061 */
062public 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}