NSImage Templates

New Toolbar Style
Apple has made some aesthetic changes to buttons in Leopard. Specifically, toolbar buttons tend to be less glossy and use 2D black and white symbols instead of full color images. The reasoning given at WWDC 2007 was that they felt the user’s focus should be on the app’s content rather than being distracted by eye candy around the edges. Whether developers agree with this or not, a good Mac app should fit seamlessly with the rest of the user experience (unless you’re a member of the delicious generation).

Old School Toolbar
The older icon style hasn’t been nixed yet, as seen in this screenshot of console’s toolbar, but it clearly the emphasis is on the flat, 2D, black and white symbols (see also the new standard folder icons).

Apple has been making an effort to make it easier for developers to integrate the Mac’s new look and feel. For instance Leopard introduces image templates. Developers now have access to a whole bunch of standard images for their apps’ buttons. These are available from the Media tab in Interface Builder 3.0’s Library. It’s a snap to find the appropriate image for standard icons and drag it to your button. No more digging through Safari’s app bundle and scavenging button icons, wondering if you’ll get a nastygram from Apple some day for stealing their graphics.

Interface Builder 3’s Media Tab
Here’s the new Library in Interface Builder, showing some of the icons in the Media tab.

But, there are bound to be times when you need to make a custom icon for a button. The recommended way to do this for these kinds of button icons is by creating it with a vector app like Illustrator or InkScape and saving it as a PDF. This way they will be ready for resolution independence (bitmaps can also be used but make sure to create them much larger than you think you’ll need).

Interface Builder 3’s Media Tab for Project Specific Files
Here I’ve added an icon for a stop button as a pdf file to my Xcode project. Interface Builder automatically picks up this addition and shows it in the Media tab of the Library floater in the project’s library (the Xcode project is named TemplateImageButtons.xcodeproj). A note about the pdf you create: the document’s dimensions determine the border around the image in the button.

First attempt at the transport. Here’s a simple transport using the custom stop icon and the system-supplied NSRightFacingTriangleTemplate for the play button. Easy! We’re done. Wait. Something’s not quite right. Notice how the play button has a subtle grey tint to it, while the stop button is infinite black, like the monolith in 2001. When I first saw this I thought maybe the system supplied template images had some kind of tint built into them. But it turns out NSImage can be told that any image is a template and as long as it meets certain criteria, it’ll automatically add tinting as needed. The secret is making sure the image’s filename ends with Template. Renaming the stop icon pdf from TransportStopIcon.pdf to TransportStopIconTemplate.pdf is all it takes. The easiest way to do that is to contextual-click on the pdf file reference in the Xcode project and choose Rename. Interface Builder will get informed of the change, and Xcode will issue the proper SCM commands as well. This is newly minted stuff in IB, so some things are a tad clunky. For instance, you’ll need to drag your renamed icon onto the button again to get the change to stick. Also, I’ve noticed that IB sometimes shows missing image icons when I close the document and open it again.

Transport with stop icon as template image. Much better! Beyond simple tinting, the system will also create an embossed version of your template images for other button types, and create that blue glow around it for the active state of a button (for example, the View/Hide Mini-month button in iCal).

One caveat to this image template system is it expects the image to be black with a clear mask. I ran into this when trying to use a red circle graphic as an image template for a record button. It was converted to a medium grey image by NSImage. I’m looking into whether you can tell a template image to draw as a color but I think in this case I’ll have to create the various button state versions of the circle graphic manually.

I noticed a trend at WWDC this year of Apple adding more things like this to make developers’ lives easier. Although there were some poorly handled transitions (*cough* dropping Carbon 64-bit *cough*), this is one area I’m very glad to see Apple focus on.

More information:
http://developer.apple.com/releasenotes/Cocoa/AppKit.html
NSImage Class Reference