How to make the system menu a toggle button than a dropdown - swift

So I made this simple Cocoa app. I’m a beginner to Swift and was just experimenting with it. This app toggles between hide/show desktop icons by clicking the menu item from the status bar item’s dropdown. I don’t want such a dropdown to happen and rather just directly toggle between show/hide desktop states on clicking it. How can I achieve this using Swift?

A hacky solution that worked for me: Implement the NSMenu delegate method menuNeedsUpdate(menu: NSMenu) to detect the click, remove all menu items and do your click action within this method.
func menuNeedsUpdate(menu: NSMenu) {
menu.removeAllItems()
NSLog("menu clicked !")
}
Don't forget to set the menu's delegate in the same class so that your method will be called.
statusMenu.delegate = self

Related

How to create a customized dock menu for my macOS application in the dock using Xcode

I am trying to create a customized dock menu for my swift application in the dock so that when the user right click on the dock tile of my app after it has been launched, it will show my customized item in addition to the default dock menu items. I prefer to do it programmatically or creating the (static) menu item using Xcode.
I have reviewed similar questions posted here (How can I add a menu to the application in the dock?) and (Adding Items to the Dock Menu from my View Controller in my Cocoa App) but both referred to the old nib interface instead of how to create one using storyboard. I also reviewed the file template library in storyboard but couldn't find a template for dock menu (I only see one for Main Menu).
Any pointer on how to achieve this using storyboard or programmatically with swift will be much appreciated.
EDIT 4/24/2020: Since Ken's response, I have decided to customize the dock menu programmatically. Here is how I implemented applicationDockMenu(_:) in AppDelegate
EDIT #2 4/24/2020: fixed missing _ input argument to method and problem solved.
func applicationDockMenu(_ sender: NSApplication) -> NSMenu? {
let myMenu = NSMenu(title: "MyMenu")
let myMenuItem = NSMenuItem(title: "My Item 1", action: nil, keyEquivalent: "")
myMenu.addItem(myMenuItem)
return myMenu
}
I must be missing something else since the new item did not show up with I right-clicked on the app's dock icon after the app is launched.
Any idea?
Thanks.
Kenny
You can implement the method applicationDockMenu(_:) in your app delegate class to return a menu of items to be added to the Dock menu.
If you check the docs for that method, it also discusses other methods for providing a static Dock menu. One of them involves creating a separate NIB. If there isn't a template for a menu NIB, you can simply create an empty one and add a menu object to it. That NIB is referenced by a key in the Info.plist file and doesn't need to involve your storyboard.

How to detect a click from an NSToolbarItem inside an NSWindowController?

I have a toolbar on my macOS app, developed in Swift. The toolbarItem is dragable onto the NSWindowController, and I can setup an IABAction function, I just have a print in the function at the moment. And when I click on the button nothing happen the click does not seem to be recognised as an action ?
I had a few more line of code in the function but deleted it and now have just the print("test") line.
#IBAction func exportCsvClicked(_ sender: NSToolbarItem) {
print("test") }
No output observed, so I'd love to get "test" in the console when I click on this button.
Here is a list of the connections associated with the toolbarItem.
I found a way to get around the fact that the IBAction from an NSToolbarItem does not recognise the click on this item:
1/I made a customSegue from the item to the main window controller (it can go anywhere)
2/The prepare for segue function posts a notification to the notification saying that the item has been clicked.
3/The main view controller observes the notification and presents, either has a popup or a sheet (I got two buttons), the view that I have setup in the storyboard (referencing with the storyboardID). I found that you need to pass on all the necessary variable to setup the view from the main view Controller, and that there was issue of code in the viewDidLoad function of the sheet/popup view not running, I am suspecting that they might be different instances.

Is there an iOS sliding menu controller working like UITabBarController?

I found some iOS sliding menu controllers (like Path 2.0 , Facebook iOS), such as ViewDeck https://github.com/Inferis/ViewDeck, ECSlidingViewController https://github.com/edgecase/ECSlidingViewController. But they does not work like UITabbar Controler.
I want to make left side menu controller work like UITabbar, and it can kepp state for each controller for every mene item. It should not create a new controller when I tap a menu item. When I tap a menu item to display a controller (as "controller a") and scroll to someplace, then I switch to another menu item, and switch back to "controller a", it should show me 'controller a' display without changed, just like a tap a UITabbar item.
Thank you.
The below link might help you :
https://github.com/stefanoa/SASlideMenu
I use ViewDeck, but I do not have the problem you mentioned. The menu calls the main view to perform a transition, not to instantiate a new view. Therefore, I can implement a back option on the menu to return to the original view in the same state as it was left.
Here is my implementation. It's a subclass of a UINavigationController, and very easy to use.
https://github.com/aryaxt/iOS-Slide-Menu

How to grab parent sender for UIMenuController

Context:
I have added my custom menu item to the UIMenuController. Everything works just fine, the canPerformAction is called as expected when the custom item is tapped.
Here is my problem:
within the view where the menu is displayed I have a few textview.
I want to be able to grab the current selected text from the current textview
when the custom menu is tapped.
I can’t because the sender is not the object that is hosting/showing the menu but the menucontroller itself.
How do I find the sender/UI_control (parent?) where the menu has been shown?
The way is supposed to work is:
You add a custom menu in the usual fashion.
In the canPerformAction you filter which action you want to enable/show
When the action occurs you check the current responder and there you apply your logic.
The canPerformAction withSender never returns you the current control that is visually hosting the custom menu.
You can find out who is the first responder looping all the views and check the isFirstResponder property. Or if you have just a couple if you can do a quick check for those two.
// called by canPerformAction
if ([myTextBox isFirstResponder]) {
NSLog(#"Found it!", nil);
}

Custom NSStatusItem with custom view - Use NSWindow, NSView, custom NSMenuItem?

I'm trying to create a LSUIElement app that behaves like Spotlight, CoverSutra and other apps of that type. I managed to create a custom NSStatusItem, which popups up an NSWindow but the problem is that the app that currently has focus will the focus to my custom NSWindow.
I've based myself on Matt Gemmell's example (http://mattgemmell.com/2008/03/04/using-maattachedwindow-with-an-nsstatusitem)
For example, if you're in Safari and click on the Spotlight icon, the current Safari window does not gray out and keeps focused. When you press ESC in Spotlight, the focus is back to the Safari window.
I haven't managed to do this with my custom NSWindow. I have to click back on a window to set focus back to it.
So I'd like to know which route to go to achieve this. Is the solution a NSWindow, NSPanel, NSMenu with a custom NSMenuItem?
Use NSPanel and NSNonactivatingPanelMask as styleMask or tick the option in IB.