summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Koivuviita <jouni@vaadin.com>2014-06-10 22:34:59 +0300
committerJouni Koivuviita <jouni@vaadin.com>2014-06-16 07:56:12 +0000
commite620bfb97271d16b6d7d329841b41cb33a594dce (patch)
treef6d8f02c9f4914c15983c06e182f2b91df3be6b9
parenta69d2ecfba35a8191f79acb6138eeaabc118c752 (diff)
downloadvaadin-framework-e620bfb97271d16b6d7d329841b41cb33a594dce.tar.gz
vaadin-framework-e620bfb97271d16b6d7d329841b41cb33a594dce.zip
Fix multiple VOverlay animation-in/out related issues
Any running animation-in is now finished before animation-out is triggered. Moved windowClone variable into WindowConnector where it should be. Change-Id: I0ee733d05558d46a08e5e46f821104ad98783118
-rw-r--r--client/src/com/vaadin/client/AnimationUtil.java14
-rw-r--r--client/src/com/vaadin/client/ui/VNotification.java77
-rw-r--r--client/src/com/vaadin/client/ui/VOverlay.java124
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java12
-rw-r--r--client/src/com/vaadin/client/ui/window/WindowConnector.java27
5 files changed, 154 insertions, 100 deletions
diff --git a/client/src/com/vaadin/client/AnimationUtil.java b/client/src/com/vaadin/client/AnimationUtil.java
index 9f80d98ef2..2077cee3c0 100644
--- a/client/src/com/vaadin/client/AnimationUtil.java
+++ b/client/src/com/vaadin/client/AnimationUtil.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.client;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
@@ -57,7 +58,7 @@ public class AnimationUtil {
}
/** For internal use only. May be removed or replaced in the future. */
- public static native void registerAnimationEndEventListener(Element elem,
+ public static native JavaScriptObject addAnimationEndListener(Element elem,
AnimationEndListener listener)
/*-{
var callbackFunc = $entry(function(e) {
@@ -71,10 +72,19 @@ public class AnimationUtil {
elem._vaadin_animationend_callbacks = [];
}
elem._vaadin_animationend_callbacks.push(callbackFunc);
+
+ return callbackFunc;
+ }-*/;
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public static native void removeAnimationEndListener(Element elem,
+ JavaScriptObject listener)
+ /*-{
+ elem.removeEventListener(@com.vaadin.client.AnimationUtil::ANIMATION_END_EVENT_NAME, listener, false);
}-*/;
/** For internal use only. May be removed or replaced in the future. */
- public static native void unregisterAnimationEndEventListeners(Element elem)
+ public static native void removeAllAnimationEndListeners(Element elem)
/*-{
if(elem._vaadin_animationend_callbacks) {
var callbacks = elem._vaadin_animationend_callbacks;
diff --git a/client/src/com/vaadin/client/ui/VNotification.java b/client/src/com/vaadin/client/ui/VNotification.java
index 855da517f9..2aa8e8f879 100644
--- a/client/src/com/vaadin/client/ui/VNotification.java
+++ b/client/src/com/vaadin/client/ui/VNotification.java
@@ -77,7 +77,7 @@ public class VNotification extends VOverlay {
private static final ArrayList<VNotification> notifications = new ArrayList<VNotification>();
private boolean infiniteDelay = false;
- private int cssTransitionDelay = -1;
+ private int cssAnimationDelay = -1;
private int x = -1;
private int y = -1;
@@ -137,10 +137,10 @@ public class VNotification extends VOverlay {
private void setDelay(int delayMsec) {
if (delayMsec < 0) {
infiniteDelay = true;
- cssTransitionDelay = 0;
+ cssAnimationDelay = 0;
} else {
infiniteDelay = false;
- cssTransitionDelay = delayMsec;
+ cssAnimationDelay = delayMsec;
}
}
@@ -238,15 +238,16 @@ public class VNotification extends VOverlay {
removeStyleDependentName(temporaryStyle);
temporaryStyle = null;
}
- if (style != null) {
+ if (style != null && style.length() > 0) {
temporaryStyle = style;
addStyleName(style);
addStyleDependentName(style);
}
+ setPosition(position);
super.show();
+ updatePositionOffsets(position);
notifications.add(this);
- setPosition(position);
positionOrSizeUpdated();
/**
* Android 4 fails to render notifications correctly without a little
@@ -257,25 +258,53 @@ public class VNotification extends VOverlay {
}
}
+ private void hideWithoutDelay() {
+ cssAnimationDelay = 0;
+ hide();
+ }
+
@Override
public void hide() {
- DOM.removeEventPreview(this);
- if (cssTransitionDelay >= 0) {
- AnimationUtil.setAnimationDelay(getElement(), cssTransitionDelay
- + "ms");
+ // Run only once
+ if (notifications.contains(this)) {
+ DOM.removeEventPreview(this);
+ if (cssAnimationDelay >= 0) {
+ AnimationUtil.setAnimationDelay(getElement(), cssAnimationDelay
+ + "ms");
+ }
+ super.hide();
+ notifications.remove(this);
+ fireEvent(new HideEvent(this));
}
- super.hide();
- notifications.remove(this);
- fireEvent(new HideEvent(this));
}
- public void setPosition(com.vaadin.shared.Position position) {
+ private void updatePositionOffsets(com.vaadin.shared.Position position) {
final Element el = getElement();
// Remove all offsets (GWT PopupPanel defaults)
el.getStyle().clearTop();
el.getStyle().clearLeft();
+ switch (position) {
+ case MIDDLE_LEFT:
+ case MIDDLE_RIGHT:
+ center();
+ el.getStyle().clearLeft();
+ break;
+ case TOP_CENTER:
+ case BOTTOM_CENTER:
+ center();
+ el.getStyle().clearTop();
+ break;
+ case MIDDLE_CENTER:
+ center();
+ break;
+ }
+ }
+
+ public void setPosition(com.vaadin.shared.Position position) {
+ final Element el = getElement();
+
// Remove any previous positions
el.removeClassName(STYLENAME_POSITION_TOP);
el.removeClassName(STYLENAME_POSITION_RIGHT);
@@ -295,16 +324,10 @@ public class VNotification extends VOverlay {
el.addClassName(STYLENAME_POSITION_RIGHT);
break;
case MIDDLE_LEFT:
- center();
- // Centering sets the left offset
- el.getStyle().clearLeft();
el.addClassName(STYLENAME_POSITION_MIDDLE);
el.addClassName(STYLENAME_POSITION_LEFT);
break;
case MIDDLE_RIGHT:
- center();
- // Centering sets the left offset
- el.getStyle().clearLeft();
el.addClassName(STYLENAME_POSITION_MIDDLE);
el.addClassName(STYLENAME_POSITION_RIGHT);
break;
@@ -317,32 +340,21 @@ public class VNotification extends VOverlay {
el.addClassName(STYLENAME_POSITION_LEFT);
break;
case TOP_CENTER:
- center();
- // Centering sets the top offset
- el.getStyle().clearTop();
el.addClassName(STYLENAME_POSITION_TOP);
el.addClassName(STYLENAME_POSITION_CENTER);
break;
case BOTTOM_CENTER:
- center();
- // Centering sets the top offset
- el.getStyle().clearTop();
el.addClassName(STYLENAME_POSITION_BOTTOM);
el.addClassName(STYLENAME_POSITION_CENTER);
break;
case ASSISTIVE:
el.addClassName(STYLENAME_POSITION_ASSISTIVE);
break;
- default:
- case MIDDLE_CENTER:
- center();
- break;
}
}
@Override
public void onBrowserEvent(Event event) {
- DOM.removeEventPreview(this);
hide();
}
@@ -353,12 +365,12 @@ public class VNotification extends VOverlay {
if (infiniteDelay || temporaryStyle == STYLE_SYSTEM) {
if (type == Event.ONCLICK) {
if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) {
- hide();
+ hideWithoutDelay();
return false;
}
} else if (type == Event.ONKEYDOWN
&& event.getKeyCode() == KeyCodes.KEY_ESCAPE) {
- hide();
+ hideWithoutDelay();
return false;
}
if (temporaryStyle == STYLE_SYSTEM) {
@@ -370,7 +382,6 @@ public class VNotification extends VOverlay {
// default
switch (type) {
case Event.ONMOUSEMOVE:
-
if (x < 0) {
x = DOM.eventGetClientX(event);
y = DOM.eventGetClientY(event);
diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java
index ab493ce383..ac4e57268a 100644
--- a/client/src/com/vaadin/client/ui/VOverlay.java
+++ b/client/src/com/vaadin/client/ui/VOverlay.java
@@ -21,13 +21,13 @@ import java.util.logging.Logger;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.aria.client.Roles;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.IFrameElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.BorderStyle;
-import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.CloseEvent;
@@ -443,6 +443,8 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
current = null;
}
+ private JavaScriptObject animateInListener;
+
private boolean maybeShowWithAnimation() {
boolean isAttached = isAttached() && isShowing();
super.show();
@@ -467,8 +469,25 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
}
if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
- AnimationUtil.registerAnimationEndEventListener(getElement(),
- getAnimationEndListener(false));
+ animateInListener = AnimationUtil.addAnimationEndListener(
+ getElement(), new AnimationEndListener() {
+ @Override
+ public void onAnimationEnd(NativeEvent event) {
+ String animationName = AnimationUtil
+ .getAnimationName(event);
+ if (animationName
+ .contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+ AnimationUtil.removeAnimationEndListener(
+ getElement(), animateInListener);
+ removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ if (isShadowEnabled()) {
+ shadow.removeClassName(CLASSNAME_SHADOW
+ + "-"
+ + ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ }
+ }
+ }
+ });
return true;
} else {
removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
@@ -936,64 +955,75 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
* @see com.google.gwt.user.client.ui.PopupPanel#hide(boolean)
*/
@Override
- public void hide(boolean autoClosed) {
+ public void hide(final boolean autoClosed) {
if (BrowserInfo.get().isIE8() || BrowserInfo.get().isIE9()) {
super.hide(autoClosed);
} else {
- // Check if animations are used
- addStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
- if (isShadowEnabled()) {
- shadow.addClassName(CLASSNAME_SHADOW + "-"
- + ADDITIONAL_CLASSNAME_ANIMATE_OUT);
- }
- ComputedStyle cs = new ComputedStyle(getElement());
- String animationName = AnimationUtil.getAnimationName(cs);
- if (animationName == null) {
- animationName = "";
- }
-
- if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
- AnimationUtil.registerAnimationEndEventListener(getElement(),
- getAnimationEndListener(autoClosed));
- // No event previews should happen after the animation has
- // started
- VOverlay.this.setPreviewingAllNativeEvents(false);
+ if (getStyleName().contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+ AnimationUtil.addAnimationEndListener(getElement(),
+ new AnimationEndListener() {
+ @Override
+ public void onAnimationEnd(NativeEvent event) {
+ if (AnimationUtil
+ .getAnimationName(event)
+ .contains(
+ ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
+ VOverlay.this.hide(autoClosed);
+ }
+ }
+ });
} else {
- removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
+ // Check if animations are used
+ addStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
if (isShadowEnabled()) {
- shadow.removeClassName(CLASSNAME_SHADOW + "-"
+ shadow.addClassName(CLASSNAME_SHADOW + "-"
+ ADDITIONAL_CLASSNAME_ANIMATE_OUT);
}
- super.hide(autoClosed);
- }
- }
- }
-
- private AnimationEndListener getAnimationEndListener(
- final boolean autoClosed) {
- return new AnimationEndListener() {
+ ComputedStyle cs = new ComputedStyle(getElement());
+ String animationName = AnimationUtil.getAnimationName(cs);
+ if (animationName == null) {
+ animationName = "";
+ }
- @Override
- public void onAnimationEnd(NativeEvent event) {
- AnimationUtil
- .unregisterAnimationEndEventListeners(getElement());
- String animationName = AnimationUtil.getAnimationName(event);
- if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_IN)) {
- removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
- if (isShadowEnabled()) {
- shadow.removeClassName(CLASSNAME_SHADOW + "-"
- + ADDITIONAL_CLASSNAME_ANIMATE_IN);
- }
- } else if (animationName
- .contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
+ if (animationName.contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
+ AnimationUtil.addAnimationEndListener(getElement(),
+ new AnimationEndListener() {
+ @Override
+ public void onAnimationEnd(NativeEvent event) {
+ String animationName = AnimationUtil
+ .getAnimationName(event);
+ if (animationName
+ .contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
+ AnimationUtil
+ .removeAllAnimationEndListeners(getElement());
+ // Remove both animation styles just in
+ // case
+ removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
+ if (isShadowEnabled()) {
+ shadow.removeClassName(CLASSNAME_SHADOW
+ + "-"
+ + ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ shadow.removeClassName(CLASSNAME_SHADOW
+ + "-"
+ + ADDITIONAL_CLASSNAME_ANIMATE_OUT);
+ }
+ VOverlay.super.hide(autoClosed);
+ }
+ }
+ });
+ // No event previews should happen after the animation has
+ // started
+ VOverlay.this.setPreviewingAllNativeEvents(false);
+ } else {
removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
if (isShadowEnabled()) {
shadow.removeClassName(CLASSNAME_SHADOW + "-"
+ ADDITIONAL_CLASSNAME_ANIMATE_OUT);
}
- VOverlay.super.hide(autoClosed);
+ super.hide(autoClosed);
}
}
- };
+ }
}
} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index e2cc33744e..7c1a21f654 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -30,7 +30,6 @@ import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
@@ -201,9 +200,6 @@ public class VWindow extends VWindowOverlay implements
/** For internal use only. May be removed or replaced in the future. */
public int bringToFrontSequence = -1;
- /** For internal use only. May be removed or replaced in the future. */
- public Node windowClone;
-
private VLazyExecutor delayedContentsSizeUpdater = new VLazyExecutor(200,
new ScheduledCommand() {
@@ -1037,14 +1033,6 @@ public class VWindow extends VWindowOverlay implements
}
private void onCloseClick() {
- // Take a copy of the contents, since the server will detach all
- // children of this window, and the window will be emptied during the
- // next hierarchy update (we need to keep the contents visible for the
- // duration of a possible 'out-animation')
- // This is used by the WindowConnector in the case the window is
- // actually closed and removed from the UI
- windowClone = getElement().getFirstChild().cloneNode(true);
-
// Send the close event to the server
client.updateVariable(id, "close", true, true);
}
diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java
index 40185099d3..2a2f031144 100644
--- a/client/src/com/vaadin/client/ui/window/WindowConnector.java
+++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java
@@ -19,6 +19,7 @@ import java.util.logging.Logger;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
@@ -58,6 +59,8 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
SimpleManagedLayout, PostLayoutListener, MayScrollChildren,
WindowMoveHandler {
+ private Node windowClone;
+
private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
@Override
protected void fireClick(NativeEvent event,
@@ -193,14 +196,16 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
// We always have 1 child, unless the child is hidden
getWidget().contentPanel.setWidget(getContentWidget());
- // If the window is removed from the UI, add the copy of the contents to
- // the window (in case of an 'out-animation')
- if (getParent() == null) {
+ if (getParent() == null && windowClone != null) {
+ // If the window is removed from the UI, add the copy of the
+ // contents to the window (in case of an 'out-animation')
getWidget().getElement().removeAllChildren();
- getWidget().getElement().appendChild(getWidget().windowClone);
+ getWidget().getElement().appendChild(windowClone);
+
+ // Clean reference
+ windowClone = null;
}
- // Clean reference
- getWidget().windowClone = null;
+
}
@Override
@@ -277,6 +282,16 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
window.center();
}
window.positionOrSizeUpdated();
+
+ if (getParent() != null) {
+ // Take a copy of the contents, since the server will detach all
+ // children of this window when it's closed, and the window will be
+ // emptied during the following hierarchy update (we need to keep
+ // the contents visible for the duration of a possible
+ // 'out-animation')
+ windowClone = getWidget().getElement().getFirstChild()
+ .cloneNode(true);
+ }
}
@Override