/******************************************************************************* * Copyright (c) 2006-2013 The RCP Company 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: * The RCP Company - initial API and implementation *******************************************************************************/ package com.rcpcompany.uibindings.observables; import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.IObserving; import org.eclipse.core.databinding.observable.value.AbstractObservableValue; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.databinding.observable.value.ValueDiff; import org.eclipse.emf.edit.domain.EditingDomain; import com.rcpcompany.uibindings.IDisposable; import com.rcpcompany.uibindings.UIBindingsUtils.IClassIdentiferMapper; import com.rcpcompany.uibindings.model.utils.BasicUtils; import com.rcpcompany.utils.logging.LogUtils; /** * Observable value that returns a value based on a mapper functor (function object). * * @author Tonny Madsen, The RCP Company */ public class MapperObservableValue extends AbstractObservableValue implements IObserving { private final IValueChangeListener myListener = new IValueChangeListener() { @Override public void handleValueChange(ValueChangeEvent event) { updateValue(); } }; private final IObservableValue myBaseObject; private final EditingDomain myEditingDomain; private final IClassIdentiferMapper myMapper; /** * Constructs and returns a new observable value for the value and mapper. * * @param value the base value for this observable value * @param editingDomain the editing domain used for all changes * @param classIdentiferMapper the mapper */ public MapperObservableValue(IObservableValue value, EditingDomain editingDomain, IClassIdentiferMapper classIdentiferMapper) { myBaseObject = value; myEditingDomain = editingDomain; myMapper = classIdentiferMapper; try { myCurrentOV = myMapper.getObservableValue(myBaseObject, myEditingDomain); } catch (final Exception ex) { LogUtils.error(myMapper, ex); } if (myCurrentOV != null) { myCurrentOV.addValueChangeListener(myListener); } updateValue(); } @Override public synchronized void dispose() { if (myCurrentOV != null) { myCurrentOV.removeValueChangeListener(myListener); } if (myMapper instanceof IDisposable) { ((IDisposable) myMapper).dispose(); } super.dispose(); } private IObservableValue myCurrentOV = null; private Object myCurrentValue; /** * Updates the resulting count for this observable value. */ protected void updateValue() { Object v; try { v = myMapper.map(myBaseObject.getValue()); } catch (final Exception ex) { LogUtils.error(myMapper, ex); v = null; } if (BasicUtils.equals(v, myCurrentValue)) return; final ValueDiff diff = Diffs.createValueDiff(myCurrentValue, v); myCurrentValue = v; getRealm().exec(new Runnable() { @Override public void run() { fireValueChange(diff); } }); } @Override protected Object doGetValue() { return myCurrentValue; } @Override protected void doSetValue(Object value) { myCurrentOV.setValue(value); } @Override public Object getValueType() { return myCurrentOV.getValueType(); } @Override public Object getObserved() { return myBaseObject.getValue(); } }