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