From: Joonas Lehtinen Date: Wed, 3 Sep 2008 16:45:05 +0000 (+0000) Subject: Fixed #2053 : Closing browse-window should trigger submitting changes and fire close... X-Git-Tag: 6.7.0.beta1~4211 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a82b19a13e69c4d948c7def26e70034261411eef;p=vaadin-framework.git Fixed #2053 : Closing browse-window should trigger submitting changes and fire close-event svn changeset:5351/svn branch:trunk --- diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index db7202c43f..0671332b68 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Vector; +import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestBuilder; @@ -28,6 +29,7 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.WindowCloseListener; +import com.google.gwt.user.client.impl.HTTPRequestImpl; import com.google.gwt.user.client.ui.FocusWidget; import com.google.gwt.user.client.ui.HasFocus; import com.google.gwt.user.client.ui.HasWidgets; @@ -131,7 +133,7 @@ public class ApplicationConnection { // TODO remove hard coded id name view = new IView(cnf.getRootPanelId()); - makeUidlRequest("", true); + makeUidlRequest("", true, false); applicationRunning = true; } @@ -236,7 +238,8 @@ public class ApplicationConnection { return (activeRequests > 0); } - private void makeUidlRequest(String requestData, boolean repaintAll) { + private void makeUidlRequest(String requestData, boolean repaintAll, + boolean forceSync) { startRequest(); console.log("Making UIDL Request with params: " + requestData); @@ -244,31 +247,51 @@ public class ApplicationConnection { if (repaintAll) { uri += "?repaintAll=1"; } - final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri); - // rb.setHeader("Content-Type", - // "application/x-www-form-urlencoded; charset=utf-8"); - rb.setHeader("Content-Type", "text/plain;charset=utf-8"); - try { - rb.sendRequest(requestData, new RequestCallback() { - public void onError(Request request, Throwable exception) { - // TODO Better reporting to user - console.error("Got error"); - endRequest(); - } - public void onResponseReceived(Request request, - Response response) { - handleReceivedJSONMessage(response); - } + if (!forceSync) { + final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, + uri); + rb.setHeader("Content-Type", "text/plain;charset=utf-8"); + try { + rb.sendRequest(requestData, new RequestCallback() { + public void onError(Request request, Throwable exception) { + // TODO Better reporting to user + console.error("Got error"); + endRequest(); + } - }); + public void onResponseReceived(Request request, + Response response) { + handleReceivedJSONMessage(response); + } - } catch (final RequestException e) { - ClientExceptionHandler.displayError(e); - endRequest(); + }); + + } catch (final RequestException e) { + ClientExceptionHandler.displayError(e); + endRequest(); + } + } else { + // Synchronized call, discarded response + + syncSendForce(((HTTPRequestImpl) GWT.create(HTTPRequestImpl.class)) + .createXmlHTTPRequest(), uri, requestData); } } + private native void syncSendForce(JavaScriptObject xmlHttpRequest, + String uri, String requestData) + /*-{ + try { + xmlHttpRequest.open("POST", uri, false); + xmlHttpRequest.setRequestHeader("Content-Type", "text/plain;charset=utf-8"); + xmlHttpRequest.send(requestData); + } catch (e) { + // No errors are managed as this is synchronous forceful send that can just fail + } + + }-*/; + private void startRequest() { activeRequests++; showLoadingIndicator(); @@ -304,7 +327,7 @@ public class ApplicationConnection { } Vector nextBurst = (Vector) pendingVariableBursts.firstElement(); pendingVariableBursts.remove(0); - buildAndSendVariableBurst(nextBurst); + buildAndSendVariableBurst(nextBurst, false); } } @@ -537,6 +560,17 @@ public class ApplicationConnection { endRequest(); } + /** + * This method assures that all pending variable changes are sent to server. + * Method uses synchronized xmlhttprequest and does not return before the + * changes are sent. No UIDL updates are processed and thut UI is left in + * inconsistent state. This method should be called only when closing + * windows - normally sendPendingVariableChanges() should be used. + */ + public void sendPendingVariableChangesSync() { + buildAndSendVariableBurst(pendingVariables, true); + } + // Redirect browser, null reloads current page private static native void redirect(String url) /*-{ @@ -624,12 +658,13 @@ public class ApplicationConnection { pendingVariables.clear(); } } else { - buildAndSendVariableBurst(pendingVariables); + buildAndSendVariableBurst(pendingVariables, false); } } } - private void buildAndSendVariableBurst(Vector pendingVariables) { + private void buildAndSendVariableBurst(Vector pendingVariables, + boolean forceSync) { final StringBuffer req = new StringBuffer(); for (int i = 0; i < pendingVariables.size(); i++) { @@ -644,7 +679,7 @@ public class ApplicationConnection { } pendingVariables.clear(); - makeUidlRequest(req.toString(), false); + makeUidlRequest(req.toString(), false, forceSync); } public void updateVariable(String paintableId, String variableName, diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java index 9cc2ff6932..7e83ce0992 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java @@ -40,6 +40,8 @@ public class ITextField extends TextBoxBase implements Paintable, Field, protected ApplicationConnection client; + private String valueBeforeEdit = null; + private boolean immediate = false; private float proportionalHeight = -1; private float proportionalWidth = -1; @@ -86,21 +88,36 @@ public class ITextField extends TextBoxBase implements Paintable, Field, } setText(uidl.getStringVariable("text")); - + valueBeforeEdit = uidl.getStringVariable("text"); } public void onChange(Widget sender) { if (client != null && id != null) { - client.updateVariable(id, "text", getText(), immediate); + String newText = getText(); + if (newText != null && !newText.equals(valueBeforeEdit)) { + client.updateVariable(id, "text", getText(), immediate); + valueBeforeEdit = newText; + } + } + } + + private static ITextField focusedTextField; + + public static void flushChangesFromFocusedTextField() { + if (focusedTextField != null) { + focusedTextField.onChange(null); } } public void onFocus(Widget sender) { addStyleDependentName(CLASSNAME_FOCUS); + focusedTextField = this; } public void onLostFocus(Widget sender) { removeStyleDependentName(CLASSNAME_FOCUS); + focusedTextField = null; + onChange(sender); } public void setColumns(int columns) { diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java index ceabc59949..f878a9bacb 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java @@ -12,6 +12,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.WindowCloseListener; import com.google.gwt.user.client.WindowResizeListener; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; @@ -26,7 +27,7 @@ import com.itmill.toolkit.terminal.gwt.client.Util; * */ public class IView extends SimplePanel implements Paintable, - WindowResizeListener { + WindowResizeListener, WindowCloseListener { private static final String CLASSNAME = "i-view"; @@ -46,6 +47,8 @@ public class IView extends SimplePanel implements Paintable, /** stored height for IE resize optimization */ private int height; + private ApplicationConnection connection; + /** * We are postponing resize process with IE. IE bugs with scrollbars in some * situations, that causes false onWindowResized calls. With Timer we will @@ -65,6 +68,7 @@ public class IView extends SimplePanel implements Paintable, RootPanel.get(elementId).add(this); Window.addWindowResizeListener(this); + Window.addWindowCloseListener(this); // set focus to iview element by default to listen possible keyboard // shortcuts @@ -112,6 +116,7 @@ public class IView extends SimplePanel implements Paintable, public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { id = uidl.getId(); + connection = client; String newTheme = uidl.getStringAttribute("theme"); if (theme != null && !newTheme.equals(theme)) { @@ -301,4 +306,22 @@ public class IView extends SimplePanel implements Paintable, $wnd.location = url; }-*/; + public void onWindowClosed() { + // Change focus on this window in order to ensure that all state is + // collected from textfields + ITextField.flushChangesFromFocusedTextField(); + + // Send the closing state to server + connection.updateVariable(id, "close", true, false); + connection.sendPendingVariableChangesSync(); + } + + private static native void focusElement(Element e) /*-{ + e.focus(); + }-*/; + + public String onWindowClosing() { + return null; + } + } diff --git a/src/com/itmill/toolkit/ui/Window.java b/src/com/itmill/toolkit/ui/Window.java index b9ecf8b255..e8201d4fdf 100644 --- a/src/com/itmill/toolkit/ui/Window.java +++ b/src/com/itmill/toolkit/ui/Window.java @@ -843,9 +843,14 @@ public class Window extends Panel implements URIHandler, ParameterHandler { /** * Method that handles window closing (from UI). If one wants to have window * that cannot be closed (with server side check), override this with and - * empty method. + * empty method. Main window of the application can not be closed (on the + * server-side). */ protected void close() { + if (getApplication() != null + && getApplication().getMainWindow() == this) { + return; + } Window parent = (Window) getParent(); if (parent == null) { setVisible(false);