[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Newsgroup Home]
|
[news.eclipse.platform.rcp] Re: [DataBinding] Does there exist a BufferedObservable?
|
Daniel, see responses below:
Daniel Krügler wrote:
JGoodies databinding provides two useful concepts among others -
BufferedValueModel and PresentationModel - where I currently
found no counter parts in jface databinding, even though I'm
sure they could be easily built on top of the API. Before I roll
my own implementation I would like to ask, whether they are
already provided, but possibly with a different name (which would
be not surprising to me, because jface databinding clearly and
intentionally defines it's own concepts).
Here a short description of what I mean:
A BufferedValueModel is actually some IObservableValue which holds
a reference to another IObservableValue (like a delegate). We could
represent it by the following interface
interface IBufferedObservableValue extends IObservableValue {
void triggerCommit();
void triggerFlush();
}
Any modifications on the wrapper *only* act on the wrapper (which
has it's own value element), and *no* delegation happens to the
wrapped observable. But if anyone invokes triggerCommit() on the
IBufferedObservableValue, then the internally hold observable's
value is set with the current value of the buffer. On the other
hand, if triggerFlush() is used, the buffer is reset to the value of
the internally hold observable - quite simple but useful.
In Eclipse DataBinding we don't have an equivalent observable, but we do
have a method of handling these situations:
1. To hold off on updating the model until a certain trigger action
occurs (e.g. the user clicks "Apply"), use an
UpdateValueStrategy(UpdateValueStrategy.POLICY_ON_REQUEST) for the
target-to-model update strategy:
bindingContext.bindValue(
WidgetProperties.text(SWT.Modify).observe(nameText),
BeanProperties.value("name").observe(person),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_ON_REQUEST),
null);
When you are ready to update the model, you can either call
DataBindingContext.updateModels() (to update all bindings at once) or
Binding.updateTargetToModel() to update a single binding.
2. To hold off on updating the model until some cross-field validation
constraint is satisfied (e.g. in a date range, the start date must be on
or before the end date) you can use MultiValidator:
final IObservableValue startDateObs =
WidgetProperties.selection().observe(startDate);
final IObservableValue endDateObs =
WidgetProperties.selection().observe(endDate);
MultiValidator dateRangeValidator = new MultiValidator() {
protected IStatus validate() {
// Using ObservableTracker magic, MultiValidator knows which
// observables you access inside this method and listens for
// changes to them so that it can revalidate as necessary
Date start = startDateObs.getValue();
Date end = endDateObs.getValue();
if (start.compareTo(end) > 0)
return ValidationStatus.error(
"Start date cannot be later than end date");
return ValidationStatus.ok();
}
};
bindingContext.addValidationStatusProvider(dateRangeValidator);
// Wrap the start and end date observables in validated wrappers so that
// they only change when the validation constraints are satisfied
bindingContext.bindValue(
dateRangeValidator.observeValidatedValue(startDateObs),
BeanProperties.value("startDate").observe(eventObject));
bindingContext.bindValue(
dateRangeValidator.observeValidatedValue(endDateObs),
BeanProperties.value("endDate").observe(eventObject));
A Presentation model is more or less a access point for observables.
It is typically constructed with a bean and is used as the actual
API for clients that ask for observables. Clients aren't aware,
which kind of data is wrapped, they just ask for a property from a
bean (This is very similar to querying BeanProperties, but the
difference is that the PresentationModel already knows the bean,
so the client query *only* provides the property name to access the
corresponding property).
This sounds like an inverse of BeanProperties, where instead of:
BeanValueProperty {
PropertyDescriptor property;
public Object getValue(Object source);
public void setValue(Object source, Object value);
}
you have:
BeanPropertyAccessor {
Object bean;
public Object getValue(String propertyName);
public void setValue(String propertyName, Object value);
}
If my understanding is correct, then no, we don't have anything like
that. Could you provide some sample code to show how this would be useful?
Matthew