001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2005, 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     * CrosshairState.java
029     * -------------------
030     * (C) Copyright 2002-2004, by Object Refinery Limited.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   -;
034     *
035     * $Id: CrosshairState.java,v 1.3.2.1 2005/10/25 20:52:07 mungady Exp $
036     *
037     * Changes
038     * -------
039     * 24-Jan-2002 : Version 1 (DG);
040     * 05-Mar-2002 : Added Javadoc comments (DG);
041     * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
042     * 19-Sep-2003 : Modified crosshair distance calculation (DG);
043     * 04-Dec-2003 : Crosshair anchor point now stored outside chart since it is
044     *               dependent on the display target (DG);
045     * 25-Feb-2004 : Replaced CrosshairInfo --> CrosshairState (DG);               
046     *
047     */
048    
049    package org.jfree.chart.plot;
050    
051    import java.awt.geom.Point2D;
052    
053    /**
054     * Maintains state information about crosshairs on a plot.
055     *
056     */
057    public class CrosshairState {
058    
059        /** 
060         * A flag that controls whether the distance is calculated in data space 
061         * or Java2D space. 
062         */
063        private boolean calculateDistanceInDataSpace = false;
064    
065        /** The x-value (in data space) for the anchor point. */
066        private double anchorX;
067    
068        /** The y-value (in data space) for the anchor point. */
069        private double anchorY;
070        
071        /** The anchor point in Java2D space - if null, don't update crosshair. */
072        private Point2D anchor;
073        
074        /** The x-value for the crosshair point. */
075        private double crosshairX;
076    
077        /** The y-value for the crosshair point. */
078        private double crosshairY;
079    
080        /** 
081         * The smallest distance so far between the anchor point and a data point. 
082         */
083        private double distance;
084    
085        /**
086         * Default constructor.
087         */
088        public CrosshairState() {
089            this(false);
090        }
091    
092        /**
093         * Creates a new info object.
094         * 
095         * @param calculateDistanceInDataSpace  a flag that controls whether the 
096         *                                      distance is calculated in data 
097         *                                      space or Java2D space.
098         */
099        public CrosshairState(boolean calculateDistanceInDataSpace) {
100            this.calculateDistanceInDataSpace = calculateDistanceInDataSpace;
101        }
102    
103        /**
104         * Sets the distance between the anchor point and the current crosshair 
105         * point.  As each data point is processed, its distance to the anchor 
106         * point is compared with this value and, if it is closer, the data point 
107         * becomes the new crosshair point.
108         *
109         * @param distance  the distance.
110         */
111        public void setCrosshairDistance(double distance) {
112            this.distance = distance;
113        }
114    
115        /**
116         * Evaluates a data point and if it is the closest to the anchor point it
117         * becomes the new crosshair point.
118         * <P>
119         * To understand this method, you need to know the context in which it will
120         * be called.  An instance of this class is passed to an 
121         * {@link org.jfree.chart.renderer.xy.XYItemRenderer} as
122         * each data point is plotted.  As the point is plotted, it is passed to
123         * this method to see if it should be the new crosshair point.
124         *
125         * @param x  x coordinate (measured against the domain axis).
126         * @param y  y coordinate (measured against the range axis).
127         * @param transX  x translated into Java2D space.
128         * @param transY  y translated into Java2D space.
129         * @param orientation  the plot orientation.
130         */
131        public void updateCrosshairPoint(double x, double y, 
132                                         double transX, double transY, 
133                                         PlotOrientation orientation) {
134    
135            if (this.anchor != null) {
136                double d = 0.0;
137                if (this.calculateDistanceInDataSpace) {
138                    d = (x - this.anchorX) * (x - this.anchorX)
139                      + (y - this.anchorY) * (y - this.anchorY);
140                }
141                else {
142                    double xx = this.anchor.getX();
143                    double yy = this.anchor.getY();
144                    if (orientation == PlotOrientation.HORIZONTAL) {
145                        double temp = yy;
146                        yy = xx;
147                        xx = temp;
148                    }
149                    d = (transX - xx) * (transX - xx) 
150                        + (transY - yy) * (transY - yy);            
151                }
152    
153                if (d < this.distance) {
154                    this.crosshairX = x;
155                    this.crosshairY = y;
156                    this.distance = d;
157                }
158            }
159    
160        }
161    
162        /**
163         * Evaluates an x-value and if it is the closest to the anchor point it
164         * becomes the new crosshair point.
165         * <P>
166         * Used in cases where only the x-axis is numerical.
167         *
168         * @param candidateX  x position of the candidate for the new crosshair 
169         *                    point.
170         */
171        public void updateCrosshairX(double candidateX) {
172    
173            double d = Math.abs(candidateX - this.anchorX);
174            if (d < this.distance) {
175                this.crosshairX = candidateX;
176                this.distance = d;
177            }
178    
179        }
180    
181        /**
182         * Evaluates a y-value and if it is the closest to the anchor point it
183         * becomes the new crosshair point.
184         * <P>
185         * Used in cases where only the y-axis is numerical.
186         *
187         * @param candidateY  y position of the candidate for the new crosshair 
188         *                    point.
189         */
190        public void updateCrosshairY(double candidateY) {
191    
192            double d = Math.abs(candidateY - this.anchorY);
193            if (d < this.distance) {
194                this.crosshairY = candidateY;
195                this.distance = d;
196            }
197    
198        }
199    
200        /** 
201         * Sets the anchor point.  This is usually the mouse click point in a chart
202         * panel, and the crosshair point will often be the data item that is 
203         * closest to the anchor point.
204         * 
205         * @param anchor  the anchor point.
206         */
207        public void setAnchor(Point2D anchor) {
208            this.anchor = anchor;
209        }
210        
211        /**
212         * Get the x-value for the crosshair point.
213         *
214         * @return The x position of the crosshair point.
215         */
216        public double getCrosshairX() {
217            return this.crosshairX;
218        }
219        
220        /**
221         * Sets the x coordinate for the crosshair.  This is the coordinate in data
222         * space measured against the domain axis.
223         * 
224         * @param x the coordinate.
225         */
226        public void setCrosshairX(double x) {
227            this.crosshairX = x;
228        }
229    
230        /**
231         * Get the y-value for the crosshair point.  This is the coordinate in data
232         * space measured against the range axis.
233         *
234         * @return The y position of the crosshair point.
235         */
236        public double getCrosshairY() {
237            return this.crosshairY;
238        }
239    
240        /**
241         * Sets the y coordinate for the crosshair.
242         * 
243         * @param y  the y coordinate.
244         */
245        public void setCrosshairY(double y) {
246            this.crosshairY = y;
247        }
248    
249    }