Browse Source

Implement @OnStateChange (#12958)

Change-Id: I8ea2b781fab42458bf55a751c1229e391365e965
tags/7.2.0.beta1
Leif Åstrand 10 years ago
parent
commit
7bfb2347ad

+ 90
- 1
client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java View File

@@ -46,8 +46,10 @@ import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.vaadin.client.JsArrayObject;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.metadata.ConnectorBundleLoader;
import com.vaadin.client.metadata.InvokationHandler;
import com.vaadin.client.metadata.OnStateChangeMethod;
import com.vaadin.client.metadata.ProxyHandler;
import com.vaadin.client.metadata.TypeData;
import com.vaadin.client.metadata.TypeDataStore;
@@ -56,6 +58,7 @@ import com.vaadin.server.widgetsetutils.metadata.ClientRpcVisitor;
import com.vaadin.server.widgetsetutils.metadata.ConnectorBundle;
import com.vaadin.server.widgetsetutils.metadata.ConnectorInitVisitor;
import com.vaadin.server.widgetsetutils.metadata.GeneratedSerializer;
import com.vaadin.server.widgetsetutils.metadata.OnStateChangeVisitor;
import com.vaadin.server.widgetsetutils.metadata.Property;
import com.vaadin.server.widgetsetutils.metadata.ServerRpcVisitor;
import com.vaadin.server.widgetsetutils.metadata.StateInitVisitor;
@@ -463,6 +466,92 @@ public class ConnectorBundleLoaderFactory extends Generator {
writePropertyTypes(logger, w, bundle);
writeSerializers(logger, w, bundle);
writeDelegateToWidget(logger, w, bundle);
writeOnStateChangeHandlers(logger, w, bundle);
}

private void writeOnStateChangeHandlers(TreeLogger logger,
SplittingSourceWriter w, ConnectorBundle bundle)
throws UnableToCompleteException {
Map<JClassType, Set<JMethod>> needsOnStateChangeHandler = bundle
.getNeedsOnStateChangeHandler();
for (Entry<JClassType, Set<JMethod>> entry : needsOnStateChangeHandler
.entrySet()) {
JClassType connector = entry.getKey();

TreeLogger typeLogger = logger.branch(
Type.DEBUG,
"Generating @OnStateChange support for "
+ connector.getName());

// Build map to speed up error checking
HashMap<String, Property> stateProperties = new HashMap<String, Property>();
JClassType stateType = ConnectorBundle
.findInheritedMethod(connector, "getState").getReturnType()
.isClassOrInterface();
for (Property property : bundle.getProperties(stateType)) {
stateProperties.put(property.getName(), property);
}

for (JMethod method : entry.getValue()) {
TreeLogger methodLogger = typeLogger.branch(Type.DEBUG,
"Processing method " + method.getName());

if (method.isPublic() || method.isProtected()) {
methodLogger
.log(Type.ERROR,
"@OnStateChange is only supported for methods with private or default visibility.");
throw new UnableToCompleteException();
}

OnStateChange onStateChange = method
.getAnnotation(OnStateChange.class);

String[] properties = onStateChange.value();

if (properties.length == 0) {
methodLogger.log(Type.ERROR,
"There are no properties to listen to");
throw new UnableToCompleteException();
}

// Verify that all properties do exist
for (String propertyName : properties) {
if (!stateProperties.containsKey(propertyName)) {
methodLogger.log(Type.ERROR,
"State class has no property named "
+ propertyName);
throw new UnableToCompleteException();
}
}

if (method.getParameters().length != 0) {
methodLogger.log(Type.ERROR,
"Method should accept zero parameters");
throw new UnableToCompleteException();
}

// new OnStateChangeMethod(Class declaringClass, String
// methodName, String[], properties)
w.print("store.addOnStateChangeMethod(%s, new %s(",
getClassLiteralString(connector),
OnStateChangeMethod.class.getName());
if (!connector.equals(method.getEnclosingType())) {
w.print("%s, ",
getClassLiteralString(method.getEnclosingType()));
}
w.print("\"%s\", ", method.getName());

w.print("new String[] {");
for (String propertyName : properties) {
w.print("\"%s\", ", propertyName);
}
w.print("}");

w.println("));");

w.splitIfNeeded();
}
}
}

private void writeSuperClasses(SplittingSourceWriter w,
@@ -1109,7 +1198,7 @@ public class ConnectorBundleLoaderFactory extends Generator {
List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList(
new ConnectorInitVisitor(), new StateInitVisitor(),
new WidgetInitVisitor(), new ClientRpcVisitor(),
new ServerRpcVisitor());
new ServerRpcVisitor(), new OnStateChangeVisitor());
for (TypeVisitor typeVisitor : visitors) {
typeVisitor.init(oracle);
}

+ 46
- 4
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java View File

@@ -69,6 +69,7 @@ public class ConnectorBundle {
private final Map<JClassType, Set<JMethod>> needsInvoker = new HashMap<JClassType, Set<JMethod>>();
private final Map<JClassType, Set<JMethod>> needsParamTypes = new HashMap<JClassType, Set<JMethod>>();
private final Map<JClassType, Set<JMethod>> needsDelayedInfo = new HashMap<JClassType, Set<JMethod>>();
private final Map<JClassType, Set<JMethod>> needsOnStateChange = new HashMap<JClassType, Set<JMethod>>();

private final Set<Property> needsProperty = new HashSet<Property>();
private final Set<Property> needsDelegateToWidget = new HashSet<Property>();
@@ -199,7 +200,7 @@ public class ConnectorBundle {
JType type = iterator.next();
iterator.remove();

if (hasSserializeSupport(type)) {
if (hasSerializeSupport(type)) {
continue;
}

@@ -516,7 +517,7 @@ public class ConnectorBundle {
}

public void setNeedsSerialize(JType type) {
if (!hasSserializeSupport(type)) {
if (!hasSerializeSupport(type)) {
needsSerializeSupport.add(type);
}
}
@@ -557,12 +558,12 @@ public class ConnectorBundle {
return false;
}

private boolean hasSserializeSupport(JType type) {
private boolean hasSerializeSupport(JType type) {
if (hasSerializeSupport.contains(type)) {
return true;
} else {
return previousBundle != null
&& previousBundle.hasSserializeSupport(type);
&& previousBundle.hasSerializeSupport(type);
}
}

@@ -585,4 +586,45 @@ public class ConnectorBundle {
return Collections.unmodifiableSet(needsDelegateToWidget);
}

public void setNeedsOnStateChangeHandler(JClassType type, JMethod method) {
if (!isNeedsOnStateChangeHandler(type, method)) {
addMapping(needsOnStateChange, type, method);
}
}

private boolean isNeedsOnStateChangeHandler(JClassType type, JMethod method) {
if (hasMapping(needsOnStateChange, type, method)) {
return true;
} else {
return previousBundle != null
&& previousBundle.isNeedsOnStateChangeHandler(type, method);
}
}

public Map<JClassType, Set<JMethod>> getNeedsOnStateChangeHandler() {
return Collections.unmodifiableMap(needsOnStateChange);
}

public static JMethod findInheritedMethod(JClassType type,
String methodName, JType... params) {

JClassType currentType = type;
while (currentType != null) {
JMethod method = currentType.findMethod(methodName, params);
if (method != null) {
return method;
}
currentType = currentType.getSuperclass();
}

JClassType[] interfaces = type.getImplementedInterfaces();
for (JClassType iface : interfaces) {
JMethod method = iface.findMethod(methodName, params);
if (method != null) {
return method;
}
}

return null;
}
}

+ 54
- 0
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/OnStateChangeVisitor.java View File

@@ -0,0 +1,54 @@
/*
* Copyright 2000-2013 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server.widgetsetutils.metadata;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.shared.ui.Connect;

/**
* Visits Connector classes and check for methods with @OnStateChange
* annotations.
*
* @since 7.2
* @author Vaadin Ltd
*/
public class OnStateChangeVisitor extends TypeVisitor {

@Override
public void visitConnector(TreeLogger logger, JClassType type,
ConnectorBundle bundle) throws UnableToCompleteException {
Connect connectAnnotation = type.getAnnotation(Connect.class);
if (connectAnnotation != null) {
// Find all the annotated methods in all the superclasses
JClassType connector = type;
while (connector != null) {
for (JMethod method : connector.getMethods()) {
if (method.getAnnotation(OnStateChange.class) != null) {
bundle.setNeedsInvoker(connector, method);
bundle.setNeedsOnStateChangeHandler(type, method);
}
}

connector = connector.getSuperclass();
}
}
}

}

+ 2
- 1
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/StateInitVisitor.java View File

@@ -24,7 +24,8 @@ public class StateInitVisitor extends TypeVisitor {
@Override
public void visitConnector(TreeLogger logger, JClassType type,
ConnectorBundle bundle) {
JMethod getState = findInheritedMethod(type, "getState");
JMethod getState = ConnectorBundle
.findInheritedMethod(type, "getState");
bundle.setNeedsReturnType(type, getState);

bundle.setNeedsSerialize(getState.getReturnType());

+ 0
- 25
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/TypeVisitor.java View File

@@ -18,8 +18,6 @@ package com.vaadin.server.widgetsetutils.metadata;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
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.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;

@@ -43,27 +41,4 @@ public abstract class TypeVisitor {
// Default does nothing
}

protected JMethod findInheritedMethod(JClassType type, String methodName,
JType... params) {

JClassType currentType = type;
while (currentType != null) {
JMethod method = currentType.findMethod(methodName, params);
if (method != null) {
return method;
}
currentType = currentType.getSuperclass();
}

JClassType[] interfaces = type.getImplementedInterfaces();
for (JClassType iface : interfaces) {
JMethod method = iface.findMethod(methodName, params);
if (method != null) {
return method;
}
}

return null;
}

}

+ 9
- 6
client-compiler/src/com/vaadin/server/widgetsetutils/metadata/WidgetInitVisitor.java View File

@@ -32,10 +32,11 @@ public class WidgetInitVisitor extends TypeVisitor {
ConnectorBundle bundle) throws UnableToCompleteException {
if (ConnectorBundle.isConnectedComponentConnector(type)) {
// The class in which createWidget is implemented
JClassType createWidgetClass = findInheritedMethod(type,
"createWidget").getEnclosingType();
JClassType createWidgetClass = ConnectorBundle.findInheritedMethod(
type, "createWidget").getEnclosingType();

JMethod getWidget = findInheritedMethod(type, "getWidget");
JMethod getWidget = ConnectorBundle.findInheritedMethod(type,
"getWidget");
JClassType widgetType = getWidget.getReturnType().isClass();

// Needs GWT constructor if createWidget is not overridden
@@ -48,7 +49,8 @@ public class WidgetInitVisitor extends TypeVisitor {
}

// Check state properties for @DelegateToWidget
JMethod getState = findInheritedMethod(type, "getState");
JMethod getState = ConnectorBundle.findInheritedMethod(type,
"getState");
JClassType stateType = getState.getReturnType().isClass();

Collection<Property> properties = bundle.getProperties(stateType);
@@ -63,8 +65,9 @@ public class WidgetInitVisitor extends TypeVisitor {
String methodName = DelegateToWidget.Helper
.getDelegateTarget(property.getName(),
delegateToWidget.value());
JMethod delegatedSetter = findInheritedMethod(widgetType,
methodName, property.getPropertyType());
JMethod delegatedSetter = ConnectorBundle
.findInheritedMethod(widgetType, methodName,
property.getPropertyType());
if (delegatedSetter == null) {
logger.log(
Type.ERROR,

+ 50
- 0
client/src/com/vaadin/client/annotations/OnStateChange.java View File

@@ -0,0 +1,50 @@
/*
* Copyright 2000-2013 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.client.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.vaadin.client.communication.StateChangeEvent;

/**
* Marks a method in Connector classes that should be used to handle changes to
* specific properties in the connector's shared state.
* <p>
* The annotated method will by called whenever at least one of the named state
* properties have changed. If multiple listened properties are changed by the
* same {@link StateChangeEvent}, the method will only be called once.
* <p>
* If there is no state variable with the provided name, the widgetset
* compilation will fail.
*
* @since 7.2
* @author Vaadin Ltd
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface OnStateChange {
/**
* Defines a list of property names to listen for.
*
* @return an array of property names, should contain at least one item
*/
public String[] value();
}

+ 111
- 0
client/src/com/vaadin/client/metadata/OnStateChangeMethod.java View File

@@ -0,0 +1,111 @@
/*
* Copyright 2000-2013 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.client.metadata;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.vaadin.client.ServerConnector;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;

/**
* Encapsulates the data that the widgetset compiler generates for supporting a
* connector method annotated with {@link OnStateChange}
*
* @since 7.2
* @author Vaadin Ltd
*/
public class OnStateChangeMethod {

private final String methodName;
private final List<String> properties;
private final Class<?> declaringClass;

/**
* Creates a new instance based on a method name, a list of parameters names
* and a list of properties to listen for.
*
* @param methodName
* the name of the method to call
* @param properties
* an array of state property names to listen to
*/
public OnStateChangeMethod(String methodName, String[] properties) {
this(null, methodName, properties);
}

/**
* Creates a new instance based on declaring class, a method name, a list of
* parameters names and a list of properties to listen for.
* <p>
* If the declaring class is <code>null</code>, the method is found based on
* the type of the connector that fired the state change event.
*
* @param declaringClass
* the class in which the target method is declared, or
* <code>null</code> to use the class of the connector firing the
* event
* @param methodName
* the name of the method to call
* @param properties
* an array of state property names to listen to
*/
public OnStateChangeMethod(Class<?> declaringClass, String methodName,
String[] properties) {

this.methodName = methodName;

this.properties = Collections.unmodifiableList(Arrays
.asList(properties));

this.declaringClass = declaringClass;
}

/**
* Invokes the listener method for a state change.
*
* @param stateChangeEvent
* the state change event
*/
public void invoke(StateChangeEvent stateChangeEvent) {
ServerConnector connector = (ServerConnector) stateChangeEvent
.getSource();

Class<?> declaringClass = this.declaringClass;
if (declaringClass == null) {
declaringClass = connector.getClass();
}
Type declaringType = TypeDataStore.getType(declaringClass);

try {
declaringType.getMethod(methodName).invoke(connector);
} catch (NoDataException e) {
throw new RuntimeException("Couldn't invoke @OnStateChange method "
+ declaringType.getSignature() + "." + methodName, e);
}
}

/**
* Gets the list of state property names to listen for.
*
* @return the list of state property names to listen for
*/
public List<String> getProperties() {
return properties;
}
}

+ 50
- 0
client/src/com/vaadin/client/metadata/TypeDataStore.java View File

@@ -23,6 +23,7 @@ import com.google.gwt.core.client.JsArrayString;
import com.vaadin.client.FastStringMap;
import com.vaadin.client.FastStringSet;
import com.vaadin.client.JsArrayObject;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.JSONSerializer;

public class TypeDataStore {
@@ -37,6 +38,12 @@ public class TypeDataStore {
private final FastStringMap<JsArrayString> delegateToWidgetProperties = FastStringMap
.create();

/**
* Maps connector class -> state property name -> hander method data
*/
private final FastStringMap<FastStringMap<JsArrayObject<OnStateChangeMethod>>> onStateChangeMethods = FastStringMap
.create();

private final FastStringSet delayedMethods = FastStringSet.create();
private final FastStringSet lastOnlyMethods = FastStringSet.create();

@@ -368,4 +375,47 @@ public class TypeDataStore {
return typeData[beanName] !== undefined ;
}-*/;

/**
* Gets data for all methods annotated with {@link OnStateChange} in the
* given connector type.
*
* @since 7.2
* @param type
* the connector type
* @return a map of state property names to handler method data
*/
public static FastStringMap<JsArrayObject<OnStateChangeMethod>> getOnStateChangeMethods(
Class<?> type) {
return get().onStateChangeMethods.get(getType(type).getSignature());
}

/**
* Adds data about a method annotated with {@link OnStateChange} for the
* given connector type.
*
* @since 7.2
* @param clazz
* the connector type
* @param method
* the state change method data
*/
public void addOnStateChangeMethod(Class<?> clazz,
OnStateChangeMethod method) {
FastStringMap<JsArrayObject<OnStateChangeMethod>> handlers = getOnStateChangeMethods(clazz);
if (handlers == null) {
handlers = FastStringMap.create();
onStateChangeMethods.put(getType(clazz).getSignature(), handlers);
}

for (String property : method.getProperties()) {
JsArrayObject<OnStateChangeMethod> propertyHandlers = handlers
.get(property);
if (propertyHandlers == null) {
propertyHandlers = JsArrayObject.createArray().cast();
handlers.put(property, propertyHandlers);
}

propertyHandlers.add(method);
}
}
}

+ 35
- 0
client/src/com/vaadin/client/ui/AbstractConnector.java View File

@@ -18,6 +18,7 @@ package com.vaadin.client.ui;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@@ -27,6 +28,7 @@ import com.google.gwt.event.shared.HandlerManager;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.FastStringMap;
import com.vaadin.client.JsArrayObject;
import com.vaadin.client.Profiler;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.Util;
@@ -35,8 +37,10 @@ import com.vaadin.client.communication.RpcProxy;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
import com.vaadin.client.metadata.NoDataException;
import com.vaadin.client.metadata.OnStateChangeMethod;
import com.vaadin.client.metadata.Type;
import com.vaadin.client.metadata.TypeData;
import com.vaadin.client.metadata.TypeDataStore;
import com.vaadin.shared.communication.ClientRpc;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.communication.SharedState;
@@ -290,6 +294,37 @@ public abstract class AbstractConnector implements ServerConnector,
}

updateEnabledState(isEnabled());

FastStringMap<JsArrayObject<OnStateChangeMethod>> handlers = TypeDataStore
.getOnStateChangeMethods(getClass());
if (handlers != null) {
Profiler.enter("AbstractConnector.onStateChanged @OnStateChange");

HashSet<OnStateChangeMethod> invokedMethods = new HashSet<OnStateChangeMethod>();

JsArrayString propertyNames = handlers.getKeys();
for (int i = 0; i < propertyNames.length(); i++) {
String propertyName = propertyNames.get(i);

if (stateChangeEvent.hasPropertyChanged(propertyName)) {
JsArrayObject<OnStateChangeMethod> propertyMethods = handlers
.get(propertyName);

for (int j = 0; j < propertyMethods.size(); j++) {
OnStateChangeMethod method = propertyMethods.get(j);

if (invokedMethods.add(method)) {

method.invoke(stateChangeEvent);

}
}
}
}

Profiler.leave("AbstractConnector.onStateChanged @OnStateChange");
}

Profiler.leave("AbstractConnector.onStateChanged");
}


+ 47
- 48
client/src/com/vaadin/client/ui/button/ButtonConnector.java View File

@@ -26,8 +26,8 @@ import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.vaadin.client.EventHelper;
import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.VButton;
@@ -56,44 +56,38 @@ 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().errorMessage) {
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("resources", new StateChangeHandler() {
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
if (getWidget().icon != null) {
getWidget().wrapper.removeChild(getWidget().icon
.getElement());
getWidget().icon = null;
}
Icon icon = getIcon();
if (icon != null) {
getWidget().icon = icon;
icon.setAlternateText(getState().iconAltText);
getWidget().wrapper.insertBefore(icon.getElement(),
getWidget().captionElement);
}
}

@OnStateChange("errorMessage")
void setErrorMessage() {
if (null != getState().errorMessage) {
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;
}
}

@OnStateChange("resources")
void onResourceChange() {
if (getWidget().icon != null) {
getWidget().wrapper.removeChild(getWidget().icon.getElement());
getWidget().icon = null;
}
Icon icon = getIcon();
if (icon != null) {
getWidget().icon = icon;
icon.setAlternateText(getState().iconAltText);
getWidget().wrapper.insertBefore(icon.getElement(),
getWidget().captionElement);
}
}

@Override
@@ -103,22 +97,27 @@ public class ButtonConnector extends AbstractComponentConnector implements
focusHandlerRegistration);
blurHandlerRegistration = EventHelper.updateBlurHandler(this,
blurHandlerRegistration);
}

if (stateChangeEvent.hasPropertyChanged("caption")
|| stateChangeEvent.hasPropertyChanged("htmlContentAllowed")) {
// Set text
if (getState().htmlContentAllowed) {
getWidget().setHtml(getState().caption);
} else {
getWidget().setText(getState().caption);
}
@OnStateChange({ "caption", "htmlContentAllowed" })
void setCaption() {
String caption = getState().caption;
if (getState().htmlContentAllowed) {
getWidget().setHtml(caption);
} else {
getWidget().setText(caption);
}
}

if (getWidget().icon != null
&& stateChangeEvent.hasPropertyChanged("iconAltText")) {
@OnStateChange("iconAltText")
void setIconAltText() {
if (getWidget().icon != null) {
getWidget().icon.setAlternateText(getState().iconAltText);
}
}

@OnStateChange("clickShortcutKeyCode")
void setClickShortcut() {
getWidget().clickShortcut = getState().clickShortcutKeyCode;
}


Loading…
Cancel
Save