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: * CrosshairState.java
029: * -------------------
030: * (C) Copyright 2002-2007, 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.4 2007/02/06 16:29:10 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: * ------------- JFREECHART 1.0.x ------------------------------------------
047: * 13-Oct-2006 : Fixed initialisation of CrosshairState - see bug report
048: * 1565168 (DG);
049: * 06-Feb-2007 : Added new fields and methods to fix bug 1086307 (DG);
050: *
051: */
052:
053: package org.jfree.chart.plot;
054:
055: import java.awt.geom.Point2D;
056:
057: /**
058: * Maintains state information about crosshairs on a plot between successive
059: * calls to the renderer's draw method. This class is used internally by
060: * JFreeChart - it is not intended for external use.
061: */
062: public class CrosshairState {
063:
064: /**
065: * A flag that controls whether the distance is calculated in data space
066: * or Java2D space.
067: */
068: private boolean calculateDistanceInDataSpace = false;
069:
070: /** The x-value (in data space) for the anchor point. */
071: private double anchorX;
072:
073: /** The y-value (in data space) for the anchor point. */
074: private double anchorY;
075:
076: /** The anchor point in Java2D space - if null, don't update crosshair. */
077: private Point2D anchor;
078:
079: /** The x-value for the current crosshair point. */
080: private double crosshairX;
081:
082: /** The y-value for the current crosshair point. */
083: private double crosshairY;
084:
085: /**
086: * The index of the domain axis that the crosshair x-value is measured
087: * against.
088: *
089: * @since 1.0.4
090: */
091: private int domainAxisIndex;
092:
093: /**
094: * The index of the range axis that the crosshair y-value is measured
095: * against.
096: *
097: * @since 1.0.4
098: */
099: private int rangeAxisIndex;
100:
101: /**
102: * The smallest distance (so far) between the anchor point and a data point.
103: */
104: private double distance;
105:
106: /**
107: * Creates a new <code>CrosshairState</code> instance that calculates
108: * distance in Java2D space.
109: */
110: public CrosshairState() {
111: this (false);
112: }
113:
114: /**
115: * Creates a new <code>CrosshairState</code> instance.
116: *
117: * @param calculateDistanceInDataSpace a flag that controls whether the
118: * distance is calculated in data
119: * space or Java2D space.
120: */
121: public CrosshairState(boolean calculateDistanceInDataSpace) {
122: this .calculateDistanceInDataSpace = calculateDistanceInDataSpace;
123: }
124:
125: /**
126: * Returns the distance between the anchor point and the current crosshair
127: * point.
128: *
129: * @return The distance.
130: *
131: * @see #setCrosshairDistance(double)
132: * @since 1.0.3
133: */
134: public double getCrosshairDistance() {
135: return this .distance;
136: }
137:
138: /**
139: * Sets the distance between the anchor point and the current crosshair
140: * point. As each data point is processed, its distance to the anchor
141: * point is compared with this value and, if it is closer, the data point
142: * becomes the new crosshair point.
143: *
144: * @param distance the distance.
145: *
146: * @see #getCrosshairDistance()
147: */
148: public void setCrosshairDistance(double distance) {
149: this .distance = distance;
150: }
151:
152: /**
153: * Evaluates a data point and if it is the closest to the anchor point it
154: * becomes the new crosshair point.
155: * <P>
156: * To understand this method, you need to know the context in which it will
157: * be called. An instance of this class is passed to an
158: * {@link org.jfree.chart.renderer.xy.XYItemRenderer} as
159: * each data point is plotted. As the point is plotted, it is passed to
160: * this method to see if it should be the new crosshair point.
161: *
162: * @param x x coordinate (measured against the domain axis).
163: * @param y y coordinate (measured against the range axis).
164: * @param transX x translated into Java2D space.
165: * @param transY y translated into Java2D space.
166: * @param orientation the plot orientation.
167: *
168: * @deprecated Use {@link #updateCrosshairPoint(double, double, int, int,
169: * double, double, PlotOrientation)}. See bug report 1086307.
170: */
171: public void updateCrosshairPoint(double x, double y, double transX,
172: double transY, PlotOrientation orientation) {
173: updateCrosshairPoint(x, y, 0, 0, transX, transY, orientation);
174: }
175:
176: /**
177: * Evaluates a data point and if it is the closest to the anchor point it
178: * becomes the new crosshair point.
179: * <P>
180: * To understand this method, you need to know the context in which it will
181: * be called. An instance of this class is passed to an
182: * {@link org.jfree.chart.renderer.xy.XYItemRenderer} as
183: * each data point is plotted. As the point is plotted, it is passed to
184: * this method to see if it should be the new crosshair point.
185: *
186: * @param x x coordinate (measured against the domain axis).
187: * @param y y coordinate (measured against the range axis).
188: * @param domainAxisIndex the index of the domain axis for this point.
189: * @param rangeAxisIndex the index of the range axis for this point.
190: * @param transX x translated into Java2D space.
191: * @param transY y translated into Java2D space.
192: * @param orientation the plot orientation.
193: *
194: * @since 1.0.4
195: */
196: public void updateCrosshairPoint(double x, double y,
197: int domainAxisIndex, int rangeAxisIndex, double transX,
198: double transY, PlotOrientation orientation) {
199:
200: if (this .anchor != null) {
201: double d = 0.0;
202: if (this .calculateDistanceInDataSpace) {
203: d = (x - this .anchorX) * (x - this .anchorX)
204: + (y - this .anchorY) * (y - this .anchorY);
205: } else {
206: double xx = this .anchor.getX();
207: double yy = this .anchor.getY();
208: if (orientation == PlotOrientation.HORIZONTAL) {
209: double temp = yy;
210: yy = xx;
211: xx = temp;
212: }
213: d = (transX - xx) * (transX - xx) + (transY - yy)
214: * (transY - yy);
215: }
216:
217: if (d < this .distance) {
218: this .crosshairX = x;
219: this .crosshairY = y;
220: this .domainAxisIndex = domainAxisIndex;
221: this .rangeAxisIndex = rangeAxisIndex;
222: this .distance = d;
223: }
224: }
225:
226: }
227:
228: /**
229: * Evaluates an x-value and if it is the closest to the anchor x-value it
230: * becomes the new crosshair value.
231: * <P>
232: * Used in cases where only the x-axis is numerical.
233: *
234: * @param candidateX x position of the candidate for the new crosshair
235: * point.
236: *
237: * @deprecated Use {@link #updateCrosshairX(double, int)}. See bug report
238: * 1086307.
239: */
240: public void updateCrosshairX(double candidateX) {
241: updateCrosshairX(candidateX, 0);
242: }
243:
244: /**
245: * Evaluates an x-value and if it is the closest to the anchor x-value it
246: * becomes the new crosshair value.
247: * <P>
248: * Used in cases where only the x-axis is numerical.
249: *
250: * @param candidateX x position of the candidate for the new crosshair
251: * point.
252: * @param domainAxisIndex the index of the domain axis for this x-value.
253: *
254: * @since 1.0.4
255: */
256: public void updateCrosshairX(double candidateX, int domainAxisIndex) {
257:
258: double d = Math.abs(candidateX - this .anchorX);
259: if (d < this .distance) {
260: this .crosshairX = candidateX;
261: this .domainAxisIndex = domainAxisIndex;
262: this .distance = d;
263: }
264:
265: }
266:
267: /**
268: * Evaluates a y-value and if it is the closest to the anchor y-value it
269: * becomes the new crosshair value.
270: * <P>
271: * Used in cases where only the y-axis is numerical.
272: *
273: * @param candidateY y position of the candidate for the new crosshair
274: * point.
275: *
276: * @deprecated Use {@link #updateCrosshairY(double, int)}. See bug report
277: * 1086307.
278: */
279: public void updateCrosshairY(double candidateY) {
280: updateCrosshairY(candidateY, 0);
281: }
282:
283: /**
284: * Evaluates a y-value and if it is the closest to the anchor y-value it
285: * becomes the new crosshair value.
286: * <P>
287: * Used in cases where only the y-axis is numerical.
288: *
289: * @param candidateY y position of the candidate for the new crosshair
290: * point.
291: * @param rangeAxisIndex the index of the range axis for this y-value.
292: *
293: * @since 1.0.4
294: */
295: public void updateCrosshairY(double candidateY, int rangeAxisIndex) {
296: double d = Math.abs(candidateY - this .anchorY);
297: if (d < this .distance) {
298: this .crosshairY = candidateY;
299: this .rangeAxisIndex = rangeAxisIndex;
300: this .distance = d;
301: }
302:
303: }
304:
305: /**
306: * Returns the anchor point.
307: *
308: * @return The anchor point.
309: *
310: * @see #setAnchor(Point2D)
311: * @since 1.0.3
312: */
313: public Point2D getAnchor() {
314: return this .anchor;
315: }
316:
317: /**
318: * Sets the anchor point. This is usually the mouse click point in a chart
319: * panel, and the crosshair point will often be the data item that is
320: * closest to the anchor point.
321: * <br><br>
322: * Note that the x and y coordinates (in data space) are not updated by
323: * this method - the caller is responsible for ensuring that this happens
324: * in sync.
325: *
326: * @param anchor the anchor point (<code>null</code> permitted).
327: *
328: * @see #getAnchor()
329: */
330: public void setAnchor(Point2D anchor) {
331: this .anchor = anchor;
332: }
333:
334: /**
335: * Returns the x-coordinate (in data space) for the anchor point.
336: *
337: * @return The x-coordinate of the anchor point.
338: *
339: * @since 1.0.3
340: */
341: public double getAnchorX() {
342: return this .anchorX;
343: }
344:
345: /**
346: * Sets the x-coordinate (in data space) for the anchor point. Note that
347: * this does NOT update the anchor itself - the caller is responsible for
348: * ensuring this is done in sync.
349: *
350: * @param x the x-coordinate.
351: *
352: * @since 1.0.3
353: */
354: public void setAnchorX(double x) {
355: this .anchorX = x;
356: }
357:
358: /**
359: * Returns the y-coordinate (in data space) for the anchor point.
360: *
361: * @return The y-coordinate of teh anchor point.
362: *
363: * @since 1.0.3
364: */
365: public double getAnchorY() {
366: return this .anchorY;
367: }
368:
369: /**
370: * Sets the y-coordinate (in data space) for the anchor point. Note that
371: * this does NOT update the anchor itself - the caller is responsible for
372: * ensuring this is done in sync.
373: *
374: * @param y the y-coordinate.
375: *
376: * @since 1.0.3
377: */
378: public void setAnchorY(double y) {
379: this .anchorY = y;
380: }
381:
382: /**
383: * Get the x-value for the crosshair point.
384: *
385: * @return The x position of the crosshair point.
386: *
387: * @see #setCrosshairX(double)
388: */
389: public double getCrosshairX() {
390: return this .crosshairX;
391: }
392:
393: /**
394: * Sets the x coordinate for the crosshair. This is the coordinate in data
395: * space measured against the domain axis.
396: *
397: * @param x the coordinate.
398: *
399: * @see #getCrosshairX()
400: * @see #setCrosshairY(double)
401: * @see #updateCrosshairPoint(double, double, double, double,
402: * PlotOrientation)
403: */
404: public void setCrosshairX(double x) {
405: this .crosshairX = x;
406: }
407:
408: /**
409: * Get the y-value for the crosshair point. This is the coordinate in data
410: * space measured against the range axis.
411: *
412: * @return The y position of the crosshair point.
413: *
414: * @see #setCrosshairY(double)
415: */
416: public double getCrosshairY() {
417: return this .crosshairY;
418: }
419:
420: /**
421: * Sets the y coordinate for the crosshair.
422: *
423: * @param y the y coordinate.
424: *
425: * @see #getCrosshairY()
426: * @see #setCrosshairX(double)
427: * @see #updateCrosshairPoint(double, double, double, double,
428: * PlotOrientation)
429: */
430: public void setCrosshairY(double y) {
431: this .crosshairY = y;
432: }
433:
434: /**
435: * Returns the domain axis index for the crosshair x-value.
436: *
437: * @return The domain axis index.
438: *
439: * @since 1.0.4
440: */
441: public int getDomainAxisIndex() {
442: return this .domainAxisIndex;
443: }
444:
445: /**
446: * Returns the range axis index for the crosshair y-value.
447: *
448: * @return The range axis index.
449: *
450: * @since 1.0.4
451: */
452: public int getRangeAxisIndex() {
453: return this.rangeAxisIndex;
454: }
455: }
|