Fixed a bug in PopupPanel where it could enter an invalid state if show() is called while it is in the process of hiding.
Patch by: jlabanca
Review by: ecc (peer programming)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4692 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 542b653..b732c69 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -466,10 +466,7 @@
if (!isShowing()) {
return;
}
- cleanup();
-
- // Hide the popup
- resizeAnimation.setState(false);
+ setState(false, true);
CloseEvent.fire(this, this, autoClosed);
}
@@ -782,13 +779,7 @@
if (showing) {
return;
}
- showing = true;
- nativePreviewHandlerRegistration = Event.addNativePreviewHandler(new NativePreviewHandler() {
- public void onPreviewNativeEvent(NativePreviewEvent event) {
- previewNativeEvent(event);
- }
- });
- resizeAnimation.setState(true);
+ setState(true, true);
}
/**
@@ -827,13 +818,15 @@
event.cancel();
}
}
-
+
@Override
protected void onUnload() {
// Just to be sure, we perform cleanup when the popup is unloaded (i.e.
// removed from the DOM). This is normally taken care of in hide(), but it
// can be missed if someone removes the popup directly from the RootPanel.
- cleanup();
+ if (isShowing()) {
+ setState(false, false);
+ }
}
/**
@@ -894,16 +887,6 @@
}
}-*/;
- private void cleanup() {
- // Clear the 'showing' flag and make sure that the event preview is cleaned
- // up.
- showing = false;
- if (nativePreviewHandlerRegistration != null) {
- nativePreviewHandlerRegistration.removeHandler();
- nativePreviewHandlerRegistration = null;
- }
- }
-
/**
* Does the event target one of the partner elements?
*
@@ -1174,4 +1157,33 @@
}
}
}
+
+ /**
+ * Set the showing state of the popup. If maybeAnimate is true, the animation
+ * will be used to set the state. If it is false, the animation will be
+ * cancelled.
+ *
+ * @param showing the new state
+ * @param maybeAnimate true to possibly run the animation
+ */
+ private void setState(boolean showing, boolean maybeAnimate) {
+ if (maybeAnimate) {
+ resizeAnimation.setState(showing);
+ } else {
+ resizeAnimation.cancel();
+ }
+ this.showing = showing;
+
+ // Create or remove the native preview handler
+ if (showing) {
+ nativePreviewHandlerRegistration = Event.addNativePreviewHandler(new NativePreviewHandler() {
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+ previewNativeEvent(event);
+ }
+ });
+ } else if (nativePreviewHandlerRegistration != null) {
+ nativePreviewHandlerRegistration.removeHandler();
+ nativePreviewHandlerRegistration = null;
+ }
+ }
}
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 a8611bd..fd735a9 100644
--- a/user/test/com/google/gwt/user/client/ui/PopupTest.java
+++ b/user/test/com/google/gwt/user/client/ui/PopupTest.java
@@ -180,6 +180,28 @@
}
}
+ /**
+ * Test the showing a popup while it is hiding will not result in an illegal
+ * state.
+ */
+ public void testShowWhileHiding() {
+ PopupPanel popup = createPopupPanel();
+
+ // Show the popup
+ popup.setAnimationEnabled(false);
+ popup.show();
+ assertTrue(popup.isShowing());
+
+ // Start hiding the popup
+ popup.setAnimationEnabled(true);
+ popup.hide();
+ assertFalse(popup.isShowing());
+
+ // Show the popup while its hiding
+ popup.show();
+ assertTrue(popup.isShowing());
+ }
+
public void testPopup() {
// Get rid of window margins so we can test absolute position.
Window.setMargin("0px");