import javax.swing.tree.*;
static > JTree jDynamicTree(A root, IF1 makeChildren, O... _) {
ret jDynamicTree(root, toF1(makeChildren), _);
}
static > JTree jDynamicTree(final A root, final F1 makeChildren, fO... _) {
// optional wrapping/unwrapping of nodes for nicer printing
optPar IF1 wrapNode;
optPar IF1 unwrapNode;
ret swing(func -> JTree {
DefaultMutableTreeNode rootNode = new(callFOrKeep(wrapNode, root));
rootNode.add(new DefaultMutableTreeNode(jDynamicTree_dummy()));
final JTree tree = new JTree(rootNode);
tree.setShowsRootHandles(true);
tree.collapseRow(0);
final bool keepChildrenOnCollapse = optParam(_, 'keepChildrenOnCollapse, false);
bool makeChildrenIsFast = boolParam makeChildrenIsFast(_) || makeChildren == null;
bool debug = boolPar debug(_);
class jDynamicTree_Listener implements TreeWillExpandListener {
public void treeWillCollapse(TreeExpansionEvent e) {}
public void treeWillExpand(TreeExpansionEvent e) { pcall {
if (debug) print("treeWillExpand");
DefaultMutableTreeNode node = cast e.getPath().getLastPathComponent();
if (!keepChildrenOnCollapse || jDynamicTree_isInDummyState(node)) {
L l = asList(callF(makeChildren, callFOrKeep(unwrapNode, (A) node.getUserObject())));
if (makeChildrenIsFast
? replaceTreeNodeChildren_withDummyChild2(node, l, jDynamicTree_dummy(), makeChildren)
: replaceTreeNodeChildren_withDummyChild(node, l, jDynamicTree_dummy()))
((DefaultTreeModel) tree.getModel()).nodeStructureChanged(node);
}
}}
}
tree.addTreeWillExpandListener(new jDynamicTree_Listener);
ret tree;
});
}