JFace TreeView with Manual Expand of TreeItems

I have a FilteredTree with check items and I was trying to expand the tree whenever the user checks an item on it. By default, the tree does only expand a TreeItem when the user clicks on the + icon and retracts when the user clicks on the - icon.
Since this tree has check items, I wanted the tree to expand when the user clicks on the check box.

This proved to be a lot harder than I expected, partially because I was using the wrong object, partially because it is lazy, and partially because it was hard to find an answer for what I was doing wrong.
So, I'm posting here how to manually expand a TreeView, which is part of a FilteredTree.

To begin with, the TreeView requires the following classes to be defined:

1. Your tree node that will hold the data of each tree item:
private class Node {

private final Node parent;
private final String word;
private List children = new ArrayList();

Node(Node parent, String word) {
this.parent = parent;
this.word = word;
if(parent != null) {
parent.children.add(this);
}
}

public Node getParent() {
return parent;
}

public Collection getChildren() {
return new ArrayList(children);
}

public boolean hasChildren() {
return children.size() > 0;
}

public void setChildren(Collection newChildren) {
if(newChildren != null) {
children = new ArrayList(newChildren);
}
}

public String getWord() {
return word;
}

}
Please note that this class can be whatever class you require, this is only an example.

2. A tree content provider that will provide the content for the tree:
private class NodeContentProvider implements ITreeContentProvider {

@Override
public Object[] getChildren(Object element) {
return ((Node)element).getChildren().toArray();
}

@Override
public Object getParent(Object element) {
return ((Node)element).getParent();
}

@Override
public boolean hasChildren(Object element) {
return ((Node)element).hasChildren();
}

@Override
public Object[] getElements(Object inputElement) {
return (Object[]) inputElement;
}

@Override
public void dispose() {
// unused
}

@Override
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
// unused
}

}

3. The label provider that will provide the label for each item in the tree:
private class NodeLabelProvider extends LabelProvider {

private final TreeViewer viewer;

NodeLabelProvider(TreeViewer viewer) {
this.viewer = viewer;
}

@Override
public String getText(Object element) {
Node node = (Node) element;
return node.getWord();
}
}

I'll create a FilteredTree, but since it makes use of TreeView, using only a TreeView is trivial:

PatternFilter patternFilter = new PatternFilter();
FilteredTree filteredTree = new FilteredTree(cTree,
SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CHECK,
this.patternFilter);
filteredTree.setInitialText("type your filter text here");
TreeViewer treeViewer = filteredTree.getViewer();

// Assign the label provider
treeViewer.setLabelProvider(new NodeLabelProvider());

// Assign the content provider
treeViewer.setContentProvider(new NodeContentProvider());

// Populate the tree with elements
Node ex1= new Node(null, "Example 1");
new Node(ex1, "Example 1.1");
new Node(ex1, "Example 1.2");
new Node(ex1, "Example 1.3");
Node ex2= new Node(null, "Example 2");
new Node(ex2, "Example 2.1");
Node[] nodes = Node[] {ex1, ex2}
viewer.setInput(nodes);

// Event for item selection
treeViewer.getTree().addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
TreeItem item = (TreeItem) event.item;
Node node = (Node)item.getData();
// Manually Expand
treeViewer.expandToLevel(node, 1);
treeViewer.update(node, null);
}
});

Please note that the tree selection event always expands the selected node, you may wish to retract it or do another operation, like check all its descendants.
This is actually quite simple, but I was calling treeViewer.expandToLevel with the TreeItem instead of using the Node object, and that was the cause of my problems.

If you're looking for a similar example but using custom images, check Eclipse Nuggets.
./M6