Setting tab order for NSTextFields of an NSView - objective-c

I am trying to set the tab order for NSTextFields on a given NSView. As far as I understand it I have to connect the NSTextFields with InterfaceBuilder by setting the nextKeyView outlet to the next NSTextField. I did this - and there is no effect. When I press tab, after being in one of the NSTextFields it just loses focus and that is it. No matter how often I press tab none of the other NSTextFields regain focus.
I also read that I need to set the initialFirstResponder of the window. I don't think I can do this in this particular case, because my AppDelegate calls up a NSView which in turn acts as a Menu-Area with many different buttons, which each call up different NSViews that are loaded as subviews of a different view. Therefore the AppDelegate has no way of knowing which NSView is currently loaded.
Is there a way to set the tab-order of NSTextFields on an NSView-basis?
Thanks

You have to disable auto-recalculation of the key loop in the window. See -[NSWindow setAutorecalculatesKeyViewLoop:].
Edited to add: this can be set in Interface Builder, too.

This may or may not help for your situation, but the following worked for me when dealing with an NSView within another NSView. I had two vertical stacks of NSTextFields. Rather than traversing horizontally, I needed to tab down one stack and then the next... So I embedded each of the two vertical stacks in their own box (In IB, first select your items, Editor> Embed In> box). Works perfect.
If you don't want the look of a box, you can clear its title and set its border type to none: invisible box.

Related

Handling tabs in Cocoa view containing a text field and scrolling view

In my Cocoa app, I have a window that contains an NSTextField (as is) and an NSScrollView (sub-classed). I've got an NSViewController that manages the window's NSView containing the text field and scrolling view.
At app startup, the NSTextField has focus, and typing enters characters into that text box. When I hit the TAB key, it loses focus. But nothing else in the interface, like the NSScrollView, gains focus. I can't tell where any key down events are going.
How does one transfer focus to the NSScrollView, so that key down events can affect it (e.g., arrow keys, implicit searching, etc.)?
First, you should try hitting Tab repeatedly to see if focus ever makes it to the scroll view or comes back around to the text field.
You don't say what's in the scroll view as the document view. Rather than having the scroll view itself accept focus, it's more common that the document view or one of its descendant views accepts focus. Then, the movement keys would be delivered to that and, if nothing consumes them, they'd bubble up the responder chain to the scroll view and it would handle them automatically.
If you really want your scroll view to accept focus, you need to override the -acceptsFirstResponder method to return YES.
The behavior of Tab is governed by the window. It maintains a key view loop. It can automatically recalculate the key view loop as views are added and removed. That's probably the most reliable way. See the autorecalculatesKeyViewLoop property.
Alternatively, you can manually tell it to recalculate as you desire, by turning off autorecalculatesKeyViewLoop and calling -recalculateKeyViewLoop.
Or, you can explicitly set up the key view loop yourself by connecting each view's nextKeyView and previousKeyView properties, either in code or in Interface Builder.

OSX Cocoa using tab to navigate between child controls within a view not working

I am new to Xcode/OSX UI so there is probably something silly I'm overlooking. This is XCode 5.11 targeting OSX 10.10 desktop.
I have inherited some code with a few views where navigating among child controls within the view using the tab key does not work.
In researching this almost everything says to be sure to set the first responder and then chain your controls using nextKeyView.
I followed the steps in this video https://www.youtube.com/watch?v=SRrE8eqp0dU (XCode 4, but all the functionality seemed to be the same for 5.11) to no avail.
I also had a look at this solution How to make child controls of view will get focus on Tab and Shift+Tab in NSViewController which sounds like a similar issue to what I am seeing, but one of the classes I inherited uses NSWindowController vs. NSViewController as the base and there is no loadView to override and the other which did derive from NSViewController did not behave any differently with the changes made to loadView.
When my window launches my first responder control (NSTextField in this case) has focus (blue highlight) but tab key is ignored and focus will not change unless I use the mouse.
So it's really not a tab ordering issue initially, it seems like a tab ignored issue and who knows what the ordering is. I tried setting focus to a NSButtonCell and NSPopUpButton using the mouse and then tab navigate from those to see if there was some issue with my NSTextField but they exhibit the same behavior. None of the controls are set to "Refuses First Responder" which was another setting it was recommended to check.
I'm at a loss and looking for any other things to try or check.
The first view I am having an issue with is: Window / Child View / Multiple Child Boxes / Multiple controls per box in case that matters or complicates things. It is basically for setting application Preferences.
The second view seems like it may be more complicated in that there is a single Window that swaps out its child view in a next/back progression (wizard interface). The initial window nib is "blank" so I didn't see how to associate a first responder from IB like I did with the Preferences window since all the controls are on their own individual view nibs (these all show as "Custom View" vs. just "View" for Preferences).
The resolution for me was to ensure that the "Auto Recalculates View Loop" setting in the Attributes Inspector was enabled for the windows hosting these views. This corresponds to the autorecalculatesKeyViewLoop property of NSWindow.

