From 9995fe0b4f0f77bf6542faef3419ef6aa2a63ed1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Tue, 28 Aug 2012 13:19:13 +0300 Subject: [PATCH] Fire change event for default values in newly created state (#9422) --- .../gwt/client/ApplicationConnection.java | 94 +++++++++++++++---- .../terminal/gwt/client/metadata/Type.java | 4 + .../gwt/client/metadata/TypeDataStore.java | 4 + .../gwt/client/ui/AbstractConnector.java | 17 +++- 4 files changed, 100 insertions(+), 19 deletions(-) diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 450972ddc6..a984433907 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -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 createdConnectors = createConnectorsIfNeeded(json); updateDuration.logDuration(" * Creating connectors completed", 10); // Update states, do not fire events - Collection pendingStateChangeEvents = updateConnectorState(json); + Collection 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 changedProperties = sce .getChangedProperties(); @@ -1385,13 +1380,15 @@ public class ApplicationConnection { VConsole.log("* Unregistered " + unregistered + " connectors"); } - private void createConnectorsIfNeeded(ValueMap json) { + private Set createConnectorsIfNeeded(ValueMap json) { VConsole.log(" * Creating connectors (if needed)"); if (!json.containsKey("types")) { - return; + return Collections.emptySet(); } + Set createdConnectors = new HashSet(); + 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 updateConnectorState( - ValueMap json) { + ValueMap json, Set newConnectors) { ArrayList events = new ArrayList(); VConsole.log(" * Updating connector states"); if (!json.containsKey("state")) { return events; } + HashSet remainingNewConnectors = new HashSet( + 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 changedProperties = new HashSet(); 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 changedProperties = new HashSet(); + 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 foundProperties, String context) { + try { + Collection 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. diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java index d869cc2599..d019ff27e0 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/Type.java @@ -94,4 +94,8 @@ public class Type { return TypeDataStore.findSerializer(this); } + public boolean hasProperties() { + return TypeDataStore.hasProperties(this); + } + } diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java index 9c19410c88..0fc8f3b3bf 100644 --- a/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java @@ -223,4 +223,8 @@ public class TypeDataStore { } return (JSONSerializer) factoryCreator.invoke(null); } + + public static boolean hasProperties(Type type) { + return get().properties.containsKey(type); + } } diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java index b861ade0bf..3a50f0a91e 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java @@ -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; -- 2.39.5