Mac OS X NSPanel with NSTabView Keyboard Event: How do I use NSTabViewDelegate to display TabItem's View for keyboard navigation?

StackOverflow https://stackoverflow.com/questions/13688972

  •  04-12-2021
  •  | 
  •  

Question

Mac OS X NSTabView: How Do I Display TabItem's View for keyboard navigation?

I have a TabView that works just fine with the mouse. I want to make the NSTabView support keyboard navigation.

Using the Arrow Key moves through the various TabItems, but does not cause the TabItem view to appear. I need to click the tab in order to show the Tab's view.

When the Arrow Key is used, the NSTabViewDelegate method

tabView:shouldSelectTabViewItem:

is called and it returns YES. NO other NSTabViewDelegate method is called, hence its View is not displayed.

What is the best/recommended way to get the mouse click(show the View) action fired when the TabItem is reached using the keyboard? Can this be fixed in Xcode or do I have to involve subclassing and/or notifications?

Was it helpful?

Solution

Inside MyAppController (mainWindow) the app originally used this code to put up editRecipeController's window, an NSPanel

// Original Code to launch the EditWindow as a sheet

    [NSApp beginSheet:[editController window] modalForWindow:[self window] modalDelegate:nil didEndSelector:nil contextInfo:nil];
    [NSApp runModalForWindow:[editController window]];
    // sheet is up here...
    [NSApp endSheet: [editController window]];
    [[editController window] orderOut:nil];
    [[editController window] close];

Inside the Window, an NSPanel, there is an NSTabView. The Panel is fully function using the mouse. It has a five Tab NSTabView. One Tab has an NSTextField, Three Tabs have an NSTextView. The fifth has an NSTableView.

The problem I had was as follows, when the user navigated from Tab to Tab using the ArrowKey, The proper Tab was Highlighted, but did not become "selected", that is , its View was not displayed. The only way to make the View appear was to click on the Tab with the mouse.

My goal is to have full keyboard support for the NSTabView

I was able to get the proper behavior for the NSTabView by following : Hillegass' Book , Chapter 25, "Sheets.

    // MyAppController.m  - WindowController for mainWindow

    - (IBAction) editRecipeAction:(id)sender {
        // setup the edit sheet controller if one hasn't been setup already
        if (editRecipeController == nil){
            editRecipeController = [[EditRecipeController alloc] initWithWindowNibName:@"EditRecipe"];
            //[editRecipeController setMyAppController:self];
        }

        [[NSApplication sharedApplication] beginSheet:editRecipeController.window
                     modalForWindow:self.window
                      modalDelegate:editRecipeController
                     didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
                         contextInfo:nil];
    }

//end MyAppController.m

// EditRecipeController.m

    - (IBAction)cancel:(id)sender
    {

        [NSApp endSheet:self.window returnCode:0 ] ;
        [self.window orderOut:self];
    }

- (void) sheetDidEnd:(NSWindow *) sheet returnCode:(int)returnCode contextInfo:(void *) contextInfo {

   DLog(@"sheet=%@",sheet);

}

If your goal is full keyboard support for such an NSTabView, I think you will need something like the following use of an NSTabViewDelegate method:

    - (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem{

        NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
        [f setNumberStyle:NSNumberFormatterDecimalStyle ];
        NSNumber *tabNumber =
        [f numberFromString:tabViewItem.identifier];
        [f release];

        switch (tabNumber.integerValue) {
            case 1:
                editRecipeController.tabView.nextKeyView = editRecipeController.textViewIngredients;
                editRecipeController.textViewIngredients.nextKeyView = editRecipeController.cancelButton;
                editRecipeController.cancelButton.nextKeyView = editRecipeController.doneButton;
                editRecipeController.doneButton.nextKeyView = editRecipeController.tabView;
                break;
            case 2:
                editRecipeController.tabView.nextKeyView = editRecipeController.textViewDirections;
                editRecipeController.textViewDirections.nextKeyView = editRecipeController.cancelButton;
                editRecipeController.cancelButton.nextKeyView = editRecipeController.doneButton;
                editRecipeController.doneButton.nextKeyView = editRecipeController.tabView;
                break;
            case 3:
                editRecipeController.tabView.nextKeyView = editRecipeController.textViewDirections;
                editRecipeController.textViewDirections.nextKeyView = editRecipeController.cancelButton;
                editRecipeController.cancelButton.nextKeyView = editRecipeController.doneButton;
                editRecipeController.doneButton.nextKeyView = editRecipeController.tabView;
                break;
            case 4: // Comments
                editRecipeController.tabView.nextKeyView = editRecipeController.textViewComments;
                editRecipeController.textViewComments.nextKeyView = editRecipeController.cancelButton;
                editRecipeController.cancelButton.nextKeyView = editRecipeController.doneButton;
                editRecipeController.doneButton.nextKeyView = editRecipeController.tabView;
                break;
            case 5: //Categories - Table can not be edited 
                editRecipeController.tabView.nextKeyView = editRecipeController.cancelButton;
                editRecipeController.cancelButton.nextKeyView = editRecipeController.doneButton;
                editRecipeController.doneButton.nextKeyView = editRecipeController.tabView;
                break;
            default:
                DLog(@"switch value error");
                break;
        }// end switch

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top