timingframework
  1. timingframework
  2. TIMINGFRAMEWORK-15

Animator.getCurrentDirection() in TimingtargetAdapter.end(Animator) after a call to Animator#reverseNow()

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 5.0 (swing, swt)
    • Fix Version/s: 5.1 (swing, swt)
    • Component/s: core
    • Labels:
      None

      Description

      Reported by : Ludovic Viegas <pigelvy@gmail.com>

      I call reverseNow() sometime during an animation and as I expected, the currentDirection is correct on TimingTargetAdapter#timingEvent(Animator) callbacks but not in TimingtargetAdapter.end(Animator). Check those logs:

      Click on the Button
      2012-07-12 17:40:52,505 TRACE: [AWT-EventQueue-0] [ObsCadreUserPanel] : Start open animation
      Animation begin. Direction:[FORWARD]
      Animation step. Direction:[FORWARD], Fraction:[9.279128967541007E-5]
      Animation step. Direction:[FORWARD], Fraction:[0.017720643903111274]
      Animation step. Direction:[FORWARD], Fraction:[0.1003103382896504]
      Animation step. Direction:[FORWARD], Fraction:[0.2768440955691545]
      Animation step. Direction:[FORWARD], Fraction:[0.48225281392878133]
      Click on the button
      Animation in progress. RevertNow !!
      Reverse animation. Direction:[BACKWARD]
      Animation step. Direction:[BACKWARD], Fraction:[0.5489863320079672]
      Animation step. Direction:[BACKWARD], Fraction:[0.34637573542596717]
      Animation step. Direction:[BACKWARD], Fraction:[0.15214357423549388]
      Animation step. Direction:[BACKWARD], Fraction:[0.03580801342995845]
      Animation step. Direction:[BACKWARD], Fraction:[0.0016139443804327497]
      Animation step. Direction:[BACKWARD], Fraction:[0.0]
      Animation finished. Direction:[FORWARD]

      As you can see, I start in FORWARD mode then in the middle change direction to BACKWARD. Why is the last callback still in FORWARD?

        Activity

        Hide
        hallorant added a comment - - edited

        I've duplicated the problem. It is caused because the stopHelper code in Animator is trying to reset mutable state for possible Animator reuse. The direction is reset here before the callback to end(Animator) of any TimingTargets.

          private boolean stopHelper(boolean notify, boolean inCallbackContext) {
            final CountDownLatch latch;
            synchronized (f_lock) {
              if (!isRunning())
                return false;
        
              f_running = false;
              f_currentDirection = f_startDirection; <<-- BUG !!
              latch = f_awaitLatch;
              f_awaitLatch = null;
            }
            f_timingSource.removeTickListener(this);
            if (notify && !f_targets.isEmpty()) {
              final Runnable task = new Runnable() {
                @Override
                public void run() {
                  for (TimingTarget target : f_targets) {
                    target.end(Animator.this);
                  }
                }
              };
              if (inCallbackContext)
                task.run();
              else
                f_timingSource.submit(task);
            }
            latch.countDown();
            return true;
          }
        
        Show
        hallorant added a comment - - edited I've duplicated the problem. It is caused because the stopHelper code in Animator is trying to reset mutable state for possible Animator reuse. The direction is reset here before the callback to end(Animator) of any TimingTargets. private boolean stopHelper( boolean notify, boolean inCallbackContext) { final CountDownLatch latch; synchronized (f_lock) { if (!isRunning()) return false ; f_running = false ; f_currentDirection = f_startDirection; <<-- BUG !! latch = f_awaitLatch; f_awaitLatch = null ; } f_timingSource.removeTickListener( this ); if (notify && !f_targets.isEmpty()) { final Runnable task = new Runnable () { @Override public void run() { for (TimingTarget target : f_targets) { target.end(Animator. this ); } } }; if (inCallbackContext) task.run(); else f_timingSource.submit(task); } latch.countDown(); return true ; }
        Hide
        hallorant added a comment -

        Removing the offending line in stopHelper (above) seems to fix the issue.

        (JUnit) I created a DirectionTimingTarget and added several test cases (timingTargetDirection*()) to TestAnimator. So that this problem will not regress

        Looking back at the "classic" Chet Haase code it looks like I introduced this problem in trying to ensure that all the TimingTarget callbacks were made in a known thread context (not just the thread context of who called the Animator). My bad

        Show
        hallorant added a comment - Removing the offending line in stopHelper (above) seems to fix the issue. (JUnit) I created a DirectionTimingTarget and added several test cases (timingTargetDirection*()) to TestAnimator. So that this problem will not regress Looking back at the "classic" Chet Haase code it looks like I introduced this problem in trying to ensure that all the TimingTarget callbacks were made in a known thread context (not just the thread context of who called the Animator). My bad
        Hide
        hallorant added a comment -

        Fixed making a new release to get this out.

        Show
        hallorant added a comment - Fixed making a new release to get this out.

          People

          • Assignee:
            hallorant
            Reporter:
            hallorant
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: