aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2013-02-21 17:04:48 +0200
committerVaadin Code Review <review@vaadin.com>2013-04-04 12:52:55 +0000
commitd937722318c47831775d2f0e6c67b0f0f1d57688 (patch)
tree92d643f4faa5a13dd86ac175d31e2484ef36cf7a /client
parent69def694d5d98f518ad08c039195fd2ac8781d2f (diff)
downloadvaadin-framework-d937722318c47831775d2f0e6c67b0f0f1d57688.tar.gz
vaadin-framework-d937722318c47831775d2f0e6c67b0f0f1d57688.zip
Maximize Restore for Window #3400
Change-Id: I164ae83bd6cf98f7a3d7e76d8e717a56e8cb5183
Diffstat (limited to 'client')
-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
3 files changed, 247 insertions, 146 deletions
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