]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fire change event for default values in newly created state (#9422)
authorLeif Åstrand <leif@vaadin.com>
Tue, 28 Aug 2012 10:19:13 +0000 (13:19 +0300)
committerLeif Åstrand <leif@vaadin.com>
Tue, 28 Aug 2012 10:19:47 +0000 (13:19 +0300)
client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
client/src/com/vaadin/terminal/gwt/client/metadata/Type.java
client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java
client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java

index 450972ddc6614b8b4413450c5cedc31255610684..a984433907213198ce236e0a25899486293019be 100644 (file)
@@ -18,6 +18,7 @@ package com.vaadin.terminal.gwt.client;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -74,6 +75,7 @@ import com.vaadin.terminal.gwt.client.metadata.Property;
 import com.vaadin.terminal.gwt.client.metadata.Type;
 import com.vaadin.terminal.gwt.client.metadata.TypeData;
 import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.AbstractConnector;
 import com.vaadin.terminal.gwt.client.ui.VContextMenu;
 import com.vaadin.terminal.gwt.client.ui.UI.UIConnector;
 import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
@@ -1130,13 +1132,14 @@ public class ApplicationConnection {
                 int startProcessing = updateDuration.elapsedMillis();
 
                 // Ensure that all connectors that we are about to update exist
-                createConnectorsIfNeeded(json);
+                Set<ServerConnector> createdConnectors = createConnectorsIfNeeded(json);
 
                 updateDuration.logDuration(" * Creating connectors completed",
                         10);
 
                 // Update states, do not fire events
-                Collection<StateChangeEvent> pendingStateChangeEvents = updateConnectorState(json);
+                Collection<StateChangeEvent> pendingStateChangeEvents = updateConnectorState(
+                        json, createdConnectors);
 
                 updateDuration.logDuration(
                         " * Update of connector states completed", 10);
@@ -1280,17 +1283,9 @@ public class ApplicationConnection {
                     ServerConnector connector = sce.getConnector();
                     if (connector instanceof ComponentConnector) {
                         ComponentConnector component = (ComponentConnector) connector;
-                        Type type = TypeData.getType(component.getClass());
 
-                        Type stateType;
-                        try {
-                            stateType = type.getMethod("getState")
-                                    .getReturnType();
-                        } catch (NoDataException e) {
-                            throw new RuntimeException(
-                                    "Can not find the state type for "
-                                            + type.getSignature(), e);
-                        }
+                        Type stateType = AbstractConnector
+                                .getStateType(component);
 
                         Set<String> changedProperties = sce
                                 .getChangedProperties();
@@ -1385,13 +1380,15 @@ public class ApplicationConnection {
                 VConsole.log("* Unregistered " + unregistered + " connectors");
             }
 
-            private void createConnectorsIfNeeded(ValueMap json) {
+            private Set<ServerConnector> createConnectorsIfNeeded(ValueMap json) {
                 VConsole.log(" * Creating connectors (if needed)");
 
                 if (!json.containsKey("types")) {
-                    return;
+                    return Collections.emptySet();
                 }
 
+                Set<ServerConnector> createdConnectors = new HashSet<ServerConnector>();
+
                 ValueMap types = json.getValueMap("types");
                 JsArrayString keyArray = types.getKeyArray();
                 for (int i = 0; i < keyArray.length(); i++) {
@@ -1411,7 +1408,8 @@ public class ApplicationConnection {
                         // Connector does not exist so we must create it
                         if (connectorClass != UIConnector.class) {
                             // create, initialize and register the paintable
-                            getConnector(connectorId, connectorType);
+                            connector = getConnector(connectorId, connectorType);
+                            createdConnectors.add(connector);
                         } else {
                             // First UIConnector update. Before this the
                             // UIConnector has been created but not
@@ -1421,11 +1419,13 @@ public class ApplicationConnection {
                                     uIConnector);
                             uIConnector.doInit(connectorId,
                                     ApplicationConnection.this);
+                            createdConnectors.add(uIConnector);
                         }
                     } catch (final Throwable e) {
                         VConsole.error(e);
                     }
                 }
+                return createdConnectors;
             }
 
             private void updateVaadin6StyleConnectors(ValueMap json) {
@@ -1480,12 +1480,15 @@ public class ApplicationConnection {
             }
 
             private Collection<StateChangeEvent> updateConnectorState(
-                    ValueMap json) {
+                    ValueMap json, Set<ServerConnector> newConnectors) {
                 ArrayList<StateChangeEvent> events = new ArrayList<StateChangeEvent>();
                 VConsole.log(" * Updating connector states");
                 if (!json.containsKey("state")) {
                     return events;
                 }
+                HashSet<ServerConnector> remainingNewConnectors = new HashSet<ServerConnector>(
+                        newConnectors);
+
                 // set states for all paintables mentioned in "state"
                 ValueMap states = json.getValueMap("state");
                 JsArrayString keyArray = states.getKeyArray();
@@ -1514,6 +1517,16 @@ public class ApplicationConnection {
                             Set<String> changedProperties = new HashSet<String>();
                             addJsonFields(stateJson, changedProperties, "");
 
+                            if (newConnectors.contains(connector)) {
+                                remainingNewConnectors.remove(connector);
+                                // Fire events for properties using the default
+                                // value for newly created connectors
+                                addAllStateFields(
+                                        AbstractConnector
+                                                .getStateType(connector),
+                                        changedProperties, "");
+                            }
+
                             StateChangeEvent event = new StateChangeEvent(
                                     connector, changedProperties);
 
@@ -1524,9 +1537,58 @@ public class ApplicationConnection {
                     }
                 }
 
+                // Fire events for properties using the default value for newly
+                // created connectors even if there were no state changes
+                for (ServerConnector connector : remainingNewConnectors) {
+                    Set<String> changedProperties = new HashSet<String>();
+                    addAllStateFields(
+                            AbstractConnector.getStateType(connector),
+                            changedProperties, "");
+
+                    StateChangeEvent event = new StateChangeEvent(connector,
+                            changedProperties);
+
+                    events.add(event);
+
+                }
+
                 return events;
             }
 
+            /**
+             * Recursively adds the names of all properties in the provided
+             * state type.
+             * 
+             * @param type
+             *            the type to process
+             * @param foundProperties
+             *            a set of all currently added properties
+             * @param context
+             *            the base name of the current object
+             */
+            private void addAllStateFields(Type type,
+                    Set<String> foundProperties, String context) {
+                try {
+                    Collection<Property> properties = type.getProperties();
+                    for (Property property : properties) {
+                        String propertyName = context + property.getName();
+                        foundProperties.add(propertyName);
+
+                        Type propertyType = property.getType();
+                        if (propertyType.hasProperties()) {
+                            addAllStateFields(propertyType, foundProperties,
+                                    propertyName + ".");
+                        }
+                    }
+                } catch (NoDataException e) {
+                    throw new IllegalStateException(
+                            "No property info for "
+                                    + type
+                                    + ". Did you remember to compile the right widgetset?",
+                            e);
+                }
+            }
+
             /**
              * Recursively adds the names of all fields in all objects in the
              * provided json object.
index d869cc259900c6d7f7ba0746d7f989f8c6f734a4..d019ff27e0fa08e271943e427f33fe376d8f085c 100644 (file)
@@ -94,4 +94,8 @@ public class Type {
         return TypeDataStore.findSerializer(this);
     }
 
+    public boolean hasProperties() {
+        return TypeDataStore.hasProperties(this);
+    }
+
 }
index 9c19410c8860e3ed0284d30c72e1003af78ee048..0fc8f3b3bf1acef55de8c7e4abd460148a522698 100644 (file)
@@ -223,4 +223,8 @@ public class TypeDataStore {
         }
         return (JSONSerializer<?>) factoryCreator.invoke(null);
     }
+
+    public static boolean hasProperties(Type type) {
+        return get().properties.containsKey(type);
+    }
 }
index b861ade0bfbaeeb94f247616bd0577168c3abc00..3a50f0a91e67f8fd4714fd4ed077960c8e2dd1d5 100644 (file)
@@ -268,10 +268,8 @@ public abstract class AbstractConnector implements ServerConnector,
      * @return A new state object
      */
     protected SharedState createState() {
-        Type connectorType = TypeData.getType(getClass());
         try {
-            Type stateType = connectorType.getMethod("getState")
-                    .getReturnType();
+            Type stateType = getStateType(this);
             Object stateInstance = stateType.createInstance();
             return (SharedState) stateInstance;
         } catch (NoDataException e) {
@@ -284,6 +282,19 @@ public abstract class AbstractConnector implements ServerConnector,
 
     }
 
+    public static Type getStateType(ServerConnector connector) {
+        try {
+            return TypeData.getType(connector.getClass()).getMethod("getState")
+                    .getReturnType();
+        } catch (NoDataException e) {
+            throw new IllegalStateException(
+                    "There is no information about the state for "
+                            + Util.getSimpleName(connector)
+                            + ". Did you remember to compile the right widgetset?",
+                    e);
+        }
+    }
+
     @Override
     public ServerConnector getParent() {
         return parent;