summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/window/window.scss27
-rw-r--r--WebContent/VAADIN/themes/reindeer/window/img/maximize.pngbin0 -> 270 bytes
-rw-r--r--WebContent/VAADIN/themes/reindeer/window/img/restore.pngbin0 -> 328 bytes
-rw-r--r--WebContent/VAADIN/themes/reindeer/window/window.scss20
-rw-r--r--WebContent/VAADIN/themes/runo/window/window.scss23
-rw-r--r--client/src/com/vaadin/client/ui/AbstractComponentConnector.java12
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java94
-rw-r--r--client/src/com/vaadin/client/ui/window/WindowConnector.java287
-rw-r--r--server/src/com/vaadin/ui/Window.java147
-rw-r--r--shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java6
-rw-r--r--shared/src/com/vaadin/shared/ui/window/WindowState.java6
-rw-r--r--uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html228
-rw-r--r--uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.java165
13 files changed, 857 insertions, 158 deletions
diff --git a/WebContent/VAADIN/themes/base/window/window.scss b/WebContent/VAADIN/themes/base/window/window.scss
index b9e7b54139..05f3b115ad 100644
--- a/WebContent/VAADIN/themes/base/window/window.scss
+++ b/WebContent/VAADIN/themes/base/window/window.scss
@@ -38,6 +38,10 @@
}
.#{$primaryStyleName}-header {
font-weight: bold;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ie-user-select: none;
+ user-select: none;
}
/* A more specific selector to make sure padding isn't so easily overridden */
div.#{$primaryStyleName}-header {
@@ -77,20 +81,37 @@ div.#{$primaryStyleName}-header {
.#{$primaryStyleName} div.#{$primaryStyleName}-footer-noresize {
height: 0;
}
-.#{$primaryStyleName}-resizebox-disabled {
+.#{$primaryStyleName}-resizebox-disabled,
+.#{$primaryStyleName}-restorebox-disabled,
+.#{$primaryStyleName}-maximizebox-disabled {
cursor: default;
display: none;
}
-.#{$primaryStyleName}-closebox {
+.#{$primaryStyleName}-closebox,
+.#{$primaryStyleName}-restorebox,
+.#{$primaryStyleName}-maximizebox {
position: absolute;
top: 0;
right: 0;
width: 1em;
height: 1em;
- background: red;
cursor: pointer;
overflow: hidden;
}
+.#{$primaryStyleName}-maximizebox,
+.#{$primaryStyleName}-restorebox {
+ right: 1.1em;
+}
+
+.#{$primaryStyleName}-closebox {
+ background: red;
+}
+.#{$primaryStyleName}-maximizebox {
+ background: blue;
+}
+.#{$primaryStyleName}-restorebox {
+ background: yellow;
+}
.#{$primaryStyleName}-modalitycurtain {
top: 0;
left: 0;
diff --git a/WebContent/VAADIN/themes/reindeer/window/img/maximize.png b/WebContent/VAADIN/themes/reindeer/window/img/maximize.png
new file mode 100644
index 0000000000..86ffff9760
--- /dev/null
+++ b/WebContent/VAADIN/themes/reindeer/window/img/maximize.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/reindeer/window/img/restore.png b/WebContent/VAADIN/themes/reindeer/window/img/restore.png
new file mode 100644
index 0000000000..119ea04259
--- /dev/null
+++ b/WebContent/VAADIN/themes/reindeer/window/img/restore.png
Binary files differ
diff --git a/WebContent/VAADIN/themes/reindeer/window/window.scss b/WebContent/VAADIN/themes/reindeer/window/window.scss
index e6a73ee2c0..7a05e52aec 100644
--- a/WebContent/VAADIN/themes/reindeer/window/window.scss
+++ b/WebContent/VAADIN/themes/reindeer/window/window.scss
@@ -14,7 +14,7 @@
border-color: rgba(0,0,0,.2);
}
.#{$primaryStyleName}-outerheader {
- padding: 12px 32px 0 14px;
+ padding: 12px 52px 0 14px;
height: 37px;
background: black repeat-x;
background-image: url(img/header-bg.png); /** sprite-ref: verticals; sprite-alignment: repeat */
@@ -61,6 +61,24 @@
.#{$primaryStyleName}-closebox:active {
background-image: url(img/close-pressed.png); /** sprite-ref: verticals */
}
+.#{$primaryStyleName}-maximizebox,
+.#{$primaryStyleName}-restorebox {
+ top: 12px;
+ right: 28px;
+ width: 15px;
+ height: 16px;
+ background: transparent;
+}
+.#{$primaryStyleName}-maximizebox {
+ &, &:hover,&:active {
+ background-image: url(img/maximize.png); /** sprite-ref: verticals */
+ }
+}
+.#{$primaryStyleName}-restorebox {
+ &, &:hover,&:active {
+ background-image: url(img/restore.png); /** sprite-ref: verticals */
+ }
+}
.#{$primaryStyleName}-contents {
background: #fff;
}
diff --git a/WebContent/VAADIN/themes/runo/window/window.scss b/WebContent/VAADIN/themes/runo/window/window.scss
index 994238f2ad..db153243e9 100644
--- a/WebContent/VAADIN/themes/runo/window/window.scss
+++ b/WebContent/VAADIN/themes/runo/window/window.scss
@@ -51,14 +51,33 @@
background: transparent;
display: block;
}
-.#{$primaryStyleName}-closebox {
+.#{$primaryStyleName}-closebox,
+.#{$primaryStyleName}-maximizebox,
+.#{$primaryStyleName}-restorebox {
position: absolute;
top: 21px;
- right: 24px;
width: 12px;
height: 12px;
background: transparent url(img/close.png);
}
+.#{$primaryStyleName}-closebox {
+ right: 24px;
+ background: transparent url(img/close.png);
+}
+
+.#{$primaryStyleName}-maximizebox,
+.#{$primaryStyleName}-restorebox {
+ right: 42px;
+}
+
+.#{$primaryStyleName}-maximizebox {
+ background: transparent url(img/maximize.png);
+}
+
+.#{$primaryStyleName}-restorebox {
+ background: transparent url(img/restore.png);
+}
+
.#{$primaryStyleName}-closebox:hover {
background-position: 0 -12px;
}
diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
index ecd6abae08..e7f7379994 100644
--- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
+++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
@@ -36,6 +36,8 @@ import com.vaadin.client.metadata.NoDataException;
import com.vaadin.client.metadata.Type;
import com.vaadin.client.metadata.TypeData;
import com.vaadin.client.metadata.TypeDataStore;
+import com.vaadin.client.ui.AbstractFieldConnector;
+import com.vaadin.client.ui.ManagedLayout;
import com.vaadin.client.ui.datefield.PopupDateFieldConnector;
import com.vaadin.client.ui.ui.UIConnector;
import com.vaadin.shared.AbstractComponentState;
@@ -205,12 +207,12 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
}
- private void updateComponentSize() {
- Profiler.enter("AbstractComponentConnector.updateComponentSize");
-
- String newWidth = getState().width == null ? "" : getState().width;
- String newHeight = getState().height == null ? "" : getState().height;
+ protected void updateComponentSize() {
+ updateComponentSize(getState().width == null ? "" : getState().width,
+ getState().height == null ? "" : getState().height);
+ }
+ protected void updateComponentSize(String newWidth, String newHeight) {
// Parent should be updated if either dimension changed between relative
// and non-relative
if (newWidth.endsWith("%") != lastKnownWidth.endsWith("%")) {
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index fd2a701334..bd9a0ed07c 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -49,6 +49,7 @@ import com.vaadin.client.LayoutManager;
import com.vaadin.client.Util;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.shared.EventId;
+import com.vaadin.shared.ui.window.WindowState.DisplayState;
/**
* "Sub window" component.
@@ -58,18 +59,6 @@ import com.vaadin.shared.EventId;
public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
ScrollHandler, KeyDownHandler, FocusHandler, BlurHandler, Focusable {
- /**
- * Minimum allowed height of a window. This refers to the content area, not
- * the outer borders.
- */
- private static final int MIN_CONTENT_AREA_HEIGHT = 100;
-
- /**
- * Minimum allowed width of a window. This refers to the content area, not
- * the outer borders.
- */
- private static final int MIN_CONTENT_AREA_WIDTH = 150;
-
private static ArrayList<VWindow> windowOrder = new ArrayList<VWindow>();
private static boolean orderingDefered;
@@ -114,6 +103,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
public Element closeBox;
/** For internal use only. May be removed or replaced in the future. */
+ public Element maximizeRestoreBox;
+
+ /** For internal use only. May be removed or replaced in the future. */
public ApplicationConnection client;
/** For internal use only. May be removed or replaced in the future. */
@@ -262,6 +254,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
resizeBox = DOM.createDiv();
DOM.setElementProperty(resizeBox, "className", CLASSNAME + "-resizebox");
closeBox = DOM.createDiv();
+ maximizeRestoreBox = DOM.createDiv();
+ DOM.setElementProperty(maximizeRestoreBox, "className", CLASSNAME
+ + "-maximizebox");
DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox");
DOM.appendChild(footer, resizeBox);
@@ -269,14 +264,15 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
DOM.setElementProperty(wrapper, "className", CLASSNAME + "-wrap");
DOM.appendChild(wrapper, header);
+ DOM.appendChild(wrapper, maximizeRestoreBox);
DOM.appendChild(wrapper, closeBox);
DOM.appendChild(header, headerText);
DOM.appendChild(wrapper, contents);
DOM.appendChild(wrapper, footer);
DOM.appendChild(super.getContainerElement(), wrapper);
- sinkEvents(Event.MOUSEEVENTS | Event.TOUCHEVENTS | Event.ONCLICK
- | Event.ONLOSECAPTURE);
+ sinkEvents(Event.ONDBLCLICK | Event.MOUSEEVENTS | Event.TOUCHEVENTS
+ | Event.ONCLICK | Event.ONLOSECAPTURE);
setWidget(contentPanel);
@@ -575,6 +571,31 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
}
}
+ public void updateMaximizeRestoreClassName(boolean visible,
+ DisplayState state) {
+ String className;
+ if (state == DisplayState.MAXIMIZED) {
+ className = CLASSNAME + "-restorebox";
+ } else {
+ className = CLASSNAME + "-maximizebox";
+ }
+ if (!visible) {
+ className = className + " " + className + "-disabled";
+ }
+ maximizeRestoreBox.setClassName(className);
+ }
+
+ // TODO this will eventually be removed, currently used to avoid updating to
+ // server side.
+ public void setPopupPositionNoUpdate(int left, int top) {
+ if (top < 0) {
+ // ensure window is not moved out of browser window from top of the
+ // screen
+ top = 0;
+ }
+ super.setPopupPosition(left, top);
+ }
+
@Override
public void setPopupPosition(int left, int top) {
if (top < 0) {
@@ -616,6 +637,8 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
return contents;
}
+ private Event headerDragPending;
+
@Override
public void onBrowserEvent(final Event event) {
boolean bubble = true;
@@ -632,6 +655,28 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
onCloseClick();
}
bubble = false;
+ } else if (target == maximizeRestoreBox) {
+ // handled in connector
+ if (type != Event.ONCLICK) {
+ bubble = false;
+ }
+ } else if (header.isOrHasChild(target) && !dragging) {
+ // dblclick handled in connector
+ if (type != Event.ONDBLCLICK && draggable) {
+ if (type == Event.ONMOUSEDOWN) {
+ headerDragPending = event;
+ } else if (type == Event.ONMOUSEMOVE
+ && headerDragPending != null) {
+ // ie won't work unless this is set here
+ dragging = true;
+ onDragEvent(headerDragPending);
+ onDragEvent(event);
+ headerDragPending = null;
+ } else {
+ headerDragPending = null;
+ }
+ bubble = false;
+ }
} else if (dragging || !contents.isOrHasChild(target)) {
onDragEvent(event);
bubble = false;
@@ -648,7 +693,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
*/
if (type == Event.ONMOUSEDOWN
&& !contentPanel.getElement().isOrHasChild(target)
- && target != closeBox) {
+ && target != closeBox && target != maximizeRestoreBox) {
contentPanel.focus();
}
@@ -746,16 +791,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
}
int w = Util.getTouchOrMouseClientX(event) - startX + origW;
- int minWidth = getMinWidth();
- if (w < minWidth) {
- w = minWidth;
- }
-
int h = Util.getTouchOrMouseClientY(event) - startY + origH;
- int minHeight = getMinHeight();
- if (h < minHeight) {
- h = minHeight;
- }
setWidth(w + "px");
setHeight(h + "px");
@@ -775,7 +811,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
}
}
- private void updateContentsSize() {
+ public void updateContentsSize() {
LayoutManager layoutManager = getLayoutManager();
layoutManager.setNeedsMeasure(ConnectorMap.get(client).getConnector(
this));
@@ -959,10 +995,6 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
contentPanel.focus();
}
- public int getMinHeight() {
- return MIN_CONTENT_AREA_HEIGHT + getDecorationHeight();
- }
-
private int getDecorationHeight() {
LayoutManager lm = getLayoutManager();
int headerHeight = lm.getOuterHeight(header);
@@ -974,10 +1006,6 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
return LayoutManager.get(client);
}
- public int getMinWidth() {
- return MIN_CONTENT_AREA_WIDTH + getDecorationWidth();
- }
-
private int getDecorationWidth() {
LayoutManager layoutManager = getLayoutManager();
return layoutManager.getOuterWidth(getElement())
diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java
index 8cfc25a9dc..66907fbfa4 100644
--- a/client/src/com/vaadin/client/ui/window/WindowConnector.java
+++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java
@@ -20,7 +20,10 @@ import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.user.client.DOM;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.DoubleClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.vaadin.client.ApplicationConnection;
@@ -31,6 +34,7 @@ import com.vaadin.client.LayoutManager;
import com.vaadin.client.Paintable;
import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractSingleComponentContainerConnector;
import com.vaadin.client.ui.ClickEventHandler;
import com.vaadin.client.ui.PostLayoutListener;
@@ -43,6 +47,7 @@ import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.window.WindowServerRpc;
import com.vaadin.shared.ui.window.WindowState;
+import com.vaadin.shared.ui.window.WindowState.DisplayState;
@Connect(value = com.vaadin.ui.Window.class)
public class WindowConnector extends AbstractSingleComponentContainerConnector
@@ -57,7 +62,32 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
}
};
- boolean minWidthChecked = false;
+ abstract class WindowEventHandler implements ClickHandler,
+ DoubleClickHandler {
+ }
+
+ private WindowEventHandler maximizeRestoreClickHandler = new WindowEventHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+ final Element target = event.getNativeEvent().getEventTarget()
+ .cast();
+ if (target == getWidget().maximizeRestoreBox) {
+ // Click on maximize/restore box
+ onMaximizeRestore();
+ }
+ }
+
+ @Override
+ public void onDoubleClick(DoubleClickEvent event) {
+ final Element target = event.getNativeEvent().getEventTarget()
+ .cast();
+ if (getWidget().header.isOrHasChild(target)) {
+ // Double click on header
+ onMaximizeRestore();
+ }
+ }
+ };
@Override
public boolean delegateCaptionHandling() {
@@ -68,12 +98,18 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
protected void init() {
super.init();
+ VWindow window = getWidget();
+
getLayoutManager().registerDependency(this,
- getWidget().contentPanel.getElement());
- getLayoutManager().registerDependency(this, getWidget().header);
- getLayoutManager().registerDependency(this, getWidget().footer);
+ window.contentPanel.getElement());
+ getLayoutManager().registerDependency(this, window.header);
+ getLayoutManager().registerDependency(this, window.footer);
- getWidget().setOwner(getConnection().getUIConnector().getWidget());
+ window.addHandler(maximizeRestoreClickHandler, ClickEvent.getType());
+ window.addHandler(maximizeRestoreClickHandler,
+ DoubleClickEvent.getType());
+
+ window.setOwner(getConnection().getUIConnector().getWidget());
}
@Override
@@ -87,109 +123,46 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
@Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidget().id = getConnectorId();
- getWidget().client = client;
-
- // Workaround needed for Testing Tools (GWT generates window DOM
- // slightly different in different browsers).
- DOM.setElementProperty(getWidget().closeBox, "id", getConnectorId()
- + "_window_close");
- if (isRealUpdate(uidl)) {
- if (getState().modal != getWidget().vaadinModality) {
- getWidget().setVaadinModality(!getWidget().vaadinModality);
- }
- if (!getWidget().isAttached()) {
- getWidget().setVisible(false); // hide until
- // possible centering
- getWidget().show();
- }
- if (getState().resizable != getWidget().resizable) {
- getWidget().setResizable(getState().resizable);
- }
- getWidget().resizeLazy = getState().resizeLazy;
+ VWindow window = getWidget();
+ String connectorId = getConnectorId();
- getWidget().setDraggable(getState().draggable);
+ window.id = getConnectorId();
+ window.client = client;
- // Caption must be set before required header size is measured. If
- // the caption attribute is missing the caption should be cleared.
- String iconURL = null;
- if (getIcon() != null) {
- iconURL = getIcon();
- }
- getWidget().setCaption(getState().caption, iconURL);
- }
+ // Workaround needed for Testing Tools (GWT generates window DOM
+ // slightly different in different browsers).
+ window.closeBox.setId(connectorId + "_window_close");
+ window.maximizeRestoreBox
+ .setId(connectorId + "_window_maximizerestore");
- getWidget().visibilityChangesDisabled = true;
+ window.visibilityChangesDisabled = true;
if (!isRealUpdate(uidl)) {
return;
}
- getWidget().visibilityChangesDisabled = false;
-
- clickEventHandler.handleEventHandlerRegistration();
-
- getWidget().immediate = getState().immediate;
-
- getWidget().setClosable(!isReadOnly());
-
- // Initialize the position form UIDL
- int positionx = getState().positionX;
- int positiony = getState().positionY;
- if (positionx >= 0 || positiony >= 0) {
- if (positionx < 0) {
- positionx = 0;
- }
- if (positiony < 0) {
- positiony = 0;
- }
- getWidget().setPopupPosition(positionx, positiony);
- }
-
- int childIndex = 0;
+ window.visibilityChangesDisabled = false;
// we may have actions
for (int i = 0; i < uidl.getChildCount(); i++) {
UIDL childUidl = uidl.getChildUIDL(i);
if (childUidl.getTag().equals("actions")) {
- if (getWidget().shortcutHandler == null) {
- getWidget().shortcutHandler = new ShortcutActionHandler(
- getConnectorId(), client);
+ if (window.shortcutHandler == null) {
+ window.shortcutHandler = new ShortcutActionHandler(
+ connectorId, client);
}
- getWidget().shortcutHandler.updateActionMap(childUidl);
+ window.shortcutHandler.updateActionMap(childUidl);
}
}
- // setting scrollposition must happen after children is rendered
- getWidget().contentPanel.setScrollPosition(getState().scrollTop);
- getWidget().contentPanel
- .setHorizontalScrollPosition(getState().scrollLeft);
-
- // Center this window on screen if requested
- // This had to be here because we might not know the content size before
- // everything is painted into the window
-
- // centered is this is unset on move/resize
- getWidget().centered = getState().centered;
- getWidget().setVisible(true);
-
- // ensure window is not larger than browser window
- if (getWidget().getOffsetWidth() > Window.getClientWidth()) {
- getWidget().setWidth(Window.getClientWidth() + "px");
- }
- if (getWidget().getOffsetHeight() > Window.getClientHeight()) {
- getWidget().setHeight(Window.getClientHeight() + "px");
- }
-
if (uidl.hasAttribute("bringToFront")) {
/*
* Focus as a side-effect. Will be overridden by
* ApplicationConnection if another component was focused by the
* server side.
*/
- getWidget().contentPanel.focus();
- getWidget().bringToFrontSequence = uidl
- .getIntAttribute("bringToFront");
+ window.contentPanel.focus();
+ window.bringToFrontSequence = uidl.getIntAttribute("bringToFront");
VWindow.deferOrdering();
}
}
@@ -224,26 +197,6 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
boolean hasContent = (content != null);
Element contentElement = window.contentPanel.getElement();
- if (!minWidthChecked) {
- boolean needsMinWidth = !isUndefinedWidth() || !hasContent
- || content.isRelativeWidth();
- int minWidth = window.getMinWidth();
- if (needsMinWidth && lm.getInnerWidth(contentElement) < minWidth) {
- minWidthChecked = true;
- // Use minimum width if less than a certain size
- window.setWidth(minWidth + "px");
- }
- minWidthChecked = true;
- }
-
- boolean needsMinHeight = !isUndefinedHeight() || !hasContent
- || content.isRelativeHeight();
- int minHeight = window.getMinHeight();
- if (needsMinHeight && lm.getInnerHeight(contentElement) < minHeight) {
- // Use minimum height if less than a certain size
- window.setHeight(minHeight + "px");
- }
-
Style contentStyle = window.contents.getStyle();
int headerHeight = lm.getOuterHeight(window.header);
@@ -291,9 +244,9 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
@Override
public void postLayout() {
- minWidthChecked = false;
VWindow window = getWidget();
- if (window.centered) {
+ if (window.centered
+ && getState().displayState != DisplayState.MAXIMIZED) {
window.center();
}
window.positionOrSizeUpdated();
@@ -304,6 +257,124 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
return (WindowState) super.getState();
}
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+
+ VWindow window = getWidget();
+ WindowState state = getState();
+
+ if (state.modal != window.vaadinModality) {
+ window.setVaadinModality(!window.vaadinModality);
+ }
+ if (!window.isAttached()) {
+ window.setVisible(false); // hide until possible centering
+ window.show();
+ }
+ boolean resizeable = state.resizable
+ && state.displayState == DisplayState.NORMAL;
+ window.setResizable(resizeable);
+
+ window.resizeLazy = state.resizeLazy;
+
+ window.setDraggable(state.draggable
+ && state.displayState == DisplayState.NORMAL);
+
+ window.updateMaximizeRestoreClassName(state.resizable,
+ state.displayState);
+
+ // Caption must be set before required header size is measured. If
+ // the caption attribute is missing the caption should be cleared.
+ String iconURL = null;
+ if (getIcon() != null) {
+ iconURL = getIcon();
+ }
+ window.setCaption(state.caption, iconURL);
+
+ clickEventHandler.handleEventHandlerRegistration();
+
+ window.immediate = state.immediate;
+
+ window.setClosable(!isReadOnly());
+ // initialize position from state
+ updateWindowPosition();
+
+ // setting scrollposition must happen after children is rendered
+ window.contentPanel.setScrollPosition(state.scrollTop);
+ window.contentPanel.setHorizontalScrollPosition(state.scrollLeft);
+
+ // Center this window on screen if requested
+ // This had to be here because we might not know the content size before
+ // everything is painted into the window
+
+ // centered is this is unset on move/resize
+ window.centered = state.centered;
+ window.setVisible(true);
+
+ // ensure window is not larger than browser window
+ if (window.getOffsetWidth() > Window.getClientWidth()) {
+ window.setWidth(Window.getClientWidth() + "px");
+ }
+ if (window.getOffsetHeight() > Window.getClientHeight()) {
+ window.setHeight(Window.getClientHeight() + "px");
+ }
+ }
+
+ // Need to override default because of DisplayState
+ @Override
+ protected void updateComponentSize() {
+ if (getState().displayState == DisplayState.NORMAL) {
+ super.updateComponentSize();
+ } else if (getState().displayState == DisplayState.MAXIMIZED) {
+ super.updateComponentSize("100%", "100%");
+ }
+ }
+
+ protected void updateWindowPosition() {
+ VWindow window = getWidget();
+ WindowState state = getState();
+ if (state.displayState == DisplayState.NORMAL) {
+ // if centered, position handled in postLayout()
+ if (!state.centered) {
+ window.setPopupPosition(state.positionX, state.positionY);
+ }
+ } else if (state.displayState == DisplayState.MAXIMIZED) {
+ window.setPopupPositionNoUpdate(0, 0);
+ window.bringToFront();
+ }
+ }
+
+ protected void updateDisplayState() {
+ VWindow window = getWidget();
+ WindowState state = getState();
+
+ // update draggable on widget
+ window.setDraggable(state.draggable
+ && state.displayState == DisplayState.NORMAL);
+ // update resizable on widget
+ window.setResizable(state.resizable
+ && state.displayState == DisplayState.NORMAL);
+ updateComponentSize();
+ updateWindowPosition();
+ window.updateMaximizeRestoreClassName(state.resizable,
+ state.displayState);
+ window.updateContentsSize();
+ }
+
+ protected void onMaximizeRestore() {
+ WindowState state = getState();
+ if (state.resizable) {
+ if (state.displayState == DisplayState.MAXIMIZED) {
+ state.displayState = DisplayState.NORMAL;
+ } else {
+ state.displayState = DisplayState.MAXIMIZED;
+ }
+ updateDisplayState();
+ getRpcProxy(WindowServerRpc.class).windowDisplayStateChanged(
+ state.displayState);
+ }
+ }
+
/**
* Gives the WindowConnector an order number. As a side effect, moves the
* window according to its order number so the windows are stacked. This
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index d8b33e6b25..0c1509663a 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -37,6 +37,8 @@ import com.vaadin.server.PaintTarget;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.window.WindowServerRpc;
import com.vaadin.shared.ui.window.WindowState;
+import com.vaadin.shared.ui.window.WindowState.DisplayState;
+import com.vaadin.util.ReflectTools;
/**
* A component that represents a floating popup window that can be added to a
@@ -71,6 +73,11 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
public void click(MouseEventDetails mouseDetails) {
fireEvent(new ClickEvent(Window.this, mouseDetails));
}
+
+ @Override
+ public void windowDisplayStateChanged(DisplayState newState) {
+ setDisplayState(newState);
+ }
};
/**
@@ -234,10 +241,11 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
/**
* Gets the distance of Window left border in pixels from left border of the
- * containing (main window).
+ * containing (main window) when the window is in
+ * {@link DisplayState#NORMAL}.
*
* @return the Distance of Window left border in pixels from left border of
- * the containing (main window). or -1 if unspecified.
+ * the containing (main window).or -1 if unspecified
* @since 4.0.0
*/
public int getPositionX() {
@@ -246,7 +254,8 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
/**
* Sets the distance of Window left border in pixels from left border of the
- * containing (main window).
+ * containing (main window). Has effect only if in
+ * {@link DisplayState#NORMAL} mode.
*
* @param positionX
* the Distance of Window left border in pixels from left border
@@ -260,10 +269,11 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
/**
* Gets the distance of Window top border in pixels from top border of the
- * containing (main window).
+ * containing (main window) when the window is in
+ * {@link DisplayState#NORMAL} state, or when next set to that state.
*
* @return Distance of Window top border in pixels from top border of the
- * containing (main window). or -1 if unspecified .
+ * containing (main window). or -1 if unspecified
*
* @since 4.0.0
*/
@@ -273,7 +283,8 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
/**
* Sets the distance of Window top border in pixels from top border of the
- * containing (main window).
+ * containing (main window). Has effect only if in
+ * {@link DisplayState#NORMAL} mode.
*
* @param positionY
* the Distance of Window top border in pixels from top border of
@@ -402,6 +413,104 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
/**
+ * Event which is fired when the display state of the Window changes.
+ *
+ * @author Vaadin Ltd
+ * @since 7.1
+ *
+ */
+ public static class DisplayStateChangeEvent extends Component.Event {
+
+ private final DisplayState displayState;
+
+ /**
+ *
+ * @param source
+ */
+ public DisplayStateChangeEvent(Component source,
+ DisplayState displayState) {
+ super(source);
+ this.displayState = displayState;
+ }
+
+ /**
+ * Gets the Window.
+ *
+ * @return the window
+ */
+ public Window getWindow() {
+ return (Window) getSource();
+ }
+
+ /**
+ * Gets the new DisplayState.
+ *
+ * @return the displayState
+ */
+ public DisplayState getDisplayState() {
+ return displayState;
+ }
+ }
+
+ /**
+ * An interface used for listening to Window maximize / restore events. Add
+ * the DisplayStateChangeListener to a window and
+ * {@link DisplayStateChangeListener#displayStateChanged(DisplayStateChangeEvent)}
+ * will be called whenever the window is maximized (
+ * {@link DisplayState#MAXIMIZED}) or restored ({@link DisplayState#NORMAL}
+ * ).
+ */
+ public interface DisplayStateChangeListener extends Serializable {
+
+ public static final Method displayStateChangeMethod = ReflectTools
+ .findMethod(DisplayStateChangeListener.class,
+ "displayStateChanged", DisplayStateChangeEvent.class);
+
+ /**
+ * Called when the user maximizes / restores a window. Use
+ * {@link DisplayStateChangeEvent#getWindow()} to get a reference to the
+ * {@link Window} that was maximized / restored. Use
+ * {@link DisplayStateChangeEvent#getDisplayState()} to get a reference
+ * to the new state.
+ *
+ * @param event
+ */
+ public void displayStateChanged(DisplayStateChangeEvent event);
+ }
+
+ /**
+ * Adds a DisplayStateChangeListener to the window.
+ *
+ * The DisplayStateChangeEvent is fired when the user changed the display
+ * state by clicking the maximize/restore button or by double clicking on
+ * the window header. The event is also fired if the state is changed using
+ * {@link #setDisplayState(DisplayState)}.
+ *
+ * @param listener
+ * the DisplayStateChangeListener to add.
+ */
+ public void addDisplayStateChangeListener(DisplayStateChangeListener listener) {
+ addListener(DisplayStateChangeEvent.class, listener,
+ DisplayStateChangeListener.displayStateChangeMethod);
+ }
+
+ /**
+ * Removes the DisplayStateChangeListener from the window.
+ *
+ * @param listener
+ * the DisplayStateChangeListener to remove.
+ */
+ public void removeDisplayStateChangeListener(DisplayStateChangeListener listener) {
+ removeListener(DisplayStateChangeEvent.class, listener,
+ DisplayStateChangeListener.displayStateChangeMethod);
+ }
+
+ protected void fireWindowDisplayStateChange() {
+ fireEvent(new Window.DisplayStateChangeEvent(this,
+ getState().displayState));
+ }
+
+ /**
* Method for the resize event.
*/
private static final Method WINDOW_RESIZE_METHOD;
@@ -670,6 +779,27 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
getState().draggable = draggable;
}
+ /**
+ * Gets the current DisplayState of the window.
+ *
+ * @return displayState the current DisplayState.
+ */
+ public DisplayState getDisplayState() {
+ return getState(false).displayState;
+ }
+
+ /**
+ * Sets the DisplayState for the window.
+ *
+ * @param displayState
+ */
+ public void setDisplayState(DisplayState displayState) {
+ if (displayState != getDisplayState()) {
+ getState().displayState = displayState;
+ fireWindowDisplayStateChange();
+ }
+ }
+
/*
* Actions
*/
@@ -873,4 +1003,9 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
protected WindowState getState() {
return (WindowState) super.getState();
}
+
+ @Override
+ protected WindowState getState(boolean markAsDirty) {
+ return (WindowState) super.getState(markAsDirty);
+ }
}
diff --git a/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java b/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java
index c42f91c006..0128adca40 100644
--- a/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java
+++ b/shared/src/com/vaadin/shared/ui/window/WindowServerRpc.java
@@ -15,8 +15,14 @@
*/
package com.vaadin.shared.ui.window;
+import com.vaadin.shared.annotations.Delayed;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.ui.ClickRpc;
+import com.vaadin.shared.ui.window.WindowState.DisplayState;
public interface WindowServerRpc extends ClickRpc, ServerRpc {
+
+ @Delayed(lastOnly = true)
+ public void windowDisplayStateChanged(DisplayState newState);
+
} \ No newline at end of file
diff --git a/shared/src/com/vaadin/shared/ui/window/WindowState.java b/shared/src/com/vaadin/shared/ui/window/WindowState.java
index 4afc20f2b1..eb6f1c758a 100644
--- a/shared/src/com/vaadin/shared/ui/window/WindowState.java
+++ b/shared/src/com/vaadin/shared/ui/window/WindowState.java
@@ -21,6 +21,11 @@ public class WindowState extends PanelState {
{
primaryStyleName = "v-window";
}
+
+ public enum DisplayState {
+ NORMAL, MAXIMIZED;
+ }
+
public boolean modal = false;
public boolean resizable = true;
public boolean resizeLazy = false;
@@ -28,4 +33,5 @@ public class WindowState extends PanelState {
public boolean centered = false;;
public int positionX = -1;
public int positionY = -1;
+ public DisplayState displayState = DisplayState.NORMAL;
} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html b/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html
new file mode 100644
index 0000000000..090579d81d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.html
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/run/" />
+<title>WindowMaximizeRestoreTest</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">WindowMaximizeRestoreTest</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.window.WindowMaximizeRestoreTest?restartApplication</td>
+ <td></td>
+</tr>
+<!--Test maximize-restore button-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-maximizebox</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Window 1</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>7,8</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-restorebox</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>9,7</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-maximizebox</td>
+</tr>
+<!--test double click on header-->
+<tr>
+ <td>doubleClickAt</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-restorebox</td>
+</tr>
+<tr>
+ <td>doubleClickAt</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-maximizebox</td>
+</tr>
+<!--Resizable = false should hide max-restore button-->
+<tr>
+ <td>assertVisible</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td>
+ <td>8,3</td>
+</tr>
+<tr>
+ <td>assertNotVisible</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td></td>
+</tr>
+<!--Test server side max-restore-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[0]/VNativeButton[0]</td>
+ <td>34,6</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-restorebox</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[0]/VNativeButton[0]</td>
+ <td>34,6</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-maximizebox</td>
+</tr>
+<!--test double click on header doesn't work-->
+<tr>
+ <td>doubleClickAt</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-maximizebox</td>
+</tr>
+<tr>
+ <td>doubleClickAt</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>v-window-maximizebox</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td>
+ <td>8,3</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[4]/VNativeButton[0]</td>
+ <td>26,9</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--test two windows with screen shot-->
+<tr>
+ <td>screenCapture</td>
+ <td>window-2-original-pos-window-1-centered</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>10,8</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td>window-1-maximized-on-top-of-window-2</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[0]/VNativeButton[0]</td>
+ <td>43,12</td>
+</tr>
+<!--maximize window 2 content-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[1]/FocusableScrollPanel[0]/VVerticalLayout[0]/Slot[3]/VNativeButton[0]</td>
+ <td>100,9</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td>window-2-original-pos-window-1-centered</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[1]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>6,11</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td>window-2-maximized-on-top-of-window-1</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[1]/domChild[0]/domChild[0]/domChild[2]</td>
+ <td>7,5</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td>window-2-closed-window-1-centered</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VFilterSelect[0]/domChild[1]</td>
+ <td>1,17</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>//div[@id='VAADIN_COMBOBOX_OPTIONLIST']/div/div[2]/table/tbody/tr[2]/td</td>
+ <td>122,6</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td>window-2-added-maximized-on-top-of-window-1</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[1]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>6,11</td>
+</tr>
+<tr>
+ <td>doubleClickAt</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowMaximizeRestoreTest::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>113,10</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td>window-1-maximized-with-doubleclick</td>
+ <td></td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.java b/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.java
new file mode 100644
index 0000000000..fe45b036a1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/WindowMaximizeRestoreTest.java
@@ -0,0 +1,165 @@
+package com.vaadin.tests.components.window;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.window.WindowState.DisplayState;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.ComponentContainer;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+import com.vaadin.ui.Window.CloseEvent;
+import com.vaadin.ui.Window.CloseListener;
+import com.vaadin.ui.Window.DisplayStateChangeEvent;
+import com.vaadin.ui.Window.DisplayStateChangeListener;
+
+public class WindowMaximizeRestoreTest extends AbstractTestUI {
+ Button.ClickListener addListener = new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ addWindow(createNewWindow());
+ }
+ };
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Button addButton = new Button("Add new Window");
+ addButton.addListener(addListener);
+ addComponent(addButton);
+
+ addWindowAgain = new ComboBox("Add Window Again");
+ addWindowAgain.setBuffered(false);
+ addWindowAgain.setImmediate(true);
+ addWindowAgain.addValueChangeListener(new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+
+ Object value = event.getProperty().getValue();
+ if (value != null && value instanceof Window) {
+ UI.getCurrent().addWindow((Window) value);
+ addWindowAgain.removeItem(value);
+ }
+ }
+ });
+ addComponent(addWindowAgain);
+
+ addWindow(createNewWindow());
+ }
+
+ private int windowCount = 0;
+ private ComboBox addWindowAgain;
+
+ private Window createNewWindow() {
+ final Window w = new Window("Window " + (++windowCount));
+ final VerticalLayout content = new VerticalLayout();
+ w.setContent(content);
+ w.setData(windowCount);
+ w.setWidth("200px");
+ w.setHeight("300px");
+ w.setPositionX(200);
+ w.setPositionY(200);
+ final NativeButton maximize = new NativeButton("Maximize");
+ Button.ClickListener listener = new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (w.getDisplayState() == DisplayState.MAXIMIZED) {
+ w.setDisplayState(DisplayState.NORMAL);
+ maximize.setCaption("Maximize");
+ } else {
+ w.setDisplayState(DisplayState.MAXIMIZED);
+ maximize.setCaption("Restore");
+ }
+ }
+
+ };
+ maximize.addClickListener(listener);
+ ((ComponentContainer) w.getContent()).addComponent(maximize);
+
+ w.addDisplayStateChangeListener(new DisplayStateChangeListener() {
+
+ @Override
+ public void displayStateChanged(DisplayStateChangeEvent event) {
+ DisplayState state = (event.getWindow().getDisplayState());
+ if (state == DisplayState.NORMAL) {
+ w.setCaption("Window " + w.getData() + " Normal");
+ maximize.setCaption("Maximize");
+ } else if (state == DisplayState.MAXIMIZED) {
+ w.setCaption("Window " + w.getData() + " Maximized");
+ maximize.setCaption("Restore");
+ }
+ }
+ });
+ final CheckBox resizeable = new CheckBox("Resizeable");
+ resizeable.setValue(w.isResizable());
+ resizeable.addValueChangeListener(new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ w.setResizable(resizeable.getValue());
+ }
+ });
+ ((ComponentContainer) w.getContent()).addComponent(resizeable);
+ final CheckBox closeable = new CheckBox("Closeable");
+ closeable.setValue(w.isClosable());
+ closeable.addValueChangeListener(new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ w.setClosable(closeable.getValue());
+ }
+ });
+ ((ComponentContainer) w.getContent()).addComponent(closeable);
+ NativeButton contentFull = new NativeButton("Set Content Size Full",
+ new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ w.getContent().setSizeFull();
+ }
+ });
+ contentFull.setWidth("100%");
+ ((ComponentContainer) w.getContent()).addComponent(contentFull);
+
+ NativeButton center = new NativeButton("Center");
+ center.addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ w.center();
+ }
+ });
+ ((ComponentContainer) w.getContent()).addComponent(center);
+
+ w.addCloseListener(new CloseListener() {
+
+ @Override
+ public void windowClose(CloseEvent e) {
+ Item item = addWindowAgain.addItem(w);
+ addWindowAgain.setItemCaption(w, "Window "
+ + w.getData().toString());
+ }
+ });
+
+ return w;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 3400;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Tests the default maximize & restore funtionality. Max. makes window 100%*100% and pos(0, 0), and restore returns it to the values that are set in windows state.";
+ }
+}