2
votes

I have created a main menu in Swift/Cocoa with custom views that replaces several menu items. The custom views are loaded from a separate NSView class/xib File. The constraints inside this custom view hold a label that is centered via Interface Builder, accordingly:

enter image description here

The replacement of the menu item has been accomplished like this:

@IBOutlet weak var statusMenu: NSMenu!
@IBOutlet weak var tabviewRoom: tabviewMenuRoom!
@IBOutlet weak var stackScenes: NSStackView!
@IBOutlet weak var menuRoomsHeader: viewMenuHeaderRooms!

...

if let itemRoomsHeader = statusMenu.item(withIdentifier: "rooms_header") {
        menuRoomsHeader.title = "Rooms"
        itemRoomsHeader.view = menuRoomsHeader
        itemRoomsHeader.target = self
    }

However, due to some missing constraints onto the view, the final result in the menu looks like this (the NSView is not stretched to the width of the menu item):

enter image description here

I am wondering how to add constraints to a menu item to keep the text centered (=width of the custom NSView shown in red, width of NSMenuItem shown in green).

3
This looks like something that can be solved in a couple of lines of code. Can you just clarify what menuRoomsHeader is, and how it's related to itemRoomsHeader?iOShit I Screwed Up
@RX9: Thanks. Just edited the post to make it more clear. FYI: tabviewMenuRoom is of type NSTabView and viewMenuHeaderRooms is of type NSView. The classes consists of their inits only, no programmatic layouting etc. The whole formatting is done in Interface Builder.Maschina

3 Answers

1
votes

Make sure you have disabled “Translates Mask Into Constraints” for the container view. Then check that the layout behaves as intended when you resize the view in Interface Builder.

You can also review active constraints at runtime by opening the menu, then clicking “Debug View Hierarchy” in Xcode and selecting NSCarbonMenuWindow in the Debug Navigator.

1
votes

It looks like your only intention is to bring the menu title in the middle and to make it bigger in size. If so, the way to go is with menu item attributedTitle.

@IBOutlet weak var menuHeader: NSMenuItem!

func setMenuTitle() {

    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .center

    let textAttributes = [NSAttributedString.Key.font: NSFont.systemFont(ofSize: 32),
                          NSAttributedString.Key.paragraphStyle: paragraphStyle]

    let attString = NSAttributedString(string: "Title", attributes: textAttributes)

    menuHeader.attributedTitle = attString
}

UPDATE:

If this is not working for you and you need more customisation take a look what Apple is writing on sizing a view in a NSMenuItem:

A menu item with a view sizes itself according to the view's frame, and the width of the other menu items. The menu item will always be at least as wide as its view, but it may be wider. If you want your view to auto-expand to fill the menu item, then make sure that its autoresizing mask has NSViewWidthSizable set; in that case, the view's width at the time setView: is called will be treated as the minimum width for the view. A menu will resize itself as its containing views change frame size. Changes to the view's frame during tracking are reflected immediately in the menu.

1
votes

From Views in Menu Items:

If you want your view to auto-expand to fill the menu item, then make sure that its autoresizing mask has NSViewWidthSizable set.

This is the horizontal line in the middle of the Autoresizing control.

Off:

enter image description here

On:

enter image description here