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... _) { ret swing(func -> JTree { optPar IF1 valueToText; DefaultMutableTreeNode rootNode = new(root); rootNode.add(new DefaultMutableTreeNode(jDynamicTree_dummy())); final JTree tree = new JTree(rootNode) { public S convertValueToText(O value, bool selected, bool expanded, bool leaf, int row, bool hasFocus) { if (valueToText != null) { O userObject = ((DefaultMutableTreeNode) value).getUserObject(); pcall { ret str(valueToText.get((A) userObject)); } } ret super.convertValueToText(value, selected, expanded, leaf, row, hasFocus); } }; 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, (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; }); }