0
votes

I have an NSTableView with a number of rows. The allowsEmptySelection property is NO, so there is always a row selected. I can move up and down the tableview with the arrow keys as expected.

I'd like to also be able to move up and down with the 'j' and 'k' keys. I've looked at the Cocoa Event-Handling Guide, but can't figure out how to make these keys simulate the up and down arrow keys.

For what it's worth, here's what I'm currently doing. I'm not really 'simulating the arrow keys'. Rather, I'm just doing the behavior I want when 'j' and 'k' are pressed. It's fine, but I'm wondering if there is a better way...

- (void)keyDown:(NSEvent *)theEvent {
    NSInteger row = [self.tableView selectedRow];
    NSInteger numRows = [self.tableView numberOfRows];
    switch ([theEvent keyCode]) {
        case 38:   // 'j'
            if (row < numRows - 1) {
                [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row+1] byExtendingSelection:NO];
            }
            break;
        case 40:   // 'k'
            if (row > 0) {
                [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row-1] byExtendingSelection:NO];
            }
            break;
        default:
            [super keyDown:theEvent];
    }
}
1

1 Answers

2
votes

Create a custom subclass of NSTableView to catch the events. Your subclass should have this method in it:

- (void)keyUp:(NSEvent *)event {
    if([event keyCode] == 26) {//J
        if([event modifierFlags] & NSShiftKeyMask) [self moveDownAndModifySelection:nil];
         else [self moveDown:nil];
    } else if([event keyCode] == 28) {//K
        if([event modifierFlags] & NSShiftKeyMask) [self moveUpAndModifySelection:nil];
         else [self moveUp:nil];
    } else [super keyUp:event];
}

This will catch any J or K keys and tell the table view to move up or down, respectively. Also, if the shift key is pressed, this will add to the selection upwards or downwards.

If you choose to use this code, make sure you filter out if any other modifiers are pressed and pass them to super also. I did not do this to make it more readable.

Edit: How to create a false event

unichar theChar = NSUpArrowFunctionKey; //NSDownArrowFunctionKey
NSString *string = [NSString stringWithCharacters:&theChar length:1];
NSEvent *newEvent =[NSEvent keyEventWithType:NSKeyUp location:[event locationInWindow] modifierFlags:[event modifierFlags] timestamp:[event timestamp] windowNumber:[event windowNumber] context:nil/*get graphics context if you want*/ characters:string charactersIgnoringModifiers:string isARepeat:[event isARepeat] keyCode:theChar];
[super keyUp:newEvent];