diff options
Diffstat (limited to 'client')
4 files changed, 293 insertions, 156 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index de034a65a6..1a637e3161 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -16,15 +16,13 @@ package com.vaadin.client; -import java.util.ArrayList; -import java.util.Collection; +import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -113,8 +111,15 @@ public class ApplicationConnection { * Helper used to return two values when updating the connector hierarchy. */ private static class ConnectorHierarchyUpdateResult { - private List<ConnectorHierarchyChangeEvent> events = new LinkedList<ConnectorHierarchyChangeEvent>(); - private List<ServerConnector> parentChanged = new LinkedList<ServerConnector>(); + /** + * Needed at a later point when the created events are fired + */ + private JsArrayObject<ConnectorHierarchyChangeEvent> events = JavaScriptObject + .createArray().cast(); + /** + * Needed to know where captions might need to get updated + */ + private FastStringSet parentChangedIds = FastStringSet.create(); } public static final String MODIFIED_CLASSNAME = "v-modified"; @@ -153,9 +158,6 @@ public class ApplicationConnection { // will hold the UIDL security key (for XSS protection) once received private String uidlSecurityKey = "init"; - private static final FastStringMap<FastStringSet> allStateFieldsCache = FastStringMap - .create(); - private final HashMap<String, String> resourcesMap = new HashMap<String, String>(); /** @@ -217,8 +219,6 @@ public class ApplicationConnection { /** redirectTimer scheduling interval in seconds */ private int sessionExpirationInterval; - private ArrayList<Widget> componentCaptionSizeChanges = new ArrayList<Widget>(); - private Date requestStartTime; private boolean validatingLayouts = false; @@ -1424,16 +1424,14 @@ public class ApplicationConnection { redirectTimer.schedule(1000 * sessionExpirationInterval); } - componentCaptionSizeChanges.clear(); - double processUidlStart = Duration.currentTimeMillis(); // Ensure that all connectors that we are about to update exist - Set<ServerConnector> createdConnectors = createConnectorsIfNeeded(json); + JsArrayString createdConnectorIds = createConnectorsIfNeeded(json); // Update states, do not fire events - Collection<StateChangeEvent> pendingStateChangeEvents = updateConnectorState( - json, createdConnectors); + JsArrayObject<StateChangeEvent> pendingStateChangeEvents = updateConnectorState( + json, createdConnectorIds); // Update hierarchy, do not fire events ConnectorHierarchyUpdateResult connectorHierarchyUpdateResult = updateConnectorHierarchy(json); @@ -1442,7 +1440,7 @@ public class ApplicationConnection { sendHierarchyChangeEvents(connectorHierarchyUpdateResult.events); updateCaptions(pendingStateChangeEvents, - connectorHierarchyUpdateResult.parentChanged); + connectorHierarchyUpdateResult.parentChangedIds); delegateToWidget(pendingStateChangeEvents); @@ -1566,27 +1564,35 @@ public class ApplicationConnection { } private void updateCaptions( - Collection<StateChangeEvent> pendingStateChangeEvents, - Collection<ServerConnector> parentChanged) { + JsArrayObject<StateChangeEvent> pendingStateChangeEvents, + FastStringSet parentChangedIds) { Profiler.enter("updateCaptions"); /* * Find all components that might need a caption update based on * pending state and hierarchy changes */ - HashSet<ServerConnector> needsCaptionUpdate = new HashSet<ServerConnector>( - parentChanged); + FastStringSet needsCaptionUpdate = FastStringSet.create(); + needsCaptionUpdate.addAll(parentChangedIds); // Find components with potentially changed caption state - for (StateChangeEvent event : pendingStateChangeEvents) { + int size = pendingStateChangeEvents.size(); + for (int i = 0; i < size; i++) { + StateChangeEvent event = pendingStateChangeEvents.get(i); if (VCaption.mightChange(event)) { ServerConnector connector = event.getConnector(); - needsCaptionUpdate.add(connector); + needsCaptionUpdate.add(connector.getConnectorId()); } } + ConnectorMap connectorMap = getConnectorMap(); + // Update captions for all suitable candidates - for (ServerConnector child : needsCaptionUpdate) { + JsArrayString dump = needsCaptionUpdate.dump(); + int needsUpdateLength = dump.length(); + for (int i = 0; i < needsUpdateLength; i++) { + String childId = dump.get(i); + ServerConnector child = connectorMap.getConnector(childId); if (child instanceof ComponentConnector && ((ComponentConnector) child) .delegateCaptionHandling()) { @@ -1604,29 +1610,45 @@ public class ApplicationConnection { } private void delegateToWidget( - Collection<StateChangeEvent> pendingStateChangeEvents) { + JsArrayObject<StateChangeEvent> pendingStateChangeEvents) { Profiler.enter("@DelegateToWidget"); VConsole.log(" * Running @DelegateToWidget"); - for (StateChangeEvent sce : pendingStateChangeEvents) { + // Keep track of types that have no @DelegateToWidget in their + // state to optimize performance + FastStringSet noOpTypes = FastStringSet.create(); + + int size = pendingStateChangeEvents.size(); + for (int eventIndex = 0; eventIndex < size; eventIndex++) { + StateChangeEvent sce = pendingStateChangeEvents + .get(eventIndex); ServerConnector connector = sce.getConnector(); if (connector instanceof ComponentConnector) { + String className = connector.getClass().getName(); + if (noOpTypes.contains(className)) { + continue; + } ComponentConnector component = (ComponentConnector) connector; Type stateType = AbstractConnector .getStateType(component); + JsArrayString delegateToWidgetProperties = stateType + .getDelegateToWidgetProperties(); + if (delegateToWidgetProperties == null) { + noOpTypes.add(className); + continue; + } - FastStringSet changedProperties = sce - .getChangedPropertiesFastSet(); - JsArrayString dump = changedProperties.dump(); - for (int i = 0; i < dump.length(); i++) { - String propertyName = dump.get(i); - Property property = stateType - .getProperty(propertyName); - String method = property - .getDelegateToWidgetMethodName(); - if (method != null) { + int length = delegateToWidgetProperties.length(); + for (int i = 0; i < length; i++) { + String propertyName = delegateToWidgetProperties + .get(i); + if (sce.hasPropertyChanged(propertyName)) { + Property property = stateType + .getProperty(propertyName); + String method = property + .getDelegateToWidgetMethodName(); Profiler.enter("doDelegateToWidget"); doDelegateToWidget(component, property, method); Profiler.leave("doDelegateToWidget"); @@ -1673,11 +1695,13 @@ public class ApplicationConnection { * The events to send */ private void sendStateChangeEvents( - Collection<StateChangeEvent> pendingStateChangeEvents) { + JsArrayObject<StateChangeEvent> pendingStateChangeEvents) { Profiler.enter("sendStateChangeEvents"); VConsole.log(" * Sending state change events"); - for (StateChangeEvent sce : pendingStateChangeEvents) { + int size = pendingStateChangeEvents.size(); + for (int i = 0; i < size; i++) { + StateChangeEvent sce = pendingStateChangeEvents.get(i); try { sce.getConnector().fireEvent(sce); } catch (final Throwable e) { @@ -1723,29 +1747,29 @@ public class ApplicationConnection { Profiler.leave("unregisterRemovedConnectors"); } - private Set<ServerConnector> createConnectorsIfNeeded(ValueMap json) { + private JsArrayString createConnectorsIfNeeded(ValueMap json) { VConsole.log(" * Creating connectors (if needed)"); + JsArrayString createdConnectors = JavaScriptObject + .createArray().cast(); if (!json.containsKey("types")) { - return Collections.emptySet(); + return createdConnectors; } Profiler.enter("Creating connectors"); - Set<ServerConnector> createdConnectors = new HashSet<ServerConnector>(); - ValueMap types = json.getValueMap("types"); JsArrayString keyArray = types.getKeyArray(); for (int i = 0; i < keyArray.length(); i++) { try { String connectorId = keyArray.get(i); - int connectorType = Integer.parseInt(types - .getString((connectorId))); ServerConnector connector = connectorMap .getConnector(connectorId); if (connector != null) { continue; } + int connectorType = Integer.parseInt(types + .getString(connectorId)); Class<? extends ServerConnector> connectorClass = configuration .getConnectorClassByEncodedTag(connectorType); @@ -1757,7 +1781,7 @@ public class ApplicationConnection { connector = getConnector(connectorId, connectorType); Profiler.leave("ApplicationConnection.getConnector"); - createdConnectors.add(connector); + createdConnectors.push(connectorId); } else { // First UIConnector update. Before this the // UIConnector has been created but not @@ -1767,7 +1791,7 @@ public class ApplicationConnection { uIConnector); uIConnector.doInit(connectorId, ApplicationConnection.this); - createdConnectors.add(uIConnector); + createdConnectors.push(connectorId); } } catch (final Throwable e) { VConsole.error(e); @@ -1829,14 +1853,16 @@ public class ApplicationConnection { } private void sendHierarchyChangeEvents( - Collection<ConnectorHierarchyChangeEvent> pendingHierarchyChangeEvents) { - if (pendingHierarchyChangeEvents.isEmpty()) { + JsArrayObject<ConnectorHierarchyChangeEvent> events) { + int eventCount = events.size(); + if (eventCount == 0) { return; } Profiler.enter("sendHierarchyChangeEvents"); VConsole.log(" * Sending hierarchy change events"); - for (ConnectorHierarchyChangeEvent event : pendingHierarchyChangeEvents) { + for (int i = 0; i < eventCount; i++) { + ConnectorHierarchyChangeEvent event = events.get(i); try { logHierarchyChange(event); event.getConnector().fireEvent(event); @@ -1871,9 +1897,10 @@ public class ApplicationConnection { VConsole.log(newChildren); } - private Collection<StateChangeEvent> updateConnectorState( - ValueMap json, Set<ServerConnector> newConnectors) { - ArrayList<StateChangeEvent> events = new ArrayList<StateChangeEvent>(); + private JsArrayObject<StateChangeEvent> updateConnectorState( + ValueMap json, JsArrayString createdConnectorIds) { + JsArrayObject<StateChangeEvent> events = JavaScriptObject + .createArray().cast(); VConsole.log(" * Updating connector states"); if (!json.containsKey("state")) { return events; @@ -1881,8 +1908,8 @@ public class ApplicationConnection { Profiler.enter("updateConnectorState"); - HashSet<ServerConnector> remainingNewConnectors = new HashSet<ServerConnector>( - newConnectors); + FastStringSet remainingNewConnectors = FastStringSet.create(); + remainingNewConnectors.addAll(createdConnectorIds); // set states for all paintables mentioned in "state" ValueMap states = json.getValueMap("state"); @@ -1923,22 +1950,15 @@ public class ApplicationConnection { } Profiler.enter("updateConnectorState create event"); - FastStringSet changedProperties = FastStringSet - .create(); - addJsonFields(stateJson, changedProperties, ""); - - if (newConnectors.contains(connector)) { - remainingNewConnectors.remove(connector); - // Fire events for properties using the default - // value for newly created connectors - FastStringSet allStateFields = getAllStateFields(AbstractConnector - .getStateType(connector)); - changedProperties.addAll(allStateFields); + + boolean isNewConnector = remainingNewConnectors + .contains(connectorId); + if (isNewConnector) { + remainingNewConnectors.remove(connectorId); } StateChangeEvent event = new StateChangeEvent( - connector, changedProperties); - + connector, stateJson, isNewConnector); events.add(event); Profiler.leave("updateConnectorState create event"); @@ -1952,12 +1972,15 @@ public class ApplicationConnection { Profiler.enter("updateConnectorState newWithoutState"); // Fire events for properties using the default value for newly // created connectors even if there were no state changes - for (ServerConnector connector : remainingNewConnectors) { - FastStringSet changedProperties = getAllStateFields(AbstractConnector - .getStateType(connector)); + JsArrayString dump = remainingNewConnectors.dump(); + int length = dump.length(); + for (int i = 0; i < length; i++) { + String connectorId = dump.get(i); + ServerConnector connector = connectorMap + .getConnector(connectorId); StateChangeEvent event = new StateChangeEvent(connector, - changedProperties); + new JSONObject(), true); events.add(event); @@ -1969,80 +1992,6 @@ public class ApplicationConnection { return events; } - private FastStringSet getAllStateFields(Type type) { - FastStringSet fields; - fields = allStateFieldsCache.get(type.getBaseTypeName()); - if (fields == null) { - Profiler.enter("getAllStateFields create"); - fields = FastStringSet.create(); - addAllStateFields(type, fields, ""); - allStateFieldsCache.put(type.getBaseTypeName(), fields); - Profiler.leave("getAllStateFields create"); - } - return fields; - } - - /** - * 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, - FastStringSet foundProperties, String context) { - try { - JsArrayObject<Property> properties = type - .getPropertiesAsArray(); - int size = properties.size(); - for (int i = 0; i < size; i++) { - Property property = properties.get(i); - 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. - * - * @param json - * the json object to process - * @param fields - * a set of all currently added fields - * @param context - * the base name of the current object - */ - private void addJsonFields(JSONObject json, FastStringSet fields, - String context) { - for (String key : json.keySet()) { - String fieldName = context + key; - fields.add(fieldName); - - JSONObject object = json.get(key).isObject(); - if (object != null) { - addJsonFields(object, fields, fieldName + "."); - } - } - } - /** * Updates the connector hierarchy and returns a list of events that * should be fired after update of the hierarchy and the state is @@ -2106,7 +2055,7 @@ public class ApplicationConnection { } if (childConnector.getParent() != parentConnector) { childConnector.setParent(parentConnector); - result.parentChanged.add(childConnector); + result.parentChangedIds.add(childConnectorId); // Not detached even if previously removed from // parent maybeDetached.remove(childConnectorId); @@ -2191,7 +2140,7 @@ public class ApplicationConnection { } private void recursivelyDetach(ServerConnector connector, - List<ConnectorHierarchyChangeEvent> events) { + JsArrayObject<ConnectorHierarchyChangeEvent> events) { /* * Reset state in an attempt to keep it consistent with the @@ -3089,9 +3038,11 @@ public class ApplicationConnection { * * @param component * the Paintable whose caption has changed + * @deprecated As of 7.0.2, has not had any effect for a long time */ + @Deprecated public void captionSizeUpdated(Widget widget) { - componentCaptionSizeChanges.add(widget); + // This doesn't do anything, it's just kept here for compatibility } /** diff --git a/client/src/com/vaadin/client/communication/StateChangeEvent.java b/client/src/com/vaadin/client/communication/StateChangeEvent.java index 35187b03d4..e17a56aa69 100644 --- a/client/src/com/vaadin/client/communication/StateChangeEvent.java +++ b/client/src/com/vaadin/client/communication/StateChangeEvent.java @@ -19,10 +19,17 @@ import java.io.Serializable; import java.util.HashSet; import java.util.Set; +import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.json.client.JSONObject; import com.vaadin.client.FastStringSet; +import com.vaadin.client.JsArrayObject; +import com.vaadin.client.Profiler; import com.vaadin.client.ServerConnector; import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler; +import com.vaadin.client.metadata.NoDataException; +import com.vaadin.client.metadata.Property; +import com.vaadin.client.ui.AbstractConnector; public class StateChangeEvent extends AbstractServerConnectorEvent<StateChangeHandler> { @@ -31,14 +38,24 @@ public class StateChangeEvent extends */ public static final Type<StateChangeHandler> TYPE = new Type<StateChangeHandler>(); - private final FastStringSet changedProperties; + /** + * Used to cache a FastStringSet representation of the properties that have + * changed if one is needed. + */ + @Deprecated + private FastStringSet changedProperties; /** * Used to cache a Set representation of the changedProperties if one is * needed. */ + @Deprecated private Set<String> changedPropertiesSet; + private boolean isNewConnector = false; + + private JSONObject stateJson; + @Override public Type<StateChangeHandler> getAssociatedType() { return TYPE; @@ -52,14 +69,16 @@ public class StateChangeEvent extends * @param changedPropertiesSet * a set of names of the changed properties * @deprecated As of 7.0.1, use - * {@link #StateChangeEvent(ServerConnector, FastStringSet)} + * {@link #StateChangeEvent(ServerConnector, JSONObject, boolean)} * instead for improved performance. */ @Deprecated public StateChangeEvent(ServerConnector connector, Set<String> changedPropertiesSet) { setConnector(connector); + // Keep instance around for caching this.changedPropertiesSet = changedPropertiesSet; + changedProperties = FastStringSet.create(); for (String property : changedPropertiesSet) { changedProperties.add(property); @@ -73,13 +92,35 @@ public class StateChangeEvent extends * the event whose state has changed * @param changedProperties * a set of names of the changed properties + * @deprecated As of 7.0.2, use + * {@link #StateChangeEvent(ServerConnector, JSONObject, boolean)} + * instead for improved performance. */ + @Deprecated public StateChangeEvent(ServerConnector connector, FastStringSet changedProperties) { setConnector(connector); this.changedProperties = changedProperties; } + /** + * /** Creates a new state change event. + * + * @param connector + * the event whose state has changed + * @param stateJson + * the JSON representation of the state change + * @param isNewConnector + * <code>true</code> if the state change is for a new connector, + * otherwise <code>false</code> + */ + public StateChangeEvent(ServerConnector connector, JSONObject stateJson, + boolean isNewConnector) { + setConnector(connector); + this.stateJson = stateJson; + this.isNewConnector = isNewConnector; + } + @Override public void dispatch(StateChangeHandler listener) { listener.onStateChanged(this); @@ -108,15 +149,16 @@ public class StateChangeEvent extends * * @return a set of names of the changed properties * - * @deprecated As of 7.0.1, use {@link #getChangedPropertiesFastSet()} or - * {@link #hasPropertyChanged(String)} instead for improved - * performance. + * @deprecated As of 7.0.1, use {@link #hasPropertyChanged(String)} instead + * for improved performance. */ @Deprecated public Set<String> getChangedProperties() { if (changedPropertiesSet == null) { + Profiler.enter("StateChangeEvent.getChangedProperties populate"); changedPropertiesSet = new HashSet<String>(); - changedProperties.addAllTo(changedPropertiesSet); + getChangedPropertiesFastSet().addAllTo(changedPropertiesSet); + Profiler.leave("StateChangeEvent.getChangedProperties populate"); } return changedPropertiesSet; } @@ -126,8 +168,24 @@ public class StateChangeEvent extends * * @return a set of names of the changed properties * + * @deprecated As of 7.0.1, use {@link #hasPropertyChanged(String)} instead + * for improved performance. */ + @Deprecated public FastStringSet getChangedPropertiesFastSet() { + if (changedProperties == null) { + Profiler.enter("StateChangeEvent.getChangedPropertiesFastSet populate"); + changedProperties = FastStringSet.create(); + + addJsonFields(stateJson, changedProperties, ""); + if (isNewConnector) { + addAllStateFields( + AbstractConnector.getStateType(getConnector()), + changedProperties, ""); + } + + Profiler.leave("StateChangeEvent.getChangedPropertiesFastSet populate"); + } return changedProperties; } @@ -140,6 +198,115 @@ public class StateChangeEvent extends * <code>false></code> */ public boolean hasPropertyChanged(String property) { - return changedProperties.contains(property); + if (isNewConnector) { + // Everything has changed for a new connector + return true; + } else if (stateJson != null) { + // Check whether it's in the json object + return isInJson(property, stateJson.getJavaScriptObject()); + } else { + // Legacy cases + if (changedProperties != null) { + // Check legacy stuff + return changedProperties.contains(property); + } else if (changedPropertiesSet != null) { + // Check legacy stuff + return changedPropertiesSet.contains(property); + } else { + throw new IllegalStateException( + "StateChangeEvent should have either stateJson, changedProperties or changePropertiesSet"); + } + } + } + + /** + * Checks whether the given property name (which might contains dots) is + * defined in some JavaScript object. + * + * @param property + * the name of the property, might include dots to reference + * inner objects + * @param target + * the JavaScript object to check + * @return true if the property is defined + */ + private static native final boolean isInJson(String property, + JavaScriptObject target) + /*-{ + var segments = property.split('.'); + while (typeof target == 'object') { + var nextSegment = segments.shift(); + if (!(nextSegment in target)) { + // Abort if segment is not found + return false; + } else if (segments.length == 0) { + // Done if there are no more segments + return true; + } else { + // Else just go deeper + target = target[nextSegment]; + } + } + // Not defined if we reach something that isn't an object + return false; + }-*/; + + /** + * Recursively adds the names of all properties in the provided state type. + * + * @param type + * the type to process + * @param changedProperties + * a set of all currently added properties + * @param context + * the base name of the current object + */ + @Deprecated + private static void addAllStateFields(com.vaadin.client.metadata.Type type, + FastStringSet changedProperties, String context) { + try { + JsArrayObject<Property> properties = type.getPropertiesAsArray(); + int size = properties.size(); + for (int i = 0; i < size; i++) { + Property property = properties.get(i); + String propertyName = context + property.getName(); + changedProperties.add(propertyName); + + com.vaadin.client.metadata.Type propertyType = property + .getType(); + if (propertyType.hasProperties()) { + addAllStateFields(propertyType, changedProperties, + 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. + * + * @param json + * the json object to process + * @param changedProperties + * a set of all currently added fields + * @param context + * the base name of the current object + */ + @Deprecated + private static void addJsonFields(JSONObject json, + FastStringSet changedProperties, String context) { + for (String key : json.keySet()) { + String fieldName = context + key; + changedProperties.add(fieldName); + + JSONObject object = json.get(key).isObject(); + if (object != null) { + addJsonFields(object, changedProperties, fieldName + "."); + } + } } } diff --git a/client/src/com/vaadin/client/metadata/Type.java b/client/src/com/vaadin/client/metadata/Type.java index 9c8a52d8e5..c09dffa638 100644 --- a/client/src/com/vaadin/client/metadata/Type.java +++ b/client/src/com/vaadin/client/metadata/Type.java @@ -17,6 +17,7 @@ package com.vaadin.client.metadata; import java.util.Collection; +import com.google.gwt.core.client.JsArrayString; import com.vaadin.client.JsArrayObject; import com.vaadin.client.communication.JSONSerializer; @@ -138,4 +139,8 @@ public class Type { return TypeDataStore.hasProperties(this); } + public JsArrayString getDelegateToWidgetProperties() { + return TypeDataStore.getDelegateToWidgetProperites(this); + } + } diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java index c1eca0a168..dff02749f8 100644 --- a/client/src/com/vaadin/client/metadata/TypeDataStore.java +++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Collection; import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.core.client.JsArrayString; import com.vaadin.client.FastStringMap; import com.vaadin.client.FastStringSet; import com.vaadin.client.JsArrayObject; @@ -35,6 +36,8 @@ public class TypeDataStore { .create(); private final FastStringMap<JsArrayObject<Property>> properties = FastStringMap .create(); + private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap + .create(); private final FastStringSet delayedMethods = FastStringSet.create(); private final FastStringSet lastOnlyMethods = FastStringSet.create(); @@ -118,11 +121,22 @@ public class TypeDataStore { return get().delegateToWidget.get(property.getSignature()); } + public static JsArrayString getDelegateToWidgetProperites(Type type) { + return get().delegateToWidgetProperties.get(type.getSignature()); + } + public void setDelegateToWidget(Class<?> clazz, String propertyName, String delegateValue) { - delegateToWidget.put( - new Property(getType(clazz), propertyName).getSignature(), + Type type = getType(clazz); + delegateToWidget.put(new Property(type, propertyName).getSignature(), delegateValue); + JsArrayString typeProperties = delegateToWidgetProperties.get(type + .getSignature()); + if (typeProperties == null) { + typeProperties = JavaScriptObject.createArray().cast(); + delegateToWidgetProperties.put(type.getSignature(), typeProperties); + } + typeProperties.push(propertyName); } public void setReturnType(Class<?> type, String methodName, Type returnType) { |