- 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: Idb26d87a8cf75cfa3e145ea670dacc1c87ce75d6tags/7.3.0.beta1
@@ -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)); | |||
} | |||
} | |||
@@ -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 |
@@ -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); | |||
} | |||
@@ -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(); | |||
} | |||
} |