[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?

Matthew Hall wrote:
Daniel Krügler wrote:

[..]

I agree that this is also some form of buffering strategy, but it is
local to one binding (which sometimes is an advantage, of-course) and
validation is also deferred according to my understanding of
POLICY_ON_REQUEST

You are correct, I should have said POLICY_CONVERT. The basic data binding pipeline is:


1. get source observable value
2. validate after get
3. convert to destination type
4. validate after convert
5. validate before set
6. set destination observable value

POLICY_ON_REQUEST does not execute this pipeline automatically, but waits until Binding.updateModel() is called. POLICY_CONVERT, by contrast, performs steps 1 through 4. POLICY_UPDATE performs all steps.

Yes, you are right, this seems to be the right way to go!

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:

Thanks, this looks very cool! Nevertheless, I assume that I need at least some form of adaption to the jgoodies binding for easier adaption of the new binding.

I not sure what you mean here.

I simply meant that even though JFace Databinding gives us a huge amount of capabilities for free I probably still need to provide an adaptor to the jgoodies-style data binding to ensure that large code parts don't need to be touched yet.

Question: from what I saw in the JGoodies slideshow, it looks like the PresentationModel is intimately familiar with the model object. However using strings to distinguish property names is not going to be portable to, say, EMF. So I'm wonder However the way you describe it makes it look like a generic switchboard:

interface IPresentationModel {
  public IObservableValue getBufferedValue(IValueProperty)
  public IObservableList getBufferedList(IListProperty)
  public IObservableSet getBufferedSet(ISetProperty)
  public IObservableMap getBufferedMap(IMapProperty)
}

We wouldn't need to create IBufferedObservable* interfaces since we can use IObservable.isStale and IStaleListener to track whether each observable is "buffering" (i.e. out of sync with model)

This seems like an excellent approach to me! With the existing property-framework in JFace Databinding this seems the best way to go.

2) We currently need to wrap this POJO in a Bean, that simply forwards
all properties of the POJO but sends proper Java Bean property change
events (I'm very impressed that JFace databinding allows direct usage
of POJO's!).

Quick note, the POJO observables only send change events if the change is initiated *through the IObservable's interface*, and only for that particular observable instance. So setting values directly on the POJO is discouraged since you don't get updates.

This really doesn't matter in our use-cases, because the POJO object wont be touched by the layer which gets the presentation model.

4) The UI layer gets the presentation model(s) and simply binds it's
observables "by name" to the corresponding widgets:

Text txt = new Text(parent, ...);
...
BufferedModel firstName = pres.getBufferedModel("firstName");

...
BindingFacade.bind(txt, firstName);

They are actually not aware of the direct nature of the complete
bean. They only need to now that there are some properties to
bind to widget's.

This sounds essentially like a two-stage binding. The presentation model would bind directly to the bean (or whatever type of model object) using POLICY_CONVERT update policies. In turn each UI form would bind its controls to the PM's observables.

Yes, this description is quite correct. I think for this reason my own opinion to that was that it should be simply possible to get the jgoodies presentation model adapted purely based on public JFace DataBinding API. In some sense the PresentationModel can be thought of a higher-level access level to JFace DataBinding functionality.

5) Especially inside a local scope (dialog/wizard) it's nice to
simply say on Ok-pressed: pres.triggerCommit() and on any cancelling
step (either cancel-pressed or undo) triggerFlush() which unrolls
the current changes back to the original ones.

void triggerCommit() { bindingContext.updateModels(); } void triggerFlush() { bindingContext.updateTargets(); }

<nod> yes that seems to be adequate operation assuming the user selected the right policy for all corresponding bindings.

Finally let me add one further remark: In the jgoodies databinding
framework you don't always need to have an individual observable
just to observe changes of some characteristic property: E.g. I
can add or remove change listener's to the buffering state of
the IBufferedObservableValue without access to the actual observable,
because in this case I only need the change deltas in the property
observer and nowhere else.

We've tried to reduce the cost of creating observables by not registering listeners on the underlying object (e.g. bean) until you actually add listeners to the observable--not sure if that mitigates your concern but I thought I'd mention it.

I agree that this is a good foundation the JFace DataBinding architecture is based on, because it consequently supports
lazy-loading.


I sometimes miss that fact in Jface
databinding, although it (usually) provides what I need: With further
wrapper techniques I could provide a *constant* view onto the
buffering state or the trigger channel (jface has ConstantObservable)
which do only exist such that clients can register IValueChangeListener's on them.

I don't follow you here.

I tried to describe my workaround here. Users typically need to know, when the buffering state of the presentation model changes. The JFace way is to provide the observable of the buffer state as part of the interface, the jgoodies way is to provide

void addBufferingChangeListener(...);
void removeBufferingChangeListener(...);

as part of the presentation model interface. The latter interface is
restricted, because users cannot unintentionally access the buffering
observable and actively change it's state, but with a normal (mutable)
JFace Databinding observable the user indeed might change the value
of this property. So my current workaround in the JFace Databinding
world is to provide immutable observables just to allow the user
to register as listener for it's changes.

It sounds like this is something we should take a closer look at. Would you submit a feature enhancement so we can discuss this further?

Thanks for your encouraging opinion. I will start as soon as possible to prepare this issue.


- Daniel