Creating an Action PopUp Button in Leopard
It seems that everywhere you look in OS X you see applications with popup action buttons. You know, that button with a gear on it. Click it and a menu full of goodies pops up for you to play with. Apple itself uses it pretty extensively in its apps; Mail and Finder are notable examples. With such a prevalent control you would think it was dirt simple to create on of these for your own application. You’d think, but prior to Leopard you’d be wrong (mostly). A quick search around the web shows that there has been much discussion on the topic with quite a few various implementations. In fact, you may have googled your way here in search of a solution. Read on and I think you’ll be pleasantly surprised.
The essence of most implementations for an action button rely on NSPopUpButton and this implementation is no different. Where things start to diverge is that this implementation can be completed entirely within Interface Builder - no subclassing or custom rendering needed. So let’s get started and we’ll crank out this puppy.
NSPopUpButton operates in two different major modes which are ‘Pop Up’ and ‘Pull Down’. For this implementation we’ll be relying on the ‘Pull Down’ behavior which gives us a button with the requisite down arrow. So, just drag an NSPopUpButton onto your application in the desired location, choose ‘Pull Down’ from the inspector, choose the arrow to be along the bottom edge, and ensure that the ‘Title’ attribute is empty. Following is a thumbnail of the full inspector for a properly configured NSPopUpButton (click to enlarge).
You should now have a popup button with a blank title area and a down arrow. Sizing of the button is a hit-or-miss exercise and is probably the biggest drawback of this technique. As you will see even though
we will have the gear icon in the built application we will not see it rendered in Interface Builder. The next major step is hooking up the menu that we will use. By default NSPopUpButton comes with a menu that has three items in it. For whatever reason if you try to modify this menu by adding new items things start to get out of control. So, we just bypass the default provided menu and create our own. When in ‘Pull Down’ mode NSPopUpButton utilizes the first NSMenuItem in the menu as the title for the button. Herein lies the trick that makes the whole thing work.
To start off this phase of the button development drag an NSMenu from the Interface Builder pallet into your NIB file. Name it something exciting like ‘ActionMenu’ in order to distinguish it from other menus in your NIB (you can do this via the ‘Identity’ tab in the inspector - see the Interface Builder Identity ‘Name’ attribute). Next build up your menu as desired reserving the very first menu item for our popup button custom use. You can connect your menu items to Actions in your code as needed (the blank menu takes no action - its used only by NSPopUpButton). Now, in order to get our gear icon to show up on our popup button we need to configure the attributes of that very first menu item. The key is to configure the menu item to have a blank title and to set the ‘Image’ attribute to have the value ‘NSActionTemplate’ (you will need to type NSActionTemplate into the text field).

The value NSActionTemplate sets the image of the menu item to be the gear icon. This comes from the new Media Library in Interface Builder 3. To see this for yourself bring up the media library, find the gear icon and click on it. You will see that its name is NSActionTemplate.

Now for the final connection. To bring the menu and the popup button together find your popup button and bring up its inspector. Connect its menu outlet to your NSMenu. That’s pretty much it. You’ll probably need to play with the actual size of the button (sans image) in order to get things to look right when you build and run the application. You can also play with some of the NSPopUpButton attributes to control the default location that the menu popups up at etc. However, you now have the often desired action popup button without any subclassing or custom rendering. Enjoy.

4 Comments