Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.animation; 027 028import javafx.beans.property.DoubleProperty; 029import javafx.beans.property.ObjectProperty; 030import javafx.beans.property.ObjectPropertyBase; 031import javafx.beans.property.SimpleDoubleProperty; 032import javafx.beans.property.SimpleObjectProperty; 033import javafx.scene.Node; 034import javafx.util.Duration; 035 036/** 037 * This {@code Transition} creates a move/translate animation that spans its 038 * {@link #duration}. This is done by updating the {@code translateX}, 039 * {@code translateY} and {@code translateZ} variables of the {@code node} at 040 * regular interval. 041 * <p> 042 * It starts from the ({@code fromX}, {@code fromY}, {@code fromZ}) value if 043 * provided else uses the {@code node}'s ({@code translateX}, {@code translateY}, {@code translateZ}) value. 044 * <p> 045 * It stops at the ({@code toX}, {@code toY}, {@code toZ}) value if provided 046 * else it will use start value plus ({@code byX}, {@code byY}, {@code byZ}) 047 * value. 048 * <p> 049 * The ({@code toX}, {@code toY}, {@code toZ}) value takes precedence if both ( 050 * {@code toX}, {@code toY}, {@code toZ}) and ({@code byX}, {@code byY}, 051 * {@code byZ}) values are specified. 052 * 053 * <p> 054 * Code Segment Example: 055 * </p> 056 * 057 * <pre> 058 * <code> 059 * import javafx.scene.shape.*; 060 * import javafx.animation.transition.*; 061 * 062 * ... 063 * 064 * Rectangle rect = new Rectangle (100, 40, 100, 100); 065 * rect.setArcHeight(50); 066 * rect.setArcWidth(50); 067 * rect.setFill(Color.VIOLET); 068 * 069 * TranslateTransition tt = new TranslateTransition(Duration.millis(2000), rect); 070 * tt.setByX(200f); 071 * tt.setCycleCount(4f); 072 * tt.setAutoReverse(true); 073 * 074 * tt.play(); 075 * 076 * ... 077 * 078 * </code> 079 * </pre> 080 * 081 * @see Transition 082 * @see Animation 083 * 084 */ 085public final class TranslateTransition extends Transition { 086 087 private static final double EPSILON = 1e-12; 088 private double startX; 089 private double startY; 090 private double startZ; 091 private double deltaX; 092 private double deltaY; 093 private double deltaZ; 094 095 /** 096 * The target node of this {@code TranslateTransition}. 097 * <p> 098 * It is not possible to change the target {@code node} of a running 099 * {@code TranslateTransition}. If the value of {@code node} is changed for 100 * a running {@code TranslateTransition}, the animation has to be stopped 101 * and started again to pick up the new value. 102 */ 103 private ObjectProperty<Node> node; 104 private static final Node DEFAULT_NODE = null; 105 106 public final void setNode(Node value) { 107 if ((node != null) || (value != null /* DEFAULT_NODE */)) { 108 nodeProperty().set(value); 109 } 110 } 111 112 public final Node getNode() { 113 return (node == null)? DEFAULT_NODE : node.get(); 114 } 115 116 public final ObjectProperty<Node> nodeProperty() { 117 if (node == null) { 118 node = new SimpleObjectProperty<Node>(this, "node", DEFAULT_NODE); 119 } 120 return node; 121 } 122 123 private Node cachedNode; 124 125 /** 126 * The duration of this {@code TranslateTransition}. 127 * <p> 128 * It is not possible to change the {@code duration} of a running 129 * {@code TranslateTransition}. If the value of {@code duration} is changed 130 * for a running {@code TranslateTransition}, the animation has to be 131 * stopped and started again to pick up the new value. 132 * <p> 133 * Note: While the unit of {@code duration} is a millisecond, the 134 * granularity depends on the underlying operating system and will in 135 * general be larger. For example animations on desktop systems usually run 136 * with a maximum of 60fps which gives a granularity of ~17 ms. 137 * 138 * Setting duration to value lower than {@link Duration#ZERO} will result 139 * in {@link IllegalArgumentException}. 140 * 141 * @defaultValue 400ms 142 */ 143 private ObjectProperty<Duration> duration; 144 private static final Duration DEFAULT_DURATION = Duration.millis(400); 145 146 public final void setDuration(Duration value) { 147 if ((duration != null) || (!DEFAULT_DURATION.equals(value))) { 148 durationProperty().set(value); 149 } 150 } 151 152 public final Duration getDuration() { 153 return (duration == null)? DEFAULT_DURATION : duration.get(); 154 } 155 156 public final ObjectProperty<Duration> durationProperty() { 157 if (duration == null) { 158 duration = new ObjectPropertyBase<Duration>(DEFAULT_DURATION) { 159 160 @Override 161 public void invalidated() { 162 try { 163 setCycleDuration(getDuration()); 164 } catch (IllegalArgumentException e) { 165 if (isBound()) { 166 unbind(); 167 } 168 set(getCycleDuration()); 169 throw e; 170 } 171 } 172 173 @Override 174 public Object getBean() { 175 return TranslateTransition.this; 176 } 177 178 @Override 179 public String getName() { 180 return "duration"; 181 } 182 }; 183 } 184 return duration; 185 } 186 187 /** 188 * Specifies the start X coordinate value of this 189 * {@code TranslateTransition}. 190 * <p> 191 * It is not possible to change {@code fromX} of a running 192 * {@code TranslateTransition}. If the value of {@code fromX} is changed for 193 * a running {@code TranslateTransition}, the animation has to be stopped 194 * and started again to pick up the new value. 195 * 196 * @defaultValue {@code Double.NaN} 197 */ 198 private DoubleProperty fromX; 199 private static final double DEFAULT_FROM_X = Double.NaN; 200 201 public final void setFromX(double value) { 202 if ((fromX != null) || (!Double.isNaN(value))) { 203 fromXProperty().set(value); 204 } 205 } 206 207 public final double getFromX() { 208 return (fromX == null) ? DEFAULT_FROM_X : fromX.get(); 209 } 210 211 public final DoubleProperty fromXProperty() { 212 if (fromX == null) { 213 fromX = new SimpleDoubleProperty(this, "fromX", DEFAULT_FROM_X); 214 } 215 return fromX; 216 } 217 218 /** 219 * Specifies the start Y coordinate value of this 220 * {@code TranslateTransition}. 221 * <p> 222 * It is not possible to change {@code fromY} of a running 223 * {@code TranslateTransition}. If the value of {@code fromY} is changed for 224 * a running {@code TranslateTransition}, the animation has to be stopped 225 * and started again to pick up the new value. 226 * 227 * @defaultValue {@code Double.NaN} 228 */ 229 private DoubleProperty fromY; 230 private static final double DEFAULT_FROM_Y = Double.NaN; 231 232 public final void setFromY(double value) { 233 if ((fromY != null) || (!Double.isNaN(value))) { 234 fromYProperty().set(value); 235 } 236 } 237 238 public final double getFromY() { 239 return (fromY == null)? DEFAULT_FROM_Y : fromY.get(); 240 } 241 242 public final DoubleProperty fromYProperty() { 243 if (fromY == null) { 244 fromY = new SimpleDoubleProperty(this, "fromY", DEFAULT_FROM_Y); 245 } 246 return fromY; 247 } 248 249 /** 250 * Specifies the start Z coordinate value of this 251 * {@code TranslateTransition}. 252 * <p> 253 * It is not possible to change {@code fromZ} of a running 254 * {@code TranslateTransition}. If the value of {@code fromZ} is changed for 255 * a running {@code TranslateTransition}, the animation has to be stopped 256 * and started again to pick up the new value. 257 * 258 * @defaultValue {@code Double.NaN} 259 */ 260 private DoubleProperty fromZ; 261 private static final double DEFAULT_FROM_Z = Double.NaN; 262 263 public final void setFromZ(double value) { 264 if ((fromZ != null) || (!Double.isNaN(value))) { 265 fromZProperty().set(value); 266 } 267 } 268 269 public final double getFromZ() { 270 return (fromZ == null)? DEFAULT_FROM_Z : fromZ.get(); 271 } 272 273 public final DoubleProperty fromZProperty() { 274 if (fromZ == null) { 275 fromZ = new SimpleDoubleProperty(this, "fromZ", DEFAULT_FROM_Z); 276 } 277 return fromZ; 278 } 279 280 /** 281 * Specifies the stop X coordinate value of this {@code TranslateTransition}. 282 * <p> 283 * It is not possible to change {@code toX} of a running 284 * {@code TranslateTransition}. If the value of {@code toX} is changed for a 285 * running {@code TranslateTransition}, the animation has to be stopped and 286 * started again to pick up the new value. 287 * 288 * @defaultValue {@code Double.NaN} 289 */ 290 private DoubleProperty toX; 291 private static final double DEFAULT_TO_X = Double.NaN; 292 293 public final void setToX(double value) { 294 if ((toX != null) || (!Double.isNaN(value))) { 295 toXProperty().set(value); 296 } 297 } 298 299 public final double getToX() { 300 return (toX == null)? DEFAULT_TO_X : toX.get(); 301 } 302 303 public final DoubleProperty toXProperty() { 304 if (toX == null) { 305 toX = new SimpleDoubleProperty(this, "toX", DEFAULT_TO_X); 306 } 307 return toX; 308 } 309 310 /** 311 * Specifies the stop Y coordinate value of this {@code TranslateTransition}. 312 * <p> 313 * It is not possible to change {@code toY} of a running 314 * {@code TranslateTransition}. If the value of {@code toY} is changed for a 315 * running {@code TranslateTransition}, the animation has to be stopped and 316 * started again to pick up the new value. 317 * 318 * @defaultValue {@code Double.NaN} 319 */ 320 private DoubleProperty toY; 321 private static final double DEFAULT_TO_Y = Double.NaN; 322 323 public final void setToY(double value) { 324 if ((toY != null) || (!Double.isNaN(value))) { 325 toYProperty().set(value); 326 } 327 } 328 329 public final double getToY() { 330 return (toY == null)? DEFAULT_TO_Y : toY.get(); 331 } 332 333 public final DoubleProperty toYProperty() { 334 if (toY == null) { 335 toY = new SimpleDoubleProperty(this, "toY", DEFAULT_TO_Y); 336 } 337 return toY; 338 } 339 340 /** 341 * Specifies the stop Z coordinate value of this {@code TranslateTransition}. 342 * <p> 343 * It is not possible to change {@code toZ} of a running 344 * {@code TranslateTransition}. If the value of {@code toZ} is changed for a 345 * running {@code TranslateTransition}, the animation has to be stopped and 346 * started again to pick up the new value. 347 * 348 * @defaultValue {@code Double.NaN} 349 * @since JavaFX 1.3 350 */ 351 private DoubleProperty toZ; 352 private static final double DEFAULT_TO_Z = Double.NaN; 353 354 public final void setToZ(double value) { 355 if ((toZ != null) || (!Double.isNaN(value))) { 356 toZProperty().set(value); 357 } 358 } 359 360 public final double getToZ() { 361 return (toZ == null)? DEFAULT_TO_Z : toZ.get(); 362 } 363 364 public final DoubleProperty toZProperty() { 365 if (toZ == null) { 366 toZ = new SimpleDoubleProperty(this, "toZ", DEFAULT_TO_Z); 367 } 368 return toZ; 369 } 370 371 /** 372 * Specifies the incremented stop X coordinate value, from the start, of 373 * this {@code TranslateTransition}. 374 * <p> 375 * It is not possible to change {@code byX} of a running 376 * {@code TranslateTransition}. If the value of {@code byX} is changed for a 377 * running {@code TranslateTransition}, the animation has to be stopped and 378 * started again to pick up the new value. 379 */ 380 private DoubleProperty byX; 381 private static final double DEFAULT_BY_X = 0.0; 382 383 public final void setByX(double value) { 384 if ((byX != null) || (Math.abs(value - DEFAULT_BY_X) > EPSILON)) { 385 byXProperty().set(value); 386 } 387 } 388 389 public final double getByX() { 390 return (byX == null)? DEFAULT_BY_X : byX.get(); 391 } 392 393 public final DoubleProperty byXProperty() { 394 if (byX == null) { 395 byX = new SimpleDoubleProperty(this, "byX", DEFAULT_BY_X); 396 } 397 return byX; 398 } 399 400 /** 401 * Specifies the incremented stop Y coordinate value, from the start, of 402 * this {@code TranslateTransition}. 403 * <p> 404 * It is not possible to change {@code byY} of a running 405 * {@code TranslateTransition}. If the value of {@code byY} is changed for a 406 * running {@code TranslateTransition}, the animation has to be stopped and 407 * started again to pick up the new value. 408 */ 409 private DoubleProperty byY; 410 private static final double DEFAULT_BY_Y = 0.0; 411 412 public final void setByY(double value) { 413 if ((byY != null) || (Math.abs(value - DEFAULT_BY_Y) > EPSILON)) { 414 byYProperty().set(value); 415 } 416 } 417 418 public final double getByY() { 419 return (byY == null)? DEFAULT_BY_Y : byY.get(); 420 } 421 422 public final DoubleProperty byYProperty() { 423 if (byY == null) { 424 byY = new SimpleDoubleProperty(this, "byY", DEFAULT_BY_Y); 425 } 426 return byY; 427 } 428 429 /** 430 * Specifies the incremented stop Z coordinate value, from the start, of 431 * this {@code TranslateTransition}. 432 * <p> 433 * It is not possible to change {@code byZ} of a running 434 * {@code TranslateTransition}. If the value of {@code byZ} is changed for a 435 * running {@code TranslateTransition}, the animation has to be stopped and 436 * started again to pick up the new value. 437 */ 438 private DoubleProperty byZ; 439 private static final double DEFAULT_BY_Z = 0.0; 440 441 public final void setByZ(double value) { 442 if ((byZ != null) || (Math.abs(value - DEFAULT_BY_Z) > EPSILON)) { 443 byZProperty().set(value); 444 } 445 } 446 447 public final double getByZ() { 448 return (byZ == null)? DEFAULT_BY_Z : byZ.get(); 449 } 450 451 public final DoubleProperty byZProperty() { 452 if (byZ == null) { 453 byZ = new SimpleDoubleProperty(this, "byZ", DEFAULT_BY_Z); 454 } 455 return byZ; 456 } 457 458 /** 459 * The constructor of {@code TranslateTransition} 460 * 461 * @param duration 462 * The duration of the {@code TranslateTransition} 463 * @param node 464 * The {@code node} which will be translated 465 */ 466 public TranslateTransition(Duration duration, Node node) { 467 setDuration(duration); 468 setNode(node); 469 setCycleDuration(duration); 470 } 471 472 /** 473 * The constructor of {@code TranslateTransition} 474 * 475 * @param duration 476 * The duration of the {@code TranslateTransition} 477 */ 478 public TranslateTransition(Duration duration) { 479 this(duration, null); 480 } 481 482 /** 483 * The constructor of {@code TranslateTransition} 484 */ 485 public TranslateTransition() { 486 this(DEFAULT_DURATION, null); 487 } 488 489 /** 490 * {@inheritDoc} 491 */ 492 @Override 493 public void interpolate(double frac) { 494 if (!Double.isNaN(startX)) { 495 cachedNode.setTranslateX(startX + frac * deltaX); 496 } 497 if (!Double.isNaN(startY)) { 498 cachedNode.setTranslateY(startY + frac * deltaY); 499 } 500 if (!Double.isNaN(startZ)) { 501 cachedNode.setTranslateZ(startZ + frac * deltaZ); 502 } 503 } 504 505 private Node getTargetNode() { 506 final Node node = getNode(); 507 return (node != null)? node : getParentTargetNode(); 508 } 509 510 @Override 511 boolean impl_startable(boolean forceSync) { 512 return super.impl_startable(forceSync) 513 && ((getTargetNode() != null) || (!forceSync && (cachedNode != null))); 514 } 515 516 @Override 517 void impl_sync(boolean forceSync) { 518 super.impl_sync(forceSync); 519 if (forceSync || (cachedNode == null)) { 520 cachedNode = getTargetNode(); 521 522 final double _fromX = getFromX(); 523 final double _fromY = getFromY(); 524 final double _fromZ = getFromZ(); 525 526 final double _toX = getToX(); 527 final double _toY = getToY(); 528 final double _toZ = getToZ(); 529 530 final double _byX = getByX(); 531 final double _byY = getByY(); 532 final double _byZ = getByZ(); 533 534 if (Double.isNaN(_fromX) && Double.isNaN(_toX) && (Math.abs(_byX) < EPSILON)) { 535 startX = Double.NaN; 536 } else { 537 startX = (!Double.isNaN(_fromX)) ? _fromX : cachedNode.getTranslateX(); 538 deltaX = (!Double.isNaN(_toX)) ? _toX - startX : _byX; 539 } 540 541 if (Double.isNaN(_fromY) && Double.isNaN(_toY) && (Math.abs(_byY) < EPSILON)) { 542 startY = Double.NaN; 543 } else { 544 startY = (!Double.isNaN(_fromY)) ? _fromY : cachedNode.getTranslateY(); 545 deltaY = (!Double.isNaN(_toY)) ? _toY - startY : getByY(); 546 } 547 548 if (Double.isNaN(_fromZ) && Double.isNaN(_toZ) && (Math.abs(_byZ) < EPSILON)) { 549 startZ = Double.NaN; 550 } else { 551 startZ = (!Double.isNaN(_fromZ)) ? _fromZ : cachedNode.getTranslateZ(); 552 deltaZ = (!Double.isNaN(_toZ)) ? _toZ - startZ : getByZ(); 553 } 554 } 555 } 556 557}