summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2016-01-07 17:20:13 +0200
committerVaadin Code Review <review@vaadin.com>2016-01-12 13:13:10 +0000
commita9632630179d0d700bd008eb07ef8561a69323ea (patch)
tree69c6bf900dafec17b5ee55bc556eead5fd36481d
parent7b7ead66c5d52c6518e2b606c7258c5bd9fdda93 (diff)
downloadvaadin-framework-a9632630179d0d700bd008eb07ef8561a69323ea.tar.gz
vaadin-framework-a9632630179d0d700bd008eb07ef8561a69323ea.zip
Split VOverlay functionality to a new base class (#19347)
This fixes the missing z-index for the Grid popup. Change-Id: I5474fe653ad4ece38e9bc3cb2331a1d2190ea898
-rwxr-xr-xclient/src/com/vaadin/DefaultWidgetSet.gwt.xml75
-rw-r--r--client/src/com/vaadin/client/ui/VOverlay.java963
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java32
-rw-r--r--client/src/com/vaadin/client/widgets/Overlay.java1010
-rw-r--r--widgets/build.xml1
5 files changed, 1071 insertions, 1010 deletions
diff --git a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml
index 03d0950126..ad345e44e2 100755
--- a/client/src/com/vaadin/DefaultWidgetSet.gwt.xml
+++ b/client/src/com/vaadin/DefaultWidgetSet.gwt.xml
@@ -1,39 +1,42 @@
<module>
- <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the
- module you want to extend when creating an extended widget set, or when creating
- a specialized widget set with a subset of the components. -->
-
- <!-- Hint for WidgetSetBuilder not to automatically update the file -->
- <!-- WS Compiler: manually edited -->
-
- <inherits name="com.vaadin.Vaadin" />
-
- <!-- Elemental is used for handling Json only -->
- <inherits name="elemental.Json" />
-
- <inherits name="com.google.gwt.precompress.Precompress"/>
-
- <entry-point class="com.vaadin.client.ApplicationConfiguration" />
-
- <generate-with
- class="com.vaadin.server.widgetsetutils.AcceptCriteriaFactoryGenerator">
- <when-type-is class="com.vaadin.client.ui.dd.VAcceptCriterionFactory" />
- </generate-with>
-
- <generate-with
- class="com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory">
- <when-type-assignable
- class="com.vaadin.client.metadata.ConnectorBundleLoader" />
- </generate-with>
-
- <replace-with
- class="com.vaadin.client.communication.DefaultReconnectDialog">
- <when-type-is class="com.vaadin.client.communication.ReconnectDialog" />
- </replace-with>
-
- <!-- Since 7.2. Compile all permutations (browser support) into one Javascript
- file. Speeds up compilation and does not make the Javascript significantly
- larger. -->
- <collapse-all-properties />
+ <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module
+ you want to extend when creating an extended widget set, or when creating
+ a specialized widget set with a subset of the components. -->
+
+ <!-- Hint for WidgetSetBuilder not to automatically update the file -->
+ <!-- WS Compiler: manually edited -->
+
+ <inherits name="com.vaadin.Vaadin" />
+
+ <!-- Elemental is used for handling Json only -->
+ <inherits name="elemental.Json" />
+
+ <inherits name="com.google.gwt.precompress.Precompress" />
+
+ <entry-point class="com.vaadin.client.ApplicationConfiguration" />
+
+ <generate-with
+ class="com.vaadin.server.widgetsetutils.AcceptCriteriaFactoryGenerator">
+ <when-type-is class="com.vaadin.client.ui.dd.VAcceptCriterionFactory" />
+ </generate-with>
+
+ <generate-with
+ class="com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory">
+ <when-type-assignable
+ class="com.vaadin.client.metadata.ConnectorBundleLoader" />
+ </generate-with>
+
+ <replace-with class="com.vaadin.client.communication.DefaultReconnectDialog">
+ <when-type-is class="com.vaadin.client.communication.ReconnectDialog" />
+ </replace-with>
+
+ <replace-with class="com.vaadin.client.ui.VOverlay">
+ <when-type-is class="com.vaadin.client.widgets.Overlay" />
+ </replace-with>
+
+ <!-- Since 7.2. Compile all permutations (browser support) into one Javascript
+ file. Speeds up compilation and does not make the Javascript significantly
+ larger. -->
+ <collapse-all-properties />
</module>
diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java
index 3649afc74f..5dc29f5a42 100644
--- a/client/src/com/vaadin/client/ui/VOverlay.java
+++ b/client/src/com/vaadin/client/ui/VOverlay.java
@@ -16,190 +16,35 @@
package com.vaadin.client.ui;
-import java.util.logging.Level;
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.core.client.GWT;
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.Position;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
-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.ComponentConnector;
-import com.vaadin.client.ComputedStyle;
import com.vaadin.client.Util;
-import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.widgets.Overlay;
/**
- * <p>
- * In Vaadin UI this Overlay should always be used for all elements that
+ * In Vaadin UI this VOverlay should always be used for all elements that
* temporary float over other components like context menus etc. This is to deal
* stacking order correctly with VWindow objects.
- * </p>
- *
- * <h3>Shadow</h3>
- * <p>
- * The separate shadow element underneath the main overlay element is <strong>
- * <em>deprecated</em></strong>, and should not be used for new overlay
- * components. CSS box-shadow should be used instead of a separate shadow
- * element. Remember to include any vendor-prefixed versions to support all
- * browsers that you need to. To cover all possible browsers that Vaadin 7
- * supports, add <code>-webkit-box-shadow</code> and the standard
- * <code>box-shadow</code> properties.
- * </p>
- *
* <p>
- * For IE8, which doesn't support CSS box-shadow, you can use the proprietary
- * DropShadow filter. It doesn't provide the exact same features as box-shadow,
- * but it is suitable for graceful degradation. Other options are to use a
- * border or a pseudo-element underneath the overlay which mimics a shadow, or
- * any combination of these.
- * </p>
+ * To use this correctly, use {@link GWT#create(Class)} to create the
+ * {@link Overlay} superclass and the default widgetset will replace it with
+ * this. The widget will not be dependent on this Vaadin specific widget and can
+ * be used in a pure GWT environment.
*
- * <p>
- * Read more about the DropShadow filter from <a
- * href="http://msdn.microsoft.com/en-us/library/ms532985(v=vs.85).aspx"
- * >Microsoft Developer Network</a>
- * </p>
+ * @deprecated as this is specifically for Vaadin only, it should not be used
+ * directly.
*/
-public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
-
- @Override
- protected void onAttach() {
- // Move the overlay to the appropriate overlay container
- final VOverlay overlay = VOverlay.current;
- if (overlay != null) {
- final Element e = overlay.getOverlayContainer();
- e.appendChild(getElement());
- }
-
- super.onAttach();
- }
-
- public static class PositionAndSize {
- private int left, top, width, height;
-
- public PositionAndSize(int left, int top, int width, int height) {
- super();
- setLeft(left);
- setTop(top);
- setWidth(width);
- setHeight(height);
- }
-
- public int getLeft() {
- return left;
- }
-
- public void setLeft(int left) {
- this.left = left;
- }
-
- public int getTop() {
- return top;
- }
-
- public void setTop(int top) {
- this.top = top;
- }
-
- public int getWidth() {
- return width;
- }
-
- public void setWidth(int width) {
- if (width < 0) {
- width = 0;
- }
-
- this.width = width;
- }
-
- public int getHeight() {
- return height;
- }
-
- public void setHeight(int height) {
- if (height < 0) {
- height = 0;
- }
-
- this.height = height;
- }
-
- public void setAnimationFromCenterProgress(double progress) {
- left += (int) (width * (1.0 - progress) / 2.0);
- top += (int) (height * (1.0 - progress) / 2.0);
- width = (int) (width * progress);
- height = (int) (height * progress);
- }
- }
-
- /*
- * The z-index value from where all overlays live. This can be overridden in
- * any extending class.
- */
- public static int Z_INDEX = 20000;
-
- private static int leftFix = -1;
-
- private static int topFix = -1;
-
- /**
- * Shadow element style. If an extending class wishes to use a different
- * style of shadow, it can use setShadowStyle(String) to give the shadow
- * element a new style name.
- *
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- public static final String CLASSNAME_SHADOW = "v-shadow";
-
- /**
- * Style name for the overlay container element (see
- * {@link #getOverlayContainer()}
- */
- public static final String CLASSNAME_CONTAINER = "v-overlay-container";
-
- /**
- * @since 7.3
- */
- public static final String ADDITIONAL_CLASSNAME_ANIMATE_IN = "animate-in";
- /**
- * @since 7.3
- */
- public static final String ADDITIONAL_CLASSNAME_ANIMATE_OUT = "animate-out";
-
- /**
- * The shadow element for this overlay.
- *
- * @deprecated See main JavaDoc for VOverlay
- *
- */
- @Deprecated
- private Element shadow;
-
- /*
- * The creator of this VOverlay (the widget that made the instance, not the
- * layout parent)
- */
- private Widget owner;
+@Deprecated
+public class VOverlay extends Overlay implements CloseHandler<PopupPanel> {
/*
* ApplicationConnection that this overlay belongs to, which is needed to
@@ -210,60 +55,16 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
*/
protected ApplicationConnection ac;
- /**
- * The shim iframe behind the overlay, allowing PDFs and applets to be
- * covered by overlays.
- */
- private IFrameElement shimElement;
-
- /**
- * The HTML snippet that is used to render the actual shadow. In consists of
- * nine different DIV-elements with the following class names:
- *
- * <pre>
- * .v-shadow[-stylename]
- * ----------------------------------------------
- * | .top-left | .top | .top-right |
- * |---------------|-----------|----------------|
- * | | | |
- * | .left | .center | .right |
- * | | | |
- * |---------------|-----------|----------------|
- * | .bottom-left | .bottom | .bottom-right |
- * ----------------------------------------------
- * </pre>
- *
- * See default theme 'shadow.css' for implementation example.
- *
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private static final String SHADOW_HTML = "<div aria-hidden=\"true\" class=\"top-left\"></div><div class=\"top\"></div><div class=\"top-right\"></div><div class=\"left\"></div><div class=\"center\"></div><div class=\"right\"></div><div class=\"bottom-left\"></div><div class=\"bottom\"></div><div class=\"bottom-right\"></div>";
-
- /**
- * Matches {@link PopupPanel}.ANIMATION_DURATION
- */
- private static final int POPUP_PANEL_ANIMATION_DURATION = 200;
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private boolean sinkShadowEvents = false;
-
public VOverlay() {
super();
- adjustZIndex();
}
public VOverlay(boolean autoHide) {
super(autoHide);
- adjustZIndex();
}
public VOverlay(boolean autoHide, boolean modal) {
super(autoHide, modal);
- adjustZIndex();
}
/**
@@ -272,185 +73,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
*/
@Deprecated
public VOverlay(boolean autoHide, boolean modal, boolean showShadow) {
- super(autoHide, modal);
- setShadowEnabled(showShadow && useShadowDiv());
- adjustZIndex();
- }
-
- /**
- * Return true if a separate shadow div should be used. Since Vaadin 7.3,
- * shadows are implemented with CSS box-shadow. Thus, a shadow div is only
- * used for IE8 by default.
- *
- * @deprecated See main JavaDoc for VOverlay
- * @since 7.3
- * @return true to use a shadow div
- */
- @Deprecated
- protected boolean useShadowDiv() {
- return BrowserInfo.get().isIE8();
- }
-
- /**
- * Method to control whether DOM elements for shadow are added. With this
- * method subclasses can control displaying of shadow also after the
- * constructor.
- *
- * @param enabled
- * true if shadow should be displayed
- *
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- protected void setShadowEnabled(boolean enabled) {
- if (enabled != isShadowEnabled()) {
- if (enabled) {
- shadow = DOM.createDiv();
- shadow.setClassName(CLASSNAME_SHADOW);
- shadow.setInnerHTML(SHADOW_HTML);
- shadow.getStyle().setPosition(Position.ABSOLUTE);
- addCloseHandler(this);
- } else {
- removeShadowIfPresent();
- shadow = null;
- }
- }
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- protected boolean isShadowEnabled() {
- return shadow != null;
- }
-
- protected boolean isShimElementEnabled() {
- return shimElement != null;
- }
-
- private void removeShimElement() {
- if (shimElement != null) {
- shimElement.removeFromParent();
- }
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private void removeShadowIfPresent() {
- if (isShadowAttached()) {
- // Remove event listener from the shadow
- unsinkShadowEvents();
-
- shadow.removeFromParent();
- }
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private boolean isShadowAttached() {
- return isShadowEnabled() && shadow.getParentElement() != null;
- }
-
- private void adjustZIndex() {
- setZIndex(Z_INDEX);
- }
-
- /**
- * Set the z-index (visual stack position) for this overlay.
- *
- * @param zIndex
- * The new z-index
- */
- protected void setZIndex(int zIndex) {
- getElement().getStyle().setZIndex(zIndex);
- if (isShadowEnabled()) {
- shadow.getStyle().setZIndex(zIndex);
- }
- }
-
- @Override
- public void setPopupPosition(int left, int top) {
- // TODO, this should in fact be part of
- // Document.get().getBodyOffsetLeft/Top(). Would require overriding DOM
- // for all permutations. Now adding fix as margin instead of fixing
- // left/top because parent class saves the position.
- Style style = getElement().getStyle();
- style.setMarginLeft(-adjustByRelativeLeftBodyMargin(), Unit.PX);
- style.setMarginTop(-adjustByRelativeTopBodyMargin(), Unit.PX);
- super.setPopupPosition(left, top);
- positionOrSizeUpdated(isAnimationEnabled() ? 0 : 1);
- }
-
- private IFrameElement getShimElement() {
- if (shimElement == null && needsShimElement()) {
- shimElement = Document.get().createIFrameElement();
-
- // Insert shim iframe before the main overlay element. It does not
- // matter if it is in front or behind the shadow as we cannot put a
- // shim behind the shadow due to its transparency.
- shimElement.getStyle().setPosition(Position.ABSOLUTE);
- shimElement.getStyle().setBorderStyle(BorderStyle.NONE);
- shimElement.setTabIndex(-1);
- shimElement.setFrameBorder(0);
- shimElement.setMarginHeight(0);
- }
- return shimElement;
- }
-
- private int getActualTop() {
- int y = getAbsoluteTop();
-
- /* This is needed for IE7 at least */
- // Account for the difference between absolute position and the
- // body's positioning context.
- y -= Document.get().getBodyOffsetTop();
- y -= adjustByRelativeTopBodyMargin();
-
- return y;
- }
-
- private int getActualLeft() {
- int x = getAbsoluteLeft();
-
- /* This is needed for IE7 at least */
- // Account for the difference between absolute position and the
- // body's positioning context.
- x -= Document.get().getBodyOffsetLeft();
- x -= adjustByRelativeLeftBodyMargin();
-
- return x;
- }
-
- private static int adjustByRelativeTopBodyMargin() {
- if (topFix == -1) {
- topFix = detectRelativeBodyFixes("top");
- }
- return topFix;
- }
-
- private native static int detectRelativeBodyFixes(String axis)
- /*-{
- try {
- var b = $wnd.document.body;
- var cstyle = b.currentStyle ? b.currentStyle : getComputedStyle(b);
- if(cstyle && cstyle.position == 'relative') {
- return b.getBoundingClientRect()[axis];
- }
- } catch(e){}
- return 0;
- }-*/;
-
- private static int adjustByRelativeLeftBodyMargin() {
- if (leftFix == -1) {
- leftFix = detectRelativeBodyFixes("left");
-
- }
- return leftFix;
+ super(autoHide, modal, showShadow);
}
/*
@@ -462,376 +85,6 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
*/
protected static VOverlay current;
- @Override
- public void show() {
- current = this;
-
- maybeShowWithAnimation();
-
- if (isAnimationEnabled()) {
- new ResizeAnimation().run(POPUP_PANEL_ANIMATION_DURATION);
- } else {
- positionOrSizeUpdated(1.0);
- }
- current = null;
- }
-
- private JavaScriptObject animateInListener;
-
- private boolean maybeShowWithAnimation() {
- boolean isAttached = isAttached() && isShowing();
- super.show();
-
- // Don't animate if already visible or browser is IE8 or IE9 (no CSS
- // animation support)
- if (isAttached || BrowserInfo.get().isIE8()
- || BrowserInfo.get().isIE9()) {
- return false;
- } else {
- // Check if animations are used
- setVisible(false);
- addStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
- if (isShadowEnabled()) {
- shadow.addClassName(CLASSNAME_SHADOW + "-"
- + ADDITIONAL_CLASSNAME_ANIMATE_IN);
- }
-
- ComputedStyle cs = new ComputedStyle(getElement());
- String animationName = AnimationUtil.getAnimationName(cs);
- 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
- 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);
- if (isShadowEnabled()) {
- shadow.removeClassName(CLASSNAME_SHADOW + "-"
- + ADDITIONAL_CLASSNAME_ANIMATE_IN);
- }
- return false;
- }
- }
- }
-
- @Override
- protected void onDetach() {
- super.onDetach();
-
- // Always ensure shadow is removed when the overlay is removed.
- removeShadowIfPresent();
- removeShimElement();
- }
-
- @Override
- public void setVisible(boolean visible) {
- super.setVisible(visible);
- if (isShadowEnabled()) {
- shadow.getStyle().setProperty("visibility",
- visible ? "visible" : "hidden");
- }
- if (isShimElementEnabled()) {
- shimElement.getStyle().setProperty("visibility",
- visible ? "visible" : "hidden");
- }
- }
-
- @Override
- public void setWidth(String width) {
- super.setWidth(width);
- positionOrSizeUpdated(1.0);
- }
-
- @Override
- public void setHeight(String height) {
- super.setHeight(height);
- positionOrSizeUpdated(1.0);
- }
-
- /**
- * Sets the shadow style for this overlay. Will override any previous style
- * for the shadow. The default style name is defined by CLASSNAME_SHADOW.
- * The given style will be prefixed with CLASSNAME_SHADOW.
- *
- * @param style
- * The new style name for the shadow element. Will be prefixed by
- * CLASSNAME_SHADOW, e.g. style=='foobar' -> actual style
- * name=='v-shadow-foobar'.
- *
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- protected void setShadowStyle(String style) {
- if (isShadowEnabled()) {
- shadow.setClassName(CLASSNAME_SHADOW + "-" + style);
- }
- }
-
- /**
- * Extending classes should always call this method after they change the
- * size of overlay without using normal 'setWidth(String)' and
- * 'setHeight(String)' methods (if not calling super.setWidth/Height).
- *
- */
- public void positionOrSizeUpdated() {
- positionOrSizeUpdated(1.0);
- }
-
- /**
- * @deprecated Call {@link #positionOrSizeUpdated()} instead.
- */
- @Deprecated
- protected void updateShadowSizeAndPosition() {
- positionOrSizeUpdated();
- }
-
- /**
- * Recalculates proper position and dimensions for the shadow and shim
- * elements. Can be used to animate the related elements, using the
- * 'progress' parameter (used to animate the shadow in sync with GWT
- * PopupPanel's default animation 'PopupPanel.AnimationType.CENTER').
- *
- * @param progress
- * A value between 0.0 and 1.0, indicating the progress of the
- * animation (0=start, 1=end).
- */
- private void positionOrSizeUpdated(final double progress) {
- // Don't do anything if overlay element is not attached
- if (!isAttached()) {
- return;
- }
- // Calculate proper z-index
- int zIndex = -1;
- try {
- // Odd behaviour with Windows Hosted Mode forces us to use
- // this redundant try/catch block (See dev.vaadin.com #2011)
- zIndex = Integer.parseInt(getElement().getStyle().getZIndex());
- } catch (Exception ignore) {
- // Ignored, will cause no harm
- zIndex = 1000;
- }
- if (zIndex == -1) {
- zIndex = Z_INDEX;
- }
- // Calculate position and size
- if (BrowserInfo.get().isIE()) {
- // Shake IE
- getOffsetHeight();
- getOffsetWidth();
- }
-
- if (isShadowEnabled() || needsShimElement()) {
-
- PositionAndSize positionAndSize = new PositionAndSize(
- getActualLeft(), getActualTop(), getOffsetWidth(),
- getOffsetHeight());
-
- // Animate the size
- positionAndSize.setAnimationFromCenterProgress(progress);
-
- Element container = getElement().getParentElement();
-
- if (isShadowEnabled()) {
- updateShadowPosition(progress, zIndex, positionAndSize);
- if (shadow.getParentElement() == null) {
- container.insertBefore(shadow, getElement());
- sinkShadowEvents();
- }
- }
-
- if (needsShimElement()) {
- updateShimPosition(positionAndSize);
- if (shimElement.getParentElement() == null) {
- container.insertBefore(shimElement, getElement());
- }
- }
- }
- // Fix for #14173
- // IE9 and IE10 have a bug, when resize an a element with box-shadow.
- // IE9 and IE10 need explicit update to remove extra box-shadows
- if (BrowserInfo.get().isIE9() || BrowserInfo.get().isIE10()) {
- WidgetUtil.forceIERedraw(getElement());
- }
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private void updateShadowPosition(final double progress, int zIndex,
- PositionAndSize positionAndSize) {
- // Opera needs some shaking to get parts of the shadow showing
- // properly (ticket #2704)
- if (BrowserInfo.get().isOpera()) {
- // Clear the height of all middle elements
- DOM.getChild(shadow, 3).getStyle().setProperty("height", "auto");
- DOM.getChild(shadow, 4).getStyle().setProperty("height", "auto");
- DOM.getChild(shadow, 5).getStyle().setProperty("height", "auto");
- }
-
- updatePositionAndSize(shadow, positionAndSize);
- shadow.getStyle().setZIndex(zIndex);
- shadow.getStyle().setProperty("display", progress < 0.9 ? "none" : "");
-
- // Opera fix, part 2 (ticket #2704)
- if (BrowserInfo.get().isOpera()) {
- // We'll fix the height of all the middle elements
- DOM.getChild(shadow, 3)
- .getStyle()
- .setPropertyPx("height",
- DOM.getChild(shadow, 3).getOffsetHeight());
- DOM.getChild(shadow, 4)
- .getStyle()
- .setPropertyPx("height",
- DOM.getChild(shadow, 4).getOffsetHeight());
- DOM.getChild(shadow, 5)
- .getStyle()
- .setPropertyPx("height",
- DOM.getChild(shadow, 5).getOffsetHeight());
- }
- }
-
- private void updateShimPosition(PositionAndSize positionAndSize) {
- updatePositionAndSize(getShimElement(), positionAndSize);
- }
-
- /**
- * Returns true if we should add a shim iframe below the overlay to deal
- * with zindex issues with PDFs and applets. Can be overriden to disable
- * shim iframes if they are not needed.
- *
- * @return true if a shim iframe should be added, false otherwise
- */
- protected boolean needsShimElement() {
- BrowserInfo info = BrowserInfo.get();
- return info.isIE() && info.isBrowserVersionNewerOrEqual(8, 0);
- }
-
- private void updatePositionAndSize(Element e,
- PositionAndSize positionAndSize) {
- e.getStyle().setLeft(positionAndSize.getLeft(), Unit.PX);
- e.getStyle().setTop(positionAndSize.getTop(), Unit.PX);
- e.getStyle().setWidth(positionAndSize.getWidth(), Unit.PX);
- e.getStyle().setHeight(positionAndSize.getHeight(), Unit.PX);
- }
-
- protected class ResizeAnimation extends Animation {
- @Override
- protected void onUpdate(double progress) {
- positionOrSizeUpdated(progress);
- }
- }
-
- @Override
- public void onClose(CloseEvent<PopupPanel> event) {
- removeShadowIfPresent();
- }
-
- @Override
- public void sinkEvents(int eventBitsToAdd) {
- super.sinkEvents(eventBitsToAdd);
- // Also sink events on the shadow if present
- sinkShadowEvents();
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private void sinkShadowEvents() {
- if (isSinkShadowEvents() && isShadowAttached()) {
- // Sink the same events as the actual overlay has sunk
- DOM.sinkEvents(shadow, DOM.getEventsSunk(getElement()));
- // Send events to VOverlay.onBrowserEvent
- DOM.setEventListener(shadow, this);
- }
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- private void unsinkShadowEvents() {
- if (isShadowAttached()) {
- DOM.setEventListener(shadow, null);
- DOM.sinkEvents(shadow, 0);
- }
- }
-
- /**
- * Enables or disables sinking the events of the shadow to the same
- * onBrowserEvent as events to the actual overlay goes.
- *
- * Please note, that if you enable this, you can't assume that e.g.
- * event.getEventTarget returns an element inside the DOM structure of the
- * overlay
- *
- * @param sinkShadowEvents
- *
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- protected void setSinkShadowEvents(boolean sinkShadowEvents) {
- this.sinkShadowEvents = sinkShadowEvents;
- if (sinkShadowEvents) {
- sinkShadowEvents();
- } else {
- unsinkShadowEvents();
- }
- }
-
- /**
- * @deprecated See main JavaDoc for VOverlay
- */
- @Deprecated
- protected boolean isSinkShadowEvents() {
- return sinkShadowEvents;
- }
-
- /**
- * Get owner (Widget that made this VOverlay, not the layout parent) of
- * VOverlay
- *
- * @return Owner (creator) or null if not defined
- */
- public Widget getOwner() {
- return owner;
- }
-
- /**
- * Set owner (Widget that made this VOverlay, not the layout parent) of
- * VOverlay
- *
- * @param owner
- * Owner (creator) of VOverlay
- */
- public void setOwner(Widget owner) {
- this.owner = owner;
- }
-
/**
* Get the {@link ApplicationConnection} that this overlay belongs to. If
* it's not set, {@link #getOwner()} is used to figure it out.
@@ -841,8 +94,8 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
protected ApplicationConnection getApplicationConnection() {
if (ac != null) {
return ac;
- } else if (owner != null) {
- ComponentConnector c = Util.findConnectorFor(owner);
+ } else if (getOwner() != null) {
+ ComponentConnector c = Util.findConnectorFor(getOwner());
if (c != null) {
ac = c.getConnection();
}
@@ -860,15 +113,16 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
* {@link ApplicationConnection} or another element if the current
* {@link ApplicationConnection} cannot be determined.
*/
+ @Override
public com.google.gwt.user.client.Element getOverlayContainer() {
ApplicationConnection ac = getApplicationConnection();
if (ac == null) {
// could not figure out which one we belong to, styling will
// probably fail
Logger.getLogger(getClass().getSimpleName())
- .log(Level.WARNING,
+ .warning(
"Could not determine ApplicationConnection for Overlay. Overlay will be attached directly to the root panel");
- return RootPanel.get().getElement();
+ return super.getOverlayContainer();
} else {
return getOverlayContainer(ac);
}
@@ -920,185 +174,4 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
overlayContainerLabel);
}
- @Override
- public void center() {
- super.center();
-
- // Some devices can be zoomed in, we should center to the visual
- // viewport for those devices
- BrowserInfo b = BrowserInfo.get();
- if (b.isAndroid() || b.isIOS()) {
- int left = (getVisualViewportWidth() - getOffsetWidth()) >> 1;
- int top = (getVisualViewportHeight() - getOffsetHeight()) >> 1;
- setPopupPosition(Math.max(Window.getScrollLeft() + left, 0),
- Math.max(Window.getScrollTop() + top, 0));
- }
-
- }
-
- /**
- * Gets the visual viewport width, which is useful for e.g iOS where the
- * view can be zoomed in while keeping the layout viewport intact.
- *
- * Falls back to layout viewport; for those browsers/devices the difference
- * is that the scrollbar with is included (if there is a scrollbar).
- *
- * @since 7.0.7
- * @return
- */
- private int getVisualViewportWidth() {
- int w = (int) getSubpixelInnerWidth();
- if (w < 0) {
- return Window.getClientWidth();
- } else {
- return w;
- }
- }
-
- /**
- * Gets the visual viewport height, which is useful for e.g iOS where the
- * view can be zoomed in while keeping the layout viewport intact.
- *
- * Falls back to layout viewport; for those browsers/devices the difference
- * is that the scrollbar with is included (if there is a scrollbar).
- *
- * @since 7.0.7
- * @return
- */
- private int getVisualViewportHeight() {
- int h = (int) getSubpixelInnerHeight();
- if (h < 0) {
- return Window.getClientHeight();
- } else {
- return h;
- }
- }
-
- private native double getSubpixelInnerWidth()
- /*-{
- return $wnd.innerWidth !== undefined ? $wnd.innerWidth : -1;
- }-*/;
-
- private native double getSubpixelInnerHeight()
- /*-{
- return $wnd.innerHeight !== undefined ? $wnd.innerHeight :-1;
- }-*/;
-
- /*
- * (non-Javadoc)
- *
- * @see com.google.gwt.user.client.ui.PopupPanel#hide()
- */
- @Override
- public void hide() {
- hide(false);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.google.gwt.user.client.ui.PopupPanel#hide(boolean)
- */
- @Override
- public void hide(final boolean autoClosed) {
- hide(autoClosed, true, true);
- }
-
- /**
- *
- * Hides the popup and detaches it from the page. This has no effect if it
- * is not currently showing. Animation-in, animation-out can be
- * enable/disabled for different use cases.
- *
- * @see com.google.gwt.user.client.ui.PopupPanel#hide(boolean)
- *
- * @param autoClosed
- * the value that will be passed to
- * {@link CloseHandler#onClose(CloseEvent)} when the popup is
- * closed
- * @param animateIn
- * enable/disable animate-in animation
- * @param animateOut
- * enable/disable animate-out animation
- * @since 7.3.7
- */
- public void hide(final boolean autoClosed, final boolean animateIn,
- final boolean animateOut) {
- if (BrowserInfo.get().isIE8() || BrowserInfo.get().isIE9()) {
- super.hide(autoClosed);
- } else {
- if (animateIn
- && 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 {
- // 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 (animateOut
- && animationName
- .contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
- // Disable GWT PopupPanel closing animation if used
- setAnimationEnabled(false);
-
- 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);
- }
- super.hide(autoClosed);
- }
- }
- }
- }
-
-}
+} \ No newline at end of file
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 80b20fa184..05b90e204d 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -34,7 +34,6 @@ import java.util.logging.Logger;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.core.shared.GWT;
-import com.google.gwt.dom.client.BodyElement;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
@@ -3620,7 +3619,7 @@ public class Grid<T> extends ResizeComposite implements
private final Grid<?> grid;
- private PopupPanel overlay;
+ private Overlay overlay;
private Sidebar(Grid<?> grid) {
this.grid = grid;
@@ -3712,33 +3711,8 @@ public class Grid<T> extends ResizeComposite implements
* Creates and initializes the overlay.
*/
private void createOverlay() {
- overlay = new PopupPanel() {
-
- @Override
- protected void onAttach() {
- // PopupPanel by default attaches itself directly to the
- // body. Try to find a Vaadin overlay container and move the
- // overlay there if found.
-
- // FIXME: This is a hack; Grid should not have
- // Vaadin-specific behavior special-cased. Instead, there
- // should be a customization point for setting the overlay
- // container.
-
- BodyElement body = Document.get().getBody();
- Element target = body.getFirstChildElement();
- while (!target.hasClassName("v-overlay-container")
- && target != null) {
- target = target.getNextSiblingElement();
- }
-
- if (target != null) {
- target.appendChild(getElement());
- }
-
- super.onAttach();
- }
- };
+ overlay = GWT.create(Overlay.class);
+ overlay.setOwner(grid);
overlay.setAutoHideEnabled(true);
overlay.addStyleDependentName("popup");
overlay.add(content);
diff --git a/client/src/com/vaadin/client/widgets/Overlay.java b/client/src/com/vaadin/client/widgets/Overlay.java
new file mode 100644
index 0000000000..5be2da325d
--- /dev/null
+++ b/client/src/com/vaadin/client/widgets/Overlay.java
@@ -0,0 +1,1010 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.client.widgets;
+
+import com.google.gwt.animation.client.Animation;
+import com.google.gwt.core.client.GWT;
+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.Position;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.AnimationUtil;
+import com.vaadin.client.AnimationUtil.AnimationEndListener;
+import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.ComputedStyle;
+import com.vaadin.client.WidgetUtil;
+
+/**
+ * Overlay widget extending the PopupPanel. Overlay is used to float elements on
+ * top of other elements temporarily.
+ * <p>
+ * <b>Note:</b> This class should always be constructed with
+ * {@link GWT#create(Class)}.
+ *
+ * <h3>Shadow</h3>
+ * <p>
+ * The separate shadow element underneath the main overlay element is <strong>
+ * <em>deprecated</em></strong>, and should not be used for new overlay
+ * components. CSS box-shadow should be used instead of a separate shadow
+ * element. Remember to include any vendor-prefixed versions to support all
+ * browsers that you need to. To cover all possible browsers that Vaadin 7
+ * supports, add <code>-webkit-box-shadow</code> and the standard
+ * <code>box-shadow</code> properties.
+ * </p>
+ *
+ * <p>
+ * For IE8, which doesn't support CSS box-shadow, you can use the proprietary
+ * DropShadow filter. It doesn't provide the exact same features as box-shadow,
+ * but it is suitable for graceful degradation. Other options are to use a
+ * border or a pseudo-element underneath the overlay which mimics a shadow, or
+ * any combination of these.
+ * </p>
+ *
+ * <p>
+ * Read more about the DropShadow filter from <a
+ * href="http://msdn.microsoft.com/en-us/library/ms532985(v=vs.85).aspx"
+ * >Microsoft Developer Network</a>
+ * </p>
+ */
+public class Overlay extends PopupPanel implements CloseHandler<PopupPanel> {
+
+ @Override
+ protected void onAttach() {
+ // Move the overlay to the appropriate overlay container
+ final Overlay overlay = Overlay.current;
+ if (overlay != null) {
+ final Element e = overlay.getOverlayContainer();
+ e.appendChild(getElement());
+ }
+
+ super.onAttach();
+ }
+
+ public static class PositionAndSize {
+ private int left, top, width, height;
+
+ public PositionAndSize(int left, int top, int width, int height) {
+ super();
+ setLeft(left);
+ setTop(top);
+ setWidth(width);
+ setHeight(height);
+ }
+
+ public int getLeft() {
+ return left;
+ }
+
+ public void setLeft(int left) {
+ this.left = left;
+ }
+
+ public int getTop() {
+ return top;
+ }
+
+ public void setTop(int top) {
+ this.top = top;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setWidth(int width) {
+ if (width < 0) {
+ width = 0;
+ }
+
+ this.width = width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setHeight(int height) {
+ if (height < 0) {
+ height = 0;
+ }
+
+ this.height = height;
+ }
+
+ public void setAnimationFromCenterProgress(double progress) {
+ left += (int) (width * (1.0 - progress) / 2.0);
+ top += (int) (height * (1.0 - progress) / 2.0);
+ width = (int) (width * progress);
+ height = (int) (height * progress);
+ }
+ }
+
+ /*
+ * The z-index value from where all overlays live. This can be overridden in
+ * any extending class.
+ */
+ public static int Z_INDEX = 20000;
+
+ private static int leftFix = -1;
+
+ private static int topFix = -1;
+
+ /**
+ * Shadow element style. If an extending class wishes to use a different
+ * style of shadow, it can use setShadowStyle(String) to give the shadow
+ * element a new style name.
+ *
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ public static final String CLASSNAME_SHADOW = "v-shadow";
+
+ /**
+ * Style name for the overlay container element (see
+ * {@link #getOverlayContainer()}
+ */
+ public static final String CLASSNAME_CONTAINER = "v-overlay-container";
+
+ /**
+ * @since 7.3
+ */
+ public static final String ADDITIONAL_CLASSNAME_ANIMATE_IN = "animate-in";
+ /**
+ * @since 7.3
+ */
+ public static final String ADDITIONAL_CLASSNAME_ANIMATE_OUT = "animate-out";
+
+ /**
+ * The shadow element for this overlay.
+ *
+ * @deprecated See main JavaDoc for Overlay
+ *
+ */
+ @Deprecated
+ private Element shadow;
+
+ /*
+ * The creator of this Overlay (the widget that made the instance, not the
+ * layout parent)
+ */
+ private Widget owner;
+
+ /**
+ * The shim iframe behind the overlay, allowing PDFs and applets to be
+ * covered by overlays.
+ */
+ private IFrameElement shimElement;
+
+ /**
+ * The HTML snippet that is used to render the actual shadow. In consists of
+ * nine different DIV-elements with the following class names:
+ *
+ * <pre>
+ * .v-shadow[-stylename]
+ * ----------------------------------------------
+ * | .top-left | .top | .top-right |
+ * |---------------|-----------|----------------|
+ * | | | |
+ * | .left | .center | .right |
+ * | | | |
+ * |---------------|-----------|----------------|
+ * | .bottom-left | .bottom | .bottom-right |
+ * ----------------------------------------------
+ * </pre>
+ *
+ * See default theme 'shadow.css' for implementation example.
+ *
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private static final String SHADOW_HTML = "<div aria-hidden=\"true\" class=\"top-left\"></div><div class=\"top\"></div><div class=\"top-right\"></div><div class=\"left\"></div><div class=\"center\"></div><div class=\"right\"></div><div class=\"bottom-left\"></div><div class=\"bottom\"></div><div class=\"bottom-right\"></div>";
+
+ /**
+ * Matches {@link PopupPanel}.ANIMATION_DURATION
+ */
+ private static final int POPUP_PANEL_ANIMATION_DURATION = 200;
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private boolean sinkShadowEvents = false;
+
+ public Overlay() {
+ super();
+ adjustZIndex();
+ }
+
+ public Overlay(boolean autoHide) {
+ super(autoHide);
+ adjustZIndex();
+ }
+
+ public Overlay(boolean autoHide, boolean modal) {
+ super(autoHide, modal);
+ adjustZIndex();
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay. Use the other constructors
+ * without the <code>showShadow</code> parameter.
+ */
+ @Deprecated
+ public Overlay(boolean autoHide, boolean modal, boolean showShadow) {
+ super(autoHide, modal);
+ setShadowEnabled(showShadow && useShadowDiv());
+ adjustZIndex();
+ }
+
+ /**
+ * Return true if a separate shadow div should be used. Since Vaadin 7.3,
+ * shadows are implemented with CSS box-shadow. Thus, a shadow div is only
+ * used for IE8 by default.
+ *
+ * @deprecated See main JavaDoc for Overlay
+ * @since 7.3
+ * @return true to use a shadow div
+ */
+ @Deprecated
+ protected boolean useShadowDiv() {
+ return BrowserInfo.get().isIE8();
+ }
+
+ /**
+ * Method to control whether DOM elements for shadow are added. With this
+ * method subclasses can control displaying of shadow also after the
+ * constructor.
+ *
+ * @param enabled
+ * true if shadow should be displayed
+ *
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ protected void setShadowEnabled(boolean enabled) {
+ if (enabled != isShadowEnabled()) {
+ if (enabled) {
+ shadow = DOM.createDiv();
+ shadow.setClassName(CLASSNAME_SHADOW);
+ shadow.setInnerHTML(SHADOW_HTML);
+ shadow.getStyle().setPosition(Position.ABSOLUTE);
+ addCloseHandler(this);
+ } else {
+ removeShadowIfPresent();
+ shadow = null;
+ }
+ }
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ protected boolean isShadowEnabled() {
+ return shadow != null;
+ }
+
+ protected boolean isShimElementEnabled() {
+ return shimElement != null;
+ }
+
+ private void removeShimElement() {
+ if (shimElement != null) {
+ shimElement.removeFromParent();
+ }
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private void removeShadowIfPresent() {
+ if (isShadowAttached()) {
+ // Remove event listener from the shadow
+ unsinkShadowEvents();
+
+ shadow.removeFromParent();
+ }
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private boolean isShadowAttached() {
+ return isShadowEnabled() && shadow.getParentElement() != null;
+ }
+
+ private void adjustZIndex() {
+ setZIndex(Z_INDEX);
+ }
+
+ /**
+ * Set the z-index (visual stack position) for this overlay.
+ *
+ * @param zIndex
+ * The new z-index
+ */
+ protected void setZIndex(int zIndex) {
+ getElement().getStyle().setZIndex(zIndex);
+ if (isShadowEnabled()) {
+ shadow.getStyle().setZIndex(zIndex);
+ }
+ }
+
+ @Override
+ public void setPopupPosition(int left, int top) {
+ // TODO, this should in fact be part of
+ // Document.get().getBodyOffsetLeft/Top(). Would require overriding DOM
+ // for all permutations. Now adding fix as margin instead of fixing
+ // left/top because parent class saves the position.
+ Style style = getElement().getStyle();
+ style.setMarginLeft(-adjustByRelativeLeftBodyMargin(), Unit.PX);
+ style.setMarginTop(-adjustByRelativeTopBodyMargin(), Unit.PX);
+ super.setPopupPosition(left, top);
+ positionOrSizeUpdated(isAnimationEnabled() ? 0 : 1);
+ }
+
+ private IFrameElement getShimElement() {
+ if (shimElement == null && needsShimElement()) {
+ shimElement = Document.get().createIFrameElement();
+
+ // Insert shim iframe before the main overlay element. It does not
+ // matter if it is in front or behind the shadow as we cannot put a
+ // shim behind the shadow due to its transparency.
+ shimElement.getStyle().setPosition(Position.ABSOLUTE);
+ shimElement.getStyle().setBorderStyle(BorderStyle.NONE);
+ shimElement.setTabIndex(-1);
+ shimElement.setFrameBorder(0);
+ shimElement.setMarginHeight(0);
+ }
+ return shimElement;
+ }
+
+ private int getActualTop() {
+ int y = getAbsoluteTop();
+
+ /* This is needed for IE7 at least */
+ // Account for the difference between absolute position and the
+ // body's positioning context.
+ y -= Document.get().getBodyOffsetTop();
+ y -= adjustByRelativeTopBodyMargin();
+
+ return y;
+ }
+
+ private int getActualLeft() {
+ int x = getAbsoluteLeft();
+
+ /* This is needed for IE7 at least */
+ // Account for the difference between absolute position and the
+ // body's positioning context.
+ x -= Document.get().getBodyOffsetLeft();
+ x -= adjustByRelativeLeftBodyMargin();
+
+ return x;
+ }
+
+ private static int adjustByRelativeTopBodyMargin() {
+ if (topFix == -1) {
+ topFix = detectRelativeBodyFixes("top");
+ }
+ return topFix;
+ }
+
+ private native static int detectRelativeBodyFixes(String axis)
+ /*-{
+ try {
+ var b = $wnd.document.body;
+ var cstyle = b.currentStyle ? b.currentStyle : getComputedStyle(b);
+ if(cstyle && cstyle.position == 'relative') {
+ return b.getBoundingClientRect()[axis];
+ }
+ } catch(e){}
+ return 0;
+ }-*/;
+
+ private static int adjustByRelativeLeftBodyMargin() {
+ if (leftFix == -1) {
+ leftFix = detectRelativeBodyFixes("left");
+
+ }
+ return leftFix;
+ }
+
+ /*
+ * A "thread local" of sorts, set temporarily so that OverlayImpl knows
+ * which Overlay is using it, so that it can be attached to the correct
+ * overlay container.
+ *
+ * TODO this is a strange pattern that we should get rid of when possible.
+ */
+ protected static Overlay current;
+
+ @Override
+ public void show() {
+ current = this;
+
+ maybeShowWithAnimation();
+
+ if (isAnimationEnabled()) {
+ new ResizeAnimation().run(POPUP_PANEL_ANIMATION_DURATION);
+ } else {
+ positionOrSizeUpdated(1.0);
+ }
+ current = null;
+ }
+
+ private JavaScriptObject animateInListener;
+
+ private boolean maybeShowWithAnimation() {
+ boolean isAttached = isAttached() && isShowing();
+ super.show();
+
+ // Don't animate if already visible or browser is IE8 or IE9 (no CSS
+ // animation support)
+ if (isAttached || BrowserInfo.get().isIE8()
+ || BrowserInfo.get().isIE9()) {
+ return false;
+ } else {
+ // Check if animations are used
+ setVisible(false);
+ addStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ if (isShadowEnabled()) {
+ shadow.addClassName(CLASSNAME_SHADOW + "-"
+ + ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ }
+
+ ComputedStyle cs = new ComputedStyle(getElement());
+ String animationName = AnimationUtil.getAnimationName(cs);
+ 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
+ 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);
+ if (isShadowEnabled()) {
+ shadow.removeClassName(CLASSNAME_SHADOW + "-"
+ + ADDITIONAL_CLASSNAME_ANIMATE_IN);
+ }
+ return false;
+ }
+ }
+ }
+
+ @Override
+ protected void onDetach() {
+ super.onDetach();
+
+ // Always ensure shadow is removed when the overlay is removed.
+ removeShadowIfPresent();
+ removeShimElement();
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (isShadowEnabled()) {
+ shadow.getStyle().setProperty("visibility",
+ visible ? "visible" : "hidden");
+ }
+ if (isShimElementEnabled()) {
+ shimElement.getStyle().setProperty("visibility",
+ visible ? "visible" : "hidden");
+ }
+ }
+
+ @Override
+ public void setWidth(String width) {
+ super.setWidth(width);
+ positionOrSizeUpdated(1.0);
+ }
+
+ @Override
+ public void setHeight(String height) {
+ super.setHeight(height);
+ positionOrSizeUpdated(1.0);
+ }
+
+ /**
+ * Sets the shadow style for this overlay. Will override any previous style
+ * for the shadow. The default style name is defined by CLASSNAME_SHADOW.
+ * The given style will be prefixed with CLASSNAME_SHADOW.
+ *
+ * @param style
+ * The new style name for the shadow element. Will be prefixed by
+ * CLASSNAME_SHADOW, e.g. style=='foobar' -> actual style
+ * name=='v-shadow-foobar'.
+ *
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ protected void setShadowStyle(String style) {
+ if (isShadowEnabled()) {
+ shadow.setClassName(CLASSNAME_SHADOW + "-" + style);
+ }
+ }
+
+ /**
+ * Extending classes should always call this method after they change the
+ * size of overlay without using normal 'setWidth(String)' and
+ * 'setHeight(String)' methods (if not calling super.setWidth/Height).
+ *
+ */
+ public void positionOrSizeUpdated() {
+ positionOrSizeUpdated(1.0);
+ }
+
+ /**
+ * @deprecated Call {@link #positionOrSizeUpdated()} instead.
+ */
+ @Deprecated
+ protected void updateShadowSizeAndPosition() {
+ positionOrSizeUpdated();
+ }
+
+ /**
+ * Recalculates proper position and dimensions for the shadow and shim
+ * elements. Can be used to animate the related elements, using the
+ * 'progress' parameter (used to animate the shadow in sync with GWT
+ * PopupPanel's default animation 'PopupPanel.AnimationType.CENTER').
+ *
+ * @param progress
+ * A value between 0.0 and 1.0, indicating the progress of the
+ * animation (0=start, 1=end).
+ */
+ private void positionOrSizeUpdated(final double progress) {
+ // Don't do anything if overlay element is not attached
+ if (!isAttached()) {
+ return;
+ }
+ // Calculate proper z-index
+ int zIndex = -1;
+ try {
+ // Odd behaviour with Windows Hosted Mode forces us to use
+ // this redundant try/catch block (See dev.vaadin.com #2011)
+ zIndex = Integer.parseInt(getElement().getStyle().getZIndex());
+ } catch (Exception ignore) {
+ // Ignored, will cause no harm
+ zIndex = 1000;
+ }
+ if (zIndex == -1) {
+ zIndex = Z_INDEX;
+ }
+ // Calculate position and size
+ if (BrowserInfo.get().isIE()) {
+ // Shake IE
+ getOffsetHeight();
+ getOffsetWidth();
+ }
+
+ if (isShadowEnabled() || needsShimElement()) {
+
+ PositionAndSize positionAndSize = new PositionAndSize(
+ getActualLeft(), getActualTop(), getOffsetWidth(),
+ getOffsetHeight());
+
+ // Animate the size
+ positionAndSize.setAnimationFromCenterProgress(progress);
+
+ Element container = getElement().getParentElement();
+
+ if (isShadowEnabled()) {
+ updateShadowPosition(progress, zIndex, positionAndSize);
+ if (shadow.getParentElement() == null) {
+ container.insertBefore(shadow, getElement());
+ sinkShadowEvents();
+ }
+ }
+
+ if (needsShimElement()) {
+ updateShimPosition(positionAndSize);
+ if (shimElement.getParentElement() == null) {
+ container.insertBefore(shimElement, getElement());
+ }
+ }
+ }
+ // Fix for #14173
+ // IE9 and IE10 have a bug, when resize an a element with box-shadow.
+ // IE9 and IE10 need explicit update to remove extra box-shadows
+ if (BrowserInfo.get().isIE9() || BrowserInfo.get().isIE10()) {
+ WidgetUtil.forceIERedraw(getElement());
+ }
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private void updateShadowPosition(final double progress, int zIndex,
+ PositionAndSize positionAndSize) {
+ // Opera needs some shaking to get parts of the shadow showing
+ // properly (ticket #2704)
+ if (BrowserInfo.get().isOpera()) {
+ // Clear the height of all middle elements
+ DOM.getChild(shadow, 3).getStyle().setProperty("height", "auto");
+ DOM.getChild(shadow, 4).getStyle().setProperty("height", "auto");
+ DOM.getChild(shadow, 5).getStyle().setProperty("height", "auto");
+ }
+
+ updatePositionAndSize(shadow, positionAndSize);
+ shadow.getStyle().setZIndex(zIndex);
+ shadow.getStyle().setProperty("display", progress < 0.9 ? "none" : "");
+
+ // Opera fix, part 2 (ticket #2704)
+ if (BrowserInfo.get().isOpera()) {
+ // We'll fix the height of all the middle elements
+ DOM.getChild(shadow, 3)
+ .getStyle()
+ .setPropertyPx("height",
+ DOM.getChild(shadow, 3).getOffsetHeight());
+ DOM.getChild(shadow, 4)
+ .getStyle()
+ .setPropertyPx("height",
+ DOM.getChild(shadow, 4).getOffsetHeight());
+ DOM.getChild(shadow, 5)
+ .getStyle()
+ .setPropertyPx("height",
+ DOM.getChild(shadow, 5).getOffsetHeight());
+ }
+ }
+
+ private void updateShimPosition(PositionAndSize positionAndSize) {
+ updatePositionAndSize(getShimElement(), positionAndSize);
+ }
+
+ /**
+ * Returns true if we should add a shim iframe below the overlay to deal
+ * with zindex issues with PDFs and applets. Can be overriden to disable
+ * shim iframes if they are not needed.
+ *
+ * @return true if a shim iframe should be added, false otherwise
+ */
+ protected boolean needsShimElement() {
+ BrowserInfo info = BrowserInfo.get();
+ return info.isIE() && info.isBrowserVersionNewerOrEqual(8, 0);
+ }
+
+ private void updatePositionAndSize(Element e,
+ PositionAndSize positionAndSize) {
+ e.getStyle().setLeft(positionAndSize.getLeft(), Unit.PX);
+ e.getStyle().setTop(positionAndSize.getTop(), Unit.PX);
+ e.getStyle().setWidth(positionAndSize.getWidth(), Unit.PX);
+ e.getStyle().setHeight(positionAndSize.getHeight(), Unit.PX);
+ }
+
+ protected class ResizeAnimation extends Animation {
+ @Override
+ protected void onUpdate(double progress) {
+ positionOrSizeUpdated(progress);
+ }
+ }
+
+ @Override
+ public void onClose(CloseEvent<PopupPanel> event) {
+ removeShadowIfPresent();
+ }
+
+ @Override
+ public void sinkEvents(int eventBitsToAdd) {
+ super.sinkEvents(eventBitsToAdd);
+ // Also sink events on the shadow if present
+ sinkShadowEvents();
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private void sinkShadowEvents() {
+ if (isSinkShadowEvents() && isShadowAttached()) {
+ // Sink the same events as the actual overlay has sunk
+ DOM.sinkEvents(shadow, DOM.getEventsSunk(getElement()));
+ // Send events to Overlay.onBrowserEvent
+ DOM.setEventListener(shadow, this);
+ }
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ private void unsinkShadowEvents() {
+ if (isShadowAttached()) {
+ DOM.setEventListener(shadow, null);
+ DOM.sinkEvents(shadow, 0);
+ }
+ }
+
+ /**
+ * Enables or disables sinking the events of the shadow to the same
+ * onBrowserEvent as events to the actual overlay goes.
+ *
+ * Please note, that if you enable this, you can't assume that e.g.
+ * event.getEventTarget returns an element inside the DOM structure of the
+ * overlay
+ *
+ * @param sinkShadowEvents
+ *
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ protected void setSinkShadowEvents(boolean sinkShadowEvents) {
+ this.sinkShadowEvents = sinkShadowEvents;
+ if (sinkShadowEvents) {
+ sinkShadowEvents();
+ } else {
+ unsinkShadowEvents();
+ }
+ }
+
+ /**
+ * @deprecated See main JavaDoc for Overlay
+ */
+ @Deprecated
+ protected boolean isSinkShadowEvents() {
+ return sinkShadowEvents;
+ }
+
+ /**
+ * Get owner (Widget that made this Overlay, not the layout parent) of
+ * Overlay
+ *
+ * @return Owner (creator) or null if not defined
+ */
+ public Widget getOwner() {
+ return owner;
+ }
+
+ /**
+ * Set owner (Widget that made this Overlay, not the layout parent) of
+ * Overlay
+ *
+ * @param owner
+ * Owner (creator) of Overlay
+ */
+ public void setOwner(Widget owner) {
+ this.owner = owner;
+ }
+
+ /**
+ * Gets the 'overlay container' element.
+ *
+ * @return the overlay container element
+ */
+ public com.google.gwt.user.client.Element getOverlayContainer() {
+ return RootPanel.get().getElement();
+ }
+
+ @Override
+ public void center() {
+ super.center();
+
+ // Some devices can be zoomed in, we should center to the visual
+ // viewport for those devices
+ BrowserInfo b = BrowserInfo.get();
+ if (b.isAndroid() || b.isIOS()) {
+ int left = (getVisualViewportWidth() - getOffsetWidth()) >> 1;
+ int top = (getVisualViewportHeight() - getOffsetHeight()) >> 1;
+ setPopupPosition(Math.max(Window.getScrollLeft() + left, 0),
+ Math.max(Window.getScrollTop() + top, 0));
+ }
+
+ }
+
+ /**
+ * Gets the visual viewport width, which is useful for e.g iOS where the
+ * view can be zoomed in while keeping the layout viewport intact.
+ *
+ * Falls back to layout viewport; for those browsers/devices the difference
+ * is that the scrollbar with is included (if there is a scrollbar).
+ *
+ * @since 7.0.7
+ * @return
+ */
+ private int getVisualViewportWidth() {
+ int w = (int) getSubpixelInnerWidth();
+ if (w < 0) {
+ return Window.getClientWidth();
+ } else {
+ return w;
+ }
+ }
+
+ /**
+ * Gets the visual viewport height, which is useful for e.g iOS where the
+ * view can be zoomed in while keeping the layout viewport intact.
+ *
+ * Falls back to layout viewport; for those browsers/devices the difference
+ * is that the scrollbar with is included (if there is a scrollbar).
+ *
+ * @since 7.0.7
+ * @return
+ */
+ private int getVisualViewportHeight() {
+ int h = (int) getSubpixelInnerHeight();
+ if (h < 0) {
+ return Window.getClientHeight();
+ } else {
+ return h;
+ }
+ }
+
+ private native double getSubpixelInnerWidth()
+ /*-{
+ return $wnd.innerWidth !== undefined ? $wnd.innerWidth : -1;
+ }-*/;
+
+ private native double getSubpixelInnerHeight()
+ /*-{
+ return $wnd.innerHeight !== undefined ? $wnd.innerHeight :-1;
+ }-*/;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.PopupPanel#hide()
+ */
+ @Override
+ public void hide() {
+ hide(false);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.PopupPanel#hide(boolean)
+ */
+ @Override
+ public void hide(final boolean autoClosed) {
+ hide(autoClosed, true, true);
+ }
+
+ /**
+ *
+ * Hides the popup and detaches it from the page. This has no effect if it
+ * is not currently showing. Animation-in, animation-out can be
+ * enable/disabled for different use cases.
+ *
+ * @see com.google.gwt.user.client.ui.PopupPanel#hide(boolean)
+ *
+ * @param autoClosed
+ * the value that will be passed to
+ * {@link CloseHandler#onClose(CloseEvent)} when the popup is
+ * closed
+ * @param animateIn
+ * enable/disable animate-in animation
+ * @param animateOut
+ * enable/disable animate-out animation
+ * @since 7.3.7
+ */
+ public void hide(final boolean autoClosed, final boolean animateIn,
+ final boolean animateOut) {
+ if (BrowserInfo.get().isIE8() || BrowserInfo.get().isIE9()) {
+ super.hide(autoClosed);
+ } else {
+ if (animateIn
+ && 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)) {
+ Overlay.this.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 (animateOut
+ && animationName
+ .contains(ADDITIONAL_CLASSNAME_ANIMATE_OUT)) {
+ // Disable GWT PopupPanel closing animation if used
+ setAnimationEnabled(false);
+
+ 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);
+ }
+ Overlay.super.hide(autoClosed);
+ }
+ }
+ });
+ // No event previews should happen after the animation has
+ // started
+ Overlay.this.setPreviewingAllNativeEvents(false);
+ } else {
+ removeStyleDependentName(ADDITIONAL_CLASSNAME_ANIMATE_OUT);
+ if (isShadowEnabled()) {
+ shadow.removeClassName(CLASSNAME_SHADOW + "-"
+ + ADDITIONAL_CLASSNAME_ANIMATE_OUT);
+ }
+ super.hide(autoClosed);
+ }
+ }
+ }
+ }
+
+}
diff --git a/widgets/build.xml b/widgets/build.xml
index 4441bc0bd0..a2eebd4276 100644
--- a/widgets/build.xml
+++ b/widgets/build.xml
@@ -45,6 +45,7 @@
<fileset dir="${result.deps}">
<include name="com/vaadin/*.gwt.xml" />
<include name="com/vaadin/client/BrowserInfo.java" />
+ <include name="com/vaadin/client/AnimationUtil.java" />
<include name="com/vaadin/client/ComputedStyle.java" />
<include name="com/vaadin/client/DeferredWorker.java" />
<include name="com/vaadin/client/Profiler.java" />