@@ -0,0 +1,1254 @@
+package jetbrains.jetpad.base.animation;%0A%0Aimport jetbrains.jetpad.base.Registration;%0Aimport jetbrains.jetpad.base.edt.EventDispatchThread;%0A%0Apublic abstract class TimerAnimation implements Animation %7B%0A  private DefaultAnimation myDefaultAnimation = new DefaultAnimation() %7B%0A    @Override%0A    protected void doStop() %7B%0A    %7D%0A  %7D;%0A  private Registration myTimerReg;%0A  private int myFrame;%0A  private int myMaxFrame;%0A%0A  protected TimerAnimation(EventDispatchThread edt, int frames, int framePeriod) %7B%0A    if (frames %3C= 0) %7B%0A      throw new IllegalArgumentException();%0A    %7D%0A%0A    myTimerReg = edt.scheduleRepeating(framePeriod, new Runnable() %7B%0A      @Override%0A      public void run() %7B%0A        onFrame();%0A      %7D%0A    %7D);%0A    myMaxFrame = frames;%0A  %7D%0A%0A  @Override%0A  public void stop() %7B%0A    myFrame = myMaxFrame;%0A    animateFrame(myFrame);%0A    lastFrame();%0A    myDefaultAnimation.stop();%0A  %7D%0A%0A  private void onFrame() %7B%0A    myFrame++;%0A    animateFrame(myFrame);%0A    if (myFrame == myMaxFrame) %7B%0A      lastFrame();%0A      myDefaultAnimation.done();%0A    %7D%0A  %7D%0A%0A  private void lastFrame() %7B%0A    myTimerReg.remove();%0A  %7D%0A%0A  protected abstract void animateFrame(int frame);%0A%0A  @Override%0A  public void whenDone(Runnable r) %7B%0A    myDefaultAnimation.whenDone(r);%0A  %7D%0A%7D%0A

implement timer based animaation