package org.marketcetera.photon.commons.ui.databinding;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.ObservablesManager;
import org.eclipse.core.databinding.ValidationStatusProvider;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.marketcetera.util.misc.ClassVersion;
/* $License$ */
/**
* Utilities for using JFace data binding.
*
* @author <a href="mailto:will@marketcetera.com">Will Horn</a>
* @version $Id: DataBindingUtils.java 16841 2014-02-20 19:59:04Z colin $
* @since 2.0.0
*/
@ClassVersion("$Id: DataBindingUtils.java 16841 2014-02-20 19:59:04Z colin $")
public class DataBindingUtils {
/**
* Key used for setting {@link ControlDecoration} on a control's
* {@link Control#getData() data}.
*/
public static final String CONTROL_DECORATION = "CONTROL_DECORATION"; //$NON-NLS-1$
/**
* Convenience method that binds the target to the model with
* {@link UpdateStrategyFactory#createEMFUpdateValueStrategyWithEmptyStringToNull()}
* as the target to model update value strategy.
*
* @param dataBindingContext
* the data binding context
* @param targetObservable
* the target observable
* @param modelObservable
* the model observable
*/
public static void bindValue(DataBindingContext dataBindingContext,
IObservableValue targetObservable, IObservableValue modelObservable) {
dataBindingContext.bindValue(targetObservable, modelObservable,
UpdateStrategyFactory
.createEMFUpdateValueStrategyWithEmptyStringToNull(),
null);
}
/**
* Convenience method that binds the target to the model with
* {@link UpdateStrategyFactory#createEMFUpdateValueStrategyWithEmptyStringToNull()}
* as the target to model update value strategy, and initializes the target
* as a required field using
* {@link RequiredFieldSupport#initFor(DataBindingContext, org.eclipse.core.databinding.observable.IObservable, String, boolean, Binding)}
* .
*
* @param dataBindingContext
* the data binding context
* @param targetObservable
* the target observable
* @param modelObservable
* the model observable
* @param description
* the field description
*/
public static void bindRequiredField(DataBindingContext dataBindingContext,
IObservableValue targetObservable,
IObservableValue modelObservable, String description) {
bindValue(dataBindingContext, targetObservable, modelObservable);
RequiredFieldSupport.initFor(dataBindingContext, targetObservable,
description, true, null);
}
/**
* Convenience method to create an observable and add it to the manager.
*
* @param manager
* the manager to use to track the observable
* @param object
* the object to observe
* @param feature
* the feature of the object to observe
* @return the observable value
*/
public static IObservableValue observeAndTrack(ObservablesManager manager,
EObject object, EStructuralFeature feature) {
final IObservableValue observable = EMFObservables.observeValue(object,
feature);
manager.addObservable(observable);
return observable;
}
/**
* Initializes ControlDecorationSupport for the provided validation status
* provider. UI code should use this instead of referencing the provisional
* Eclipse code directly.
*
* @param provider
* the object that will control the state of the control
* decoration
*/
public static void initControlDecorationSupportFor(
ValidationStatusProvider provider) {
initControlDecorationSupportFor(provider, SWT.TOP | SWT.LEFT);
}
/**
* Initializes ControlDecorationSupport for the provided validation status
* provider. UI code should use this instead of referencing the provisional
* Eclipse code directly.
*
* @param provider
* the object that will control the state of the control
* decoration
* @param position
* the position of the decoration
*/
public static void initControlDecorationSupportFor(
ValidationStatusProvider provider, int position) {
initControlDecorationSupportFor(provider, position,
new CaptureUpdater());
}
/**
* Initializes ControlDecorationSupport for the provided validation status
* provider. UI code should use this instead of referencing the provisional
* Eclipse code directly.
*
* @param provider
* the object that will control the state of the control
* decoration
* @param position
* the position of the decoration
* @param updater
* controls the appearance of the {@link ControlDecoration}
*/
public static void initControlDecorationSupportFor(
ValidationStatusProvider provider,
int position,
org.eclipse.jface.databinding.fieldassist.ControlDecorationUpdater updater) {
org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport
.create(provider, position, null, updater);
}
/**
* Attaches the control decoration to the control using the
* {@value #CONTROL_DECORATION} key. This enables the decoration to be
* accessed for testing purposes.
*
* @param decoration
* the decoration to attach to its control
*/
public static void attachControlDecoration(ControlDecoration decoration) {
// add the decoration to the control for testing access
decoration.getControl().setData(CONTROL_DECORATION, decoration);
}
/**
* Captures the control decoration and attaches it to the control.
*/
@ClassVersion("$Id: DataBindingUtils.java 16841 2014-02-20 19:59:04Z colin $")
static class CaptureUpdater
extends
org.eclipse.jface.databinding.fieldassist.ControlDecorationUpdater {
@Override
protected void update(ControlDecoration decoration, IStatus status) {
attachControlDecoration(decoration);
super.update(decoration, status);
}
}
private DataBindingUtils() {
throw new AssertionError("non-instantiable"); //$NON-NLS-1$
}
}