blob: a70e09bcd0063eb0595b2f6c5f061839b900ef15 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.databinding;
import java.beans.BeanInfo;
import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
import org.eclipse.core.internal.databinding.property.value.SimplePropertyObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.xwt.IDataProvider;
import org.eclipse.xwt.XWT;
import org.eclipse.xwt.XWTException;
import org.eclipse.xwt.internal.core.ScopeManager;
import org.eclipse.xwt.internal.core.UpdateSourceTrigger;
import org.eclipse.xwt.internal.databinding.menuitem.MenuItemEnabledObservableValue;
import org.eclipse.xwt.internal.databinding.menuitem.MenuItemSelectionObservableValue;
import org.eclipse.xwt.internal.utils.LoggerManager;
import org.eclipse.xwt.internal.utils.UserData;
import org.eclipse.xwt.javabean.metadata.properties.EventProperty;
import org.eclipse.xwt.metadata.IMetaclass;
import org.eclipse.xwt.metadata.IProperty;
/**
*
* @author yyang (yves.yang@soyatec.com)
*/
public class JFaceXWTDataBinding {
static final String ENABLED = "enabled";
static final String SELECTION = "selection";
static final String TEXT = "text";
public static final Class<?>[] CONTROL_ARGUMENT_TYPES = new Class[] { Control.class };
public static final Class<?>[] VIEWER_ARGUMENT_TYPES = new Class[] { Viewer.class };
static String[] VIEWERS_PROPERTIES = null;
static {
Method[] methods = ViewerProperties.class.getDeclaredMethods();
VIEWERS_PROPERTIES = new String[methods.length];
for (int i = 0; i < methods.length; i++) {
VIEWERS_PROPERTIES[i] = methods[i].getName();
}
}
public static boolean isViewerProperty(String propertyName) {
for (String name : VIEWERS_PROPERTIES) {
if (name.equals(propertyName)) {
return true;
}
}
return false;
}
public static Class<?> getValueType(Class<?> type, String propertyName) {
if (type == null || propertyName == null || propertyName.indexOf(".") != -1) {
return null;
}
try {
IMetaclass metaclass = XWT.getMetaclass(type);
IProperty property = metaclass.findProperty(propertyName);
if (property != null) {
return property.getType();
}
} catch (Exception e) {
LoggerManager.log(e);
}
return null;
}
public static Object getValue(Object target, String propertyName) {
if (target == null || propertyName == null || propertyName.indexOf(".") != -1) {
return target;
}
Class<?> type = target.getClass();
try {
BeanInfo beanInfo = java.beans.Introspector.getBeanInfo(type);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : propertyDescriptors) {
if (propertyName.equalsIgnoreCase(pd.getName())) {
Method readMethod = pd.getReadMethod();
if (readMethod != null) {
return readMethod.invoke(target);
}
}
}
Field[] fields = type.getDeclaredFields();
for (Field field : fields) {
if (propertyName.equalsIgnoreCase(field.getName())) {
Object object = field.get(target);
return object;
}
}
return UserData.getLocalData(target, propertyName);
} catch (Exception e) {
LoggerManager.log(e);
}
return null;
}
public static void setValue(Object target, String propertyName, Object value) {
Class<?> type = target.getClass();
try {
BeanInfo beanInfo = java.beans.Introspector.getBeanInfo(type);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : propertyDescriptors) {
if (propertyName.equals(pd.getName())) {
Method writeMethod = pd.getWriteMethod();
if (writeMethod == null) {
return;
}
if (!writeMethod.isAccessible()) {
writeMethod.setAccessible(true);
}
Class<?>[] parameterTypes = writeMethod.getParameterTypes();
Class targetType = parameterTypes[0];
if (targetType != value.getClass()) {
if (targetType.isEnum() && value instanceof String) {
try {
writeMethod.invoke(target, new Object[] { Enum.valueOf(targetType, (String) value) });
return;
} catch (Exception e) {
}
}
IConverter c = XWT.findConvertor(value.getClass(), targetType);
if (c != null) {
value = c.convert(value);
}
}
writeMethod.invoke(target, new Object[] { value });
return;
}
}
Field[] fields = type.getDeclaredFields();
for (Field field : fields) {
if (propertyName.equals(field.getName())) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
Class fieldType = field.getType();
if (fieldType.isEnum() && value instanceof String) {
try {
field.set(target, Enum.valueOf(fieldType, (String) value));
return;
} catch (Exception e) {
}
}
IConverter c = XWT.findConvertor(value.getClass(), fieldType);
if (c != null) {
value = c.convert(value);
}
field.set(target, value);
return;
}
}
IMetaclass metaclass = XWT.getMetaclass(type);
IProperty property = metaclass.findProperty(propertyName);
if (property != null) {
property.setValue(target, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static boolean isPropertyReadOnly(Class<?> type, String propertyName) {
if (type == null || propertyName == null || propertyName.indexOf(".") != -1) {
return true;
}
try {
IMetaclass metaclass = XWT.getMetaclass(type);
IProperty property = metaclass.findProperty(propertyName);
if (property != null) {
return property.isReadOnly();
}
} catch (Exception e) {
LoggerManager.log(e);
}
return true;
}
public static boolean isBeanSupport(Object target) {
Class<?> type = toType(target);
Method method = null;
try {
try {
method = type.getMethod("addPropertyChangeListener", new Class[] { String.class, PropertyChangeListener.class });
} catch (NoSuchMethodException e) {
method = type.getMethod("addPropertyChangeListener", new Class[] { PropertyChangeListener.class });
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
}
return method != null;
}
public static Class<?> toType(Object target) {
Class<?> type = null;
if (target instanceof IObservableValue) {
IObservableValue value = (IObservableValue) target;
Object valueType = value.getValueType();
if (valueType instanceof Class<?>) {
type = (Class<?>) valueType;
}
} else if (target instanceof Class<?>) {
type = (Class<?>)target;
} else if (target instanceof IDataProvider) {
IDataProvider dataProvider = (IDataProvider) target;
type = (Class<?>) toType(dataProvider.getData(null));
} else {
type = target.getClass();
}
if (type == null) {
return Object.class;
}
return type;
}
public static boolean isValueProperty(Class<?> object, String propertyName) {
if (propertyName == null) {
return false;
}
if (Viewer.class.isAssignableFrom(object)) {
return isViewerValueProperty(object, propertyName);
} else if (MenuItem.class.isAssignableFrom(object)) {
//
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=280157
// testcase:
// org.eclipse.xwt.tests.databinding.bindcontrol.BindMenuItem
//
if (ENABLED.equalsIgnoreCase(propertyName)) {
return true;
} else if (SELECTION.equalsIgnoreCase(propertyName)) {
return true;
}
}
boolean isProperty = isControlValueProperty(object, propertyName);
if (isProperty) {
return true;
}
return false;
}
public static IObservable observeWidget(Object object,
String propertyName, UpdateSourceTrigger updateSourceTrigger, int observedKind) {
if (propertyName == null) {
return null;
}
try {
switch (observedKind) {
case ScopeManager.AUTO:
return observePropertyValue(object,
propertyName, updateSourceTrigger);
case ScopeManager.COLLECTION:
case ScopeManager.SET:
case ScopeManager.LIST:
break;
case ScopeManager.VALUE:
return observePropertyValue(object,
propertyName, updateSourceTrigger);
default:
break;
}
} catch (XWTException e) {
}
return null;
}
protected static IObservable observePropertyValue(Object object,
String propertyName, UpdateSourceTrigger updateSourceTrigger) {
if (object instanceof Viewer) {
if ("input".equals(propertyName)) {
Viewer viewer = (Viewer) object;
SimpleValueProperty property = (SimpleValueProperty) ViewerProperties.input();
IObservableValue observableValue = new SimplePropertyObservableValue(XWT.getRealm(), viewer, property);
return new TypedViewerObservableValueDecorator(observableValue, viewer);
}
else if ("singleSelection".equals(propertyName)) {
Viewer viewer = (Viewer) object;
SimpleValueProperty property = (SimpleValueProperty) ViewerProperties.singleSelection();
IObservableValue observableValue = new SimplePropertyObservableValue(XWT.getRealm(), viewer, property);
return new TypedViewerObservableValueDecorator(observableValue, viewer);
}
return observePropertyValue((Viewer) object, propertyName, updateSourceTrigger);
} else if (object instanceof MenuItem) {
//
// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=280157
// testcase:
// org.eclipse.xwt.tests.databinding.bindcontrol.BindMenuItem
//
if (ENABLED.equalsIgnoreCase(propertyName)) {
return new MenuItemEnabledObservableValue((MenuItem) object);
} else if (SELECTION.equalsIgnoreCase(propertyName)) {
return new MenuItemSelectionObservableValue((MenuItem) object);
}
} else if (object instanceof Control) {
return observePropertyValue((Control) object, propertyName, updateSourceTrigger);
}
return null;
}
protected static boolean isControlValueProperty(Class<?> type,
String propertyName) {
if (TEXT.equalsIgnoreCase(propertyName)) {
if (Text.class.isAssignableFrom(type)) {
return true;
}
// widget button is not supported at 3.4 version.
if (SWT.getVersion() == 3449 && Button.class.isAssignableFrom(type)) {
return false;
}
}
String getterName = "observe"
+ propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1);
Method method;
try {
method = SWTObservables.class.getMethod(getterName,
CONTROL_ARGUMENT_TYPES);
if (method == null) {
for (Method element : SWTObservables.class.getMethods()) {
if (element.getParameterTypes().length != 0) {
continue;
}
if (element.getName().equalsIgnoreCase(getterName)) {
return true;
}
}
}
} catch (Exception e) {
throw new XWTException(e);
}
IMetaclass mateclass = XWT.getMetaclass(type);
IProperty property = mateclass.findProperty(propertyName);
if (property instanceof EventProperty) {
return true;
}
return false;
}
protected static IObservableValue observePropertyValue(Control control,
String propertyName, UpdateSourceTrigger updateSourceTrigger) {
if (TEXT.equalsIgnoreCase(propertyName)) {
if (control instanceof Text || control instanceof StyledText) {
int event = SWT.None;
switch (updateSourceTrigger) {
case Default:
event = SWT.FocusOut;
break;
case LostFocus:
event = SWT.FocusOut;
break;
case PropertyChanged:
event = SWT.Modify;
break;
default:
throw new IllegalStateException("UpdateSourceTrigger of value " + updateSourceTrigger.name());
}
IObservableValue observableValue = SWTObservables.observeText(
control, event);
if (observableValue != null) {
return observableValue;
}
}
// widget button is not supported at 3.4 version.
if (SWT.getVersion() == 3449 && control instanceof Button) {
return null;
}
try {
IObservableValue observableValue = SWTObservables
.observeText(control);
if (observableValue != null) {
return observableValue;
}
} catch (IllegalArgumentException e) {
throw new XWTException(e);
}
} else {
if (propertyName == null) {
return null;
}
String getterName = "observe"
+ propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1);
Method method;
try {
method = SWTObservables.class.getMethod(getterName,
CONTROL_ARGUMENT_TYPES);
if (method == null) {
for (Method element : SWTObservables.class.getMethods()) {
if (element.getParameterTypes().length != 0) {
continue;
}
if (element.getName().equalsIgnoreCase(getterName)) {
method = element;
break;
}
}
}
if (method != null) {
IObservableValue observableValue = (IObservableValue) method
.invoke(null, control);
if (observableValue != null) {
return observableValue;
}
}
} catch (Exception e) {
throw new XWTException(e);
}
}
IMetaclass mateclass = XWT.getMetaclass(control);
IProperty property = mateclass.findProperty(propertyName);
if (property instanceof EventProperty) {
return new EventPropertyObservableValue(control,
(EventProperty) property);
}
return null;
}
protected static boolean isViewerValueProperty(Class<?> viewerType,
String property) {
String getterName = "observe" + property.substring(0, 1).toUpperCase()
+ property.substring(1);
try {
Method method = ViewersObservables.class.getMethod(getterName,
VIEWER_ARGUMENT_TYPES);
if (method == null) {
for (Method element : ViewersObservables.class.getMethods()) {
if (element.getParameterTypes().length != 0) {
continue;
}
if (element.getName().equalsIgnoreCase(getterName)) {
return true;
}
}
}
} catch (Exception e) {
throw new XWTException(e);
}
return false;
}
protected static IObservable observePropertyValue(Viewer viewer,
String property, UpdateSourceTrigger updateSourceTrigger) {
String getterName = "observe" + property.substring(0, 1).toUpperCase()
+ property.substring(1);
Method method;
try {
method = ViewersObservables.class.getMethod(getterName,
VIEWER_ARGUMENT_TYPES);
if (method == null) {
for (Method element : ViewersObservables.class.getMethods()) {
if (element.getParameterTypes().length != 0) {
continue;
}
if (element.getName().equalsIgnoreCase(getterName)) {
method = element;
break;
}
}
}
if (method != null) {
IObservable observableValue = (IObservable) method
.invoke(null, viewer);
if (observableValue != null) {
return observableValue;
}
}
} catch (Exception e) {
throw new XWTException(e);
}
return null;
}
}