Source for org.jfree.chart.plot.CrosshairState

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * -------------------
  28:  * CrosshairState.java
  29:  * -------------------
  30:  * (C) Copyright 2002-2007, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * Changes
  36:  * -------
  37:  * 24-Jan-2002 : Version 1 (DG);
  38:  * 05-Mar-2002 : Added Javadoc comments (DG);
  39:  * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
  40:  * 19-Sep-2003 : Modified crosshair distance calculation (DG);
  41:  * 04-Dec-2003 : Crosshair anchor point now stored outside chart since it is
  42:  *               dependent on the display target (DG);
  43:  * 25-Feb-2004 : Replaced CrosshairInfo --> CrosshairState (DG);
  44:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  45:  * 13-Oct-2006 : Fixed initialisation of CrosshairState - see bug report 
  46:  *               1565168 (DG);
  47:  * 06-Feb-2007 : Added new fields and methods to fix bug 1086307 (DG);
  48:  *
  49:  */
  50: 
  51: package org.jfree.chart.plot;
  52: 
  53: import java.awt.geom.Point2D;
  54: 
  55: /**
  56:  * Maintains state information about crosshairs on a plot between successive 
  57:  * calls to the renderer's draw method.  This class is used internally by 
  58:  * JFreeChart - it is not intended for external use.
  59:  */
  60: public class CrosshairState {
  61: 
  62:     /** 
  63:      * A flag that controls whether the distance is calculated in data space 
  64:      * or Java2D space.
  65:      */
  66:     private boolean calculateDistanceInDataSpace = false;
  67: 
  68:     /** The x-value (in data space) for the anchor point. */
  69:     private double anchorX;
  70: 
  71:     /** The y-value (in data space) for the anchor point. */
  72:     private double anchorY;
  73:     
  74:     /** The anchor point in Java2D space - if null, don't update crosshair. */
  75:     private Point2D anchor;
  76:     
  77:     /** The x-value for the current crosshair point. */
  78:     private double crosshairX;
  79: 
  80:     /** The y-value for the current crosshair point. */
  81:     private double crosshairY;
  82: 
  83:     /**
  84:      * The index of the domain axis that the crosshair x-value is measured
  85:      * against.
  86:      * 
  87:      * @since 1.0.4
  88:      */
  89:     private int domainAxisIndex;
  90:     
  91:     /**
  92:      * The index of the range axis that the crosshair y-value is measured
  93:      * against.
  94:      * 
  95:      * @since 1.0.4
  96:      */
  97:     private int rangeAxisIndex;
  98:     
  99:     /** 
 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: }