]> source.dussan.org Git - vaadin-framework.git/commitdiff
#8510 Support using Resources through URLReference/ResourceReference in
authorArtur Signell <artur@vaadin.com>
Fri, 9 Mar 2012 09:47:09 +0000 (11:47 +0200)
committerArtur Signell <artur@vaadin.com>
Tue, 13 Mar 2012 16:10:40 +0000 (18:10 +0200)
shared state and RPC calls

30 files changed:
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/ComponentState.java
src/com/vaadin/terminal/gwt/client/VCaption.java
src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java
src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java
src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java
src/com/vaadin/terminal/gwt/client/communication/ResourceReference.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/communication/URLReference.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
src/com/vaadin/terminal/gwt/client/ui/ButtonConnector.java
src/com/vaadin/terminal/gwt/client/ui/CheckBoxConnector.java
src/com/vaadin/terminal/gwt/client/ui/FormConnector.java
src/com/vaadin/terminal/gwt/client/ui/LinkConnector.java
src/com/vaadin/terminal/gwt/client/ui/NativeButtonConnector.java
src/com/vaadin/terminal/gwt/client/ui/PanelConnector.java
src/com/vaadin/terminal/gwt/client/ui/TabsheetBaseConnector.java
src/com/vaadin/terminal/gwt/client/ui/TreeConnector.java
src/com/vaadin/terminal/gwt/client/ui/VAccordion.java
src/com/vaadin/terminal/gwt/client/ui/VFormLayout.java
src/com/vaadin/terminal/gwt/client/ui/VMenuBar.java
src/com/vaadin/terminal/gwt/client/ui/VNotification.java
src/com/vaadin/terminal/gwt/client/ui/VPanel.java
src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
src/com/vaadin/terminal/gwt/client/ui/WindowConnector.java
src/com/vaadin/terminal/gwt/server/JsonCodec.java
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java
src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java
src/com/vaadin/ui/AbstractComponent.java
src/com/vaadin/ui/TabSheet.java

index 8ac2f1f7b11192d80310a6d2d817ef95f83cb088..c889a65ce53555c6a9063daf26ea5047f813fe1f 100644 (file)
@@ -1197,7 +1197,8 @@ public class ApplicationConnection {
                                     states.getJavaScriptObject(connectorId));
 
                             Object state = JsonDecoder.convertValue(
-                                    stateDataAndType, connectorMap);
+                                    stateDataAndType, connectorMap,
+                                    ApplicationConnection.this);
 
                             paintable.setState((SharedState) state);
                         }
@@ -1317,7 +1318,7 @@ public class ApplicationConnection {
         Object[] parameters = new Object[parametersJson.size()];
         for (int j = 0; j < parametersJson.size(); ++j) {
             parameters[j] = JsonDecoder.convertValue(
-                    (JSONArray) parametersJson.get(j), getConnectorMap());
+                    (JSONArray) parametersJson.get(j), getConnectorMap(), this);
         }
         return new MethodInvocation(connectorId, interfaceName, methodName,
                 parameters);
@@ -1438,7 +1439,8 @@ public class ApplicationConnection {
                 for (int i = 0; i < invocation.getParameters().length; ++i) {
                     // TODO non-static encoder? type registration?
                     paramJson.set(i, JsonEncoder.encode(
-                            invocation.getParameters()[i], getConnectorMap()));
+                            invocation.getParameters()[i], getConnectorMap(),
+                            this));
                 }
                 invocationJson.set(3, paramJson);
                 reqJson.set(reqJson.size(), invocationJson);
index e42afd6d03217dab0f0280aafd0d6cc9a635f5e7..9a72f7cd80e91bbb1af8222997168e16872e0f51 100644 (file)
@@ -5,6 +5,7 @@
 package com.vaadin.terminal.gwt.client;
 
 import com.vaadin.terminal.gwt.client.communication.SharedState;
