Apple Mail-Style Interface Source

Thursday, December 21, 2006

Ever try to build an interface similar to the one used by Apple Mail? That's what I wanted for my new application: a source list on the left, a content list on the right, and a detail view below that. All with no margins. Unfortunately you just can't whip this up with Interface Builder.

As always, I started by searching the web for a Cocoa example that would show me how to do this. Unfortunately I didn't find any, so I had to figure it out on my own.

The first challenge was to display a gradient splitter bar rather than Interface Builder's dimple control in the horizontal split view. Then I'd need to add that to a vertical split view with a simple 1-pixel wide line dividing the two views, and a thumb at the bottom that can be used to drag the splitter.

Unfortunately these different types of splitters can't be done with Interface Builder, so some subclassing of NSSplitView would be required. I figured somebody had done this before, so I searched around for some existing code to help me out. I found RBSplitView by Rainer Brockerhoff and KFSplitView by Ken Ferry. Both looked great, but I decided to go with KFSplitView, because it seemed to be the simpler (as far as capabilities) of the two, yet still met my needs.

KFSplitView worked exactly as advertised. In addition to giving me a thumb to move the vertical split view, it also collapses and expands the horizontal split view when double-clicked, just like the one in Apple Mail. And it behaves better when the window is resized than the standard NSSplitView. Finally, it automatically remembers its position the next time the window is opened.

Unfortunately Interface Builder just wouldn't cooperate when I tried to move objects within a split view that's within another split view. Grabbing the right objects was difficult enough, but nudging them a pixel or two in the right direction seemed completely impossible. So I decided instead to move the objects out of the vertical split view and into two separate NSViews. This would allow me to easily manipulate them in Interface Builder. The NSViews get moved into the NSSplitView when the window loads.

Next I wanted to display icons with each item in the source list. I also wanted items in the source list to highlight with a gradient when selected. Matt Gemmell's iTableView source helped me with both of these goals. I later modified his code to use Chad Weider's CTGradient class to draw the selection gradient. I also replaced Matt's NSTextFieldCell subclass with Daniel Jalkut's RSVerticallyCenteredTextField class so the text would behave better while being edited.

All of this seems pretty simple now, but being a new Cocoa developer, it took about a week for me to get it all working. So here's that example project that will show you how to create an Apple Mail-style interface for your Cocoa project:

DBInterfaceDemo 1.0

To add some context to the demo, I implemented the email example code from Scott Stevenson's Introduction to Cocoa Bindings tutorial.

Thanks to Ken, Matt, Chad, Daniel, and Scott for allowing me to repost some of their code as part of this example.

12 Comments