Alternating between several NSViews

What I need may be pretty basic, but I'm definitely not sure as to how to proceed (I've done that before but none of my choices seem that Cocoa-friendly).
Ok, let's say we've got 2 NSViews - one next to the other:
The one on the left serves as a menu.
The one on the right will show a NSView (from a different XIB perhaps?) depending on the selection on the menu.
My questions :
How should I go about loading the different NSViews into the rightmost NSView?
How do I make sure that the subview (the one currently active) is properly resized when the window is resized?
rdelmar's solution should work, but another approach, which may be simpler, is to use an NSTabView to handle switching between the content views. You can hide NSTabView's tabs using the settings pane in interface builder, or by calling [self.tabView setTabViewType:NSNoTabsNoBorder]. I'd probably use a table view for the left side. When the user selects a row, you do something like:
-(void)tableViewSelectionDidChange:(NSNotification *)notification
{
[self.tabView selectTabViewItemAtIndex:[self.menuTableView selectedRow]];
}
The NSTabView can/will take care of properly resizing its content views as long as you've set up its and its content views' autoresizing masks (springs and struts) properly.
You should be able to create a custom view in IB that looks like your yellow view, and set its resizing behavior to expand in both directions with window resizing. Then, when you get your new view (by just referencing one you already have or loading a new xib), add it as a subview of the custom view, and set its frame to that of the custom view. I think that views resize their subviews by default, so it should resize correctly with the custom view.

delaysContentTouches only on specific elements without subclassing?

I have a simple question. In my app, I have a some buttons for navigation inside a UIScrollView, which scroll with the content. This way, when the user enters a text field and the keyboard pops up, the buttons will scroll away for extra space. However, the buttons don't highlight immediately when I tap on them. I've learned that I can eliminate this problem by setting delaysContentTouches to NO, but this makes scrolling nearly impossible, because all the UITextFields and buttons in the view also highlight immediately, stealing the scroll.
I have found a way to only not delay the buttons via a UIScrollView subclass, so this is an option, but I was wondering if there is another way. I generally hate subclassing when it is to fix just one little thing.
The touchesShouldBegin:withEvent:inContentView: method of UIScrollView is intended to be overridden by subclasses if delaysContentTouches is set to YES. So this is the case when subclassing is completely OK.

Drawing an "NSView" to a Custom-View - How? Am I taking the right approach?

I'm using Objective-C and Cocoa, whilst developing for Mac OS X - so not the iPhone/Cocoa Touch. (That said, I'd be interested if it was the same procedure for the iPhone)
I'm working on a preferences window for a simple app. I have a NSWindow with a toolbar - there are 5 different items on the toolbar, all of which need to bring up a different set of options.
So I set the NSToolbar and its items in Interface Builder, and then placed a custom view underneath the menu - taking up the rest of the window. My plan is to work out the interface too each of the NSToolbarItems options, and then draw the corresponding view on to the custom view when the specified NSToolbarItem is clicked.
I'm guessing that I simply create a NSView sub-class for each view, an empty xib in Interface Builder - set the xib to my custom NSView, code it as usual... But here's a few problems;
1 - Just how can I get the xib file to appear on the custom-view then? I have looked around and most articles don't seem to have this situation, or a situation I can relate too.
2 - When the window comes up, I want the default view to appear on the custom view. Once again, I'm guessing I just write that in the initialisation code for the NSWindow - its no big deal. It just goes back to question 1 though - how do I draw my NSView to the custom-view specified in Interface Builder?
I'd be really grateful for any help!
Cheers in advance.
So I set the NSToolbar and its items in Interface Builder, and then placed a custom view underneath the menu - taking up the rest of the window.
You can't have a menu inside of a window. You can have a pop-up button, which has a menu, but not a menu directly. Did you mean “toolbar” here?
You don't need to create a custom view for this. Make a tab view and set it to be tabless. Give it as many tab view items as you have toolbar items. In your controller, write an action method for each of the toolbar items, and in each action method, switch the active tab of the tab view.
You can activate different tabs in IB to populate them with views in IB. The active tab is saved in the nib, so make sure you set it back to the first tab before saving, so that the first tab is the one that's initially active when your app runs.
Just how can I get the xib file to appear on the custom-view then?
That question doesn't make sense.
Once again, I'm guessing I just write that in the initialisation code for the NSWindow - its no big deal.
You would only be able to do that if you have your own initialization code for the window, which you would only have if you have subclassed NSWindow. There are very few reasons to do that; unless you're making the window itself look different (not making an Aqua or HUD window), you should move that initialization code elsewhere, probably to the aforementioned controller (which should be the File's Owner of the nib).
It just goes back to question 1 though - how do I draw my NSView to the custom-view specified in Interface Builder?
A custom view in Interface Builder is a plain NSView (unless you explicitly change it to a subclass of NSView you create). However, you do not need one for anything you have described in your question.