Refactored the Animation library to no longer use a Deferred Binding (its always on).  Moved it to its own package "com.google.gwt.animation.client" and removed the WidgetAnimation class entirely.  All animations are disabled by default but can be enabled for each widget instance that supports animations.  The StackPanel animation is removed, but may be readded in the future.  This patch also fixes a couple minor animation bugs.

Patch by: jlabanca
Review by: jgw (desk review)



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2610 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java b/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java
index 5d87045..8fe6a20 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Shortcuts.java
@@ -56,7 +56,6 @@
     add(images, new Contacts(images), images.contactsgroup(), "Contacts");
 
     initWidget(stackPanel);
-    stackPanel.setAnimationEnabled(false);
   }
 
   @Override
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml b/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml
index e67e176..5143eb8 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/Showcase.gwt.xml
@@ -4,10 +4,6 @@
 	<inherits name='com.google.gwt.user.User'/>
 	<inherits name="com.google.gwt.i18n.I18N"/>
 
-	<!-- Enable Animations -->
-	<set-property name="gwt.enableAnimations" value="true"/> 
-	<set-property name="gwt.enableWidgetAnimations" value="true"/> 
-
 	<!-- Enable debug ID. -->
 	<inherits name="com.google.gwt.user.Debug"/>
 	<set-property name="gwt.enableDebugId" value="true"/> 
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java
index c5b31ff..96e98d3 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java
@@ -306,6 +306,7 @@
     // Setup the main menu
     ApplicationImages treeImages = GWT.create(ApplicationImages.class);
     mainMenu = new Tree(treeImages);
