Action on VK_ESCAPE in EditorTextField as TableCellEditor

Answered

Hi,

I'm having troubles assigning custom action to EditorTextFied with VK_ESCAPE keyboard shortcut. EditorTextField is used as custom TableCellEditor component inside JBTable.

When I assign different shortcut, eg. SHIFT_DOWN_MASK+VK_ENTER, then action is called. With VK_ESCAPE, my action is not called. Some generic action is done instead and since I resize row and default action cancel selection in table, it throws null pointer exception later in BasicTreeUI.

End goal is to cancel cell editing and call cancelCellEditing() method of my TableCellEditor, which resizes row to previous height and also notifies CellEditorListener to update model/remote server.

When I just select different row, then editings stops correctly (well, calls stopCellEditing() instead of cancelCellEditing(), but at least my shared logic is called and I later know, that it was stopped from outside and consider it as cancel action). I want table/editor to do the same, when user hits ESC key while editing value in EditorTextField.

When I previously used ExtendableTextField as TableCellEditor component, I could assign KeyListener and handle submit/cancel by my own. With EditorTextField, KeyListener approach no longer works.

Any hints will be much appreciated. Thank you.

0
3 comments

I had the same issue with ENTER not completing table cell editing in a dialog and just performing OK action without applying any cell changes.

The solution I used was to handle the event in the dispatch queue:

    // stop table editing with <ENTER> (if any) and consume the event to prevent any further processing (dialog closing etc.)
    class EditingCommitter : IdeEventQueue.EventDispatcher {
        override fun dispatch(e: AWTEvent): Boolean {
            if (e is KeyEvent && e.getID() == KeyEvent.KEY_PRESSED && e.keyCode == KeyEvent.VK_ENTER) {
                if (e.modifiersEx and (InputEvent.CTRL_DOWN_MASK).inv() == 0) {
                    // DEPRECATED: replacement ComponentUtil#findParentByCondition appeared in 2019-06-08
                    @Suppress("DEPRECATION")
                    val owner = UIUtil.findParentByCondition(KeyboardFocusManager.getCurrentKeyboardFocusManager().focusOwner) { component ->
                        component is JTable
                    }

                    if (owner is JTable && owner.isEditing) {
                        owner.editingStopped(null)
                        return true
                    }
                }
            }
            return false
        }
    }

Then in the component which contains the table:

init {
    IdeEventQueue.getInstance().addDispatcher(myCommitter as IdeEventQueue.EventDispatcher, this)
}

The component is also Disposable so it is used as the parent disposable for the EditingCommitter instance.

You will probably have to do the same for the ESC key but instead of editing stopped, invoke editing cancelled.

0

Thank you for suggestion. It again works for standard keys, but for VK_ESCAPE I can see only following key events:

java.awt.event.KeyEvent[KEY_TYPED,keyCode=0,keyText=Unknown keyCode: 0x0,keyChar=Escape,keyLocation=KEY_LOCATION_UNKNOWN,rawCode=0,primaryLevelUnicode=27,scancode=0,extendedKeyCode=0x0] on frame0
java.awt.event.KeyEvent[KEY_RELEASED,keyCode=27,keyText=Escape,keyChar=Escape,keyLocation=KEY_LOCATION_STANDARD,rawCode=9,primaryLevelUnicode=27,scancode=0,extendedKeyCode=0x1b] on frame0

At the time of processing them, table is not editing any more and I can't get grasp of that specific TableCellEditor which should be cancelled.

It seems, that KEY_PRESSED event is processed before by something else. I tried to add myCommiter also like this:

IdeEventQueue.getInstance().addPostprocessor(myCommiter, this)

Then I receive KEY_PRESSED event for VK_ESCAPE, but at the time editor component seems to be already removed from table. Simply it wont find any parent table, since editor seems to have no connection to it.

Any ideas ?

0

It looks like there is another EventDispatcher registered before yours which handles the key press event. I do not have any suggestion on dealing with this other than debugging to find where it occurs and finding a way to handle the changes.

One way you can try is to keep track of which cell enters edit mode and when you see ESC key typed event, performing your cleanup if edit mode was not exited properly. A bit of a kludge but sometimes it gets the job done when no other solution is obvious.

0

Please sign in to leave a comment.