i'm trying to implement a custom focus traversal policy on a JTree so that i get the following behavior:
-when editing if you press enter, the tree stops editing ( default)
-when a node is selected, pressing enter would surf to the next node,if selected node is the last node,than create a new node
-when tab is pressed,the tree should stop editing if it is and focus should move out of the tree to the next component in the frame ( it's a JInternalFrame in fact ).
I learned that JTrees cannot be used as a root of a focus traversal cycle, so i considered implementing the desired behavior
using key bindings.
here's what i did
//currently setting Enter key pressed behavior
private void registerSurfAction(JComponent comp,final DefaultMutableTreeNode root,int condition){
ActionMap am = comp.getActionMap();
InputMap im=comp.getInputMap(condition);
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
Object enterKey = im.get(enter)==null ? "surf" : im.get(enter);
//final Action oldEnterAction = am.get(im.get(enter));
Action surfAction = new AbstractAction(){
public void actionPerformed(ActionEvent ae)
{
//oldEnterAction.actionPerformed(ae);
int nodeCount = containerTree.getModel().getChildCount(root);
int selectedNode = containerTree.getMaxSelectionRow();
if(containerTree.isEditing())
containerTree.stopEditing();
if(selectedNode==nodeCount)
{
DefaultTreeModel model = (DefaultTreeModel)containerTree.getModel();
DefaultMutableTreeNode newNode=new DefaultMutableTreeNode();
model.insertNodeInto(newNode, root, root.getChildCount());
newNode.setUserObject("container #"+root.getChildCount());
TreePath path = new TreePath(newNode.getPath());
containerTree.scrollPathToVisible(path);
containerTree.setSelectionPath(path);
containerTree.startEditingAtPath(path);
}
else if(selectedNode>=0)
{
containerTree.setSelectionRow(selectedNode+1);
}
}
};
im.put(enter, enterKey);
am.put(enterKey, surfAction);
}
then i register this action with all of the JTree,its CellEditor editing component which is a DefaultTextField ( i'm using the DefaultTreeCellEditor ) and the tree's cell renderer's rendering component which is a JLabel.
so basically
// with the JTree itself
registerSurfAction(containerTree, root, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
...
//with rendering component of the Tree cell renderer
registerSurfAction((JLabel)label, root, JComponent.WHEN_FOCUSED);
...
// with editing component of the tree cell editor
registerSurfAction((JComponent)editingComponent, root, JComponent.WHEN_FOCUSED);
what's happening is that if the tree is editing,it stops editing,the next node is selected ( created before if not exists ) and editing starts but the focus leaves the tree to the next component in the frame.
If no editing was being made, only a node is selected then focus moves to the next node and then leaves the tree to the next component in the frame.
Is key binding the right way to implement this or might there be another way ?