ListView and ChoiceView are two very nice components that can be used to display Node hierarchies. For the RepositoryBrowser Component of my VisualOSGi project I wanted to have a combination of both, a ChoiceView on Top for selecting the Repository and a ListView below for displaying and selecting the individual Bundles. It would be possible to have all the functrionality in a ListView or a BeanTreeView, etc. but I think the combination of a JComboBox and a List is most intuitive.
This is the Node Hierarchy I want to display.
+ Root (AbstractNode)
++ RepositoryNode
+++BundleNode
My first try was using a Palette, but it didn’t play nicely with lazy loading, so I decided to do it myself. The task is now to correctly synchronize the selection between both and still stay in the same Node Hierarchy. My idea was to put the ChoiceView in a JPanel and add a nested JPanel implementing ExplorerManager.Provider with a ListView. The nested Panel then listens for selection changes in the outer Components ExplorerManager to set the root node of it’s own ExplorerManager. So I was very happy to find out that the Rich Client Programming book by Jarda, Tim and Geertjan has an example that is almost exactly what I wanted (Page 186).
I used this code to create a little Component called NestedListView. The View is a JPanel that implements ExplorerManager.Provider to control it’s own Nodes and PropertyChangeListener to listen to changes in the parent. To find the parent, I need to make sure that our component is already added to a parent component, so I’ve put the addNotify method:
@Override
public void addNotify() {
super.addNotify();
parentManager = ExplorerManager.find(this);
if (parentManager != null) {
parentManager.addPropertyChangeListener(this);
}
}
On receiving an interesting PropertyChangeEvent:
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())){
updateRootNode();
}
}
I can update the Node:
public void updateRootNode() {
Node [] n = parentManager.getSelectedNodes();
if (n.length == 0){
explorerManager.setRootContext(new AbstractNode(Children.LEAF));
}
else {
explorerManager.setRootContext(n[0]);
}
}
As the outer component I’ve created another JPanel called ChoiceListView. It contains a ChoiceView to the North.
So now I’ve got a ListView that does exactly what I want:

Since I’ve got a ChildFactory for loading the Nodes the ListView will display some visual feedback while the Nodes are loaded, and the UI isn’t blocked. Another detail is, that I also expose the inner Explorermanager from my ChoiceListView:
public ExplorerManager getChildExplorerManager() {
return choiceListView.getExplorerManager();
}
…because it makes more sense to expose the selected Nodes of the nested Component from the TopComponents Lookup:
associateLookup(ExplorerUtils.createLookup(choiceListView.getChildExplorerManager(), getActionMap()));

Update : As per Geertjan’s request I’m adding the source code of the two classes. The inner class is called Nested ListView and the Outer class is called ChoiceListView. So you can find the two classes here: choicelistview1, nestedlistview1.
Your TopComponent needs to implement ExplorerManager.Provider and define a variable “ExplorerManger explorerManager= new Explorermanager();”. Here’s some Dummy code you can use inside your TopComponents constructor to get them to work:
setLayout(new BorderLayout());
ChoiceListView choiceListView = new ChoiceListView();
add(choiceListView, BorderLayout.CENTER);
// create a three level node hierarchy, like for a palette
Children.Array outer = new Children.Array();
Node[] outerNodes = new Node[3];
for (int j = 0; j < outerNodes.length; j++) {
Children.Array array = new Children.Array();
Node[] children = new Node[3];
for (int i = 0; i < children.length; i++) {
AbstractNode node = new AbstractNode(Children.LEAF);
node.setDisplayName(”Node ” + j+i);
children[i] = node;
}
array.add(children);
AbstractNode choice = new AbstractNode(array);
choice.setDisplayName(”Choice ” + j);
outerNodes[j] = choice;
}
outer.add(outerNodes);
AbstractNode root = new AbstractNode(outer);
root.setDisplayName(”Select something”);
explorerManager.setRootContext(root);
// this exposes the content of the ListView instead of the ChoiceView
associateLookup(ExplorerUtils.createLookup(choiceListView.getChildExplorerManager(), getActionMap()));