I'm creating an application where a menubar seems to be the most convenient way to have the user's desktop clean without a window. I've seen many tutorials online and on stack overflow but they seem to be only for Objective-C. I only use Swift. If you don't know what a menubar is, they're these icons:
I would like my app to have one of these instead of a constant full window. And if I can, how can I have a button on my menubar that brings up the window. Lastly, how can I have my icon not show, but I still have the finder advantages. (Like File, Edit..). For example,
I have already tried to put
Application is Agent (UIElement) to False
in my Info.plist but that also takes away my finder advantages.
Presumably what you're saying is that you want the text editing items (like Undo, Cut, Copy, Paste, Select All) from the Edit menu to work in your app's window.
Those menu items are part of another application, and only send messages in that application. They aren't available to your application, regardless of whether it's an “agent” (with no visible menu bar of its own). If one of your agent app's windows is the key window and the user clicks on a menu title (like File or Edit) that belongs to another app, then that app will activate and your app's window will “resign” the key window status.
You can make the usual shortcut keys (like ⌘X for Cut) work for your app, and it's easy. When one of your app's windows is the user's key window, your app receives keyboard events, and your NSApplication object (created for you automatically) will check its mainMenu for keyboard shortcuts even though the main menu is not displayed on the screen.
The OS X “Cocoa Application” project template sets up a main menu bar for you in MainMenu.xib (or in Main.storyboard), with all of the menu items wired up to the appropriate actions. So if you keep that main menu bar and the Edit menu and the menu items in the Edit menu and leave the shortcuts set on those items, then the keyboard shortcuts will work even if you set LSUIElement to YES in your Info.plist, when one of your app's windows is the key window. In other words, the shortcut keys will work by default, and you have to change things to make them stop working.
Text fields in your app's windows will also still get the default right-click menu with the usual items like Cut, Copy, and Paste, so you don't need to do anything else to make that work either.
Here's the contents of my test app's MainMenu.xib:
I've left the main menu bar alone. I've created a separate menu with two items, “Show Window” and “Quit”. I've set the shortcut for “Quit” to ⌘Q, but this shortcut has no effect. The StatusItem > Quit menu item (not visible in my screen shot) off the main menu bar has the same shortcut set, and that's the setting that matters. I've set the shortcut on this other Quit item because it's visible to the user, and the main menu bar won't be visible to the user.
I've wired this Quit item to the terminate: action of First Responder. (The StatusItem > Quit menu item is connected the same way by default.)
Here's my AppDelegate:
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet var window: NSWindow!
#IBOutlet var statusItemMenu: NSMenu!
var statusItem: NSStatusItem?
func applicationDidFinishLaunching(aNotification: NSNotification) {
self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
let statusItem = self.statusItem!
let button = statusItem.button!
button.title = "Hello"
statusItem.menu = statusItemMenu
}
#IBAction func showWindow(sender: AnyObject) {
NSApp.activateIgnoringOtherApps(true)
window.makeKeyAndOrderFront(sender)
}
}
I've wired the “Show Window” menu item to the showWindow(_:) action, and I've connected the statusItemMenu outlet to that standalone menu in the XIB.
I also set “Application is Agent (UIElement)” to “YES” in Info.plist.
When I run this app, it creates the status item in the menu bar. I can choose “Show Window” from the item and my window comes to the front and becomes key. I can right-click the text field to get its context menu. I can use the standard shortcuts to cut/copy/paste/etc., to close the window, and even to quit the app.
Related
I am currently creating a macOS menubar for an app without using any interface builder (no XIB/NIB files), just pure code. However I was expecting some items to be auto-generated during the start-up of the app. Items like "Start Dictation", "Emoji & Symbols" under Edit menu were existing as well as the "Enter Full Screen" menu item under the View Menu. But when it comes to Window Menu nothing was automatically generated, only the menu items I've set in the code. Do I have to enable some flags or options when instantiating a Window NSMenu so it automatically generates those items? I am new to macOS development so I feel like I am kind of lost. Thanks in advance.
The Window and Help menus are a little special in that they have their own NSApplication properties, so you will need to set them to your menus so that the system will know what they are.
For example, if you just create a window menu and add it to the main, all you will get are the items that you have provided. If you also set it as the application’s windowsMenu, in addition you will get all the stuff for moving, tab support, etc.
Setting NSApp’s helpMenu is similar, where a Spotlight menu item is added to the menu.
I am making my first OS X application in Xcode, and I have no idea how to make a specified keyboard shortcut trigger some code (e.g. ⌘ Cmd+ C/⌘ Cmd+V). All I can find online is keyboard shortcuts in Xcode itself.
Thanks in advance
This is usually setup for you automatically. The MainMenu.xib by default has an Edit menu with these shortcuts bound, activating [firstResponder copy:] and [firstResponder paste:]. The first responder is item currently having keyboard focus, or it's parent view if it doesn't answer to those actions, up to the window at the top level.
For new shortcuts, Apple recommends that you have menu items associated to all those. If you do, you can set the shortcut in the interface builder using the attributes inspector. You then ctrl-drag from the menu item to the object you want to send the action to, e.g. the app delegate. You will have to create the target method first obviously. You should also use bindings to control when the menu item is enabled or not.
It's not recommended, but if you want to do this programmatically, without a menu item, you override the
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
method of the view or window in question. It will be called if it's in the responder chain when the key is pressed, and you return YES to indicate you've handled the event.
I am new to Mac os x and am having some difficulties with the the transition from windows and widgets. In my MainMenu.xib, I have the main window of my app, call it window A, and I added a menu tab to the main menu tabs as well as a new window B to the MainMenu.xib. When I launch my app, I want window A to open (which it does) and then when the user clicks the new menu tab, I want window B to appear. Is there an easy to way to connect the menu tab to window B in the IB so that it opens when the menu tab is clicked?
Thanks for your help
What are main menu tabs?
To show Window B call [myWindowB makeKeyAndOrderFront:sender].
For window B , uncheck visible at lunch from interface builder(window attribute). when the user clicks the new menu tab.
[WindowA orderOut:sender];
[WindowB makeKeyAndOrderFront:sender];
write this code.
XCode works in mysterious ways (at least to me).
I simply want to create a Preference pane in my app. When I run my app, the stock menu bar comes up (Apple, MyApp, File, Edit...) and the "Preferences" menu item is grayed out. It makes sense since I haven't started playing with it.
How on earth do I add/remove/activate/inactivate menu items? I'm not talking about adding anything new, simply using what should be there.
Thanks in advance.
NSMenu has "Auto Enable Items" enabled by default. That means if the menu item does not have it's action message hooked up, it will appear grayed out. So in your case, you would simply set the Preferences menu item's "Sent Action" to whatever action shows your preferences window. This can be hooked to some sort of showPreferencesWindow: method of your AppDelegate, or directly to the showWindow: method of a window controller.
To dynamically enable/disable menu items the best way is to implement the NSUserInterfaceItemValidation protocol which is excellently documented here
Edit: Your app's menu bar items live in the MainMenu.xib file. The menu bar appears as a "Main Menu" object on the left hand side (if you're using Xcode 4) Simply click on the items to modify them, and you can Ctrl+drag connections to and from them like any UI object.
I want my app to show his menu on launch only if the user didn't open a file. Now I can't seem to make it work. Hiding the menu makes the dock and the status bar invisible. I want them to still be there, but not with my own menu (e.g. if you open a file from finder, the finder menu is still visible, but my app opens a window that handles the file, and quits if the user cancels or on completion).
I probably didn't explain it well enough, but here's what I did to solve it :
Add this line to the plist of my app (this produces an app without dock icon or menu), the dock and the menu bar will still be there, but won't be changed by the app :
LSUIElement
(And set the checkbox to true).
This makes your app UI-only (it doesn't show his NSMenu nor does it add an icon to the dock, but just shows your GUI.