UIFocusGuide: only forward if system has no solution - objective-c

I have a wide "dock" area at the bottom of the screen. I have placed a UIFocusGuide across the top of it. Depending on which element in the dock has focus, the system may or may not have a focus solution if the user swipes up.
How can I tell my focus guide to use the system-calculated new focus item if there is one, but if not, it should use the one configured in my setPreferredFocusEnvironments:
Alternatively, is there a way to determine where a "swipe up" will take the focus without actually doing it? As the focused element in the dock changes, I could check this and if it has no destination provided by the system, I can add one.
My dock is a view within a main view controller but preferredFocusEnvironments is never called when the user tries to move to a non-existent view from an element in the dock.

Related

Detect if menu bar is hidden or visible

Is there a way in Cocoa to receive a notification (or something similar) when the menu bar becomes hidden or visible? I tried looking around and have not found any information on this topic.
Thanks
I solved this by using Carbon's menu event handlers.
I registered for events kEventMenuBarHidden and kEventMenuBarShown under the class kEventClassMenu.
Optionally watch out for (Cocoa) notifications for an object of class NSStatusBarWindow and notifications like
NSWindowDidChangeOcclusionStateNotification
NSWindowWillCloseNotification
to get notified when the menu bar showing or hiding.
If you only need the current state of the menu bar, another approach is to use the visibleFrame property of NSScreen:
The returned rectangle is always based on the current user-interface settings and does not include the area currently occupied by the dock and menu bar.
However, this won't be sufficient by itself if you need to be notified of menu bar visibility changes.
I believe the correct approach to this is to use Key-Value Observing (KVO) to observe the presentationOptions or currentSystemPresentationOptions property of the application object (NSApp or [NSApplication sharedApplication]). When that changes, check its value to see if it includes NSApplicationPresentationHideMenuBar or NSApplicationPresentationAutoHideMenuBar. If it does, then the menu is hidden (or hides when the cursor is not near the top of the main screen.
The difference between presentationOptions and currentSystemPresentationOptions is whether you're interested in whether the calling app has hidden its menu bar or whether the active app (which may be another app) has hidden its menu bar. The latter indicates whether the user can see any menu bar.

Move focus to other UIButton

I am working on a small game for Apple TV, and one thing I can't get to work is moving the focus from one button to the other (programmatically), or temporarily remove focus from any object (buttons) as the game is doing stuff.
I've seen the guide about objects and focus, but is there really no way to programmatically move the focus to an other part of the screen as the input is needed there (instead of letting the user move all the way across the screen)?
There will always be a view that has focus. It's not possible to not have a focused view.
You could temporarily change the focused appearance of an item, so it doesn't appear to have focus, but that would likely be be confusing for the user, or conflict with Human Interface Guidelines.
There's no explicit way to programmatically move focus from one control to another, per the App Programming Guide for tvOS:
The Focus Engine Controls Focus
Only the focus engine can explicitly update focus, meaning there is no API for directly setting the focused view or moving focus in a certain direction. ...
The focus engine controls focus to make sure that it does not move around the screen unexpectedly, and that it behaves similarly across different applications.
Answers to other questions have suggested that you could "game" the system by overriding preferredFocusedView, conditionally setting it to the desired control to move to, then requesting a focus update. Such an approach would likely be fragile.

making a dock bar [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I want to make a dock bar which contains application's icons. If I click on any icon then that application should lunch and how can I hide that dock bar ?
I am new to cocoa and I have no idea about it .
so can any one give me basic idea to do it .
thanks in advance
There are several key elements here:
Like almost anything else on the screen, your Dock would have to be in a window. Presumably, you aren't imagining a window with the standard frame (title bar, stoplight, and resize handles), so you'd want a borderless window. It will have to be at a particular window level, namely this one.
Each icon would be a button to start with. You'd evolve this into custom views that are capable of bouncing, showing running state (as the Dock does with its LEDs), etc.
The Dock populates itself with three kinds of items: Running applications, bookmarked applications (those that stay in the Dock even when running), and bookmarked files (documents, folders, etc.). Applications go on the left side of the divider; bookmarked files and the Trash go on the right side.
Speaking of the Trash, if you want that, you'll need to use FSEvents to detect when any Trash becomes non-empty, NSWorkspace or an Apple Event to the Finder to open the Trash, and an Apple Event to the Finder to empty it.
When the user clicks on a bookmarked application that isn't running, you'll use NSWorkspace to launch that application.
For applications that are already running, you'll need to activate them (if not already active) or “reopen” them (if already active). I'd first try just launching them and seeing whether that Does the Right Thing in all three cases; if it doesn't, then you get to send Apple Events yourself when necessary.
Bookmarked folders can be perused in the Dock with one of three UIs: List (a menu), grid (a collection view), and “fan”. Menus are easy enough to make, but I'm not sure how to make one popover-styled. The grid UI would be a collection view in a HUD-styled popover. “Fan” is entirely custom, in a popover.
You'll need to detect when applications launch and terminate, in order to add them to your Dock (if not already there as bookmarks) and remove them from it (if they're not bookmarked then). NSWorkspace has notifications for this.
You probably can't get applications' custom Dock menus. That's all private stuff between Apple's Dock and AppKit.
Likewise, good luck implementing the “Assign to Desktop” menu items.
The other commands in each application's Dock menu correspond to NSRunningApplication methods.
You'll also want to handle drag and drop in your Dock-icon views, both to enable reordering and to handle the user dragging items off of the Dock to un-bookmark them. Remember to handle the case of un-bookmarking a running application (the Dock does un-bookmark it, but snaps the app back into place because it is still running). When un-bookmarking, play the poof effect when the user drops it.
When the user ⌘-drags any item out of the Dock, drag the file represented by that item. This doesn't work on the Finder (in Apple's Dock—you could do this if you want) or the Trash (it doesn't represent a single item). Do not remove the item from the Dock.
And, on the other end, you should highlight an icon when the user drags to it, if and only if the item represented by the icon can receive that drag.
When the user drags files to an application, highlight it if all of the files' types are among the application's document types. Complete the drag by using NSWorkspace to open the file URLs with that application.
When the user drags non-file URLs to an application, highlight it if all of the URLs' schemes are among the application's URL schemes. Complete the drag by using NSWorkspace to open the URLs with that application.
When the user drags content to an application, highlight it if the application has a service that can handle any of the content types on the drag pasteboard. Complete it by invoking that service. (I don't know of a public API to do this with a specific application—you'll need to just use the service name and hope for the best.)
When the user drags files to a folder, highlight it if the folder is writable or contains any folders. If the user hovers there for a certain amount of time, open the folder in the Finder (this feature is called spring-loaded folders). If the user drops the files on the folder in your Dock, complete the drag by moving or copying the files to the folder, or by creating aliases to them in the folder, depending on the state of the modifier keys.
The same goes for files to the Trash, but you'll need to determine the correct Trash for each file. If the file is within the Home folder, the correct Trash is the Home folder's Trash. Otherwise, it's the volume-level Trash of whatever volume the file is on.
When the user drags any volume(s) to the Trash, change its icon to an Eject icon (kEjectMediaIcon, used with iconForFileType:). Complete the drag by ejecting the volume(s). If the user completes the drag, cancels it, or drags away from the Trash, change the Trash's icon back.
Oh, and you'll need to handle dragging between items, including before and after the divider, to add items. This will overlap with the dragging to reorder that I mentioned above.
For auto-hiding, you'll need to have a 1-pt-tall/-wide borderless window, of the same width/height as the real Dock, at the edge of the screen that bears the Dock (ordinarily the first screen, if there are any). When the user mouses over this window, show the Dock (which should cover up the thin window). When the user moves the mouse outside of the Dock, hide it.
The Dock has a contextual menu containing various options on its divider.
Ideally, you should anticipate supporting theming at some point, since the Dock has at least two themes already (the default “glass” theme and the 2D HUD-style theme).
Let me know if I missed anything.

Controlling NSSegmentedControl with the keyboard

I have a form in my Cocoa app that contains an NSSegmentedControl that I want to be controllable via the keyboard. It seems that NSSegmentedControl is very reluctant to become the first responder, however.
Setting the initial first responder of the window to the segmented control does nothing -- it will not have keyboard focus when the window is first loaded. It does receive focus if I manually set the first responder like this, however:
[segmentedControl.window makeFirstResponder: segmentedControl];
That will work fine if the only part of the form is the segmented control. If I add another field (say, an NSTextField), and I set the nextResponder of the segmented control to that field, the segmented control will never become first responder. Focus will immediately go to the text field, and pressing tab to switch back to the segmented control doesn't work.
I've tried subclassing NSSegmentedControl and overriding acceptsFirstResponder, becomeFirstResponder, etc. to no avail. The only one that makes any difference is resignFirstResponder -- if I return NO from that method then the segmented control will indeed retain focus, but obviously I don't want it to retain focus all the time.
Any ideas on how to get the control to behave like a normal responder?
It's behaving as intended. Not all controls participate in the "key view loop". Full keyboard navigation is turned on through Universal Access in System Preferences for all apps and it's not for individual apps to implement on their own.
It's best not to use a segmented control in a form intended for heavy keyboard entry. NSPopUpButton works more closely to what we all exepect in a web form so it's not as if it's necessarily the wrong choice in your app's UI.
Rather than answer exactly the question you asked (which someone else can do), I humbly suggest you choose on the side of functionality at the cost of a slightly prettier UI element since that prettier UI element wasn't intended to get along with the keyboard.

How can I keep an NSPopUpButton open after the user selects a menu item?

I have an NSPopUpButton providing the NSMenu for a status item with a custom view. The popup button displays a list of links. When the user selects a link from the list, the link is displayed in the user's browser (in the background).
Naturally, the menu closes every time the user selects a link.
I would like to change this: I want the menu to stay open while the user clicks on various links, all of which can be opened in the background. The menu can then go away when the user clicks elsewhere.
How can this be accomplished? Should I subclass NSMenuItem and intercept the mouse clicks somehow? Overlay a transparent NSView on the popped-up menu and, again, intercept the clicks somehow? I make these suggestions blithely, but I would have trouble implementing either of these...pointers to the right methods for override would be appreciated.
Instead of using a menu, one might use a collapsible box.I have seen that in many apps ( also provided by Apple) , so I guess this is the recommended style guide for multiple selections.
The collapsible box expands when you click the disclosure button, and it gives free all items desired - like a tableview with checkboxes.
Views below this box must move down in this case, not to interfere with the box.
Clicking again on the disclosure button will shrink the box back to its origin. The effect is similar to closing a menu.
Usually you should not bend a control too far past it's original intent. Users expect pop up buttons to close after making a selection. I don't think you should, or can, force NSPopUpButtonCell to behave in this way. If you do, you'll be subclassing and modifying the control so heavily that it might change/break with a future version of Mac OS X. You'd also have to worry about the usability problem of users thinking the menu will close after making a selection.
You might consider writing you're own subclass of NSView to work like the menu button you're describing. After the user clicks on the button. You'll want to create a new NSWindow, with no border by using NSBorderlessWindowMask as the style mask. The content view of that window should be another custom view of yours that you implement the menu selection in.