]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix overlay animation-in/out for VNotification and PopupView
authorJouni Koivuviita <jouni@vaadin.com>
Thu, 12 Jun 2014 12:44:14 +0000 (15:44 +0300)
committerJouni Koivuviita <jouni@vaadin.com>
Mon, 16 Jun 2014 08:18:58 +0000 (08:18 +0000)
- Notification delay now applied to browsers without CSS animation
support

- PopupView now also supports animation-in and animation-out, and also
shows the “loading” widget when the popup is opened and the server
response takes a little longer. The popupComponentWidget is also kept
in the popup during the animation-out

Change-Id: Idb26d87a8cf75cfa3e145ea670dacc1c87ce75d6

client/src/com/vaadin/client/ui/VNotification.java
client/src/com/vaadin/client/ui/VOverlay.java
client/src/com/vaadin/client/ui/VPopupView.java
client/src/com/vaadin/client/ui/popupview/PopupViewConnector.java

index 2aa8e8f879e5c86de64af948ffccbc16f43a5ac3..d89dcb76344ecf149054884bd4442209cd7758e6 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Iterator;
 import com.google.gwt.aria.client.Roles;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
@@ -32,6 +33,7 @@ import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.client.AnimationUtil;
+import com.vaadin.client.AnimationUtil.AnimationEndListener;
 import com.vaadin.client.ApplicationConnection;
 import com.vaadin.client.BrowserInfo;
 import com.vaadin.client.UIDL;
