]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fixed #2053 : Closing browse-window should trigger submitting changes and fire close...
authorJoonas Lehtinen <joonas.lehtinen@itmill.com>
Wed, 3 Sep 2008 16:45:05 +0000 (16:45 +0000)
committerJoonas Lehtinen <joonas.lehtinen@itmill.com>
Wed, 3 Sep 2008 16:45:05 +0000 (16:45 +0000)
svn changeset:5351/svn branch:trunk

src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
src/com/itmill/toolkit/terminal/gwt/client/ui/ITextField.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IView.java
src/com/itmill/toolkit/ui/Window.java

index db7202c43f880b2e4dd04ab2038e9c09eed9c83d..0671332b680af37180af601bb2da167378236537 100755 (executable)
@@ -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,
index 9cc2ff6932c4aadd84c90badd01f009890d9775c..7e83ce09922f99050249b3cffde82b80ab12b5da 100644 (file)
@@ -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) {
index ceabc599490f12ed6bcb6b3a3e7a1310be24ae15..f878a9bacbdacf230f5a938ed59674db1309eb3b 100644 (file)
@@ -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;
+    }
+
 }
index b9ecf8b255b2188f843859522ef60be0f602fbe0..e8201d4fdf451539af6c1cbadc7c55fe14450ad7 100644 (file)
@@ -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);