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:  * $Id: CrosshairState.java,v 1.3.2.4 2007/02/06 16:29:10 mungady Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 24-Jan-2002 : Version 1 (DG);
  40:  * 05-Mar-2002 : Added Javadoc comments (DG);
  41:  * 26-Sep-2002 : Fixed errors reported by Checkstyle (DG);
  42:  * 19-Sep-2003 : Modified crosshair distance calculation (DG);
  43:  * 04-Dec-2003 : Crosshair anchor point now stored outside chart since it is
  44:  *               dependent on the display target (DG);
  45:  * 25-Feb-2004 : Replaced CrosshairInfo --> CrosshairState (DG);
  46:  * ------------- JFREECHART 1.0.x ------------------------------------------           
  47:  * 13-Oct-2006 : Fixed initialisation of CrosshairState - see bug report 
  48:  *               1565168 (DG);
  49:  * 06-Feb-2007 : Added new fields and methods to fix bug 1086307 (DG);
  50:  *
  51:  */
  52: 
  53: package org.jfree.chart.plot;
  54: 
  55: import java.awt.geom.Point2D;
  56: 
  57: /**
  58:  * Maintains state information about crosshairs on a plot between successive 
  59:  * calls to the renderer's draw method.  This class is used internally by 
  60:  * JFreeChart - it is not intended for external use.
  61:  */
  62: public class CrosshairState {
  63: 
  64:     /** 
  65:      * A flag that controls whether the distance is calculated in data space 
  66:      * or Java2D space.
  67:      */
  68:     private boolean calculateDistanceInDataSpace = false;
  69: 
  70:     /** The x-value (in data space) for the anchor point. */
  71:     private double anchorX;
  72: 
  73:     /** The y-value (in data space) for the anchor point. */
  74:     private double anchorY;
  75:     
  76:     /** The anchor point in Java2D space - if null, don't update crosshair. */
  77:     private Point2D anchor;
  78:     
  79:     /** The x-value for the current crosshair point. */
  80:     private double crosshairX;
  81: 
  82:     /** The y-value for the current crosshair point. */
  83:     private double crosshairY;
  84: 
  85:     /**
  86:      * The index of the domain axis that the crosshair x-value is measured
  87:      * against.
  88:      * 
  89:      * @since 1.0.4
  90:      */
  91:     private int domainAxisIndex;
  92:     
  93:     /**
  94:      * The index of the range axis that the crosshair y-value is measured
  95:      * against.
  96:      * 
  97:      * @since 1.0.4
  98:      */
  99:     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: }