How do I keep NSMenuItem selected in a NSPopover with NSMenu?
In the end, I changed how I did it.
I am using a NSButton to show the menu and NSTextField to display the results.
If anyone is interested in the details, here they are.
Build the menu up and use .representedObject to store whatever you need to access at the other end. I used a struct with the name and code the in it.
You need to assign the NSMenu to the NSButton.menu
Then have a click, something like this.
@IBAction func changeVoiceClicked(_ sender: NSButton)
{
if let event = NSApplication.shared.currentEvent {
NSMenu.popUpContextMenu(sender.menu!, with: event, for: sender)
}
}
Your NSMenuItem should have an action on it, which using a selector points to a function.
Something like this:
@objc func voiceChanged(sender: NSMenuItem)
{
// cope will nil
var voice : VoiceDetail = VoiceDetail();
if (sender.representedObject != nil) {
voice = sender.representedObject as! VoiceDetail;
}
// Do what you need to on menu select.
// update text field.
}
Is it possible to group items in a NSPopupButton?
The following code groups menu, but not like the way you mentioned.
let items = [["First","Second"],["First","Second"],["First","Second"]]
lazy var addNewViewButton : NSPopUpButton = {
let popupButton = NSPopUpButton()
let firstMenuItem = NSMenuItem(title: "First Group", action: nil, keyEquivalent: "")
let secondMenuItem = NSMenuItem(title: "Second Group", action: nil, keyEquivalent: "")
let thirdMenuItem = NSMenuItem(title: "Third Group", action: nil, keyEquivalent: "")
let superMenu = NSMenu()
superMenu.addItem(firstMenuItem)
superMenu.addItem(secondMenuItem)
superMenu.addItem(thirdMenuItem)
for (index,item) in items.enumerated()
{
let menu = NSMenu()
for title in item
{
let menuItem = NSMenuItem(title: title, action: nil, keyEquivalent: "")
menuItem.target = self
menu.addItem(menuItem)
}
menu.addItem(NSMenuItem.separator())
superMenu.setSubmenu(menu, for: superMenu.items[index])
}
popupButton.menu = superMenu
popupButton.translatesAutoresizingMaskIntoConstraints = false
return popupButton
}()
Add the popupbutton in your code and you will get results like this
Each one will be having its own items inside.
refresh NSMenuItem on click/open of NSStatusItem
Keep a reference to the created NSMenuItem
in your app delegate and update its state (assuming you use the item only in a single menu).
class AppDelegate: NSApplicationDelegate {
var fooMenuItem: NSMenuItem?
}
func createStatusBarItem() {
...
let enableDisableMenuItem = NSMenuItem(title: "Enabled", action: #selector(toggleAdvancedMouseHandlingObjc), keyEquivalent: "e")
self.fooMenuItem = enableDisableMenuItem
...
}
@objc func toggleAdvancedMouseHandlingObjc() {
if sHandler.isAdvancedMouseHandlingEnabled() {
sHandler.disableAdvancedMouseHandling()
} else {
sHandler.enableAdvancedMouseHandling()
}
self.fooMenuItem.state = sHandler.isAdvancedMouseHandlingEnabled() ? NSControl.StateValue.on : NSControl.StateValue.off
}
How do I change/modify the displayed title of an NSPopUpButton
Subclass NSPopUpButtonCell
, override drawTitle(_:withFrame:in:)
and call super
with the title you want.
override func drawTitle(_ title: NSAttributedString, withFrame frame: NSRect, in controlView: NSView) -> NSRect {
var attributedTitle = title
if let popUpButton = self.controlView as? NSPopUpButton {
if let object = popUpButton.selectedItem?.representedObject as? Dictionary<String, String> {
if let shortTitle = object["shortTitle"] {
attributedTitle = NSAttributedString(string:shortTitle, attributes:title.attributes(at:0, effectiveRange:nil))
}
}
}
return super.drawTitle(attributedTitle, withFrame:frame, in:controlView)
}
In the same way you can override intrinsicContentSize
in a subclass of NSPopUpButton
. Replace the menu, call super
and put the original menu back.
override var intrinsicContentSize: NSSize {
if let popUpButtonCell = self.cell {
if let orgMenu = popUpButtonCell.menu {
let menu = NSMenu(title: "")
for item in orgMenu.items {
if let object = item.representedObject as? Dictionary<String, String> {
if let shortTitle = object["shortTitle"] {
menu.addItem(withTitle: shortTitle, action: nil, keyEquivalent: "")
}
}
}
popUpButtonCell.menu = menu
let size = super.intrinsicContentSize
popUpButtonCell.menu = orgMenu
return size
}
}
return super.intrinsicContentSize
}
Related Topics
How to Assign Elements of a Dictionary to JSON Object in Vapor 3
Swiftui Navigationview Starting Inside Itself
iOS Charts - Single Values Not Showing Swift
A Warning "'Init()' Is Deprecated". [Swift, iOS App, Learning Model]
Uialertview or UIalertcontroller to Display Only Once in Swift
iOS 10. Coredata Insert New Object Sig Abrt
Why Is There Multiple Collision Calls Sprite Kit Swift
How to Properly Map JSON Properties to Model Properties in Realm.Create
Create Objects/Instances in Variables Swift
Keep Getting an Error: "Uiimagepickercontroller Extension Discovery Failed with Error: (Null)"
Swift - Nsurl Fileurlwithpath Not Unwrapped
Loading Many UIimages from Disk Blocks Main Thread
How to Programmatically Scroll iOS Wkwebview, Swift 4
How to Get Data to Return from Nsurlsessiondatatask in Swift