[DataBinding] Control order of event processing [message #1734557] |
Thu, 09 June 2016 06:53  |
Eclipse User |
|
|
|
Hi,
I have a problem with the order of event processing in the data binding framework. Consider the following situation: My editor consists of a list viewer showing a number of model elements, and a combo viewer showing the value of a particular property of the model element selected in the list viewer. The combo viewer's selectable items are computed based on the selected model element in the list viewer.
Using databinding, the input of the list viewer is bound to a list of model elements; the combo viewer's input is bound to a computed list, which is in turn bound to the list viewer's selection; the combo viewer's selection is bound to a detail observable, which observes a particular property of the list viewer's currently selected element.
Now, the problem is that the selectable items of the combo viewer may change. For one model element, there may be several selectable items, for another there may be none. When a different element in the list viewer is selected, this leads to the following chain of events:
The list viewer fires a selection change event that is received by the computed list and the detail observable. First, the computed list processes the event, it recomputes the selectable items of the combo viewer and updates the combo viewer's input. For simplicity, suppose the combo viewer's input is now an empty list. This makes the combo viewer fire a selection changed event because the selection is now empty. This selection changed event is received by the detail observable. However, at this point the detail observable has not yet processed the selection changed event coming from the list viewer. Therefore, the detail observable sets the property value on the previously selected model element.
Following is some Xtend code for Illustration:
// This is the property, whose value is shown by the combo viewer
val feature = EPackage.Registry.INSTANCE.getEPackage("http://dummydsl/1.0").eAllContents.filter(EAttribute).
findFirst [
name == "dummyEnum"
]
val listViewer = new ListViewer(composite)
GridDataFactory.fillDefaults.align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(listViewer.control)
listViewer.contentProvider = new ObservableListContentProvider
//AllModelElementsObservableList returns all model elements in the editing domain
listViewer.input = new AllModelElementsObservableList(editingDomain)
/**
* create combo viewer
*/
val comboViewer = new ComboViewer(composite)
GridDataFactory.fillDefaults.align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(comboViewer.control)
comboViewer.contentProvider = new ObservableListContentProvider
// FeatureChoiceOfValuesObservableList returns the values that can be assigned to the feature of the currently selected list
// viewer element.
comboViewer.input = new FeatureChoiceOfValuesObservableList(
ViewerProperties.singleSelection.observe(listViewer),
editingDomain,
feature
)
dataBindingContext.bindValue(
ViewerProperties.singleSelection.observe(comboViewer),
EMFEditProperties.value(editingDomain, feature).observeDetail(ViewerProperties.singleSelection.observe(listViewer))
)
What I want to achieve is this: After another element is selected in the list viewer, the combo viewer's selectable items should be updated, but the resulting selection changed event should not be forwarded to the detail observable. Instead, since the detail observable's master (the list viewer's selection) changes, the combo viewer's selection should be set according to the detail observable's value. How can I achieve that?
Best regards,
Stephan
P.S.: I posted this problem also in the EMF forum (https://www.eclipse.org/forums/index.php/t/1078212/). However, since this problem seems to be related to the data binding framework in general, I am posting it here, too.
|
|
|
Re: [DataBinding] Control order of event processing [message #1734586 is a reply to message #1734557] |
Thu, 09 June 2016 10:40  |
Eclipse User |
|
|
|
I have solved the problem with the following solution: I added a DecoratingObservableValue to the list viewer's selection. If the list viewer's selection changes, the binding between the combo viewer and the detail observable is disposed. Then the change event is forwarded to the computed value to compute the combo viewer's new input. Finally, the binding between the combo viewer and the detail observable is restored.
val volatileBindingObservable = new DecoratingObservableValue(listViewerSelection, true) {
Binding comboViewerSelectionBinding
override protected handleValueChange(ValueChangeEvent arg0) {
if (comboViewerSelectionBinding !== null) {
comboViewerSelectionBinding.dispose
comboViewerSelectionBinding = null
}
super.handleValueChange(arg0)
comboViewerSelectionBinding = jfaceGmcEditor.dataBindingContext.bindValue(
ViewerProperties.singleSelection.observe(comboViewer),
EMFEditProperties.value(jfaceGmcEditor.modelEditingDomain.transactionalEditingDomain, feature).
observeDetail(this)
)
}
}
comboViewer.input = new FeatureChoiceOfValuesObservableList(
volatileBindingObservable,
jfaceGmcEditor.modelEditingDomain,
feature
)
|
|
|
Powered by
FUDForum. Page generated in 0.03978 seconds