/******************************************************************************* * Copyright (c) 2008 Matthew Hall 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: * Matthew Hall - initial API and implementation (bug 194734) ******************************************************************************/ package org.eclipse.core.internal.databinding.property.value; 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.property.INativePropertyListener; import org.eclipse.core.databinding.property.IProperty; import org.eclipse.core.databinding.property.IPropertyObservable; import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.SimplePropertyEvent; import org.eclipse.core.databinding.property.value.SimpleValueProperty; import org.eclipse.core.internal.databinding.Util; /** * @since 1.2 * */ public class SimplePropertyObservableValue extends AbstractObservableValue implements IPropertyObservable { private Object source; private SimpleValueProperty property; private boolean updating = false; private Object cachedValue; private INativePropertyListener listener; /** * @param realm * @param source * @param property */ public SimplePropertyObservableValue(Realm realm, Object source, SimpleValueProperty property) { super(realm); this.source = source; this.property = property; } protected void firstListenerAdded() { if (!isDisposed()) { cachedValue = property.getValue(source); if (listener == null) { listener = property .adaptListener(new ISimplePropertyListener() { public void handlePropertyChange( final SimplePropertyEvent event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { notifyIfChanged((ValueDiff) event.diff); } }); } } }); } property.addListener(source, listener); } } protected void lastListenerRemoved() { if (listener != null) { property.removeListener(source, listener); } cachedValue = null; } protected Object doGetValue() { notifyIfChanged(null); return property.getValue(source); } protected void doSetValue(Object value) { updating = true; try { property.setValue(source, value); } finally { updating = false; } notifyIfChanged(null); } private void notifyIfChanged(ValueDiff diff) { if (hasListeners()) { Object oldValue = cachedValue; Object newValue = cachedValue = property.getValue(source); if (diff == null) diff = Diffs.createValueDiff(oldValue, newValue); if (hasListeners() && !Util.equals(oldValue, newValue)) { fireValueChange(diff); } } } public Object getValueType() { return property.getValueType(); } public Object getObserved() { return source; } public IProperty getProperty() { return property; } public synchronized void dispose() { if (!isDisposed()) { if (listener != null) property.removeListener(source, listener); source = null; property = null; listener = null; } super.dispose(); } }