+import com.vaadin.terminal.gwt.client.communication.URLReference;
 import com.vaadin.ui.Component;
 
 /**
@@ -26,6 +27,7 @@ public class ComponentState extends SharedState {
     // string!
     private String caption = null;
     private boolean visible = true;
+    private URLReference icon = null;
 
     /**
      * Returns the component height as set by the server.
@@ -288,4 +290,12 @@ public class ComponentState extends SharedState {
         this.visible = visible;
     }
 
+    public URLReference getIcon() {
+        return icon;
+    }
+
+    public void setIcon(URLReference icon) {
+        this.icon = icon;
+    }
+
 }
index b7d66612a9e0a79e21cb111cd107f83cb2b9553c..e639da950288a26ba2b21fb76491a17a58355205 100644 (file)
@@ -118,8 +118,7 @@ public class VCaption extends HTML {
         }
         setStyleName(style);
 
-        boolean hasIcon = uidl
-                .hasAttribute(AbstractComponentConnector.ATTRIBUTE_ICON);
+        boolean hasIcon = owner.getState().getIcon() != null;
         boolean showRequired = uidl
                 .getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_REQUIRED);
         boolean showError = uidl
@@ -138,8 +137,7 @@ public class VCaption extends HTML {
             // Icon forces the caption to be above the component
             placedAfterComponent = false;
 
-            icon.setUri(uidl
-                    .getStringAttribute(AbstractComponentConnector.ATTRIBUTE_ICON));
+            icon.setUri(owner.getState().getIcon().getURL());
 
         } else if (icon != null) {
             // Remove existing
@@ -257,7 +255,7 @@ public class VCaption extends HTML {
 
     @Deprecated
     public boolean updateCaptionWithoutOwner(UIDL uidl, String caption,
-            boolean disabled, boolean hasDescription) {
+            boolean disabled, boolean hasDescription, String iconURL) {
         // TODO temporary method, needed because some tabsheet and accordion
         // internal captions do not have an owner or shared state. Simplified to
         // only support those cases
@@ -281,8 +279,7 @@ public class VCaption extends HTML {
                 removeStyleDependentName("hasdescription");
             }
         }
-        boolean hasIcon = uidl
-                .hasAttribute(AbstractComponentConnector.ATTRIBUTE_ICON);
+        boolean hasIcon = iconURL != null;
         boolean showError = uidl
                 .hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)
                 && !uidl.getBooleanAttribute(AbstractComponentConnector.ATTRIBUTE_HIDEERRORS);
@@ -299,8 +296,7 @@ public class VCaption extends HTML {
             // Icon forces the caption to be above the component
             placedAfterComponent = false;
 
-            icon.setUri(uidl
-                    .getStringAttribute(AbstractComponentConnector.ATTRIBUTE_ICON));
+            icon.setUri(iconURL);
 
         } else if (icon != null) {
             // Remove existing
@@ -412,7 +408,7 @@ public class VCaption extends HTML {
         if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ERROR)) {
             return true;
         }
-        if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ICON)) {
+        if (state.getIcon() != null) {
             return true;
         }
         if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_REQUIRED)) {
index ee03323618515585d6b8e7830c333f35186afcff..c626d31d0ac2701e31e130da532f80a71911baa4 100644 (file)
@@ -5,6 +5,7 @@
 package com.vaadin.terminal.gwt.client.communication;
 
 import com.google.gwt.json.client.JSONObject;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.ConnectorMap;
 import com.vaadin.terminal.gwt.server.JsonCodec;
 
@@ -21,7 +22,7 @@ import com.vaadin.terminal.gwt.server.JsonCodec;
  * 
  * @since 7.0
  */
