Amongst other places, I've looked here and here, but I've not found an answer to my question.
A little background:
- I'm implementing a view that represents a subset of the resources in an eclipse project.
- The project nodes in the tree will check whether the project is open to see if they should contain children. Effectively, the Project node's
hasChildren()
method returnsIProject.isOpen()
. - The eclipse view subscribes to resourceChangeEvents, and in the case that any change occurs, it calls
refresh()
on the TreeViewer.
Based on information from this question:
If you have added or removed objects in the tree use
TreeViewer.refresh();
refresh()
(with no arguments) should then go through and update the entire tree with fresh information from the model.
By setting breakpoints in the code, I've discovered that during the refresh process, the framework calls hasChildren() several times on a node, but never calls getChildren().
Let us say that Project
is currently open, and the node representing it in the tree is expanded with some children. I close the project and resource change event is fired. This causes a refresh()
. When asked, the project
now returns false from hasChildren()
, and yet the children are still present in the tree.
Conversely, if the project is closed and the node has no children (there is no expansion arrow), opening the project will fire a resource change event, which refresh()
es the tree, the project node returns true from hasChildren()
and yet getChildren()
is never called to find out what these children are. The node still has no children and no expansion arrow.
Currently the model fires events when new nodes are added and old ones removed, and the tree listens for these and calls add(Object, Object)
and remove(Object)
on the TreeViewer as appropriate, but the model only checks to see whether its children need to be changed when it is asked for them via the content provider's getChildren() method.
The problem can be partially alleviated by calling getChildren()
from hasChildren()
, but this seems messy, and from my understanding of how refresh() works, shouldn't be necessary.
Why does the TreeViewer's refresh()
method not re-query a node to see what its children are? Given that is doesn't do this, how is it meant to handle adding and removing objects?