Mercurial > projects > dwt2
diff org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.d @ 95:6208d4f6a277
Added trees for databinding.beans and observable
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 21 Apr 2009 10:55:51 +0200 |
parents | |
children | b74ac5dfcc06 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.d Tue Apr 21 10:55:51 2009 +0200 @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Brad Reynolds - bug 164653 + * Brad Reynolds - bug 164134, 171616 + *******************************************************************************/ +package org.eclipse.core.internal.databinding.beans; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.eclipse.core.databinding.BindingException; +import org.eclipse.core.databinding.beans.BeansObservables; +import org.eclipse.core.databinding.beans.IBeanObservable; +import org.eclipse.core.databinding.observable.Diffs; +import org.eclipse.core.databinding.observable.Realm; +import org.eclipse.core.databinding.observable.value.AbstractObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; +import org.eclipse.core.databinding.util.Policy; +import org.eclipse.core.internal.databinding.Util; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @since 1.0 + * + */ +public class JavaBeanObservableValue : AbstractObservableValue , IBeanObservable { + private final Object object; + private bool updating = false; + + private final PropertyDescriptor propertyDescriptor; + private ListenerSupport listenerSupport; + + private bool attachListeners; + + /** + * @param realm + * @param object + * @param descriptor + */ + public this(Realm realm, Object object, + PropertyDescriptor descriptor) { + this(realm, object, descriptor, true); + } + + /** + * @param realm + * @param object + * @param descriptor + * @param attachListeners + */ + public this(Realm realm, Object object, + PropertyDescriptor descriptor, bool attachListeners) { + super(realm); + this.object = object; + this.propertyDescriptor = descriptor; + this.attachListeners = attachListeners; + } + + protected void firstListenerAdded() { + if (!attachListeners) { + return; + } + + PropertyChangeListener listener = new class() PropertyChangeListener { + public void propertyChange(java.beans.PropertyChangeEvent event) { + if (!updating) { + final ValueDiff diff = Diffs.createValueDiff(event.getOldValue(), + event.getNewValue()); + getRealm().exec(new class() Runnable { + public void run() { + fireValueChange(diff); + }}); + } + } + }; + + if (listenerSupport is null) { + listenerSupport = new ListenerSupport(listener, propertyDescriptor.getName()); + } + + listenerSupport.hookListener(object); + } + + public void doSetValue(Object value) { + updating = true; + try { + Object oldValue = doGetValue(); + + if (Util.equals(oldValue, value)) { + return; + } + + Method writeMethod = propertyDescriptor.getWriteMethod(); + if (!writeMethod.isAccessible()) { + writeMethod.setAccessible(true); + } + writeMethod.invoke(object, new Object[] { value }); + fireValueChange(Diffs.createValueDiff(oldValue, doGetValue())); + } catch (InvocationTargetException e) { + /* + * InvocationTargetException wraps any exception thrown by the + * invoked method. + */ + throw new RuntimeException(e.getCause()); + } catch (Exception e) { + if cast(BeansObservables.DEBUG) { + Policy + .getLog() + .log( + new Status( + IStatus.WARNING, + Policy.JFACE_DATABINDING, + IStatus.OK, + "Could not change value of " + object + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$ + } + } finally { + updating = false; + } + } + + public Object doGetValue() { + try { + Method readMethod = propertyDescriptor.getReadMethod(); + if (readMethod is null) { + throw new BindingException(propertyDescriptor.getName() + + " property does not have a read method."); //$NON-NLS-1$ + } + if (!readMethod.isAccessible()) { + readMethod.setAccessible(true); + } + return readMethod.invoke(object, null); + } catch (InvocationTargetException e) { + /* + * InvocationTargetException wraps any exception thrown by the + * invoked method. + */ + throw new RuntimeException(e.getCause()); + } catch (Exception e) { + if cast(BeansObservables.DEBUG) { + Policy + .getLog() + .log( + new Status( + IStatus.WARNING, + Policy.JFACE_DATABINDING, + IStatus.OK, + "Could not read value of " + object + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$ + } + return null; + } + } + + protected void lastListenerRemoved() { + unhookListener(); + } + + private void unhookListener() { + if (listenerSupport !is null) { + listenerSupport.dispose(); + listenerSupport = null; + } + } + + public Object getValueType() { + return propertyDescriptor.getPropertyType(); + } + + public Object getObserved() { + return object; + } + + public PropertyDescriptor getPropertyDescriptor() { + return propertyDescriptor; + } + + public synchronized void dispose() { + unhookListener(); + super.dispose(); + } +}