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, 172 double transX, double transY, 173 PlotOrientation orientation) { 174 updateCrosshairPoint(x, y, 0, 0, transX, transY, orientation); 175 } 176 177 /** 178 * Evaluates a data point and if it is the closest to the anchor point it 179 * becomes the new crosshair point. 180 * <P> 181 * To understand this method, you need to know the context in which it will 182 * be called. An instance of this class is passed to an 183 * {@link org.jfree.chart.renderer.xy.XYItemRenderer} as 184 * each data point is plotted. As the point is plotted, it is passed to 185 * this method to see if it should be the new crosshair point. 186 * 187 * @param x x coordinate (measured against the domain axis). 188 * @param y y coordinate (measured against the range axis). 189 * @param domainAxisIndex the index of the domain axis for this point. 190 * @param rangeAxisIndex the index of the range axis for this point. 191 * @param transX x translated into Java2D space. 192 * @param transY y translated into Java2D space. 193 * @param orientation the plot orientation. 194 * 195 * @since 1.0.4 196 */ 197 public void updateCrosshairPoint(double x, double y, int domainAxisIndex, 198 int rangeAxisIndex, double transX, double transY, 199 PlotOrientation orientation) { 200 201 if (this.anchor != null) { 202 double d = 0.0; 203 if (this.calculateDistanceInDataSpace) { 204 d = (x - this.anchorX) * (x - this.anchorX) 205 + (y - this.anchorY) * (y - this.anchorY); 206 } 207 else { 208 double xx = this.anchor.getX(); 209 double yy = this.anchor.getY(); 210 if (orientation == PlotOrientation.HORIZONTAL) { 211 double temp = yy; 212 yy = xx; 213 xx = temp; 214 } 215 d = (transX - xx) * (transX - xx) 216 + (transY - yy) * (transY - yy); 217 } 218 219 if (d < this.distance) { 220 this.crosshairX = x; 221 this.crosshairY = y; 222 this.domainAxisIndex = domainAxisIndex; 223 this.rangeAxisIndex = rangeAxisIndex; 224 this.distance = d; 225 } 226 } 227 228 } 229 230 /** 231 * Evaluates an x-value and if it is the closest to the anchor x-value it 232 * becomes the new crosshair value. 233 * <P> 234 * Used in cases where only the x-axis is numerical. 235 * 236 * @param candidateX x position of the candidate for the new crosshair 237 * point. 238 * 239 * @deprecated Use {@link #updateCrosshairX(double, int)}. See bug report 240 * 1086307. 241 */ 242 public void updateCrosshairX(double candidateX) { 243 updateCrosshairX(candidateX, 0); 244 } 245 246 /** 247 * Evaluates an x-value and if it is the closest to the anchor x-value it 248 * becomes the new crosshair value. 249 * <P> 250 * Used in cases where only the x-axis is numerical. 251 * 252 * @param candidateX x position of the candidate for the new crosshair 253 * point. 254 * @param domainAxisIndex the index of the domain axis for this x-value. 255 * 256 * @since 1.0.4 257 */ 258 public void updateCrosshairX(double candidateX, int domainAxisIndex) { 259 260 double d = Math.abs(candidateX - this.anchorX); 261 if (d < this.distance) { 262 this.crosshairX = candidateX; 263 this.domainAxisIndex = domainAxisIndex; 264 this.distance = d; 265 } 266 267 } 268 269 /** 270 * Evaluates a y-value and if it is the closest to the anchor y-value it 271 * becomes the new crosshair value. 272 * <P> 273 * Used in cases where only the y-axis is numerical. 274 * 275 * @param candidateY y position of the candidate for the new crosshair 276 * point. 277 * 278 * @deprecated Use {@link #updateCrosshairY(double, int)}. See bug report 279 * 1086307. 280 */ 281 public void updateCrosshairY(double candidateY) { 282 updateCrosshairY(candidateY, 0); 283 } 284 285 /** 286 * Evaluates a y-value and if it is the closest to the anchor y-value it 287 * becomes the new crosshair value. 288 * <P> 289 * Used in cases where only the y-axis is numerical. 290 * 291 * @param candidateY y position of the candidate for the new crosshair 292 * point. 293 * @param rangeAxisIndex the index of the range axis for this y-value. 294 * 295 * @since 1.0.4 296 */ 297 public void updateCrosshairY(double candidateY, int rangeAxisIndex) { 298 double d = Math.abs(candidateY - this.anchorY); 299 if (d < this.distance) { 300 this.crosshairY = candidateY; 301 this.rangeAxisIndex = rangeAxisIndex; 302 this.distance = d; 303 } 304 305 } 306 307 /** 308 * Returns the anchor point. 309 * 310 * @return The anchor point. 311 * 312 * @see #setAnchor(Point2D) 313 * @since 1.0.3 314 */ 315 public Point2D getAnchor() { 316 return this.anchor; 317 } 318 319 /** 320 * Sets the anchor point. This is usually the mouse click point in a chart 321 * panel, and the crosshair point will often be the data item that is 322 * closest to the anchor point. 323 * <br><br> 324 * Note that the x and y coordinates (in data space) are not updated by 325 * this method - the caller is responsible for ensuring that this happens 326 * in sync. 327 * 328 * @param anchor the anchor point (<code>null</code> permitted). 329 * 330 * @see #getAnchor() 331 */ 332 public void setAnchor(Point2D anchor) { 333 this.anchor = anchor; 334 } 335 336 /** 337 * Returns the x-coordinate (in data space) for the anchor point. 338 * 339 * @return The x-coordinate of the anchor point. 340 * 341 * @since 1.0.3 342 */ 343 public double getAnchorX() { 344 return this.anchorX; 345 } 346 347 /** 348 * Sets the x-coordinate (in data space) for the anchor point. Note that 349 * this does NOT update the anchor itself - the caller is responsible for 350 * ensuring this is done in sync. 351 * 352 * @param x the x-coordinate. 353 * 354 * @since 1.0.3 355 */ 356 public void setAnchorX(double x) { 357 this.anchorX = x; 358 } 359 360 /** 361 * Returns the y-coordinate (in data space) for the anchor point. 362 * 363 * @return The y-coordinate of teh anchor point. 364 * 365 * @since 1.0.3 366 */ 367 public double getAnchorY() { 368 return this.anchorY; 369 } 370 371 /** 372 * Sets the y-coordinate (in data space) for the anchor point. Note that 373 * this does NOT update the anchor itself - the caller is responsible for 374 * ensuring this is done in sync. 375 * 376 * @param y the y-coordinate. 377 * 378 * @since 1.0.3 379 */ 380 public void setAnchorY(double y) { 381 this.anchorY = y; 382 } 383 384 /** 385 * Get the x-value for the crosshair point. 386 * 387 * @return The x position of the crosshair point. 388 * 389 * @see #setCrosshairX(double) 390 */ 391 public double getCrosshairX() { 392 return this.crosshairX; 393 } 394 395 /** 396 * Sets the x coordinate for the crosshair. This is the coordinate in data 397 * space measured against the domain axis. 398 * 399 * @param x the coordinate. 400 * 401 * @see #getCrosshairX() 402 * @see #setCrosshairY(double) 403 * @see #updateCrosshairPoint(double, double, double, double, 404 * PlotOrientation) 405 */ 406 public void setCrosshairX(double x) { 407 this.crosshairX = x; 408 } 409 410 /** 411 * Get the y-value for the crosshair point. This is the coordinate in data 412 * space measured against the range axis. 413 * 414 * @return The y position of the crosshair point. 415 * 416 * @see #setCrosshairY(double) 417 */ 418 public double getCrosshairY() { 419 return this.crosshairY; 420 } 421 422 /** 423 * Sets the y coordinate for the crosshair. 424 * 425 * @param y the y coordinate. 426 * 427 * @see #getCrosshairY() 428 * @see #setCrosshairX(double) 429 * @see #updateCrosshairPoint(double, double, double, double, 430 * PlotOrientation) 431 */ 432 public void setCrosshairY(double y) { 433 this.crosshairY = y; 434 } 435 436 /** 437 * Returns the domain axis index for the crosshair x-value. 438 * 439 * @return The domain axis index. 440 * 441 * @since 1.0.4 442 */ 443 public int getDomainAxisIndex() { 444 return this.domainAxisIndex; 445 } 446 447 /** 448 * Returns the range axis index for the crosshair y-value. 449 * 450 * @return The range axis index. 451 * 452 * @since 1.0.4 453 */ 454 public int getRangeAxisIndex() { 455 return this.rangeAxisIndex; 456 } 457 }