+    mainMenu.setAnimationEnabled(true);
     mainMenu.addStyleName(DEFAULT_STYLE_NAME + "-menu");
     mainMenu.addTreeListener(new TreeListener() {
       public void onTreeItemSelected(TreeItem item) {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwMenuBar.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwMenuBar.java
index 2544f50..fcc45a7 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwMenuBar.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwMenuBar.java
@@ -111,6 +111,7 @@
     MenuBar menu = new MenuBar();
     menu.setAutoOpen(true);
     menu.setWidth("500px");
+    menu.setAnimationEnabled(true);
 
     // Create a sub menu of recent documents
     MenuBar recentDocsMenu = new MenuBar(true);
@@ -121,6 +122,7 @@
 
     // Create the file menu
     MenuBar fileMenu = new MenuBar(true);
+    fileMenu.setAnimationEnabled(true);
     menu.addItem(new MenuItem(constants.cwMenuBarFileCategory(), fileMenu));
     String[] fileOptions = constants.cwMenuBarFileOptions();
     for (int i = 0; i < fileOptions.length; i++) {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
index a9987de..b21750e 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
@@ -87,6 +87,7 @@
   public Widget onInitialize() {
     // Create a static tree and a container to hold it
     Tree staticTree = createStaticTree();
+    staticTree.setAnimationEnabled(true);
     staticTree.ensureDebugId("cwTree-staticTree");
     ScrollPanel staticTreeWrapper = new ScrollPanel(staticTree);
     staticTreeWrapper.ensureDebugId("cwTree-staticTree-Wrapper");
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java
index eef9c79..9dbdf25 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java
@@ -15,10 +15,10 @@
  */
 package com.google.gwt.sample.showcase.client.content.other;
 
+import com.google.gwt.animation.client.Animation;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.Showcase;
-import com.google.gwt.user.client.animation.Animation;
 import com.google.gwt.user.client.ui.AbsolutePanel;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.ClickListener;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwDisclosurePanel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwDisclosurePanel.java
index e1e8169..39a9880 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwDisclosurePanel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwDisclosurePanel.java
@@ -144,6 +144,7 @@
     // Add advanced options to form in a disclosure panel
     DisclosurePanel advancedDisclosure = new DisclosurePanel(
         constants.cwDisclosurePanelFormAdvancedCriteria());
+    advancedDisclosure.setAnimationEnabled(true);
     advancedDisclosure.ensureDebugId("cwDisclosurePanel");
     advancedDisclosure.setContent(advancedOptions);
     layout.setWidget(3, 0, advancedDisclosure);
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwTabPanel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwTabPanel.java
index 0362fe7..f4f05ca 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwTabPanel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwTabPanel.java
@@ -88,7 +88,7 @@
     TabPanel tabPanel = new TabPanel();
     tabPanel.setWidth("400px");
 
-    // Unlike most widgets, animations are disabled by default
+    // Enable the deck panel animation
     tabPanel.getDeckPanel().setAnimationEnabled(true);
 
     // Add a home tab
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java
index 04df7e6..66689fb 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java
@@ -110,6 +110,7 @@
     // Create a popup to show the full size image
     Image jimmyFull = Showcase.images.jimmy().createImage();
     final PopupPanel imagePopup = new PopupPanel(true);
+    imagePopup.setAnimationEnabled(true);
     imagePopup.ensureDebugId("cwBasicPopup-imagePopup");
     imagePopup.setWidget(jimmyFull);
     jimmyFull.addClickListener(new ClickListener() {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
index 4d79687..1a8d27f 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
@@ -100,6 +100,7 @@
   public Widget onInitialize() {
     // Create the dialog box
     final DialogBox dialogBox = createDialogBox();
+    dialogBox.setAnimationEnabled(true);
 
     // Create a button to show the dialog Box
     Button openButton = new Button(constants.cwDialogBoxShowButton(),
diff --git a/user/test/com/google/gwt/user/WidgetAnimationTest.gwt.xml b/user/src/com/google/gwt/animation/Animation.gwt.xml
similarity index 69%
rename from user/test/com/google/gwt/user/WidgetAnimationTest.gwt.xml
rename to user/src/com/google/gwt/animation/Animation.gwt.xml
index f3db27d..a34f63d 100644
--- a/user/test/com/google/gwt/user/WidgetAnimationTest.gwt.xml
+++ b/user/src/com/google/gwt/animation/Animation.gwt.xml
@@ -12,7 +12,13 @@
 <!-- implied. License for the specific language governing permissions and   -->
 <!-- limitations under the License.                                         -->
 
+<!-- Module used to include Animation class.                                -->
+<!--                                                                        -->
+<!-- This module is typically inherited via com.google.gwt.user.User        -->
+<!--                                                                        -->
 <module>
-	<inherits name="com.google.gwt.user.UserTest"/>
-	<set-property name="gwt.enableWidgetAnimations" value="false"/>
+  <inherits name="com.google.gwt.core.Core"/>
+  
+  <!-- Include User module to inherit Timer -->
+  <inherits name="com.google.gwt.user.User"/>
 </module>
diff --git a/user/src/com/google/gwt/animation/client/Animation.java b/user/src/com/google/gwt/animation/client/Animation.java
new file mode 100644
index 0000000..9e55db7
--- /dev/null
+++ b/user/src/com/google/gwt/animation/client/Animation.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.animation.client;
+
+import com.google.gwt.core.client.Duration;
+import com.google.gwt.user.client.Timer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An {@link Animation} is a continuous event that updates progressively over
+ * time at a non-fixed frame rate.
+ */
+public abstract class Animation {
+  /**
+   * The default time in milliseconds between frames.
+   */
+  private static final int DEFAULT_FRAME_DELAY = 25;
+
+  /**
+   * The {@link Animation}s that are currently in progress.
+   */
+  private static List<Animation> animations = null;
+
+  /**
+   * The {@link Timer} that applies the animations.
+   */
+  private static Timer animationTimer = null;
+
+  /**
+   * Update all {@link Animation}s.
+   */
+  private static void updateAnimations() {
+    // Iterator through the animations
+    double curTime = Duration.currentTimeMillis();
+    for (int i = 0; i < animations.size(); i++) {
+      Animation animation = animations.get(i);
+      if (animation.update(curTime)) {
+        animations.remove(i);
+        i--;
+      }
+    }
+
+    // Reschedule the timer
+    if (animations.size() > 0) {
+      animationTimer.schedule(DEFAULT_FRAME_DELAY);
+    }
+  }
+
+  /**
+   * The duration of the {@link Animation} in milliseconds.
+   */
+  private int duration = -1;
+
+  /**
+   * Has the {@link Animation} been started.
+   */
+  private boolean started = false;
+
+  /**
+   * The start time of the {@link Animation}.
+   */
+  private double startTime = -1;
+
+  /**
+   * Immediately cancel this animation.
+   */
+  public void cancel() {
+    // No animations available
+    if (animations == null) {
+      return;
+    }
+
+    // Remove the animation
+    started = false;
+    if (animations.remove(this)) {
+      onCancel();
+    }
+  }
+
+  /**
+   * Immediately run this animation. If the animation is already running, it
+   * will be canceled first.
+   * 
+   * @param duration the duration of the animation in milliseconds
+   */
+  public void run(int duration) {
+    run(duration, Duration.currentTimeMillis());
+  }
+
+  /**
+   * Run this animation at the given startTime. If the startTime has already
+   * passed, the animation will be synchronize as if it started at the specified
+   * start time. If the animation is already running, it will be canceled first.
+   * 
+   * @param duration the duration of the animation in milliseconds
+   * @param startTime the synchronized start time in milliseconds
+   */
+  public void run(int duration, double startTime) {
+    // Cancel the animation if it is running
+    cancel();
+
+    // Save the duration and startTime
+    this.duration = duration;
+    this.startTime = startTime;
+
+    // Start synchronously if start time has passed
+    if (update(Duration.currentTimeMillis())) {
+      return;
+    }
+
+    // Add to the list of animations
+    if (animations == null) {
+      animations = new ArrayList<Animation>();
+      animationTimer = new Timer() {
+        @Override
+        public void run() {
+          updateAnimations();
+        }
+      };
+    }
+    animations.add(this);
+
+    // Restart the timer if there is the only animation
+    if (animations.size() == 1) {
+      animationTimer.schedule(DEFAULT_FRAME_DELAY);
+    }
+  }
+
+  /**
+   * Interpolate the linear progress into a more natural easing function.
+   * 
+   * Depending on the {@link Animation}, the return value of this method can be
+   * less than 0.0 or greater than 1.0.
+   * 
+   * @param progress the linear progress, between 0.0 and 1.0
+   * @return the interpolated progress
+   */
+  protected double interpolate(double progress) {
+    return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2;
+  }
+
+  /**
+   * Called immediately after the animation is canceled.
+   */
+  protected abstract void onCancel();
+
+  /**
+   * Called immediately after the animation completes.
+   */
+  protected abstract void onComplete();
+
+  /**
+   * Called immediately before the animation starts.
+   */
+  protected abstract void onStart();
+
+  /**
+   * Called when the animation should be updated.
+   * 
+   * The value of progress is between 0.0 and 1.0 inclusively, but it is not
+   * safe to assume that either 0.0 or 1.0 will be passed in. Use
+   * {@link #onStart()} and {@link #onComplete()} to do setup and tear down
+   * procedures.
+   */
+  protected abstract void onUpdate(double progress);
+
+  /**
+   * Update the {@link Animation}.
+   * 
+   * @param curTime the current time
+   * @return true if the animation is complete, false if still running
+   */
+  private boolean update(double curTime) {
+    // Start the animation
+    if (!started && curTime >= startTime) {
+      started = true;
+      onStart();
+    }
+
+    if (curTime >= startTime + duration) {
+      // Animation is complete
+      started = false;
+      onComplete();
+      return true;
+    } else if (curTime >= startTime) {
+      // Animation is in progress
+      double progress = (curTime - startTime) / duration;
+      onUpdate(interpolate(progress));
+    }
+    return false;
+  }
+}
diff --git a/user/src/com/google/gwt/user/Animation.gwt.xml b/user/src/com/google/gwt/user/Animation.gwt.xml
deleted file mode 100644
index e4f521d..0000000
--- a/user/src/com/google/gwt/user/Animation.gwt.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--                                                                        -->
-<!-- Copyright 2008 Google Inc.                                             -->
-<!-- Licensed under the Apache License, Version 2.0 (the "License"); you    -->
-<!-- may not use this file except in compliance with the License. You may   -->
-<!-- may obtain a copy of the License at                                    -->
-<!--                                                                        -->
-<!-- http://www.apache.org/licenses/LICENSE-2.0                             -->
-<!--                                                                        -->
-<!-- Unless required by applicable law or agreed to in writing, software    -->
-<!-- distributed under the License is distributed on an "AS IS" BASIS,      -->
-<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        -->
-<!-- implied. License for the specific language governing permissions and   -->
-<!-- limitations under the License.                                         -->
-
-<!-- Adds Animation support.                                                -->
-<module>
-  <!-- Enable or disable Animations -->
-  <define-property name="gwt.enableAnimations" values="true, false"/>
-
-  <!-- Enable or disable Widget Animations -->
-  <define-property name="gwt.enableWidgetAnimations" values="true, false"/>
-
-    <!-- Default to enabled -->
-  <set-property name="gwt.enableAnimations" value="true"/> 
-  <set-property name="gwt.enableWidgetAnimations" value="true"/> 
-
-  <!-- Replace the AnimationImpl -->
-  <replace-with class="com.google.gwt.user.client.animation.Animation.AnimationImplEnabled">
-    <when-type-is class="com.google.gwt.user.client.animation.Animation.AnimationImpl"/>
-    <when-property-is name="gwt.enableAnimations" value="true"/>
-  </replace-with>
-
-  <!-- Replace the WidgetAnimationImpl -->
-  <replace-with class="com.google.gwt.user.client.animation.WidgetAnimation.WidgetAnimationImplEnabled">
-    <when-type-is class="com.google.gwt.user.client.animation.WidgetAnimation.WidgetAnimationImpl"/>
-    <all>
-      <when-property-is name="gwt.enableWidgetAnimations" value="true"/>
-      <when-property-is name="gwt.enableAnimations" value="true"/>
-    </all>
-  </replace-with>
-</module>
diff --git a/user/src/com/google/gwt/user/StackPanel.gwt.xml b/user/src/com/google/gwt/user/StackPanel.gwt.xml
deleted file mode 100644
index 3076726..0000000
--- a/user/src/com/google/gwt/user/StackPanel.gwt.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-  Copyright 2008 Google Inc.
-
-  Licensed under the Apache License, Version 2.0 (the "License"); you may not
-  use this file except in compliance with the License. You may obtain a copy of
-  the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-  License for the specific language governing permissions and limitations under
-  the License.
--->
-<module>
-  <inherits name="com.google.gwt.user.User"/>
-
-  <replace-with class="com.google.gwt.user.client.ui.StackPanel.StackAnimation">
-    <when-type-is class="com.google.gwt.user.client.ui.StackPanel.StackAnimation"/>
-  </replace-with>
-
-  <replace-with class="com.google.gwt.user.client.ui.StackPanel.StackAnimationIE">
-    <when-type-is class="com.google.gwt.user.client.ui.StackPanel.StackAnimation"/>
-    <when-property-is name="user.agent" value="ie6"/>
-  </replace-with>
-
-</module>
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index eda5a3c..707e33c 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -19,7 +19,7 @@
 <!--                                                                        -->
 <module>
    <inherits name="com.google.gwt.core.Core"/>
-   <inherits name="com.google.gwt.user.Animation"/>
+   <inherits name="com.google.gwt.animation.Animation"/>
    <inherits name="com.google.gwt.user.RemoteService"/>
    <inherits name="com.google.gwt.user.DocumentRoot" />
    <inherits name="com.google.gwt.user.DOM"/>
@@ -35,7 +35,6 @@
    <inherits name="com.google.gwt.user.ClippedImage"/>
    <inherits name="com.google.gwt.user.RichText"/>
    <inherits name="com.google.gwt.user.SplitPanel"/>
-   <inherits name="com.google.gwt.user.StackPanel"/>
    <inherits name="com.google.gwt.user.ListBox" />
    <inherits name="com.google.gwt.user.CaptionPanel" />
    <inherits name="com.google.gwt.user.Window" />
diff --git a/user/src/com/google/gwt/user/client/animation/Animation.java b/user/src/com/google/gwt/user/client/animation/Animation.java
deleted file mode 100644
index 1f23b9f..0000000
--- a/user/src/com/google/gwt/user/client/animation/Animation.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.user.client.animation;
-
-import com.google.gwt.core.client.Duration;
-import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.Timer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An {@link Animation} is a continuous event that updates progressively over
- * time at a non-fixed frame rate.
- */
-public abstract class Animation {
-  /**
-   * Implementation class for {@link Animation} that does not allow any
-   * animations. If an animation is called, it is immediately started and
-   * completed.
-   */
-  public static class AnimationImpl {
-    protected void cancel(Animation anim) {
-    }
-
-    protected void run(Animation anim, int duration, double startTime) {
-      anim.onRunWhenDisabled();
-    }
-  }
-
-  /**
-   * Implementation class for {@link Animation} that actually performs
-   * animations.
-   */
-  public static class AnimationImplEnabled extends AnimationImpl {
-    /**
-     * The default time in milliseconds between frames.
-     */
-    private static final int DEFAULT_FRAME_DELAY = 25;
-
-    /**
-     * The {@link Animation}s that are currently in progress.
-     */
-    private static List<Animation> animations;
-
-    /**
-     * The {@link Timer} that applies the animations.
-     */
-    private static Timer animationTimer;
-
-    @Override
-    protected void cancel(Animation anim) {
-      // No animations available
-      if (animations == null) {
-        return;
-      }
-
-      // Remove the animation
-      anim.started = false;
-      if (animations.remove(anim)) {
-        anim.onCancel();
-      }
-    }
-
-    @Override
-    protected void run(Animation anim, int duration, double startTime) {
-      // Cancel the animation if it is running
-      anim.cancel();
-
-      // Save the duration and startTime
-      anim.duration = duration;
-      anim.startTime = startTime;
-
-      // Start synchronously if start time has passed
-      if (anim.update(Duration.currentTimeMillis())) {
-        return;
-      }
-
-      // Add to the list of animations
-      if (animations == null) {
-        animations = new ArrayList<Animation>();
-        animationTimer = new Timer() {
-          @Override
-          public void run() {
-            updateAnimations();
-          }
-        };
-      }
-      animations.add(anim);
-
-      // Restart the timer if there is the only animation
-      if (animations.size() == 1) {
-        animationTimer.schedule(DEFAULT_FRAME_DELAY);
-      }
-    }
-
-    /**
-     * Update all {@link Animation}s.
-     */
-    private void updateAnimations() {
-      // Iterator through the animations
-      double curTime = Duration.currentTimeMillis();
-      for (int i = 0; i < animations.size(); i++) {
-        Animation animation = animations.get(i);
-        if (animation.update(curTime)) {
-          animations.remove(i);
-          i--;
-        }
-      }
-
-      // Reschedule the timer
-      if (animations.size() > 0) {
-        animationTimer.schedule(DEFAULT_FRAME_DELAY);
-      }
-    }
-  }
-
-  /**
-   * The implementation class.
-   */
-  static AnimationImpl impl = GWT.create(AnimationImpl.class);
-
-  /**
-   * The duration of the {@link Animation} in milliseconds.
-   */
-  private int duration = -1;
-
-  /**
-   * Has the {@link Animation} been started.
-   */
-  private boolean started = false;
-
-  /**
-   * The start time of the {@link Animation}.
-   */
-  private double startTime = -1;
-
-  /**
-   * Immediately cancel this animation.
-   */
-  public void cancel() {
-    impl.cancel(this);
-  }
-
-  /**
-   * Called immediately after the animation is canceled.
-   */
-  public abstract void onCancel();
-
-  /**
-   * Called immediately after the animation completes.
-   */
-  public abstract void onComplete();
-
-  /**
-   * Called immediately before the animation starts.
-   */
-  public abstract void onStart();
-
-  /**
-   * Called when the animation should be updated.
-   * 
-   * The value of progress is between 0.0 and 1.0 inclusively, but it is not
-   * safe to assume that either 0.0 or 1.0 will be passed in. Use
-   * {@link #onStart()} and {@link #onComplete()} to do setup and tear down
-   * procedures.
-   */
-  public abstract void onUpdate(double progress);
-
-  /**
-   * Immediately run this animation. If the animation is already running, it
-   * will be canceled first.
-   * 
-   * @param duration the duration of the animation in milliseconds
-   */
-  public void run(int duration) {
-    run(duration, Duration.currentTimeMillis());
-  }
-
-  /**
-   * Run this animation at the given startTime. If the startTime has already
-   * passed, the animation will be synchronize as if it started at the specified
-   * start time. If the animation is already running, it will be canceled first.
-   * 
-   * @param duration the duration of the animation in milliseconds
-   * @param startTime the synchronized start time in milliseconds
-   */
-  public void run(int duration, double startTime) {
-    impl.run(this, duration, startTime);
-  }
-
-  /**
-   * Interpolate the linear progress into a more natural easing function.
-   * 
-   * Depending on the {@link Animation}, the return value of this method can be
-   * less than 0.0 or greater than 1.0.
-   * 
-   * @param progress the linear progress, between 0.0 and 1.0
-   * @return the interpolated progress
-   */
-  protected double interpolate(double progress) {
-    return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2;
-  }
-
-  /**
-   * Called when we run an animation that is disabled.
-   */
-  void onRunWhenDisabled() {
-    onStart();
-    onComplete();
-  }
-
-  /**
-   * Update the {@link Animation}.
-   * 
-   * @param curTime the current time
-   * @return true if the animation is complete, false if still running
-   */
-  private boolean update(double curTime) {
-    // Start the animation
-    if (!started && curTime >= startTime) {
-      started = true;
-      onStart();
-    }
-
-    if (curTime >= startTime + duration) {
-      // Animation is complete
-      started = false;
-      onComplete();
-      return true;
-    } else if (curTime >= startTime) {
-      // Animation is in progress
-      double progress = (double) (curTime - startTime) / (double) duration;
-      onUpdate(interpolate(progress));
-    }
-    return false;
-  }
-}
diff --git a/user/src/com/google/gwt/user/client/animation/WidgetAnimation.java b/user/src/com/google/gwt/user/client/animation/WidgetAnimation.java
deleted file mode 100644
index 02dd464..0000000
--- a/user/src/com/google/gwt/user/client/animation/WidgetAnimation.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.user.client.animation;
-
-import com.google.gwt.core.client.GWT;
-
-/**
- * An {@link WidgetAnimation} is an {@link Animation} specifically designed for
- * use with Widgets. If the animation is disabled, the #onInstantaneousRun
- * method will be called instead of onStart and onComplete. This allows you to
- * increase performance when animations are disabled.
- */
-public abstract class WidgetAnimation extends Animation {
-  /**
-   * Implementation class for {@link WidgetAnimation} that does not allow any
-   * animations. If an animation is called, it is immediately started and
-   * completed.
-   */
-  public static class WidgetAnimationImpl {
-    protected void cancel(WidgetAnimation anim) {
-    }
-
-    protected void run(WidgetAnimation anim, int duration, double startTime) {
-      anim.onRunWhenDisabled();
-    }
-  }
-
-  /**
-   * Implementation class for {@link WidgetAnimation} that actually performs
-   * animations.
-   */
-  public static class WidgetAnimationImplEnabled extends WidgetAnimationImpl {
-    @Override
-    protected void cancel(WidgetAnimation anim) {
-      Animation.impl.cancel(anim);
-    }
-
-    @Override
-    protected void run(WidgetAnimation anim, int duration, double startTime) {
-      Animation.impl.run(anim, duration, startTime);
-    }
-  }
-
-  /**
-   * The implementation class.
-   */
-  private static WidgetAnimationImpl widgetImpl = GWT.create(WidgetAnimationImpl.class);
-
-  /**
-   * Immediately cancel this animation.
-   */
-  @Override
-  public void cancel() {
-    widgetImpl.cancel(this);
-  }
-
-  /**
-   * Called if this animation is run when it is disabled. If this method is
-   * called, {@link #onStart()} and {@link #onComplete()} will not be called.
-   */
-  public abstract void onInstantaneousRun();
-
-  /**
-   * Run this animation at the given startTime. If the startTime has already
-   * passed, the animation will be synchronize as if it started at the specified
-   * start time. If the animation is already running, it will be canceled first.
-   * 
-   * @param duration the duration of the animation in milliseconds
-   * @param startTime the synchronized start time in milliseconds
-   */
-  @Override
-  public void run(int duration, double startTime) {
-    widgetImpl.run(this, duration, startTime);
-  }
-
-  /**
-   * Called when we run an animation that is disabled.
-   */
-  @Override
-  void onRunWhenDisabled() {
-    onInstantaneousRun();
-  }
-
-}
diff --git a/user/src/com/google/gwt/user/client/ui/DeckPanel.java b/user/src/com/google/gwt/user/client/ui/DeckPanel.java
index 47b59ac..8861888 100644
--- a/user/src/com/google/gwt/user/client/ui/DeckPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DeckPanel.java
@@ -15,9 +15,9 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.animation.client.Animation;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.animation.WidgetAnimation;
 
 /**
  * A panel that displays all of its child widgets in a 'deck', where only one
@@ -33,9 +33,9 @@
  */
 public class DeckPanel extends ComplexPanel implements HasAnimation {
   /**
-   * An {@link WidgetAnimation} used to slide in the new content.
+   * An {@link Animation} used to slide in the new content.
    */
-  private static class SlideAnimation extends WidgetAnimation {
+  private static class SlideAnimation extends Animation {
     /**
      * The {@link Element} holding the {@link Widget} with a lower index.
      */
@@ -76,11 +76,12 @@
         DOM.setStyleAttribute(container2, "height", "100%");
         UIObject.setVisible(container2, true);
       }
+      DOM.setStyleAttribute(container1, "overflow", "visible");
+      DOM.setStyleAttribute(container2, "overflow", "visible");
       container1 = null;
       container2 = null;
     }
 
-    @Override
     public void onInstantaneousRun() {
       UIObject.setVisible(container1, growing);
       UIObject.setVisible(container2, !growing);
@@ -105,6 +106,8 @@
       }
 
       // Start the animation
+      DOM.setStyleAttribute(container1, "overflow", "hidden");
+      DOM.setStyleAttribute(container2, "overflow", "hidden");
       onUpdate(0.0);
       UIObject.setVisible(container1, true);
       UIObject.setVisible(container2, true);
@@ -190,7 +193,7 @@
   }
 
   /**
-   * The {@link WidgetAnimation} used to slide in the new {@link Widget}.
+   * The {@link Animation} used to slide in the new {@link Widget}.
    */
   private static SlideAnimation slideAnimation;
 
@@ -264,9 +267,6 @@
     finishWidgetInitialization(container, w);
   }
 
-  /**
-   * @see HasAnimation#isAnimationEnabled()
-   */
   public boolean isAnimationEnabled() {
     return isAnimationEnabled;
   }
@@ -286,9 +286,6 @@
     return removed;
   }
 
-  /**
-   * @see HasAnimation#setAnimationEnabled(boolean)
-   */
   public void setAnimationEnabled(boolean enable) {
     isAnimationEnabled = enable;
   }
@@ -320,7 +317,6 @@
     Element container = DOM.createDiv();
     DOM.setStyleAttribute(container, "width", "100%");
     DOM.setStyleAttribute(container, "height", "0px");
-    DOM.setStyleAttribute(container, "overflow", "hidden");
     DOM.setStyleAttribute(container, "padding", "0px");
     DOM.setStyleAttribute(container, "margin", "0px");
     return container;
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java b/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
index 9805bc3..89ff7e6 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
@@ -15,12 +15,12 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.animation.client.Animation;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.animation.WidgetAnimation;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -50,9 +50,9 @@
 public final class DisclosurePanel extends Composite implements
     FiresDisclosureEvents, HasWidgets, HasAnimation {
   /**
-   * An {@link WidgetAnimation} used to open the content.
+   * An {@link Animation} used to open the content.
    */
-  private static class ContentAnimation extends WidgetAnimation {
+  private static class ContentAnimation extends Animation {
     /**
      * Whether the item is being opened or closed.
      */
@@ -79,12 +79,6 @@
     }
 
     @Override
-    public void onInstantaneousRun() {
-      curPanel.contentWrapper.setVisible(opening);
-      curPanel = null;
-    }
-
-    @Override
     public void onStart() {
       onUpdate(0.0);
       if (opening) {
@@ -118,13 +112,12 @@
       cancel();
 
       // Open the new item
-      curPanel = panel;
-      opening = panel.isOpen;
-
       if (animate) {
+        curPanel = panel;
+        opening = panel.isOpen;
         run(350);
       } else {
-        onInstantaneousRun();
+        panel.contentWrapper.setVisible(panel.isOpen);
       }
     }
   }
@@ -244,7 +237,7 @@
   private static final String STYLENAME_CONTENT = "content";
 
   /**
-   * The {@link WidgetAnimation} used to open and close the content.
+   * The {@link Animation} used to open and close the content.
    */
   private static ContentAnimation contentAnimation;
 
@@ -277,7 +270,7 @@
    */
   private Widget content;
 
-  private boolean isAnimationEnabled = true;
+  private boolean isAnimationEnabled = false;
 
   private boolean isOpen = false;
 
@@ -445,7 +438,7 @@
     }
     handlers.remove(handler);
   }
- 
+
   public void setAnimationEnabled(boolean enable) {
     isAnimationEnabled = enable;
   }
diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java
index 1d63ab1..002fcdf 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -101,7 +101,7 @@
   private Element body;
 
   private MenuBarImages images = null;
-  private boolean isAnimationEnabled = true;
+  private boolean isAnimationEnabled = false;
   private MenuBar parentMenu;
   private PopupPanel popup;
   private MenuItem selectedItem;
@@ -280,9 +280,6 @@
     return autoOpen;
   }
 
-  /**
-   * @see HasAnimation#isAnimationEnabled()
-   */
   public boolean isAnimationEnabled() {
     return isAnimationEnabled;
   }
@@ -401,9 +398,6 @@
     }
   }
 
-  /**
-   * @see HasAnimation#setAnimationEnabled(boolean)
-   */
   public void setAnimationEnabled(boolean enable) {
     isAnimationEnabled = enable;
   }
@@ -549,21 +543,13 @@
       }
     };
     popup.setAnimationType(AnimationType.ONE_WAY_CORNER);
+    popup.setAnimationEnabled(isAnimationEnabled);
     popup.setStyleName("gwt-MenuBarPopup");
     popup.addPopupListener(this);
 
     shownChildMenu = item.getSubMenu();
     item.getSubMenu().parentMenu = this;
 
-    // If any parent MenuBar has animations disabled, then do not animate
-    MenuBar parent = parentMenu;
-    boolean animate = isAnimationEnabled;
-    while (animate && parent != null) {
-      animate = parent.isAnimationEnabled();
-      parent = parent.parentMenu;
-    }
-    popup.setAnimationEnabled(animate);
-
     // Show the popup, ensuring that the menubar's event preview remains on top
     // of the popup's.
     popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
diff --git a/user/src/com/google/gwt/user/client/ui/PopupPanel.java b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
index ad1fe1c..c81c919 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -15,15 +15,15 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.animation.client.Animation;
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventPreview;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.animation.WidgetAnimation;
 import com.google.gwt.user.client.ui.impl.PopupImpl;
-import com.google.gwt.i18n.client.LocaleInfo;
 
 /**
  * A panel that can "pop up" over other widgets. It overlays the browser's
@@ -65,9 +65,9 @@
   }
 
   /**
-   * An {@link WidgetAnimation} used to enlarge the popup into view.
+   * An {@link Animation} used to enlarge the popup into view.
    */
-  private static class ResizeAnimation extends WidgetAnimation {
+  private static class ResizeAnimation extends Animation {
     /**
      * The offset height and width of the current {@link PopupPanel}.
      */
@@ -98,7 +98,6 @@
       curPanel = null;
     }
 
-    @Override
     public void onInstantaneousRun() {
       if (showing) {
         // Set the position attribute, and then attach to the DOM. Otherwise,
@@ -247,7 +246,7 @@
 
   private String desiredWidth;
 
-  private boolean isAnimationEnabled = true;
+  private boolean isAnimationEnabled = false;
 
   // the left style attribute in pixels
   private int leftPosition = -1;
@@ -384,9 +383,6 @@
     hide(false);
   }
 
-  /**
-   * @see HasAnimation#isAnimationEnabled()
-   */
   public boolean isAnimationEnabled() {
     return isAnimationEnabled;
   }
@@ -493,9 +489,6 @@
     }
   }
 
-  /**
-   * @see HasAnimation#setAnimationEnabled(boolean)
-   */
   public void setAnimationEnabled(boolean enable) {
     isAnimationEnabled = enable;
   }
diff --git a/user/src/com/google/gwt/user/client/ui/StackPanel.java b/user/src/com/google/gwt/user/client/ui/StackPanel.java
index a70de0c..2c18ac1 100644
--- a/user/src/com/google/gwt/user/client/ui/StackPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/StackPanel.java
@@ -15,11 +15,9 @@
  */
 package com.google.gwt.user.client.ui;
 
-import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.animation.WidgetAnimation;
 
 /**
  * A panel that stacks its children vertically, displaying only one at a time,
@@ -40,143 +38,12 @@
  * {@example com.google.gwt.examples.StackPanelExample}
  * </p>
  */
-public class StackPanel extends ComplexPanel implements HasAnimation {
-  /**
-   * An {@link WidgetAnimation} used to switch between the visible stack.
-   */
-  public static class StackAnimation extends WidgetAnimation {
-    /**
-     * The {@link StackPanel} being affected.
-     */
-    private StackPanel curPanel = null;
-
-    /**
-     * The index of the stack that is being hidden.
-     */
-    private int oldIndex = -1;
-
-    /**
-     * The index of the stack that is being displayed.
-     */
-    private int newIndex = -1;
-
-    /**
-     * The container that is being displayed.
-     */
-    private Element newTD = null;
-
-    @Override
-    public void onCancel() {
-      onComplete();
-    }
-
-    @Override
-    public void onComplete() {
-      if (curPanel != null) {
-        curPanel.setStackContentVisible(oldIndex, false);
-        curPanel.setStackContentVisible(newIndex, true);
-        clearOpacity(newTD);
-        curPanel = null;
-      }
-    }
-
-    @Override
-    public void onInstantaneousRun() {
-      curPanel.setStackContentVisible(oldIndex, false);
-      curPanel.setStackContentVisible(newIndex, true);
-      curPanel = null;
-    }
-
-    @Override
-    public void onStart() {
-      onUpdate(0.0);
-      curPanel.setStackContentVisible(oldIndex, false);
-      curPanel.setStackContentVisible(newIndex, true);
-    }
-
-    @Override
-    public void onUpdate(double progress) {
-      setOpacity(newTD, progress);
-    }
-
-    /**
-     * Open or close the content.
-     * 
-     * @param panel the panel being affected
-     * @param oldIndex the index being closed
-     * @param newIndex the index being opened
-     */
-    public void showStack(StackPanel panel, int oldIndex, int newIndex) {
-      // Immediately complete previous open
-      cancel();
-
-      // Do not animate if there is no stack currently visible
-      if (oldIndex < 0) {
-        panel.setStackContentVisible(newIndex, true);
-        return;
-      }
-
-      // Get all of the affected Elements
-      curPanel = panel;
-      this.oldIndex = oldIndex;
-      this.newIndex = newIndex;
-      newTD = DOM.getFirstChild(DOM.getChild(curPanel.body, (2 * newIndex) + 1));
-
-      // Run the animation
-      if (panel.isAnimationEnabled) {
-        run(250);
-      } else {
-        onInstantaneousRun();
-      }
-    }
-
-    /**
-     * Clear the opacity of an {@link Element}.
-     * 
-     * @param elem the {@link Element}
-     */
-    protected void clearOpacity(Element elem) {
-      DOM.setStyleAttribute(elem, "opacity", "");
-    }
-
-    /**
-     * Set the opacity of an {@link Element}.
-     * 
-     * @param elem the {@link Element}
-     * @param opacity the opacity between 0.0 and 1.0, inclusively
-     */
-    protected void setOpacity(Element elem, double opacity) {
-      DOM.setStyleAttribute(elem, "opacity", opacity + "");
-    }
-  }
-
-  /**
-   * IE version of {@link StackAnimation} that sets opacity using filters.
-   */
-  public static class StackAnimationIE extends StackAnimation {
-    @Override
-    protected void clearOpacity(Element elem) {
-      DOM.setStyleAttribute(elem, "filter", "");
-    }
-
-    @Override
-    protected void setOpacity(Element elem, double opacity) {
-      int opac = (int) (100 * opacity);
-      DOM.setStyleAttribute(elem, "filter", "alpha(opacity=" + opac + ")");
-    }
-  }
-
+public class StackPanel extends ComplexPanel {
   private static final String DEFAULT_STYLENAME = "gwt-StackPanel";
   private static final String DEFAULT_ITEM_STYLENAME = DEFAULT_STYLENAME
       + "Item";
 
-  /**
-   * The {@link WidgetAnimation} used to switch stacks.
-   */
-  private static StackAnimation stackAnimation;
-
   private Element body;
-  private boolean isAnimationEnabled = true;
   private int visibleStack = -1;
 
   /**
@@ -286,22 +153,15 @@
     if (visibleStack == -1) {
       showStack(0);
     } else {
-      setStackVisible(beforeIndex, false, true);
+      setStackVisible(beforeIndex, false);
       if (visibleStack >= beforeIndex) {
         ++visibleStack;
       }
       // Reshow the stack to apply style names
-      setStackVisible(visibleStack, true, true);
+      setStackVisible(visibleStack, true);
     }
   }
 
-  /**
-   * @see HasAnimation#isAnimationEnabled()
-   */
-  public boolean isAnimationEnabled() {
-    return isAnimationEnabled;
-  }
-
   @Override
   public void onBrowserEvent(Event event) {
     if (DOM.eventGetType(event) == Event.ONCLICK) {
@@ -324,13 +184,6 @@
   }
 
   /**
-   * @see HasAnimation#setAnimationEnabled(boolean)
-   */
-  public void setAnimationEnabled(boolean enable) {
-    isAnimationEnabled = enable;
-  }
-
-  /**
    * Sets the text associated with a child by its index.
    * 
    * @param index the index of the child whose text is to be set
@@ -375,15 +228,11 @@
 
     int oldIndex = visibleStack;
     if (visibleStack >= 0) {
-      setStackVisible(visibleStack, false, false);
+      setStackVisible(visibleStack, false);
     }
 
     visibleStack = index;
-    setStackVisible(visibleStack, true, false);
-    if (stackAnimation == null) {
-      stackAnimation = GWT.create(StackAnimation.class);
-    }
-    stackAnimation.showStack(this, oldIndex, index);
+    setStackVisible(visibleStack, true);
   }
 
   /**
@@ -487,7 +336,7 @@
     getWidget(index).setVisible(visible);
   }
 
-  private void setStackVisible(int index, boolean visible, boolean render) {
+  private void setStackVisible(int index, boolean visible) {
     // Get the first table row containing the widget's selector item.
     Element tr = DOM.getChild(body, (index * 2));
     if (tr == null) {
@@ -499,9 +348,7 @@
     setStyleName(td, DEFAULT_ITEM_STYLENAME + "-selected", visible);
 
     // Show/hide the contained widget.
-    if (render) {
-      setStackContentVisible(index, visible);
-    }
+    setStackContentVisible(index, visible);
 
     // Set the style of the next header
     Element trNext = DOM.getChild(body, ((index + 1) * 2));
diff --git a/user/src/com/google/gwt/user/client/ui/Tree.java b/user/src/com/google/gwt/user/client/ui/Tree.java
index 24d0a3f..0b1c511 100644
--- a/user/src/com/google/gwt/user/client/ui/Tree.java
+++ b/user/src/com/google/gwt/user/client/ui/Tree.java
@@ -179,7 +179,7 @@
   private Element focusable;
   private FocusListenerCollection focusListeners;
   private TreeImages images;
-  private boolean isAnimationEnabled = true;
+  private boolean isAnimationEnabled = false;
   private KeyboardListenerCollection keyboardListeners;
   private TreeListenerCollection listeners;
   private MouseListenerCollection mouseListeners = null;
@@ -365,9 +365,6 @@
     return FocusPanel.impl.getTabIndex(focusable);
   }
 
-  /**
-   * @see HasAnimation#isAnimationEnabled()
-   */
   public boolean isAnimationEnabled() {
     return isAnimationEnabled;
   }
@@ -575,9 +572,6 @@
     FocusPanel.impl.setAccessKey(focusable, key);
   }
 
-  /**
-   * @see HasAnimation#setAnimationEnabled(boolean)
-   */
   public void setAnimationEnabled(boolean enable) {
     isAnimationEnabled = enable;
   }
diff --git a/user/src/com/google/gwt/user/client/ui/TreeItem.java b/user/src/com/google/gwt/user/client/ui/TreeItem.java
index f3c2c15..9c033dc 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeItem.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeItem.java
@@ -15,10 +15,10 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.animation.client.Animation;
+import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
-import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.animation.WidgetAnimation;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -38,11 +38,11 @@
 public class TreeItem extends UIObject implements HasHTML {
 
   /**
-   * An {@link WidgetAnimation} used to open the child elements. If a
-   * {@link TreeItem} is in the process of opening, it will immediately be
-   * opened and the new {@link TreeItem} will use this animation.
+   * An {@link Animation} used to open the child elements. If a {@link TreeItem}
+   * is in the process of opening, it will immediately be opened and the new
+   * {@link TreeItem} will use this animation.
    */
-  private static class TreeItemAnimation extends WidgetAnimation {
+  private static class TreeItemAnimation extends Animation {
 
     /**
      * The {@link TreeItem} currently being affected.
@@ -76,12 +76,6 @@
     }
 
     @Override
-    public void onInstantaneousRun() {
-      UIObject.setVisible(curItem.childSpanElem, opening);
-      curItem = null;
-    }
-
-    @Override
     public void onStart() {
       DOM.setStyleAttribute(curItem.childSpanElem, "overflow", "hidden");
       onUpdate(0.0);
@@ -123,12 +117,12 @@
       cancel();
 
       // Open the new item
-      curItem = item;
-      opening = item.open;
       if (animate) {
+        curItem = item;
+        opening = item.open;
         run(Math.min(200, 75 * curItem.getChildCount()));
       } else {
-        onInstantaneousRun();
+        UIObject.setVisible(item.childSpanElem, item.open);
       }
     }
   }
diff --git a/user/test/com/google/gwt/user/client/animation/AnimationTest.java b/user/test/com/google/gwt/animation/client/AnimationTest.java
similarity index 99%
rename from user/test/com/google/gwt/user/client/animation/AnimationTest.java
rename to user/test/com/google/gwt/animation/client/AnimationTest.java
index ef6ddd4..874fb29 100644
--- a/user/test/com/google/gwt/user/client/animation/AnimationTest.java
+++ b/user/test/com/google/gwt/animation/client/AnimationTest.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.user.client.animation;
+package com.google.gwt.animation.client;
 
 import com.google.gwt.core.client.Duration;
 import com.google.gwt.junit.client.GWTTestCase;
diff --git a/user/test/com/google/gwt/user/client/animation/WidgetAnimationTest.java b/user/test/com/google/gwt/user/client/animation/WidgetAnimationTest.java
deleted file mode 100644
index 466a5fe..0000000
--- a/user/test/com/google/gwt/user/client/animation/WidgetAnimationTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.user.client.animation;
-
-import com.google.gwt.junit.client.GWTTestCase;
-
-/**
- * Tests the {@link WidgetAnimation} class.
- */
-public class WidgetAnimationTest extends GWTTestCase {
-  /**
-   * A customer {@link Animation} used for testing.
-   */
-  private static class TestWidgetAnimation extends WidgetAnimation {
-    public boolean cancelled = false;
-    public boolean completed = false;
-    public boolean started = false;
-    public boolean instaneousRun = false;
-    public double curProgress = -1.0;
-
-    @Override
-    public void onCancel() {
-      cancelled = true;
-    }
-
-    @Override
-    public void onComplete() {
-      completed = true;
-    }
-
-    @Override
-    public void onInstantaneousRun() {
-      instaneousRun = true;
-    }
-
-    @Override
-    public void onStart() {
-      started = true;
-    }
-
-    @Override
-    public void onUpdate(double progress) {
-      curProgress = progress;
-    }
-
-    public void reset() {
-      cancelled = false;
-      completed = false;
-      started = false;
-      curProgress = -1.0;
-    }
-  }
-
-  @Override
-  /**
-   * Return a module that disables widget animations.
-   */
-  public String getModuleName() {
-    return "com.google.gwt.user.WidgetAnimationTest";
-  }
-
-  /**
-   * Test general functionality.
-   */
-  public void testRun() {
-    TestWidgetAnimation anim = new TestWidgetAnimation();
-
-    // Run animations
-    anim.run(300);
-
-    // Check the results
-    assertFalse(anim.started);
-    assertFalse(anim.completed);
-    assertTrue(anim.instaneousRun);
-    assertEquals(-1.0, anim.curProgress);
-  }
-}
diff --git a/user/test/com/google/gwt/user/client/ui/PopupTest.java b/user/test/com/google/gwt/user/client/ui/PopupTest.java
index f228733..ad989d5 100644
--- a/user/test/com/google/gwt/user/client/ui/PopupTest.java
+++ b/user/test/com/google/gwt/user/client/ui/PopupTest.java
@@ -46,9 +46,9 @@
     PopupPanel popup = new PopupPanel();
     
     // Animation enabled
-    assertTrue(popup.isAnimationEnabled());
-    popup.setAnimationEnabled(false);
     assertFalse(popup.isAnimationEnabled());
+    popup.setAnimationEnabled(true);
+    assertTrue(popup.isAnimationEnabled());
   }
 
   public void testPopup() {