Fixing a bug in DeckLayoutPanel where animating the current widget causes the current widget to disappear.  This can happen if the user calls forceLayout() without setting a new widget, or if the user calls setWidget() with the currently visible widget.

http://gwt-code-reviews.appspot.com/1354801

Review by: pdr@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9716 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/DeckLayoutPanel.java b/user/src/com/google/gwt/user/client/ui/DeckLayoutPanel.java
index 7cdd76d..ed83651 100644
--- a/user/src/com/google/gwt/user/client/ui/DeckLayoutPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DeckLayoutPanel.java
@@ -332,20 +332,29 @@
     double hDirection = isAnimationVertical ? 0.0
         : LocaleInfo.getCurrentLocale().isRTL() ? -direction : direction;
 
-    // Position the layers in their start positions.
-    if (oldLayer != null) {
-      // The old layer starts centered in the panel.
-      oldLayer.setTopHeight(0.0, Unit.PCT, 100.0, Unit.PCT);
-      oldLayer.setLeftWidth(0.0, Unit.PCT, 100.0, Unit.PCT);
-      setWidgetVisible(lastVisibleWidget, oldLayer, true);
+    /*
+     * Position the old widget in the center of the panel, and the new widget
+     * off to one side. If the old widget is the same as the new widget, then
+     * skip this step.
+     */
+    hidingWidget = null;
+    if (visibleWidget != lastVisibleWidget) {
+      // Position the layers in their start positions.
+      if (oldLayer != null) {
+        // The old layer starts centered in the panel.
+        oldLayer.setTopHeight(0.0, Unit.PCT, 100.0, Unit.PCT);
+        oldLayer.setLeftWidth(0.0, Unit.PCT, 100.0, Unit.PCT);
+        setWidgetVisible(lastVisibleWidget, oldLayer, true);
+      }
+      if (newLayer != null) {
+        // The new layer starts off to one side.
+        newLayer.setTopHeight(vDirection, Unit.PCT, 100.0, Unit.PCT);
+        newLayer.setLeftWidth(hDirection, Unit.PCT, 100.0, Unit.PCT);
+        setWidgetVisible(visibleWidget, newLayer, true);
+      }
+      layout.layout();
+      hidingWidget = lastVisibleWidget;
     }
-    if (newLayer != null) {
-      // The new layer starts off to one side.
-      newLayer.setTopHeight(vDirection, Unit.PCT, 100.0, Unit.PCT);
-      newLayer.setLeftWidth(hDirection, Unit.PCT, 100.0, Unit.PCT);
-      setWidgetVisible(visibleWidget, newLayer, true);
-    }
-    layout.layout();
 
     // Set the end positions of the layers.
     if (oldLayer != null) {
@@ -367,7 +376,6 @@
       setWidgetVisible(visibleWidget, newLayer, true);
     }
 
-    hidingWidget = lastVisibleWidget;
     lastVisibleWidget = visibleWidget;
   }
 
diff --git a/user/test/com/google/gwt/user/client/ui/DeckLayoutPanelTest.java b/user/test/com/google/gwt/user/client/ui/DeckLayoutPanelTest.java
index 87ee8e8..5103ad6 100644
--- a/user/test/com/google/gwt/user/client/ui/DeckLayoutPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/DeckLayoutPanelTest.java
@@ -21,6 +21,34 @@
  */
 public class DeckLayoutPanelTest extends PanelTestBase<DeckLayoutPanel> {
 
+  /**
+   * Test that forcing layout without changing the widget doesn't cause the
+   * widget to disappear.
+   */
+  public void testForceLayoutSameWidget() {
+    DeckLayoutPanel deck = createPanel();
+    Label[] labels = new Label[2];
+    for (int i = 0; i < labels.length; i++) {
+      labels[i] = new Label("content" + i);
+      deck.add(labels[i]);
+    }
+
+    // Show widget at index 1, make sure it becomes visible.
+    deck.showWidget(1);
+    assertEquals(1, deck.getVisibleWidgetIndex());
+    assertEquals(labels[1], deck.getVisibleWidget());
+    deck.forceLayout();
+    assertFalse(labels[0].isVisible());
+    assertTrue(labels[1].isVisible());
+
+    // Force layout and make sure that widget 1 is still visible.
+    deck.forceLayout();
+    assertEquals(1, deck.getVisibleWidgetIndex());
+    assertEquals(labels[1], deck.getVisibleWidget());
+    assertFalse(labels[0].isVisible());
+    assertTrue(labels[1].isVisible());
+  }
+
   public void testSetWidget() {
     DeckLayoutPanel deck = createPanel();
     Label[] labels = new Label[2];
@@ -93,6 +121,36 @@
     assertFalse(labels[2].isVisible());
   }
 
+  /**
+   * Test that toggling a widget out and back in within the same event loop
+   * doesn't cause the widget to be hidden.
+   */
+  public void testShowWidgetToggle() {
+    DeckLayoutPanel deck = createPanel();
+    Label[] labels = new Label[2];
+    for (int i = 0; i < labels.length; i++) {
+      labels[i] = new Label("content" + i);
+      deck.add(labels[i]);
+    }
+
+    // Show widget at index 1, make sure it becomes visible.
+    deck.showWidget(1);
+    assertEquals(1, deck.getVisibleWidgetIndex());
+    assertEquals(labels[1], deck.getVisibleWidget());
+    deck.forceLayout();
+    assertFalse(labels[0].isVisible());
+    assertTrue(labels[1].isVisible());
+
+    // Toggle the widget out and back in.
+    deck.showWidget(0);
+    deck.showWidget(1);
+    assertEquals(1, deck.getVisibleWidgetIndex());
+    assertEquals(labels[1], deck.getVisibleWidget());
+    deck.forceLayout();
+    assertFalse(labels[0].isVisible());
+    assertTrue(labels[1].isVisible());
+  }
+
   @Override
   protected DeckLayoutPanel createPanel() {
     return new DeckLayoutPanel();