Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a NSPopUpButton that uses a fixed Image, and no arrows?

I'm trying to get NSPopUpButton to render like a standard NSButton with only an image set, but not having any luck.

Much like the "+" button in Mail.app:

Not clickedClicked

I assume they did this with NSPopUpButton. The obvious thing I've tried is:

NSMenuItem *imageItem = [[[NSMenuItem alloc] init] autorelease];
[imageItem setImage:[NSImage imageNamed:NSImageNameAddTemplate]];

[[popUpButton cell] setUsesItemFromMenu:NO];
[[popUpButton cell] setMenuItem:imageItem];
[[popUpButton cell] setImagePosition:NSImageOnly];

This doesn't show the image however, instead it just shows a pair of arrows (I suspect they're drawn over where the image would be). Calling [popUpButton setImage:...] also does nothing.

Is there a documented way to do this, or does it come down to some custom subclassing?

like image 224
d11wtq Avatar asked Dec 07 '10 12:12

d11wtq


2 Answers

To prevent the button from displaying the arrow:

[popupButton.cell setArrowPosition:NSPopUpNoArrow];
like image 125
Tomer Avatar answered Oct 21 '22 10:10

Tomer


Here is the code I used to finally get this working in Swift (modeled after Apple's Menu Madness demo app).

func setUpButton() {
    let popupButton = NSPopUpButton()
    popupButton.translatesAutoresizingMaskIntoConstraints = false
    popupButton.pullsDown = true
    popupButton.bordered = false
    let popupCell = popupButton.cell as! NSPopUpButtonCell
    popupCell.arrowPosition = NSPopUpArrowPosition.NoArrow
    popupButton.addItemWithTitle("")
    var item = popupButton.itemAtIndex(0)
    item?.image = NSImage(named: "add")
    item?.onStateImage = nil
    item?.mixedStateImage = nil
    popupButton.addItemWithTitle("Item1")
    item = popupButton.itemAtIndex(1)
    item?.action = #selector(item1Pressed)
    item?.target = self
    popupButton.addItemWithTitle("Item2")
    item = popupButton.itemAtIndex(2)
    item?.action = #selector(item2Tapped)
    item?.target = self
    self.addSubview(popupButton)

    // NOTE: These are auto layout helper methods I made that you won't have. 
    // Just note that here is where I set up the auto layout constraints.
    popupButton.widthConstraint(40)
    popupButton.heightConstraint(20)
    popupButton.centerVerticallyInSuperview()
    popupButton.trailingSpaceToSuperview(0)
}

// TO MAKE SURE ALL ITEMS ALWAYS VALID (WHAT I WANTED FOR MY USE CASE)
override func validateMenuItem(menuItem: NSMenuItem) -> Bool {
    return true
}

func item1Pressed() {
    // do stuff
}

func item2Pressed() {
    // do stuff
}

Be sure to make the width/height of the button big enough for the image. I found there was some padding on the right side of the button that covered my small image until I made the button wide enough to accommodate the mysterious padding.

like image 20
Adam Johns Avatar answered Oct 21 '22 12:10

Adam Johns