Java Disable Cut Action for JTree / TransferHandler
I've created a custom TransferHandler for my JTree and as such have disabled Copy (by only supporting Move) and Paste (by checking support.isDrop() in canImport) but I can't figure out how to disable the Cut operation.
It looks like I have to make the determination in the exportDone method but no luck so far. So far my method looks like this but both Drag and Cut are associated with the Move action.
protected void exportDone(JComponent source, Transferable data, int action) {
if(action == TransferHandler.MOVE) {
try {
List<TreePath> list = ((TestTreeList) data.getTransferData(TestTreeList.testTreeListFlavor)).getNodes();开发者_JAVA技巧
int count = list.size();
for(int i = 0; i < count; i++) {
TestTreeNode node = (TestTreeNode) list.get(i).getLastPathComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
model.removeNodeFromParent(node);
}
tree.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} catch (UnsupportedFlavorException e) {
Log.logException(e);
} catch (IOException e) {
Log.logException(e);
}
}
}
You can disable CUT, COPY, PASTE from the user interface as well by removing the Actions from the ActionMap.
JTree tree = new JTree();
...
tree.getActionMap().put( "cut", null );
tree.getActionMap().put( "copy", null );
tree.getActionMap().put( "paste", null );
That stops someone from copying, cutting, or pasting using this tree as the source.
JTree "WHEN_FOCUSED" InputMap, but not the first "generation": InputMaps can have "parent" (grandparent, great-grandparent, etc.) InputMap(s).
tree.getInputMap( JComponent.WHEN_FOCUSED ).getParent().remove( KeyStroke.getKeyStroke( KeyEvent.VK_X, KE.CTRL_DOWN_MASK ) )
NB to avoid much head-scratching you might also like to know that there is a "hierarchy" (or more accurately order of "consultation") between the different types of InputMap: WHEN_FOCUSED is consulted first, then WHEN_ANCESTOR, and finally WHEN_IN_FOCUSED_WINDOW. If you put a Ctrl-X in a WHEN_ANCESTOR InputMap of a JComponent (perhaps hoping it will override what is already there), this will be "eclipsed" if there is a Ctrl-X in a WHEN_FOCUSED InputMap of the same JComponent.
Much enlightenment can be gained by making a simple method to explore all the hierarchy up from a given component, showing all key bindings (at least in the hierarchy going up: showing all the WHEN_IN_FOCUSED_WINDOW keystrokes in a given Window is a bit more involved).
I am a Jython user but this should be understandable: a similar (but inevitably less elegant) utility can be written in Java.
def show_ancestor_comps( comp, method ):
height = 0
while comp:
if method:
# this method can return True if it wants the ancestor exploration to stop
if method( comp, height ):
return
height = height + 1
comp = comp.parent
''' NB this can be combined with the previous one: show_ancestor_comps( comp, show_all_inputmap_gens_key_value_pairs ):
gives you all the InputMaps in the entire Window/Frame, etc. '''
def show_all_inputmap_gens_key_value_pairs( component, height ):
height_indent = ' ' * height
if not isinstance( component, javax.swing.JComponent ):
logger.info( '%s# %s not a JComponent... no InputMaps' % ( height_indent, type( component ), ))
return
logger.info( '%s# InputMap stuff for component of type %s' % ( height_indent, type( component ), ))
map_types = [ 'when focused', 'ancestor of focused', 'in focused window' ]
for i in range( 3 ):
im = component.getInputMap( i )
logger.info( '%s# focus type %s' % ( height_indent, map_types[ i ], ))
generation = 1
while im:
gen_indent = ' ' * generation
logger.info( '%s%s# generation %d InputMap %s' % ( height_indent, gen_indent, generation, im, ))
if im.keys():
for keystroke in im.keys():
logger.info( '%s%s# keystroke %s value %s' % ( height_indent, gen_indent + ' ', keystroke, im.get( keystroke )))
im = im.parent
generation += 1
ActionMap actionMap = tree.getActionMap();
actionMap.put( "cut", null );
actionMap.put( "copy", null );
actionMap.put( "paste", null );
actionMap.getParent().put( "cut", null );
actionMap.getParent().put( "copy", null );
actionMap.getParent().put( "paste", null );
精彩评论