Detecting arrow keys pressed in NSTextField

I have a view with a grid of cells.


When user click on a cell, an NSTextFied overlays the cell to allow for entering value.


When Tab, Shift-tab or return are pressed, the editing cell moves to next or previous one.

This is done in the


    override func controlTextDidEndEditing(notification: NSNotification)


I would like to do the same with arrow keys, to allow for fast moving in the grid.


When arrow is pressed, cursor moves in the TextField ; I would need to intercept this pressed key and act accordingly. How can I do this ?


I tried to implement

    override func keyDown(theEvent: NSEvent!)


but the method is not called when arrowkey is pressed (it is called when any other key is typed).


I tried also :


    override func controlTextDidBeginEditing(obj: NSNotification) {
    }


Doesn't work either.

Answered by QuinceyMorris in 127786022

You're tap dancing in a minefield here.


a. How could you possibly want to have text editing without the arrow keys to move the cursor within the text? There is nothing more frustrating to users than standard UI elements with non-standard behavior.


b. Of course 'keyDown' is called — somewhere. The particular method implementation is chosen by traversing the responder chain. So, it matters where you put your override (you didn't say where you put yours).


c. When a text field is being edited, the editing does not happen in the text field, but in an auxiliary field editor belonging to the window as a whole. That's where you would have to override 'keyDown' in this case, which means subclassing the field editor, and that's a world of pain you probably don't want.


d. The easiest way to modify the tab/return behavior is not in the delegate method 'controlTextDidEndEditing', but in delegate method 'control:textView:doCommandBySelector:'. As it happens, you can detect arrow key usage in this method too.

Accepted Answer

You're tap dancing in a minefield here.


a. How could you possibly want to have text editing without the arrow keys to move the cursor within the text? There is nothing more frustrating to users than standard UI elements with non-standard behavior.


b. Of course 'keyDown' is called — somewhere. The particular method implementation is chosen by traversing the responder chain. So, it matters where you put your override (you didn't say where you put yours).


c. When a text field is being edited, the editing does not happen in the text field, but in an auxiliary field editor belonging to the window as a whole. That's where you would have to override 'keyDown' in this case, which means subclassing the field editor, and that's a world of pain you probably don't want.


d. The easiest way to modify the tab/return behavior is not in the delegate method 'controlTextDidEndEditing', but in delegate method 'control:textView:doCommandBySelector:'. As it happens, you can detect arrow key usage in this method too.

Thanks,


control:textView:doCommandBySelector was the way to get it.


I agree on point a ; but in this specific case, a cell should only contain a number, usually from 1 to 9, and rarely up to 20 ; so there is little value to use arrow keys for editing, where there is more to move easiliy in the grid.


I put the keyDown override in myView: NSView, NSTextFieldDelegate, which contains the NSTextField.

It's never called ; as I want to filter what is typed in (only numbers), I'll use controlTextDidChange

How about you do it like this:


— In the normal case, don't use text field editing. Instead, have a "selected" grid cell that's visually distinguished. In this mode, the arrow keys (also tab) move between grid cells, and the number keys change the selected cell to the corresponding single-digit value. Maybe pressing a number key also moves right or down or whatever, after entering its value.


— Use (say) the return or enter key to start text editing on the selected cell. In this case, use a text field in which the arrow keys work normally for text editing. Return or enter ends the mode. If you want, you could have tab move forward or backward to the next cell, keeping the editing mode alive. If the cells always contain a number, you could also allow Option+arrow keys (function "move left/right/up/down by word") move the editing cell but keep editing mode.


That way, you can do all the navigation you want, keep the common things extremely simple, and yet not abuse the standard editing UI.

Detecting arrow keys pressed in NSTextField
 
 
Q