diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-06-11 21:52:26 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-06-11 21:52:26 +0300 |
commit | 9b757f047fc8450d8a7d3d7aa5a7b7e43bfa1312 (patch) | |
tree | e3814cb6b78cb90570f2b9c31978728e44c7ec33 /src/com | |
parent | 24e3409e6ff117ff954f36a9c9378690c76634f8 (diff) | |
download | vaadin-framework-9b757f047fc8450d8a7d3d7aa5a7b7e43bfa1312.tar.gz vaadin-framework-9b757f047fc8450d8a7d3d7aa5a7b7e43bfa1312.zip |
Initial javascript callback support (#6730)
Diffstat (limited to 'src/com')
6 files changed, 181 insertions, 0 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java new file mode 100644 index 0000000000..979a6d22c4 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerConnector.java @@ -0,0 +1,78 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.extensions.javascriptmanager; + +import java.util.HashSet; +import java.util.Set; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArray; +import com.google.gwt.json.client.JSONArray; +import com.vaadin.terminal.gwt.client.communication.MethodInvocation; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.ui.AbstractConnector; +import com.vaadin.terminal.gwt.client.ui.Connect; +import com.vaadin.ui.JavascriptManager; + +@Connect(JavascriptManager.class) +public class JavascriptManagerConnector extends AbstractConnector { + private Set<String> currentNames = new HashSet<String>(); + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + super.onStateChanged(stateChangeEvent); + + Set<String> newNames = getState().getNames(); + + // Current names now only contains orphan callbacks + currentNames.removeAll(newNames); + + for (String name : currentNames) { + removeCallback(name); + } + + currentNames = new HashSet<String>(newNames); + for (String name : newNames) { + addCallback(name); + } + } + + // TODO Ensure we don't overwrite anything (important) in $wnd + private native void addCallback(String name) + /*-{ + var m = this; + $wnd[name] = $entry(function() { + //Must make a copy because arguments is an array-like object (not instanceof Array), causing suboptimal JSON encoding + var args = Array.prototype.slice.call(arguments, 0); + m.@com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavascriptManagerConnector::sendRpc(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(name, args); + }); + }-*/; + + // TODO only remove what we actually added + private native void removeCallback(String name) + /*-{ + delete $wnd[name]; + }-*/; + + public void sendRpc(String name, JsArray<JavaScriptObject> arguments) { + Object[] parameters = new Object[] { name, new JSONArray(arguments) }; + + /* + * Must invoke manually as the RPC interface can't be used in GWT + * because of the JSONArray parameter + */ + getConnection() + .addMethodInvocationToQueue( + new MethodInvocation( + getConnectorId(), + "com.vaadin.ui.JavascriptManager$JavascriptCallbackRpc", + "call", parameters), true); + } + + @Override + public JavascriptManagerState getState() { + return (JavascriptManagerState) super.getState(); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerState.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerState.java new file mode 100644 index 0000000000..77794ffdca --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavascriptManagerState.java @@ -0,0 +1,22 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.extensions.javascriptmanager; + +import java.util.HashSet; +import java.util.Set; + +import com.vaadin.terminal.gwt.client.communication.SharedState; + +public class JavascriptManagerState extends SharedState { + private Set<String> names = new HashSet<String>(); + + public Set<String> getNames() { + return names; + } + + public void setNames(Set<String> names) { + this.names = names; + } +} diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index fb2d289484..b693514a66 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -123,6 +123,9 @@ public class JsonCodec implements Serializable { // Try to decode object using fields if (value == JSONObject.NULL) { return null; + } else if (targetType == JSONObject.class + || targetType == JSONArray.class) { + return value; } else { return decodeObject(targetType, (JSONObject) value, application); } diff --git a/src/com/vaadin/ui/JavascriptCallback.java b/src/com/vaadin/ui/JavascriptCallback.java new file mode 100644 index 0000000000..4a34167256 --- /dev/null +++ b/src/com/vaadin/ui/JavascriptCallback.java @@ -0,0 +1,13 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import java.io.Serializable; + +import com.vaadin.external.json.JSONArray; + +public interface JavascriptCallback extends Serializable { + public void call(JSONArray arguments); +} diff --git a/src/com/vaadin/ui/JavascriptManager.java b/src/com/vaadin/ui/JavascriptManager.java new file mode 100644 index 0000000000..e52962f177 --- /dev/null +++ b/src/com/vaadin/ui/JavascriptManager.java @@ -0,0 +1,53 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.ui; + +import java.util.HashMap; +import java.util.Map; + +import com.vaadin.external.json.JSONArray; +import com.vaadin.terminal.AbstractExtension; +import com.vaadin.terminal.gwt.client.communication.ServerRpc; +import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavascriptManagerState; + +public class JavascriptManager extends AbstractExtension { + private Map<String, JavascriptCallback> callbacks = new HashMap<String, JavascriptCallback>(); + + // Can not be defined in client package as this JSONArray is not available + // in GWT + public interface JavascriptCallbackRpc extends ServerRpc { + public void call(String name, JSONArray arguments); + } + + public JavascriptManager() { + registerRpc(new JavascriptCallbackRpc() { + public void call(String name, JSONArray arguments) { + JavascriptCallback callback = callbacks.get(name); + // TODO error handling + callback.call(arguments); + } + }); + } + + @Override + public JavascriptManagerState getState() { + return (JavascriptManagerState) super.getState(); + } + + public void addCallback(String name, JavascriptCallback javascriptCallback) { + callbacks.put(name, javascriptCallback); + if (getState().getNames().add(name)) { + requestRepaint(); + } + } + + public void removeCallback(String name) { + callbacks.remove(name); + if (getState().getNames().remove(name)) { + requestRepaint(); + } + } + +} diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java index 8792bf1912..9814084cbc 100644 --- a/src/com/vaadin/ui/Root.java +++ b/src/com/vaadin/ui/Root.java @@ -408,6 +408,8 @@ public abstract class Root extends AbstractComponentContainer implements private DirtyConnectorTracker dirtyConnectorTracker = new DirtyConnectorTracker( this); + private JavascriptManager javascriptManager; + private RootServerRpc rpc = new RootServerRpc() { public void click(MouseEventDetails mouseDetails) { fireEvent(new ClickEvent(Root.this, mouseDetails)); @@ -1590,4 +1592,14 @@ public abstract class Root extends AbstractComponentContainer implements return dirtyConnectorTracker; } + public JavascriptManager getJavascriptManager() { + if (javascriptManager == null) { + // Create and attach on first use + javascriptManager = new JavascriptManager(); + addExtension(javascriptManager); + } + + return javascriptManager; + } + } |