diff --git a/openide.explorer/apichanges.xml b/openide.explorer/apichanges.xml --- a/openide.explorer/apichanges.xml +++ b/openide.explorer/apichanges.xml @@ -50,6 +50,20 @@ Explorer API + + + TreeView.editNode added + + + + + + Added TreeView.editNode(Node) to programmatically + enter inline-edit mode on a TreeView. Method is thread-safe. + + + + Hide node icons in OutlineView and TreeView. diff --git a/openide.explorer/manifest.mf b/openide.explorer/manifest.mf --- a/openide.explorer/manifest.mf +++ b/openide.explorer/manifest.mf @@ -2,5 +2,5 @@ OpenIDE-Module: org.openide.explorer OpenIDE-Module-Localizing-Bundle: org/openide/explorer/Bundle.properties AutoUpdate-Essential-Module: true -OpenIDE-Module-Specification-Version: 6.59 +OpenIDE-Module-Specification-Version: 6.60 diff --git a/openide.explorer/src/org/openide/explorer/view/TreeView.java b/openide.explorer/src/org/openide/explorer/view/TreeView.java --- a/openide.explorer/src/org/openide/explorer/view/TreeView.java +++ b/openide.explorer/src/org/openide/explorer/view/TreeView.java @@ -141,6 +141,7 @@ import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.openide.awt.QuickSearch; +import org.openide.util.Parameters; /** @@ -620,6 +621,52 @@ }); } + /** + * Initiate inline-edit mode for a Node, expanding its parent + * and selecting it if necessary. This method is thread-safe. + *

+ * If this TreeView is not actually on-screen when the edit is + * initiated (for example, a call after the call to editNode() removes + * it from the AWT hierarchy) then this method logs an error and does + * nothing. + * + * @since 6.60 + * @param node A node whose name should be edited visually by the user + */ + public final void editNode(final Node node) { + Parameters.notNull("node", node); //NOI18N + //Do not use VisualizerNode.runSafe(), which will call + //EQ.invokeAndWait() + Mutex.EVENT.readAccess(new EditInitiator(node)); + } + + private final class EditInitiator implements Runnable { + private final Node node; + EditInitiator (Node target) { + this.node = target; + } + + @Override + public void run() { + if (!isDisplayable()) { + Logger.getLogger(TreeView.class.getName()).log( + Level.WARNING, "Attempt to edit node {0} but " + //NOI18N + "component not on screen", node); //NOI18N + return; + } + lookupExplorerManager(); + TreePath path = getTreePath(node); + if (path == null) { + throw new IllegalArgumentException ("Unknown node " + node); //NOI18N + } + if (!tree.isExpanded(path)) { + tree.expandPath(path); + } + tree.setSelectionPath(path); + tree.startEditingAtPath(path); + } + } + /** Test whether a node is expanded in the tree or not * @param n the node to test * @return true if the node is expanded diff --git a/openide.explorer/src/org/openide/explorer/view/TreeViewCellEditor.java b/openide.explorer/src/org/openide/explorer/view/TreeViewCellEditor.java --- a/openide.explorer/src/org/openide/explorer/view/TreeViewCellEditor.java +++ b/openide.explorer/src/org/openide/explorer/view/TreeViewCellEditor.java @@ -172,6 +172,10 @@ public void focusGained(FocusEvent evt) { } + Ed ed() { //editNodeTest + return (Ed) realEditor; + } + /** * This is invoked if a TreeCellEditor is not supplied in the constructor. * It returns a TextField editor. @@ -371,6 +375,10 @@ super(tf); } + JTextField comp() { //editNodeTest + return (JTextField) super.getComponent(); + } + /** Main method of the editor. * @return component of editor */ diff --git a/openide.explorer/test/unit/src/org/openide/explorer/view/BeanTreeViewTest.java b/openide.explorer/test/unit/src/org/openide/explorer/view/BeanTreeViewTest.java --- a/openide.explorer/test/unit/src/org/openide/explorer/view/BeanTreeViewTest.java +++ b/openide.explorer/test/unit/src/org/openide/explorer/view/BeanTreeViewTest.java @@ -69,6 +69,14 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; +import java.awt.EventQueue; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.concurrent.CountDownLatch; +import javax.swing.JTextField; +import org.openide.explorer.view.TreeViewCellEditor.Ed; /** * Tests for class BeanTreeViewTest @@ -539,4 +547,97 @@ return em; } } + + public void testEditNode() throws Exception { + Children.Array kids = new Children.Array(); + Node[] n = new Node[20]; + Node node = null; + for (int i=0; i < n.length; i++) { + n[i] = new RenamableNode ("" + i); + if (i == 5) { + node = n[i]; //pick one to edit + } + } + kids.add(n); + final Node root = new AbstractNode (kids); + root.setDisplayName("Root"); + final WL wl = new WL(); + final F[] ff = new F[1]; + EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + ff[0] = new F(root); + ff[0].addWindowListener(wl); + ff[0].pack(); + ff[0].setVisible(true); + } + + }); + wl.latch.await(); + F f = ff[0]; + //sanity check + assertTrue (f.isDisplayable()); + assertTrue (f.isShowing()); + assertTrue (f.view.isShowing()); + JTree tree = f.view.tree; + TreeViewCellEditor ce = (TreeViewCellEditor) tree.getCellEditor(); + Ed ed = ce.ed(); + final JTextField comp = ed.comp(); + final CountDownLatch latch = new CountDownLatch(1); + comp.addHierarchyListener(new HierarchyListener() { + + @Override + public void hierarchyChanged(HierarchyEvent e) { + if (comp.isDisplayable()) { + latch.countDown(); + } + } + + }); + f.view.editNode(node); + latch.await(); + assertTrue (tree.isEditing()); + assertTrue (comp.isDisplayable()); + f.setVisible(false); + f.dispose(); + } + + private static final class RenamableNode extends AbstractNode { + RenamableNode (String name) { + super (Children.LEAF); + setDisplayName(name); + setName (name); + } + + @Override + public boolean canRename() { + return true; + } + } + + private static final class F extends JFrame implements ExplorerManager.Provider { + private final ExplorerManager mgr = new ExplorerManager(); + private final BeanTreeView view = new BeanTreeView(); + F(Node root) { + setContentPane(view); + mgr.setRootContext(root); + } + + @Override + public ExplorerManager getExplorerManager() { + return mgr; + } + + } + + private static final class WL extends WindowAdapter { + CountDownLatch latch = new CountDownLatch(1); + + @Override + public void windowOpened(WindowEvent e) { + super.windowOpened(e); + latch.countDown(); + } + } }