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.

Comments

Great tutorial Dave, I think its going to help a lot of people (including me!). Well done for bringing together all of the useful classes produced by other developers- nobody likes re-inventing the wheel.

Posted by Adam Chester on December 24, 2006 9:12 AM


Thank you very much. I hope this will help many people.

Posted by Ferhat Ayaz on December 24, 2006 1:37 PM


One thing to keep in mind is licensing. KSSplitView has a non-commercial license. So if you're planning on selling your app, you should probably avoid it.

I've been using RBSplitView in most of my projects and it's just as easy to work with and gives a ton of nice features that NSSplitView is missing. It's also under an MIT License. So you can use it in any app. Just give Rainer a plug somewhere in the app and kick him back a license if your being generous.

Posted by Brad Miller on December 28, 2006 6:30 PM


Brad, you're absolutely right about respecting Ken's license on KFSplitView. However, I got the impression from Ken that he really wants people to benefit from this class, and my guess is he'd probably let an indie developer use it in a shareware product if asked. He was very happy to let me include it with this sample code (I got permission from all of the developers listed above).

However, RBSplitView is also a great alternative. It can handle this interface as just as easily KFSplitView, and has some extra functionality to boot.

I simply chose KFSplitView because it did what I needed, but with a smaller footprint.

Posted by Dave Batton on December 30, 2006 1:34 PM


Hello, i m a french developper and i would said that it's a great tutorial. But may i ask you to have
1° a step by step tutorial to understand how reproduce your soft
2° an adaptation on coredata. i ve try to replace objects by coredata entities and i can't find how to do !!!!
please help
thanks
Pascal

Posted by Atlantisman on March 28, 2007 7:16 AM


Wow... Thanks a lot for your example. This is exactly what I was looking for. See here:

http://www.idevapps.com/forum/showthread.php?p=51189#post51189

My opinion is that developing UI's should not be this difficult. You should not have to go scouring the web for interface elements that are "standard" for apple iApps. Thats just silly. Also, for an application named "Interface Builder" it is not really that good at building interfaces. The fact that all of the icons, and images are baked in as bitmap images really bothers me as well. What if I want to change the "theme" somewhere in the future? Also the fact that your selection gradient need to be so complex is simply unfortunate. Obviously, none of this is your fault - and I commend you for providing valuable os x iApp hints.

Posted by johnny on September 3, 2007 11:16 PM


Great tutorial. But I would like to see how I can use your "Apple Mail-Style Interface" with Core Data and not with Scott Stevenson's email example. Maybe you can put a tutorial on your Blog, when you have finished your new Application.

Thanks.

Posted by Ralph on October 8, 2007 4:11 AM


@Ralph:

I'll consider creating a Core Data version of this example project. But I'm probably not the best person to write that tutorial. I've got Core Data working, but it's been a bit of a struggle for me. Trying to get Core Data and bindings working together makes my head hurt. :-)

Posted by Dave Batton on October 8, 2007 8:23 AM


Is it possible to create a reusable interface, ala a framework?

I find most of the time, my applications interfaces have similar requirements and structure. It would be useful to create a "template" that I can add to new projects.

Posted by Nick on November 1, 2007 3:55 PM


In case I wasn't clear, I was asking if it was possible or common in the conceptual sense. I wasn't asking if you could put one together. :)

I seem to spend far more time tweaking in IB than writing code. If I get one of my apps to a good level of polish and intergration, it's usually too specific to easily re-use in a new app.

Posted by Nick on November 1, 2007 4:16 PM


This is the first example I've come across using the "side panel". (It helps using the correct term in searching...)

The date of this tutorial is December 2006 so, is the method of using the suggested SplitViews still the best way? Particularly if using Core Data?

Posted by Andrew Greaney on March 5, 2009 8:30 AM


Thanks! I've been looking for something exactly like this. I wish the Hillegass book had another chapter on how to get some of the standard "looks" you see in OS X applications. Between this and the ViewController sample from Apple I think I have a good idea of how to get things structured now. :-)

Posted by Ron on March 28, 2009 2:23 PM


Add a Comment
Please fill in the fields below to add a comment:
Name*:
Email Address*:
URL:
Spam Protection*:     Type "san francisco" without the quotes.
Message*:
  Your email will not be published and the URL provided will be used as
a link on your name.

* indicates a required field.