ObservableCollectionTreeContentProvider duplicate TreeNode creation [message #20562] |
Mon, 13 July 2009 19:59 |
Will Horn Messages: 265 Registered: July 2009 |
Senior Member |
|
|
ObservableCollectionTreeContentProvider has logic to prevent creating a
duplicate TreeNode. However, this relies on the hash code of the input,
which in a list's case is dependent on the list contents.
The test case below will cause 2 TreeNodes to be created (one during
setInput and one during the manual getElements call). On shell close, the
content provider will throw
"org.eclipse.core.runtime.AssertionFailedException: assertion failed: Getter
called on disposed observable
org.eclipse.core.databinding.observable.list.WritableList@148cc8c" when
disposing the second TreeNode.
At least in my case, the error happens because I call "getElements" on the
content provider directly. If this is not allowed, it needs to be
documented. Otherwise, maybe an IdentityHashMap should be used.
Thanks,
Will
final Display d = new Display();
Realm.runWithDefault(SWTObservables.getRealm(d), new Runnable() {
public void run() {
Shell s = new Shell(d);
TreeViewer v = new TreeViewer(s);
ObservableListTreeContentProvider cp = new
ObservableListTreeContentProvider(
new IObservableFactory() {
@Override
public IObservable createObservable(Object target) {
if (target instanceof IObservableList) {
return (IObservableList) target;
}
return null;
}
}, new TreeStructureAdvisor() {
});
v.setContentProvider(cp);
WritableList input = WritableList.withElementType(String.class);
v.setInput(input);
input.add("ABC");
cp.getElements(input);
s.close();
}
});
|
|
|
|
|
|
Re: ObservableCollectionTreeContentProvider duplicate TreeNode creation [message #20607 is a reply to message #20599] |
Tue, 14 July 2009 00:38 |
Will Horn Messages: 265 Registered: July 2009 |
Senior Member |
|
|
"Matthew Hall" <matthall@woodcraftmill.com> wrote in message
news:h3g9kq$2a1$1@build.eclipse.org...
> Will Horn wrote:
>> "Matthew Hall" <matthall@woodcraftmill.com> wrote in message
>> news:h3g4af$j32$1@build.eclipse.org...
>>> You need to set an IElementComparer on the viewer before binding it.
>>> Your ObservableListTreeContentProvider will honor that element comparer.
>> Okay, thanks for the tip. Is that documented anywhere?
>
> I think this is documented in StructuredViewer.
This seems like a "gotcha" worth documenting in
ObservableListTreeContentProvider. From the StructuredViewer perspective,
the comparer seems to be an advanced feature used with setUseHashLookup
optimization. But when using ObservableListTreeContentProvider, it is a
requirement. Or am I mistaken?
>> In my recent investigation/usage of ObservableListTreeContentProvider, I
>> have come across some other caveats which I have not seen documented:
>>
>> 1) Constructor must be called on the realm of the current display (maybe
>> this goes without saying, but wouldn't hurt to document since most of the
>> databinding code is very good about documenting such restrictions).
>
> This should be documented. Would you open a bug for this?
http://bugs.eclipse.org/283351
>> 2) If the input is an IObservableList and you use it as the "children" of
>> itself, it will be disposed with the viewer or on input change.
>
> The tree content providers are expected to clean up after themselves. This
> is why they dispose all the observables they create through the
> IObservableFactory.
This makes sense.
While I'm at it: caveat number 3
3) The input to the viewer, if an observable, must be on the realm of the
current display. I've tried to get around this, but even I create a proxy
observable in IObservableFactory and use an identity element comparere,
errors still occur since the viewer calls equals directly on the input in
AbstractTreeViewer#internalIsInputOrEmptyPath. It's just a good idea to use
the display realm :o)
|
|
|
Powered by
FUDForum. Page generated in 0.03757 seconds