@Override
public void treeExpanded(final TreeExpansionEvent event) {
logger.debug("Tree detected an expansion event.");
final JTree tree = (JTree) event.getSource();
TreePath path = event.getPath();
final MCTMutableTreeNode selectedNode = (MCTMutableTreeNode) path.getLastPathComponent();
if (selectedNode.isProxy()) {
// Insert a dummy node to alert the user that the expansion may take a while.
final MutableTreeNode newChild = new MessageTreeNode(bundle.getString("PLACEHOLDER_NODE_TEXT"));
// only add the node after the timer has expired to avoid flashing
// 200 ms is the threshold that users can perceive a delay
final Timer t = new Timer(150, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// if the node has been closed before the action has run
// but before this action has been canceled then do not
// insert the please wait node
if (!selectedNode.isProxy()) {
((DefaultTreeModel) tree.getModel()).insertNodeInto(newChild, selectedNode, 0);
}
}
});
t.setRepeats(false);
// signal that initialization has occurred
selectedNode.setProxy(false);
t.start();
// Load the actual children in a background thread. The dummy node will be
// removed, and the tree redisplayed with the actual children, when the
// child components are loaded from the database.
(new SwingWorker<Object,Object>() {
@Override
protected Object doInBackground() throws Exception {
View gui = (View) selectedNode.getUserObject();
AbstractComponent component = gui.getManifestedComponent();
return component.getComponents();
}
@Override
protected void done() {
// this runs in the AWT Thread
t.stop();
// this is true if the node has been collapsed
if (selectedNode.isProxy()) {
return;
}
// Let the node know it needs to refresh itself
View gui = (View) selectedNode.getUserObject();
gui.updateMonitoredGUI();
}
}).execute();
}
}