@@ -268,13 +270,45 @@ public class VNotification extends VOverlay {
         // Run only once
         if (notifications.contains(this)) {
             DOM.removeEventPreview(this);
-            if (cssAnimationDelay >= 0) {
-                AnimationUtil.setAnimationDelay(getElement(), cssAnimationDelay
-                        + "ms");
+
+            // Still animating in, wait for it to finish before touching
+            // the animation delay (which would restart the animation-in
+            // in some browsers)
+            if (getStyleName().contains(
+                    VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+                AnimationUtil.addAnimationEndListener(getElement(),
+                        new AnimationEndListener() {
+                            @Override
+                            public void onAnimationEnd(NativeEvent event) {
+                                if (AnimationUtil
+                                        .getAnimationName(event)
+                                        .contains(
+                                                VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+                                    VNotification.this.hide();
+                                }
+                            }
+                        });
+            } else {
+                // Use a timer in browsers without CSS animation support
+                // to show the notification for the duration of the delay
+                if (BrowserInfo.get().isIE8() || BrowserInfo.get().isIE9()) {
+                    new Timer() {
+                        @Override
+                        public void run() {
+                            VNotification.super.hide();
+                        }
+                    }.schedule(cssAnimationDelay);
+                } else {
+                    if (cssAnimationDelay > 0) {
+                        AnimationUtil.setAnimationDelay(getElement(),
+                                cssAnimationDelay + "ms");
+                    }
+                    VNotification.super.hide();
+
+                }
+                fireEvent(new HideEvent(this));
+                notifications.remove(this);
             }
-            super.hide();
-            notifications.remove(this);
-            fireEvent(new HideEvent(this));
         }
     }
 
index ac4e57268a03ed77d2e1d285e33281d3b6801e0b..1d653a8ff5c0d8bdbff586172326c4e0eb68cff7 100644 (file)
@@ -164,8 +164,8 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
      */
     public static final String CLASSNAME_CONTAINER = "v-overlay-container";
 
-    private static final String ADDITIONAL_CLASSNAME_ANIMATE_IN = "animate-in";
-    private static final String ADDITIONAL_CLASSNAME_ANIMATE_OUT = "animate-out";
+    public static final String ADDITIONAL_CLASSNAME_ANIMATE_IN = "animate-in";
+    public static final String ADDITIONAL_CLASSNAME_ANIMATE_OUT = "animate-out";
 
     /**
      * The shadow element for this overlay.
@@ -433,9 +433,9 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
     public void show() {
         current = this;
 
-        boolean hasAnimationIn = maybeShowWithAnimation();
+        maybeShowWithAnimation();
 
-        if (isAnimationEnabled() && !hasAnimationIn) {
+        if (isAnimationEnabled()) {
             new ResizeAnimation().run(POPUP_PANEL_ANIMATION_DURATION);
         } else {
             positionOrSizeUpdated(1.0);
@@ -456,6 +456,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
             return false;
         } else {
             // Check if animations are used
+            setVisible(false);
             addStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
             if (isShadowEnabled()) {
                 shadow.addClassName(CLASSNAME_SHADOW + "-"
@@ -467,8 +468,11 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
             if (animationName == null) {
                 animationName = "";
             }
+            setVisible(true);
 
             if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+                // Disable GWT PopupPanel animation if used
+                setAnimationEnabled(false);
                 animateInListener = AnimationUtil.addAnimationEndListener(
                         getElement(), new AnimationEndListener() {
                             @Override
@@ -974,6 +978,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
                         });
             } else {
                 // Check if animations are used
+                setVisible(false);
                 addStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
                 if (isShadowEnabled()) {
                     shadow.addClassName(CLASSNAME_SHADOW + "-"
@@ -984,8 +989,12 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
                 if (animationName == null) {
                     animationName = "";
                 }
+                setVisible(true);
 
                 if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
+                    // Disable GWT PopupPanel closing animation if used
+                    setAnimationEnabled(false);
+
                     AnimationUtil.addAnimationEndListener(getElement(),
                             new AnimationEndListener() {
                                 @Override
index adf070f453e2eb190755a86eb065ed4535fd561e..931945e5462d6ee74315b75daac50d722de4fb0d 100644 (file)
@@ -91,6 +91,9 @@ public class VPopupView extends HTML implements Iterable<Widget> {
         addClickHandler(new ClickHandler() {
             @Override
             public void onClick(ClickEvent event) {
+                preparePopup(popup);
+                showPopup(popup);
+                center();
                 fireEvent(new VisibilityChangeEvent(true));
             }
         });
@@ -111,7 +114,8 @@ public class VPopupView extends HTML implements Iterable<Widget> {
 
     /** For internal use only. May be removed or replaced in the future. */
     public void preparePopup(final CustomPopup popup) {
-        popup.setVisible(false);
+        popup.setVisible(true);
+        popup.setWidget(loading);
         popup.show();
     }
 
@@ -128,8 +132,6 @@ public class VPopupView extends HTML implements Iterable<Widget> {
      */
     public void showPopup(final CustomPopup popup) {
         popup.setPopupPosition(0, 0);
-
-        popup.setVisible(true);
     }
 
     /** For internal use only. May be removed or replaced in the future. */
@@ -270,9 +272,7 @@ public class VPopupView extends HTML implements Iterable<Widget> {
         public void hide(boolean autoClosed) {
             VConsole.log("Hiding popupview");
             syncChildren();
-            if (popupComponentWidget != null && popupComponentWidget != loading) {
-                remove(popupComponentWidget);
-            }
+            clearPopupComponentConnector();
             hasHadMouseOver = false;
             shortcutActionHandler = null;
             super.hide(autoClosed);
@@ -333,15 +333,18 @@ public class VPopupView extends HTML implements Iterable<Widget> {
             }
         }
 
-        @Override
-        public boolean remove(Widget w) {
+        private void clearPopupComponentConnector() {
             if (popupComponentConnector != null) {
                 popupComponentConnector.removeStateChangeHandler(this);
             }
             popupComponentConnector = null;
             popupComponentWidget = null;
             captionWrapper = null;
+        }
 
+        @Override
+        public boolean remove(Widget w) {
+            clearPopupComponentConnector();
             return super.remove(w);
         }
 
index bde5f6a051c6b7f5fc777a809a25e2abbd1d2f96..6afceb75de12550bcebf4f86e1575931713462d1 100644 (file)
@@ -26,6 +26,7 @@ import com.vaadin.client.VCaptionWrapper;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.ui.AbstractHasComponentsConnector;
 import com.vaadin.client.ui.PostLayoutListener;
+import com.vaadin.client.ui.VOverlay;
 import com.vaadin.client.ui.VPopupView;
 import com.vaadin.shared.ui.ComponentStateUtil;
 import com.vaadin.shared.ui.Connect;
@@ -100,27 +101,37 @@ public class PopupViewConnector extends AbstractHasComponentsConnector
         if (!getChildComponents().isEmpty()) {
             getWidget().preparePopup(getWidget().popup);
             getWidget().popup.setPopupConnector(getChildComponents().get(0));
-            if (ComponentStateUtil.hasStyles(getState())) {
-                final StringBuffer styleBuf = new StringBuffer();
-                final String primaryName = getWidget().popup
-                        .getStylePrimaryName();
+
+            final StringBuffer styleBuf = new StringBuffer();
+            final String primaryName = getWidget().popup.getStylePrimaryName();
+            styleBuf.append(primaryName);
+
+            // Add "animate-in" class back if already present
+            boolean isAnimatingIn = getWidget().popup.getStyleName().contains(
+                    VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN);
+
+            if (isAnimatingIn) {
+                styleBuf.append(" ");
                 styleBuf.append(primaryName);
+                styleBuf.append("-");
+                styleBuf.append(VOverlay.ADDITIONAL_CLASSNAME_ANIMATE_IN);
+            }
+
+            if (ComponentStateUtil.hasStyles(getState())) {
                 for (String style : getState().styles) {
                     styleBuf.append(" ");
                     styleBuf.append(primaryName);
                     styleBuf.append("-");
                     styleBuf.append(style);
                 }
-                getWidget().popup.setStyleName(styleBuf.toString());
-            } else {
-                getWidget().popup.setStyleName(getWidget().popup
-                        .getStylePrimaryName());
             }
+
+            getWidget().popup.setStyleName(styleBuf.toString());
             getWidget().showPopup(getWidget().popup);
             centerAfterLayout = true;
 
-            // The popup shouldn't be visible, try to hide it.
         } else {
+            // The popup shouldn't be visible, try to hide it.
             getWidget().popup.hide();
         }
     }