< prev index next >

modules/graphics/src/main/java/javafx/animation/ParallelTransition.java

Print this page


   1 /*
   2  * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 320                     animation.getTotalDuration() : animation.getTotalDuration().divide(absRate);
 321             final Duration childDuration = totalDuration.add(animation.getDelay());
 322             if (childDuration.isIndefinite()) {
 323                 return Duration.INDEFINITE;
 324             } else {
 325                 if (childDuration.greaterThan(maxTime)) {
 326                     maxTime = childDuration;
 327                 }
 328             }
 329         }
 330         return maxTime;
 331     }
 332 
 333     private double calculateFraction(long currentTicks, long cycleTicks) {
 334         final double frac = (double) currentTicks / cycleTicks;
 335         return (frac <= 0.0) ? 0 : (frac >= 1.0) ? 1.0 : frac;
 336     }
 337 
 338     private boolean startChild(Animation child, int index) {
 339         final boolean forceSync = forceChildSync[index];
 340         if (child.impl_startable(forceSync)) {
 341             child.clipEnvelope.setRate(rates[index] * Math.signum(getCurrentRate()));
 342             child.impl_start(forceSync);
 343             forceChildSync[index] = false;
 344             return true;
 345         }
 346         return false;
 347     }
 348 
 349     @Override
 350     void impl_sync(boolean forceSync) {
 351         super.impl_sync(forceSync);
 352         if ((forceSync && childrenChanged) || (durations == null)) {
 353             cachedChildren = getChildren().toArray(EMPTY_ANIMATION_ARRAY);
 354             final int n = cachedChildren.length;
 355             durations = new long[n];
 356             delays = new long[n];
 357             rates = new double[n];
 358             offsetTicks = new long[n];
 359             forceChildSync = new boolean[n];
 360             cycleTime = 0;
 361             int i = 0;
 362             for (final Animation animation : cachedChildren) {
 363                 rates[i] = Math.abs(animation.getRate());
 364                 if (rates[i] < EPSILON) {
 365                     rates[i] = 1;
 366                 }
 367                 durations[i] = fromDuration(animation.getTotalDuration(), rates[i]);
 368                 delays[i] = fromDuration(animation.getDelay());
 369                 cycleTime = Math.max(cycleTime, add(durations[i], delays[i]));
 370                 forceChildSync[i] = true;
 371                 i++;
 372             }
 373             childrenChanged = false;
 374         } else if (forceSync) {
 375             final int n = forceChildSync.length;
 376             for (int i=0; i<n; i++) {
 377                 forceChildSync[i] = true;
 378             }
 379         }
 380     }
 381 
 382     @Override
 383     void impl_pause() {
 384         super.impl_pause();
 385         for (final Animation animation : cachedChildren) {
 386             if (animation.getStatus() == Status.RUNNING) {
 387                 animation.impl_pause();
 388             }
 389         }
 390     }
 391 
 392     @Override
 393     void impl_resume() {
 394         super.impl_resume();
 395         int i = 0;
 396         for (final Animation animation : cachedChildren) {
 397             if (animation.getStatus() == Status.PAUSED) {
 398                 animation.impl_resume();
 399                 animation.clipEnvelope.setRate(rates[i] * Math.signum(getCurrentRate()));
 400             }
 401             i++;
 402         }
 403     }
 404 
 405     @Override
 406     void impl_start(boolean forceSync) {
 407         super.impl_start(forceSync);
 408         toggledRate = false;
 409         rateProperty().addListener(rateListener);
 410         double curRate = getCurrentRate();
 411         final long currentTicks = TickCalculation.fromDuration(getCurrentTime());
 412         if (curRate < 0) {
 413             jumpToEnd();
 414             if (currentTicks < cycleTime) {
 415                 impl_jumpTo(currentTicks, cycleTime, false);
 416             }
 417         } else {
 418             jumpToStart();
 419             if (currentTicks > 0) {
 420                 impl_jumpTo(currentTicks, cycleTime, false);
 421             }
 422         }
 423     }
 424 
 425     @Override
 426     void impl_stop() {
 427         super.impl_stop();
 428         for (final Animation animation : cachedChildren) {
 429             if (animation.getStatus() != Status.STOPPED) {
 430                 animation.impl_stop();
 431             }
 432         }
 433         if (childrenChanged) {
 434             setCycleDuration(computeCycleDuration());
 435         }
 436         rateProperty().removeListener(rateListener);
 437     }
 438 
 439 
 440     /**
 441      * @treatAsPrivate implementation detail
 442      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 443      */
 444     @Deprecated
 445     @Override public void impl_playTo(long currentTicks, long cycleTicks) {
 446         impl_setCurrentTicks(currentTicks);
 447         final double frac = calculateFraction(currentTicks, cycleTicks);
 448         final long newTicks = Math.max(0, Math.min(getCachedInterpolator().interpolate(0, cycleTicks, frac), cycleTicks));
 449         if (toggledRate) {
 450             for (int i = 0; i < cachedChildren.length; ++i) {
 451                 if (cachedChildren[i].getStatus() == Status.RUNNING) {
 452                     offsetTicks[i] -= Math.signum(getCurrentRate()) * (durations[i] - 2 * (oldTicks - delays[i]));
 453                 }
 454             }
 455             toggledRate = false;
 456         }
 457         if (getCurrentRate() > 0) {
 458             int i = 0;
 459             for (final Animation animation : cachedChildren) {
 460                 if ((newTicks >= delays[i]) && ((oldTicks <= delays[i]) ||
 461                         ((newTicks < add(delays[i], durations[i])) && (animation.getStatus() == Status.STOPPED)))) {
 462                     final boolean enteringCycle = oldTicks <= delays[i];
 463                     if (startChild(animation, i)) {
 464                         animation.clipEnvelope.jumpTo(0);
 465                     } else {
 466                         if (enteringCycle) {
 467                             final EventHandler<ActionEvent> handler = animation.getOnFinished();
 468                             if (handler != null) {
 469                                 handler.handle(new ActionEvent(this, null));
 470                             }
 471                         }
 472                         continue;
 473                     }
 474                 }
 475                 if (newTicks >= add(durations[i], delays[i])) {
 476                     if (animation.getStatus() == Status.RUNNING) {
 477                         animation.impl_timePulse(sub(durations[i], offsetTicks[i]));
 478                         offsetTicks[i] = 0;
 479                     }
 480                 } else if (newTicks > delays[i]) {
 481                     animation.impl_timePulse(sub(newTicks - delays[i], offsetTicks[i]));
 482                 }
 483                 i++;
 484             }
 485         } else {
 486             int i = 0;
 487             for (final Animation animation : cachedChildren) {
 488                 if (newTicks < add(durations[i], delays[i])) {
 489                     if ((oldTicks >= add(durations[i], delays[i])) || ((newTicks >= delays[i]) && (animation.getStatus() == Status.STOPPED))){
 490                         final boolean enteringCycle = oldTicks >= add(durations[i], delays[i]);
 491                         if (startChild(animation, i)) {
 492                             animation.clipEnvelope.jumpTo(Math.round(durations[i] * rates[i]));
 493                         } else {
 494                             if (enteringCycle) {
 495                                 final EventHandler<ActionEvent> handler = animation.getOnFinished();
 496                                 if (handler != null) {
 497                                     handler.handle(new ActionEvent(this, null));
 498                                 }
 499                             }
 500                             continue;
 501                         }
 502                     }
 503                     if (newTicks <= delays[i]) {
 504                         if (animation.getStatus() == Status.RUNNING) {
 505                             animation.impl_timePulse(sub(durations[i], offsetTicks[i]));
 506                             offsetTicks[i] = 0;
 507                         }
 508                     } else {
 509                         animation.impl_timePulse(sub( add(durations[i], delays[i]) - newTicks, offsetTicks[i]));
 510                     }
 511                 }
 512                 i++;
 513             }
 514         }
 515         oldTicks = newTicks;
 516     }
 517 
 518     /**
 519      * @treatAsPrivate implementation detail
 520      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 521      */
 522     @Deprecated
 523     @Override public void impl_jumpTo(long currentTicks, long cycleTicks, boolean forceJump) {
 524         impl_setCurrentTicks(currentTicks);
 525         if (getStatus() == Status.STOPPED && !forceJump) {
 526             return;
 527         }
 528         impl_sync(false);
 529         final double frac = calculateFraction(currentTicks, cycleTicks);
 530         final long newTicks = Math.max(0, Math.min(getCachedInterpolator().interpolate(0, cycleTicks, frac), cycleTicks));
 531         int i = 0;
 532         for (final Animation animation : cachedChildren) {
 533             final Status status = animation.getStatus();
 534             if (newTicks <= delays[i]) {
 535                 offsetTicks[i] = 0;
 536                 if (status != Status.STOPPED) {
 537                     animation.clipEnvelope.jumpTo(0);
 538                     animation.impl_stop();
 539                 } else if(TickCalculation.fromDuration(animation.getCurrentTime()) != 0) {
 540                     animation.impl_jumpTo(0, durations[i], true);
 541                 }
 542             } else if (newTicks >= add(durations[i], delays[i])) {
 543                 offsetTicks[i] = 0;
 544                 if (status != Status.STOPPED) {
 545                     animation.clipEnvelope.jumpTo(Math.round(durations[i] * rates[i]));
 546                     animation.impl_stop();
 547                 } else if (TickCalculation.fromDuration(animation.getCurrentTime()) != durations[i]) {
 548                     animation.impl_jumpTo(durations[i], durations[i], true);
 549                 }
 550             } else {
 551                 if (status == Status.STOPPED) {
 552                     startChild(animation, i);
 553                     if (getStatus() == Status.PAUSED) {
 554                         animation.impl_pause();
 555                     }
 556 
 557                     offsetTicks[i] = (getCurrentRate() > 0)? newTicks - delays[i] : add(durations[i], delays[i]) - newTicks;
 558                 } else if (status == Status.PAUSED) {
 559                     offsetTicks[i] += (newTicks - oldTicks) * Math.signum(this.clipEnvelope.getCurrentRate());
 560                 } else {
 561                     offsetTicks[i] += (getCurrentRate() > 0) ? newTicks - oldTicks : oldTicks - newTicks;
 562                 }
 563                 animation.clipEnvelope.jumpTo(Math.round(sub(newTicks, delays[i]) * rates[i]));
 564             }
 565             i++;
 566         }
 567         oldTicks = newTicks;
 568     }
 569 
 570     /**
 571      * {@inheritDoc}
 572      */
 573     @Override
 574     protected void interpolate(double frac) {
 575         // no-op
 576     }
 577 
 578     private void jumpToEnd() {
 579         for (int i = 0 ; i < cachedChildren.length; ++i) {
 580             if (forceChildSync[i]) {
 581                 // See explanation in SequentialTransition#jumpToEnd
 582                 cachedChildren[i].impl_sync(true);
 583             }
 584             cachedChildren[i].impl_jumpTo(durations[i], durations[i], true);
 585         }
 586     }
 587 
 588     private void jumpToStart() {
 589         for (int i = cachedChildren.length - 1 ; i >= 0; --i) {
 590             if (forceChildSync[i]) {
 591                 cachedChildren[i].impl_sync(true);
 592             }
 593             cachedChildren[i].impl_jumpTo(0, durations[i], true);
 594         }
 595     }
 596 
 597 }
   1 /*
   2  * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 320                     animation.getTotalDuration() : animation.getTotalDuration().divide(absRate);
 321             final Duration childDuration = totalDuration.add(animation.getDelay());
 322             if (childDuration.isIndefinite()) {
 323                 return Duration.INDEFINITE;
 324             } else {
 325                 if (childDuration.greaterThan(maxTime)) {
 326                     maxTime = childDuration;
 327                 }
 328             }
 329         }
 330         return maxTime;
 331     }
 332 
 333     private double calculateFraction(long currentTicks, long cycleTicks) {
 334         final double frac = (double) currentTicks / cycleTicks;
 335         return (frac <= 0.0) ? 0 : (frac >= 1.0) ? 1.0 : frac;
 336     }
 337 
 338     private boolean startChild(Animation child, int index) {
 339         final boolean forceSync = forceChildSync[index];
 340         if (child.startable(forceSync)) {
 341             child.clipEnvelope.setRate(rates[index] * Math.signum(getCurrentRate()));
 342             child.doStart(forceSync);
 343             forceChildSync[index] = false;
 344             return true;
 345         }
 346         return false;
 347     }
 348 
 349     @Override
 350     void sync(boolean forceSync) {
 351         super.sync(forceSync);
 352         if ((forceSync && childrenChanged) || (durations == null)) {
 353             cachedChildren = getChildren().toArray(EMPTY_ANIMATION_ARRAY);
 354             final int n = cachedChildren.length;
 355             durations = new long[n];
 356             delays = new long[n];
 357             rates = new double[n];
 358             offsetTicks = new long[n];
 359             forceChildSync = new boolean[n];
 360             cycleTime = 0;
 361             int i = 0;
 362             for (final Animation animation : cachedChildren) {
 363                 rates[i] = Math.abs(animation.getRate());
 364                 if (rates[i] < EPSILON) {
 365                     rates[i] = 1;
 366                 }
 367                 durations[i] = fromDuration(animation.getTotalDuration(), rates[i]);
 368                 delays[i] = fromDuration(animation.getDelay());
 369                 cycleTime = Math.max(cycleTime, add(durations[i], delays[i]));
 370                 forceChildSync[i] = true;
 371                 i++;
 372             }
 373             childrenChanged = false;
 374         } else if (forceSync) {
 375             final int n = forceChildSync.length;
 376             for (int i=0; i<n; i++) {
 377                 forceChildSync[i] = true;
 378             }
 379         }
 380     }
 381 
 382     @Override
 383     void doPause() {
 384         super.doPause();
 385         for (final Animation animation : cachedChildren) {
 386             if (animation.getStatus() == Status.RUNNING) {
 387                 animation.doPause();
 388             }
 389         }
 390     }
 391 
 392     @Override
 393     void doResume() {
 394         super.doResume();
 395         int i = 0;
 396         for (final Animation animation : cachedChildren) {
 397             if (animation.getStatus() == Status.PAUSED) {
 398                 animation.doResume();
 399                 animation.clipEnvelope.setRate(rates[i] * Math.signum(getCurrentRate()));
 400             }
 401             i++;
 402         }
 403     }
 404 
 405     @Override
 406     void doStart(boolean forceSync) {
 407         super.doStart(forceSync);
 408         toggledRate = false;
 409         rateProperty().addListener(rateListener);
 410         double curRate = getCurrentRate();
 411         final long currentTicks = TickCalculation.fromDuration(getCurrentTime());
 412         if (curRate < 0) {
 413             jumpToEnd();
 414             if (currentTicks < cycleTime) {
 415                 doJumpTo(currentTicks, cycleTime, false);
 416             }
 417         } else {
 418             jumpToStart();
 419             if (currentTicks > 0) {
 420                 doJumpTo(currentTicks, cycleTime, false);
 421             }
 422         }
 423     }
 424 
 425     @Override
 426     void doStop() {
 427         super.doStop();
 428         for (final Animation animation : cachedChildren) {
 429             if (animation.getStatus() != Status.STOPPED) {
 430                 animation.doStop();
 431             }
 432         }
 433         if (childrenChanged) {
 434             setCycleDuration(computeCycleDuration());
 435         }
 436         rateProperty().removeListener(rateListener);
 437     }
 438 
 439     @Override
 440     void doPlayTo(long currentTicks, long cycleTicks) {
 441         setCurrentTicks(currentTicks);





 442         final double frac = calculateFraction(currentTicks, cycleTicks);
 443         final long newTicks = Math.max(0, Math.min(getCachedInterpolator().interpolate(0, cycleTicks, frac), cycleTicks));
 444         if (toggledRate) {
 445             for (int i = 0; i < cachedChildren.length; ++i) {
 446                 if (cachedChildren[i].getStatus() == Status.RUNNING) {
 447                     offsetTicks[i] -= Math.signum(getCurrentRate()) * (durations[i] - 2 * (oldTicks - delays[i]));
 448                 }
 449             }
 450             toggledRate = false;
 451         }
 452         if (getCurrentRate() > 0) {
 453             int i = 0;
 454             for (final Animation animation : cachedChildren) {
 455                 if ((newTicks >= delays[i]) && ((oldTicks <= delays[i]) ||
 456                         ((newTicks < add(delays[i], durations[i])) && (animation.getStatus() == Status.STOPPED)))) {
 457                     final boolean enteringCycle = oldTicks <= delays[i];
 458                     if (startChild(animation, i)) {
 459                         animation.clipEnvelope.jumpTo(0);
 460                     } else {
 461                         if (enteringCycle) {
 462                             final EventHandler<ActionEvent> handler = animation.getOnFinished();
 463                             if (handler != null) {
 464                                 handler.handle(new ActionEvent(this, null));
 465                             }
 466                         }
 467                         continue;
 468                     }
 469                 }
 470                 if (newTicks >= add(durations[i], delays[i])) {
 471                     if (animation.getStatus() == Status.RUNNING) {
 472                         animation.doTimePulse(sub(durations[i], offsetTicks[i]));
 473                         offsetTicks[i] = 0;
 474                     }
 475                 } else if (newTicks > delays[i]) {
 476                     animation.doTimePulse(sub(newTicks - delays[i], offsetTicks[i]));
 477                 }
 478                 i++;
 479             }
 480         } else {
 481             int i = 0;
 482             for (final Animation animation : cachedChildren) {
 483                 if (newTicks < add(durations[i], delays[i])) {
 484                     if ((oldTicks >= add(durations[i], delays[i])) || ((newTicks >= delays[i]) && (animation.getStatus() == Status.STOPPED))){
 485                         final boolean enteringCycle = oldTicks >= add(durations[i], delays[i]);
 486                         if (startChild(animation, i)) {
 487                             animation.clipEnvelope.jumpTo(Math.round(durations[i] * rates[i]));
 488                         } else {
 489                             if (enteringCycle) {
 490                                 final EventHandler<ActionEvent> handler = animation.getOnFinished();
 491                                 if (handler != null) {
 492                                     handler.handle(new ActionEvent(this, null));
 493                                 }
 494                             }
 495                             continue;
 496                         }
 497                     }
 498                     if (newTicks <= delays[i]) {
 499                         if (animation.getStatus() == Status.RUNNING) {
 500                             animation.doTimePulse(sub(durations[i], offsetTicks[i]));
 501                             offsetTicks[i] = 0;
 502                         }
 503                     } else {
 504                         animation.doTimePulse(sub( add(durations[i], delays[i]) - newTicks, offsetTicks[i]));
 505                     }
 506                 }
 507                 i++;
 508             }
 509         }
 510         oldTicks = newTicks;
 511     }
 512 
 513     @Override
 514     void doJumpTo(long currentTicks, long cycleTicks, boolean forceJump) {
 515         setCurrentTicks(currentTicks);




 516         if (getStatus() == Status.STOPPED && !forceJump) {
 517             return;
 518         }
 519         sync(false);
 520         final double frac = calculateFraction(currentTicks, cycleTicks);
 521         final long newTicks = Math.max(0, Math.min(getCachedInterpolator().interpolate(0, cycleTicks, frac), cycleTicks));
 522         int i = 0;
 523         for (final Animation animation : cachedChildren) {
 524             final Status status = animation.getStatus();
 525             if (newTicks <= delays[i]) {
 526                 offsetTicks[i] = 0;
 527                 if (status != Status.STOPPED) {
 528                     animation.clipEnvelope.jumpTo(0);
 529                     animation.doStop();
 530                 } else if(TickCalculation.fromDuration(animation.getCurrentTime()) != 0) {
 531                     animation.doJumpTo(0, durations[i], true);
 532                 }
 533             } else if (newTicks >= add(durations[i], delays[i])) {
 534                 offsetTicks[i] = 0;
 535                 if (status != Status.STOPPED) {
 536                     animation.clipEnvelope.jumpTo(Math.round(durations[i] * rates[i]));
 537                     animation.doStop();
 538                 } else if (TickCalculation.fromDuration(animation.getCurrentTime()) != durations[i]) {
 539                     animation.doJumpTo(durations[i], durations[i], true);
 540                 }
 541             } else {
 542                 if (status == Status.STOPPED) {
 543                     startChild(animation, i);
 544                     if (getStatus() == Status.PAUSED) {
 545                         animation.doPause();
 546                     }
 547 
 548                     offsetTicks[i] = (getCurrentRate() > 0)? newTicks - delays[i] : add(durations[i], delays[i]) - newTicks;
 549                 } else if (status == Status.PAUSED) {
 550                     offsetTicks[i] += (newTicks - oldTicks) * Math.signum(this.clipEnvelope.getCurrentRate());
 551                 } else {
 552                     offsetTicks[i] += (getCurrentRate() > 0) ? newTicks - oldTicks : oldTicks - newTicks;
 553                 }
 554                 animation.clipEnvelope.jumpTo(Math.round(sub(newTicks, delays[i]) * rates[i]));
 555             }
 556             i++;
 557         }
 558         oldTicks = newTicks;
 559     }
 560 
 561     /**
 562      * {@inheritDoc}
 563      */
 564     @Override
 565     protected void interpolate(double frac) {
 566         // no-op
 567     }
 568 
 569     private void jumpToEnd() {
 570         for (int i = 0 ; i < cachedChildren.length; ++i) {
 571             if (forceChildSync[i]) {
 572                 // See explanation in SequentialTransition#jumpToEnd
 573                 cachedChildren[i].sync(true);
 574             }
 575             cachedChildren[i].doJumpTo(durations[i], durations[i], true);
 576         }
 577     }
 578 
 579     private void jumpToStart() {
 580         for (int i = cachedChildren.length - 1 ; i >= 0; --i) {
 581             if (forceChildSync[i]) {
 582                 cachedChildren[i].sync(true);
 583             }
 584             cachedChildren[i].doJumpTo(0, durations[i], true);
 585         }
 586     }
 587 
 588 }
< prev index next >