From e81cf22601718cd7909fea1db295bb538b104c9a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Thu, 16 Aug 2012 15:46:11 +0300 Subject: [PATCH] Support StateChangeHandler for selected parts of the state (#8598) --- .../gwt/client/ApplicationConnection.java | 33 +++++++- .../terminal/gwt/client/ServerConnector.java | 17 +++- .../communication/StateChangeEvent.java | 41 ++++++++- .../gwt/client/ui/AbstractConnector.java | 31 +++++++ .../gwt/client/ui/button/ButtonConnector.java | 84 ++++++++++++------- 5 files changed, 169 insertions(+), 37 deletions(-) diff --git a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 664a73dc12..32b15d6d87 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/client/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -1473,9 +1473,12 @@ public class ApplicationConnection { .getName(), null), stateJson, state, ApplicationConnection.this); - StateChangeEvent event = GWT - .create(StateChangeEvent.class); - event.setConnector(connector); + Set changedProperties = new HashSet(); + addJsonFields(stateJson, changedProperties, ""); + + StateChangeEvent event = new StateChangeEvent( + connector, changedProperties); + events.add(event); } } catch (final Throwable e) { @@ -1486,6 +1489,30 @@ public class ApplicationConnection { return events; } + /** + * 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, Set 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 diff --git a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java index ff37f04f04..8788de74bf 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ServerConnector.java @@ -75,7 +75,7 @@ public interface ServerConnector extends Connector { String rpcInterfaceId); /** - * Adds a handler that is called whenever some part of the state has been + * Adds a handler that is called whenever any part of the state has been * updated by the server. * * @param handler @@ -85,6 +85,21 @@ public interface ServerConnector extends Connector { */ public HandlerRegistration addStateChangeHandler(StateChangeHandler handler); + /** + * Adds a handler that is called whenever the given part of the state has + * been updated by the server. + * + * @param propertyName + * the name of the property for which the handler should be + * called + * @param handler + * The handler that should be added. + * @return A handler registration reference that can be used to unregister + * the handler + */ + public HandlerRegistration addStateChangeHandler(String propertyName, + StateChangeHandler handler); + /** * Sends the given event to all registered handlers. * diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java b/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java index e1847bdab7..8ed32bc94b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java +++ b/client/src/com/vaadin/terminal/gwt/client/communication/StateChangeEvent.java @@ -16,8 +16,11 @@ package com.vaadin.terminal.gwt.client.communication; import java.io.Serializable; +import java.util.Collections; +import java.util.Set; import com.google.gwt.event.shared.EventHandler; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; public class StateChangeEvent extends @@ -27,12 +30,25 @@ public class StateChangeEvent extends */ public static final Type TYPE = new Type(); + private Set changedProperties; + @Override public Type getAssociatedType() { return TYPE; } - public StateChangeEvent() { + /** + * Creates a new state change event. + * + * @param connector + * the event whose state has changed + * @param changedProperties + * a set of names of the changed properties + */ + public StateChangeEvent(ServerConnector connector, + Set changedProperties) { + setConnector(connector); + this.changedProperties = changedProperties; } @Override @@ -40,7 +56,30 @@ public class StateChangeEvent extends listener.onStateChanged(this); } + /** + * Event handler that gets notified whenever any part of the state has been + * updated by the server. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0.0 + */ public interface StateChangeHandler extends Serializable, EventHandler { + /** + * Notifies the event handler that the state has changed. + * + * @param stateChangeEvent + * the state change event with details about the change + */ public void onStateChanged(StateChangeEvent stateChangeEvent); } + + /** + * Gets the properties that have changed. + * + * @return a set of names of the changed properties + */ + public Set getChangedProperties() { + return Collections.unmodifiableSet(changedProperties); + } } 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 514f63fdd8..435fff8a5b 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java @@ -48,6 +48,7 @@ public abstract class AbstractConnector implements ServerConnector, private String id; private HandlerManager handlerManager; + private Map statePropertyHandlerManagers; private Map> rpcImplementations; private final boolean debugLogging = false; @@ -168,6 +169,17 @@ public abstract class AbstractConnector implements ServerConnector, if (handlerManager != null) { handlerManager.fireEvent(event); } + if (statePropertyHandlerManagers != null + && event instanceof StateChangeEvent) { + for (String property : ((StateChangeEvent) event) + .getChangedProperties()) { + HandlerManager manager = statePropertyHandlerManagers + .get(property); + if (manager != null) { + manager.fireEvent(event); + } + } + } } protected HandlerManager ensureHandlerManager() { @@ -184,6 +196,25 @@ public abstract class AbstractConnector implements ServerConnector, .addHandler(StateChangeEvent.TYPE, handler); } + @Override + public HandlerRegistration addStateChangeHandler(String propertyName, + StateChangeHandler handler) { + return ensureHandlerManager(propertyName).addHandler( + StateChangeEvent.TYPE, handler); + } + + private HandlerManager ensureHandlerManager(String propertyName) { + if (statePropertyHandlerManagers == null) { + statePropertyHandlerManagers = new HashMap(); + } + HandlerManager manager = statePropertyHandlerManagers.get(propertyName); + if (manager == null) { + manager = new HandlerManager(this); + statePropertyHandlerManagers.put(propertyName, manager); + } + return manager; + } + @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { if (debugLogging) { diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java index 59e187014c..59f90a9840 100644 --- a/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java +++ b/client/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java @@ -16,6 +16,8 @@ package com.vaadin.terminal.gwt.client.ui.button; +import java.util.Set; + import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -34,6 +36,7 @@ import com.vaadin.terminal.gwt.client.EventHelper; import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder; import com.vaadin.terminal.gwt.client.communication.RpcProxy; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.Icon; import com.vaadin.ui.Button; @@ -59,6 +62,47 @@ public class ButtonConnector extends AbstractComponentConnector implements super.init(); getWidget().addClickHandler(this); getWidget().client = getConnection(); + addStateChangeHandler("errorMessage", new StateChangeHandler() { + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + if (null != getState().getErrorMessage()) { + if (getWidget().errorIndicatorElement == null) { + getWidget().errorIndicatorElement = DOM.createSpan(); + getWidget().errorIndicatorElement + .setClassName("v-errorindicator"); + } + getWidget().wrapper.insertBefore( + getWidget().errorIndicatorElement, + getWidget().captionElement); + + } else if (getWidget().errorIndicatorElement != null) { + getWidget().wrapper + .removeChild(getWidget().errorIndicatorElement); + getWidget().errorIndicatorElement = null; + } + } + }); + + addStateChangeHandler("icon", new StateChangeHandler() { + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + if (getState().getIcon() != null) { + if (getWidget().icon == null) { + getWidget().icon = new Icon(getConnection()); + getWidget().wrapper.insertBefore( + getWidget().icon.getElement(), + getWidget().captionElement); + } + getWidget().icon.setUri(getState().getIcon().getURL()); + } else { + if (getWidget().icon != null) { + getWidget().wrapper.removeChild(getWidget().icon + .getElement()); + getWidget().icon = null; + } + } + } + }); } @Override @@ -68,39 +112,15 @@ public class ButtonConnector extends AbstractComponentConnector implements focusHandlerRegistration); blurHandlerRegistration = EventHelper.updateBlurHandler(this, blurHandlerRegistration); - // Set text - if (getState().isHtmlContentAllowed()) { - getWidget().setHtml(getState().getCaption()); - } else { - getWidget().setText(getState().getCaption()); - } - // handle error - if (null != getState().getErrorMessage()) { - if (getWidget().errorIndicatorElement == null) { - getWidget().errorIndicatorElement = DOM.createSpan(); - getWidget().errorIndicatorElement - .setClassName("v-errorindicator"); - } - getWidget().wrapper.insertBefore(getWidget().errorIndicatorElement, - getWidget().captionElement); - - } else if (getWidget().errorIndicatorElement != null) { - getWidget().wrapper.removeChild(getWidget().errorIndicatorElement); - getWidget().errorIndicatorElement = null; - } - - if (getState().getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().wrapper.insertBefore(getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getState().getIcon().getURL()); - } else { - if (getWidget().icon != null) { - getWidget().wrapper.removeChild(getWidget().icon.getElement()); - getWidget().icon = null; + Set changedProperties = stateChangeEvent.getChangedProperties(); + if (changedProperties.contains("caption") + || changedProperties.contains("htmlContentAllowed")) { + // Set text + if (getState().isHtmlContentAllowed()) { + getWidget().setHtml(getState().getCaption()); + } else { + getWidget().setText(getState().getCaption()); } } -- 2.39.5