-public interface JSONSerializer {
+public interface JSONSerializer<T> {
 
     /**
      * Creates and deserializes an object received from the server. Must be
@@ -37,7 +38,8 @@ public interface JSONSerializer {
      *            references to paintables
      * @return A deserialized object
      */
-    Object deserialize(JSONObject jsonValue, ConnectorMap idMapper);
+    T deserialize(JSONObject jsonValue, ConnectorMap idMapper,
+            ApplicationConnection connection);
 
     /**
      * Serialize the given object into JSON. Must be compatible with
@@ -52,6 +54,7 @@ public interface JSONSerializer {
      *            references to paintables
      * @return A JSON serialized version of the object
      */
-    JSONObject serialize(Object value, ConnectorMap idMapper);
+    JSONObject serialize(T value, ConnectorMap idMapper,
+            ApplicationConnection connection);
 
 }
index 444faa62767eb2dd58b030276ffce7463a7c44b9..2250bbbb8dc4a464fec3f3e4d022ba9120ee8d50 100644 (file)
@@ -14,6 +14,7 @@ import com.google.gwt.core.client.GWT;
 import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONString;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.Connector;
 import com.vaadin.terminal.gwt.client.ConnectorMap;
 
@@ -39,23 +40,26 @@ public class JsonDecoder {
      *            JSON array with two elements
      * @param idMapper
      *            mapper between connector ID and {@link Connector} objects
+     * @param connection
+     *            reference to the current ApplicationConnection
      * @return converted value (does not contain JSON types)
      */
-    public static Object convertValue(JSONArray jsonArray, ConnectorMap idMapper) {
+    public static Object convertValue(JSONArray jsonArray,
+            ConnectorMap idMapper, ApplicationConnection connection) {
         String type = ((JSONString) jsonArray.get(0)).stringValue();
-        return convertValue(type, jsonArray.get(1), idMapper);
+        return convertValue(type, jsonArray.get(1), idMapper, connection);
     }
 
     private static Object convertValue(String variableType, Object value,
-            ConnectorMap idMapper) {
+            ConnectorMap idMapper, ApplicationConnection connection) {
         Object val = null;
         // TODO type checks etc.
         if (JsonEncoder.VTYPE_UNDEFINED.equals(variableType)) {
             val = null;
         } else if (JsonEncoder.VTYPE_ARRAY.equals(variableType)) {
-            val = convertArray((JSONArray) value, idMapper);
+            val = convertArray((JSONArray) value, idMapper, connection);
         } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) {
-            val = convertMap((JSONObject) value, idMapper);
+            val = convertMap((JSONObject) value, idMapper, connection);
         } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) {
             val = convertStringArray((JSONArray) value);
         } else if (JsonEncoder.VTYPE_STRING.equals(variableType)) {
@@ -83,8 +87,8 @@ public class JsonDecoder {
             JSONSerializer serializer = serializerMap
                     .getSerializer(variableType);
             // TODO handle case with no serializer found
-            Object object = serializer
-                    .deserialize((JSONObject) value, idMapper);
+            Object object = serializer.deserialize((JSONObject) value,
+                    idMapper, connection);
             return object;
         }
 
@@ -92,12 +96,14 @@ public class JsonDecoder {
     }
 
     private static Map<String, Object> convertMap(JSONObject jsonMap,
-            ConnectorMap idMapper) {
+            ConnectorMap idMapper, ApplicationConnection connection) {
         HashMap<String, Object> map = new HashMap<String, Object>();
         Iterator<String> it = jsonMap.keySet().iterator();
         while (it.hasNext()) {
             String key = it.next();
-            map.put(key, convertValue((JSONArray) jsonMap.get(key), idMapper));
+            map.put(key,
+                    convertValue((JSONArray) jsonMap.get(key), idMapper,
+                            connection));
         }
         return map;
     }
@@ -112,12 +118,12 @@ public class JsonDecoder {
     }
 
     private static Object[] convertArray(JSONArray jsonArray,
-            ConnectorMap idMapper) {
+            ConnectorMap idMapper, ApplicationConnection connection) {
         List<Object> tokens = new ArrayList<Object>();
         for (int i = 0; i < jsonArray.size(); ++i) {
             // each entry always has two elements: type and value
             JSONArray entryArray = (JSONArray) jsonArray.get(i);
-            tokens.add(convertValue(entryArray, idMapper));
+            tokens.add(convertValue(entryArray, idMapper, connection));
         }
         return tokens.toArray(new Object[tokens.size()]);
     }
index faa701f2db5bcadb1b208ddca7ebab4e8b3a1bed..c7d49875d7f82128497add9a1da3892673106c78 100644 (file)
@@ -12,6 +12,7 @@ import com.google.gwt.json.client.JSONNull;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONString;
 import com.google.gwt.json.client.JSONValue;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.Connector;
 import com.vaadin.terminal.gwt.client.ConnectorMap;
 
@@ -52,9 +53,11 @@ public class JsonEncoder {
      *            value to convert
      * @param connectorMap
      *            mapper from connectors to connector IDs
+     * @param connection
      * @return JSON representation of the value
      */
-    public static JSONValue encode(Object value, ConnectorMap connectorMap) {
+    public static JSONValue encode(Object value, ConnectorMap connectorMap,
+            ApplicationConnection connection) {
         if (null == value) {
             // TODO as undefined type?
             return combineTypeAndValue(VTYPE_UNDEFINED, JSONNull.getInstance());
@@ -76,7 +79,7 @@ public class JsonEncoder {
             JSONArray jsonArray = new JSONArray();
             for (int i = 0; i < array.length; ++i) {
                 // TODO handle object graph loops?
-                jsonArray.set(i, encode(array[i], connectorMap));
+                jsonArray.set(i, encode(array[i], connectorMap, connection));
             }
             return combineTypeAndValue(VTYPE_ARRAY, jsonArray);
         } else if (value instanceof Map) {
@@ -85,7 +88,7 @@ public class JsonEncoder {
             for (String mapKey : map.keySet()) {
                 // TODO handle object graph loops?
                 Object mapValue = map.get(mapKey);
-                jsonMap.put(mapKey, encode(mapValue, connectorMap));
+                jsonMap.put(mapKey, encode(mapValue, connectorMap, connection));
             }
             return combineTypeAndValue(VTYPE_MAP, jsonMap);
         } else if (value instanceof Connector) {
@@ -105,7 +108,7 @@ public class JsonEncoder {
 
                 // TODO handle case with no serializer found
                 return combineTypeAndValue(type,
-                        serializer.serialize(value, connectorMap));
+                        serializer.serialize(value, connectorMap, connection));
             }
         }
     }
diff --git a/src/com/vaadin/terminal/gwt/client/communication/ResourceReference.java b/src/com/vaadin/terminal/gwt/client/communication/ResourceReference.java
new file mode 100644 (file)
index 0000000..1bfde31
--- /dev/null
@@ -0,0 +1,47 @@
+package com.vaadin.terminal.gwt.client.communication;
+
+import com.vaadin.Application;
+import com.vaadin.terminal.ApplicationResource;
+import com.vaadin.terminal.ExternalResource;
+import com.vaadin.terminal.Resource;
+import com.vaadin.terminal.ThemeResource;
+
+public class ResourceReference extends URLReference {
+
+    private Resource resource;
+
+    public ResourceReference(Resource resource) {
+        this.resource = resource;
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+
+    @Override
+    public String getURL() {
+        if (resource instanceof ExternalResource) {
+            return ((ExternalResource) resource).getURL();
+        } else if (resource instanceof ApplicationResource) {
+            final ApplicationResource r = (ApplicationResource) resource;
+            final Application a = r.getApplication();
+            if (a == null) {
+                throw new RuntimeException(
+                        "An ApplicationResource ("
+                                + r.getClass().getName()
+                                + " must be attached to an application when it is sent to the client.");
+            }
+            final String uri = a.getRelativeLocation(r);
+            return uri;
+        } else if (resource instanceof ThemeResource) {
+            final String uri = "theme://"
+                    + ((ThemeResource) resource).getResourceId();
+            return uri;
+        } else {
+            throw new RuntimeException(getClass().getSimpleName()
+                    + " does not support resources of type: "
+                    + resource.getClass().getName());
+        }
+
+    }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference.java
new file mode 100644 (file)
index 0000000..eb88094
--- /dev/null
@@ -0,0 +1,26 @@
+package com.vaadin.terminal.gwt.client.communication;
+
+public class URLReference {
+
+    private String URL;
+
+    /**
+     * Returns the URL that this object refers to.
+     * <p>
+     * Note that the URL can use special protocols like theme://
+     * 
+     * @return The URL for this reference or null if unknown.
+     */
+    public String getURL() {
+        return URL;
+    }
+
+    /**
+     * Sets the URL that this object refers to
+     * 
+     * @param URL
+     */
+    public void setURL(String URL) {
+        this.URL = URL;
+    }
+}
\ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java
new file mode 100644 (file)
index 0000000..24053d2
--- /dev/null
@@ -0,0 +1,29 @@
+package com.vaadin.terminal.gwt.client.communication;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONObject;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
+
+public class URLReference_Serializer implements JSONSerializer<URLReference> {
+
+    public URLReference deserialize(JSONObject jsonValue,
+            ConnectorMap idMapper, ApplicationConnection connection) {
+        URLReference reference = GWT.create(URLReference.class);
+        JSONArray jsonURL = (JSONArray) jsonValue.get("URL");
+        String URL = (String) JsonDecoder.convertValue(jsonURL, idMapper,
+                connection);
+        reference.setURL(connection.translateVaadinUri(URL));
+        return reference;
+    }
+
+    public JSONObject serialize(URLReference value, ConnectorMap idMapper,
+            ApplicationConnection connection) {
+        JSONObject json = new JSONObject();
+        json.put("URL",
+                JsonEncoder.encode(value.getURL(), idMapper, connection));
+        return json;
+    }
+
+}
index f2d4f082d1a0332c71b3d8826ecfdec5149d383c..24baa22940b0f5a6153ef2828d7450eada0e37d4 100644 (file)
@@ -33,7 +33,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector
     // constants, which may refer to these.
     // Not all references to the string literals have been converted to use
     // these!
-    public static final String ATTRIBUTE_ICON = "icon";
     public static final String ATTRIBUTE_REQUIRED = "required";
     public static final String ATTRIBUTE_ERROR = "error";
     public static final String ATTRIBUTE_HIDEERRORS = "hideErrors";
index c9e69235b1039ed1fb11e623e2d7848a1b29ac62..903047171a9d8129046dbb1a71ea90a322367840 100644 (file)
@@ -88,13 +88,13 @@ public class ButtonConnector extends AbstractComponentConnector {
             getWidget().errorIndicatorElement = null;
         }
 
-        if (uidl.hasAttribute(ATTRIBUTE_ICON)) {
+        if (getState().getIcon() != null) {
             if (getWidget().icon == null) {
                 getWidget().icon = new Icon(client);
                 getWidget().wrapper.insertBefore(getWidget().icon.getElement(),
                         getWidget().captionElement);
             }
-            getWidget().icon.setUri(uidl.getStringAttribute(ATTRIBUTE_ICON));
+            getWidget().icon.setUri(getState().getIcon().getURL());
         } else {
             if (getWidget().icon != null) {
                 getWidget().wrapper.removeChild(getWidget().icon.getElement());
index f198fdc00faa8f369d789409efb425e4582aa0a2..e59777ef31f6143dc212712f8104ead0de7fb992 100644 (file)
@@ -59,7 +59,7 @@ public class CheckBoxConnector extends AbstractComponentConnector {
             getWidget().setEnabled(false);
         }
 
-        if (uidl.hasAttribute(ATTRIBUTE_ICON)) {
+        if (getState().getIcon() != null) {
             if (getWidget().icon == null) {
                 getWidget().icon = new Icon(client);
                 DOM.insertChild(getWidget().getElement(),
@@ -67,7 +67,7 @@ public class CheckBoxConnector extends AbstractComponentConnector {
                 getWidget().icon.sinkEvents(VTooltip.TOOLTIP_EVENTS);
                 getWidget().icon.sinkEvents(Event.ONCLICK);
             }
-            getWidget().icon.setUri(uidl.getStringAttribute(ATTRIBUTE_ICON));
+            getWidget().icon.setUri(getState().getIcon().getURL());
         } else if (getWidget().icon != null) {
             // detach icon
             DOM.removeChild(getWidget().getElement(),
index 2e3478122847698dc993f67e3f1517229124099a..9ff7a38ccf0643202ace6c72ad0a03069f1dc89b 100644 (file)
@@ -43,12 +43,12 @@ public class FormConnector extends AbstractComponentContainerConnector
         } else {
             getWidget().caption.setInnerText("");
         }
-        if (uidl.hasAttribute(ATTRIBUTE_ICON)) {
+        if (getState().getIcon() != null) {
             if (getWidget().icon == null) {
                 getWidget().icon = new Icon(client);
                 getWidget().legend.insertFirst(getWidget().icon.getElement());
             }
-            getWidget().icon.setUri(uidl.getStringAttribute(ATTRIBUTE_ICON));
+            getWidget().icon.setUri(getState().getIcon().getURL());
             legendEmpty = false;
         } else {
             if (getWidget().icon != null) {
index a8c10650c146330a10040611e14fd30f3ae7cdf5..7d6e7e04ce5adf091a8295bef0f3340c34ad1cf0 100644 (file)
@@ -74,13 +74,13 @@ public class LinkConnector extends AbstractComponentConnector {
                     "none");
         }
 
-        if (uidl.hasAttribute(ATTRIBUTE_ICON)) {
+        if (getState().getIcon() != null) {
             if (getWidget().icon == null) {
                 getWidget().icon = new Icon(client);
                 getWidget().anchor.insertBefore(getWidget().icon.getElement(),
                         getWidget().captionElement);
             }
-            getWidget().icon.setUri(uidl.getStringAttribute(ATTRIBUTE_ICON));
+            getWidget().icon.setUri(getState().getIcon().getURL());
         }
 
     }
index 20737fc70b095ad3f7debd2415175372557105ff..135fb4f676578c435693958ccd05d88ff2f8773c 100644 (file)
@@ -18,8 +18,7 @@ public class NativeButtonConnector extends AbstractComponentConnector {
     public void init() {
         super.init();
 
-        ButtonServerRpc rpcProxy = GWT
-                .create(ButtonServerRpc.class);
+        ButtonServerRpc rpcProxy = GWT.create(ButtonServerRpc.class);
         getWidget().buttonRpcProxy = initRPC(rpcProxy);
     }
 
@@ -68,14 +67,14 @@ public class NativeButtonConnector extends AbstractComponentConnector {
             getWidget().errorIndicatorElement = null;
         }
 
-        if (uidl.hasAttribute(ATTRIBUTE_ICON)) {
+        if (getState().getIcon() != null) {
             if (getWidget().icon == null) {
                 getWidget().icon = new Icon(client);
                 getWidget().getElement().insertBefore(
                         getWidget().icon.getElement(),
                         getWidget().captionElement);
             }
-            getWidget().icon.setUri(uidl.getStringAttribute(ATTRIBUTE_ICON));
+            getWidget().icon.setUri(getState().getIcon().getURL());
         } else {
             if (getWidget().icon != null) {
                 getWidget().getElement().removeChild(
index d5ed3fcaf37a208a2fda7b5bcd065b57a2e4a32c..c54b9fbf60d37ea40586d1a082a1814adffadd3c 100644 (file)
@@ -105,7 +105,11 @@ public class PanelConnector extends AbstractComponentContainerConnector
         getWidget().client = client;
         getWidget().id = uidl.getId();
 
-        getWidget().setIconUri(uidl, client);
+        if (getState().getIcon() != null) {
+            getWidget().setIconUri(getState().getIcon().getURL(), client);
+        } else {
+            getWidget().setIconUri(null, client);
+        }
 
         getWidget().handleError(uidl);
 
index 8a52d5bb49bfe1a2bb18bf6b6e9e72e86c6487ce..1840ac159e64b4514bfa3e98e298fc3778cbb46f 100644 (file)
@@ -18,6 +18,7 @@ public abstract class TabsheetBaseConnector extends
     public static final String ATTRIBUTE_TAB_DISABLED = "disabled";
     public static final String ATTRIBUTE_TAB_DESCRIPTION = "description";
     public static final String ATTRIBUTE_TAB_CAPTION = "caption";
+    public static final String ATTRIBUTE_TAB_ICON = "icon";
 
     @Override
     public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
index 118b01fe03617fa5b52c0e22663935cf510d9ee8..b6e6095ef2aeaa67b1bfdeb90fb5fe8fabd406c6 100644 (file)
@@ -16,10 +16,10 @@ public class TreeConnector extends AbstractComponentConnector {
 
     public static final String ATTRIBUTE_NODE_STYLE = "style";
     public static final String ATTRIBUTE_NODE_CAPTION = "caption";
-    public static final String ATTRIBUTE_NODE_ICON = AbstractComponentConnector.ATTRIBUTE_ICON;
+    public static final String ATTRIBUTE_NODE_ICON = "icon";
 
     public static final String ATTRIBUTE_ACTION_CAPTION = "caption";
-    public static final String ATTRIBUTE_ACTION_ICON = AbstractComponentConnector.ATTRIBUTE_ICON;
+    public static final String ATTRIBUTE_ACTION_ICON = ATTRIBUTE_NODE_ICON;
 
     @Override
     public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
index e0c1510ae91116b9a8856bc244b7ce2b78e8e8d7..95db3227305cf2921303677c2ee732bfa77f9deb 100644 (file)
@@ -443,7 +443,8 @@ public class VAccordion extends VTabsheetBase {
                     uidl,
                     uidl.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_CAPTION),
                     uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DISABLED),
-                    uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION));
+                    uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION),
+                    uidl.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_ICON));
         }
 
         public int getWidgetWidth() {
index b322be660121733a6ac1dea81b33b130be51c851..cf9f35dc8d1e489490c330cf46b0fe1916cdc8cc 100644 (file)
@@ -267,14 +267,13 @@ public class VFormLayout extends SimplePanel {
 
             boolean isEmpty = true;
 
-            if (uidl.hasAttribute(AbstractComponentConnector.ATTRIBUTE_ICON)) {
+            if (state.getIcon() != null) {
                 if (icon == null) {
                     icon = new Icon(client);
 
                     DOM.insertChild(getElement(), icon.getElement(), 0);
                 }
-                icon.setUri(uidl
-                        .getStringAttribute(AbstractComponentConnector.ATTRIBUTE_ICON));
+                icon.setUri(state.getIcon().getURL());
                 isEmpty = false;
             } else {
                 if (icon != null) {
index e1682b72d32612a40e8684ae1b5f11db134ed418..2276320cbbea4f3bb69279449564ea0fad71cd19 100644 (file)
@@ -65,7 +65,7 @@ public class VMenuBar extends SimpleFocusablePanel implements
 
     public static final String ATTRIBUTE_CHECKED = "checked";
     public static final String ATTRIBUTE_ITEM_DESCRIPTION = "description";
-    public static final String ATTRIBUTE_ITEM_ICON = AbstractComponentConnector.ATTRIBUTE_ICON;
+    public static final String ATTRIBUTE_ITEM_ICON = "icon";
     public static final String ATTRIBUTE_ITEM_DISABLED = "disabled";
     public static final String ATTRIBUTE_ITEM_STYLE = "style";
 
index 2cbd562d43142ac6ce0d027a1ec2b3a5206a8b46..cf62bb2de859f2cb875163ee0f32259f2f8820b1 100644 (file)
@@ -59,7 +59,7 @@ public class VNotification extends VOverlay {
     public static final String ATTRIBUTE_NOTIFICATION_STYLE = "style";
     public static final String ATTRIBUTE_NOTIFICATION_CAPTION = "caption";
     public static final String ATTRIBUTE_NOTIFICATION_MESSAGE = "message";
-    public static final String ATTRIBUTE_NOTIFICATION_ICON = AbstractComponentConnector.ATTRIBUTE_ICON;
+    public static final String ATTRIBUTE_NOTIFICATION_ICON = "icon";
     public static final String ATTRIBUTE_NOTIFICATION_POSITION = "position";
     public static final String ATTRIBUTE_NOTIFICATION_DELAY = "delay";
 
index 768a9596aef214176f981e679b62e05a9057dfcb..7dcfa24d89795afe30cf19c3719b68620c28b42b 100644 (file)
@@ -133,11 +133,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
         }
     }
 
-    void setIconUri(UIDL uidl, ApplicationConnection client) {
-        final String iconUri = uidl
-                .hasAttribute(AbstractComponentConnector.ATTRIBUTE_ICON) ? uidl
-                .getStringAttribute(AbstractComponentConnector.ATTRIBUTE_ICON)
-                : null;
+    void setIconUri(String iconUri, ApplicationConnection client) {
         if (iconUri == null) {
             if (icon != null) {
                 DOM.removeChild(captionNode, icon.getElement());
index 5b14bede1d8cea62aa234efe1bd88afbf6d1dce7..7b166ee25fa7455633a56a8eda0e092ff5ba3450 100644 (file)
@@ -266,7 +266,8 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
                     uidl,
                     uidl.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_CAPTION),
                     uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DISABLED),
-                    uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION));
+                    uidl.hasAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION),
+                    uidl.getStringAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_ICON));
 
             setClosable(uidl.hasAttribute("closable"));
 
index 5bae9cd99a951e2b9e37b16c12f3d92f7b744c84..5a00950a4870351052f37c96d6f1b31c5a0717af 100644 (file)
@@ -86,10 +86,11 @@ public class WindowConnector extends AbstractComponentContainerConnector
 
             // Caption must be set before required header size is measured. If
             // the caption attribute is missing the caption should be cleared.
-            getWidget()
-                    .setCaption(
-                            getState().getCaption(),
-                            uidl.getStringAttribute(AbstractComponentConnector.ATTRIBUTE_ICON));
+            String iconURL = null;
+            if (getState().getIcon() != null) {
+                iconURL = getState().getIcon().getURL();
+            }
+            getWidget().setCaption(getState().getCaption(), iconURL);
         }
 
         getWidget().visibilityChangesDisabled = true;
index 350a70d9d46e1af52fe12451fc97c9122b5dccab..0a617470a538b3d52d7daff64df4e644859803bc 100644 (file)
@@ -153,6 +153,12 @@ public class JsonCodec implements Serializable {
      */
     public static JSONArray encode(Object value, PaintableIdMapper idMapper)
             throws JSONException {
+        return encode(value, null, idMapper);
+    }
+
+    public static JSONArray encode(Object value, Class<?> valueType,
+            PaintableIdMapper idMapper) throws JSONException {
+
         if (null == value) {
             // TODO as undefined type?
             return combineTypeAndValue(JsonEncoder.VTYPE_UNDEFINED,
@@ -188,7 +194,11 @@ public class JsonCodec implements Serializable {
         } else {
             // Any object that we do not know how to encode we encode by looping
             // through fields
-            return combineTypeAndValue(value.getClass().getCanonicalName(),
+            if (valueType == null) {
+                valueType = value.getClass();
+            }
+
+            return combineTypeAndValue(valueType.getCanonicalName(),
                     encodeObject(value, idMapper));
         }
     }
@@ -201,12 +211,13 @@ public class JsonCodec implements Serializable {
             for (PropertyDescriptor pd : Introspector.getBeanInfo(
                     value.getClass()).getPropertyDescriptors()) {
                 String fieldName = pd.getName();
+                Class<?> fieldType = pd.getPropertyType();
                 if (pd.getReadMethod() == null || pd.getWriteMethod() == null) {
                     continue;
                 }
                 Method getterMethod = pd.getReadMethod();
                 Object fieldValue = getterMethod.invoke(value, null);
-                jsonMap.put(fieldName, encode(fieldValue, idMapper));
+                jsonMap.put(fieldName, encode(fieldValue, fieldType, idMapper));
             }
         } catch (Exception e) {
             // TODO: Should exceptions be handled in a different way?
index f992b3ff2c37a4841931162bc74bb8f2e0a9acd9..f80b7a3f27ebf153e688f174cf5b10949ef90754 100644 (file)
@@ -24,11 +24,12 @@ import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
 import com.google.gwt.user.rebind.SourceWriter;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.communication.JSONSerializer;
 import com.vaadin.terminal.gwt.client.communication.JsonDecoder;
 import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
 import com.vaadin.terminal.gwt.client.communication.SerializerMap;
-import com.vaadin.terminal.gwt.client.communication.JSONSerializer;
 
 /**
  * GWT generator for creating serializer classes for custom classes sent from
@@ -113,10 +114,12 @@ public class SerializerGenerator extends Generator {
 
         // Serializer
 
-        // public JSONValue serialize(Object value, ConnectorMap idMapper) {
+        // public JSONValue serialize(Object value, ConnectorMap idMapper,
+        // ApplicationConnection connection) {
         sourceWriter.println("public " + JSONObject.class.getName()
                 + " serialize(" + Object.class.getName() + " value, "
-                + ConnectorMap.class.getName() + " idMapper) {");
+                + ConnectorMap.class.getName() + " idMapper, "
+                + ApplicationConnection.class.getName() + " connection) {");
         sourceWriter.indent();
         // MouseEventDetails castedValue = (MouseEventDetails) value;
         sourceWriter.println(beanQualifiedSourceName + " castedValue = ("
@@ -136,10 +139,11 @@ public class SerializerGenerator extends Generator {
                         + ". Serialization will likely fail");
             }
             // json.put("button",
-            // JsonEncoder.encode(castedValue.getButton(), idMapper));
+            // JsonEncoder.encode(castedValue.getButton(), idMapper,
+            // connection));
             sourceWriter.println("json.put(\"" + fieldName + "\", "
                     + JsonEncoder.class.getName() + ".encode(castedValue."
-                    + getterName + "(), idMapper));");
+                    + getterName + "(), idMapper, connection));");
         }
         // return json;
         sourceWriter.println("return json;");
@@ -149,7 +153,8 @@ public class SerializerGenerator extends Generator {
         // Deserializer
         sourceWriter.println("public " + beanQualifiedSourceName
                 + " deserialize(" + JSONObject.class.getName() + " jsonValue, "
-                + ConnectorMap.class.getName() + " idMapper) {");
+                + ConnectorMap.class.getName() + " idMapper, "
+                + ApplicationConnection.class.getName() + " connection) {");
         sourceWriter.indent();
 
         // VButtonState state = GWT.create(VButtonState.class);
@@ -170,7 +175,7 @@ public class SerializerGenerator extends Generator {
                     + " = (JSONArray) jsonValue.get(\"" + fieldName + "\");");
 
             // state.setHeight((String)
-            // JsonDecoder.convertValue(jsonFieldValue,idMapper));
+            // JsonDecoder.convertValue(jsonFieldValue,idMapper, connection));
 
             String fieldType;
             JPrimitiveType primitiveType = setterParameterType.isPrimitive();
@@ -183,7 +188,7 @@ public class SerializerGenerator extends Generator {
 
             sourceWriter.println("state." + setterName + "((" + fieldType
                     + ") JsonDecoder.convertValue(" + jsonFieldName
-                    + ", idMapper));");
+                    + ", idMapper, connection));");
         }
 
         // return state;
index 8282547eb0a7361488c11e9f75acd8668511fb13..c2a54030f785a9f81fd118976f58b7cc9235cb8d 100644 (file)
@@ -19,13 +19,16 @@ import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.JMethod;
 import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
 import com.google.gwt.user.rebind.SourceWriter;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
 import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+import com.vaadin.terminal.gwt.client.communication.JSONSerializer;
 import com.vaadin.terminal.gwt.client.communication.SerializerMap;
 import com.vaadin.terminal.gwt.client.communication.ServerRpc;
 import com.vaadin.terminal.gwt.client.communication.SharedState;
-import com.vaadin.terminal.gwt.client.communication.JSONSerializer;
 
 /**
  * GWT generator that creates a {@link SerializerMap} implementation (mapper
@@ -47,13 +50,17 @@ public class SerializerMapGenerator extends Generator {
             TypeOracle typeOracle = context.getTypeOracle();
             Set<JClassType> typesNeedingSerializers = findTypesNeedingSerializers(
                     typeOracle, logger);
-
+            Set<JClassType> typesWithExistingSerializers = findTypesWithExistingSerializers(
+                    typeOracle, logger);
+            Set<JClassType> serializerMappings = new HashSet<JClassType>();
+            serializerMappings.addAll(typesNeedingSerializers);
+            serializerMappings.addAll(typesWithExistingSerializers);
             // get classType and save instance variables
             JClassType classType = typeOracle.getType(typeName);
             packageName = classType.getPackage().getName();
             className = classType.getSimpleSourceName() + "Impl";
             // Generate class source code for SerializerMapImpl
-            generateSerializerMap(typesNeedingSerializers, logger, context);
+            generateSerializerMap(serializerMappings, logger, context);
 
             SerializerGenerator sg = new SerializerGenerator();
             for (JClassType type : typesNeedingSerializers) {
@@ -67,6 +74,27 @@ public class SerializerMapGenerator extends Generator {
         return packageName + "." + className;
     }
 
+    private Set<JClassType> findTypesWithExistingSerializers(
+            TypeOracle typeOracle, TreeLogger logger) {
+        JClassType serializerInterface = typeOracle
+                .findType(JSONSerializer.class.getName());
+        Set<JClassType> types = new HashSet<JClassType>();
+        for (JClassType serializer : serializerInterface.getSubtypes()) {
+            JType[] deserializeParamTypes = new JType[] {
+                    typeOracle.findType(JSONObject.class.getName()),
+                    typeOracle.findType(ConnectorMap.class.getName()),
+                    typeOracle.findType(ApplicationConnection.class.getName()) };
+            JMethod deserializeMethod = serializer.findMethod("deserialize",
+                    deserializeParamTypes);
+            if (deserializeMethod == null) {
+                continue;
+            }
+
+            types.add(deserializeMethod.getReturnType().isClass());
+        }
+        return types;
+    }
+
     /**
      * Generate source code for SerializerMapImpl
      * 
index 92e064a33fdc0e649c9e0da5487399903193f844..06a15fabf8c1da938fa89d904d98a6d17d779b63 100644 (file)
@@ -35,7 +35,7 @@ import com.vaadin.terminal.Resource;
 import com.vaadin.terminal.Terminal;
 import com.vaadin.terminal.gwt.client.ComponentState;
 import com.vaadin.terminal.gwt.client.communication.ClientRpc;
-import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.communication.ResourceReference;
 import com.vaadin.terminal.gwt.server.ClientMethodInvocation;
 import com.vaadin.terminal.gwt.server.ComponentSizeValidator;
 import com.vaadin.terminal.gwt.server.RpcManager;
@@ -70,11 +70,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource
      */
     private Object applicationData;
 
-    /**
-     * Icon to be shown together with caption.
-     */
-    private Resource icon;
-
     /**
      * The container this component resides in.
      */
@@ -341,7 +336,7 @@ public abstract class AbstractComponent implements Component, MethodEventSource
      * use the default documentation from implemented interface.
      */
     public Resource getIcon() {
-        return icon;
+        return ((ResourceReference) getState().getIcon()).getResource();
     }
 
     /**
@@ -353,7 +348,11 @@ public abstract class AbstractComponent implements Component, MethodEventSource
      *            the icon to be shown with the component's caption.
      */
     public void setIcon(Resource icon) {
-        this.icon = icon;
+        if (icon == null) {
+            getState().setIcon(null);
+        } else {
+            getState().setIcon(new ResourceReference(icon));
+        }
         requestRepaint();
     }
 
@@ -736,15 +735,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource
 
             // Only paint content of visible components.
             if (isVisible()) {
-                // width and height are only in shared state
-
-                // TODO probably can remove also icon once all the VCaption
-                // related code has been updated
-                if (getIcon() != null) {
-                    target.addAttribute(
-                            AbstractComponentConnector.ATTRIBUTE_ICON,
-                            getIcon());
-                }
 
                 if (eventIdentifiers != null) {
                     target.addAttribute("eventListeners",
index 01f808099aa981e7c2ea9b94c268a46b47661b50..89c363e554945af2adaf06e1fbbcd49e360ff235 100644 (file)
@@ -25,7 +25,6 @@ import com.vaadin.terminal.KeyMapper;
 import com.vaadin.terminal.PaintException;
 import com.vaadin.terminal.PaintTarget;
 import com.vaadin.terminal.Resource;
-import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
 import com.vaadin.terminal.gwt.client.ui.TabsheetBaseConnector;
 import com.vaadin.terminal.gwt.client.ui.TabsheetConnector;
 import com.vaadin.terminal.gwt.client.ui.VTabsheet;
@@ -408,7 +407,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
             // VCaption.updateCaption(uidl)
             final Resource icon = tab.getIcon();
             if (icon != null) {
-                target.addAttribute(AbstractComponentConnector.ATTRIBUTE_ICON,
+                target.addAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_ICON,
                         icon);
             }
             final String caption = tab.getCaption();