Inert Detritus The Internet's dust bunnies

21 June 2008 @ 6pm

(Re-)Designing a Preferences Window

(Edit: My apologies: comments were closed earlier; they closed automatically after 2 weeks. They’re open now.)

CPU History 1.0 was an obvious work in progress. It shipped without multicore support, with a redrawing bug, and with a horrid preference window design. The first two bugs were fixed months ago, when I pushed a beta of 1.1 to a few multicore testers. However, the third bug wasn’t on my radar until Peter Hosey (@boredzo) brought the Apple Human Interface Guidelines (HIG) to my attention.

Without further ado, here’s the 1.0 preference window.

Preferences 1.0

The list of things wrong with this layout is longer than the list of things right. Inconsistent spacing, and no attempt at vertical alignment of labels or controls.

When I added features (namely, multicore graphing) to 1.1, I had to add another control to the preferences. Hence, the 1.1 b1 preference window.

Preferences 1.1 b1

This is the release that compelled Peter to link me the HIG writeup on laying out windows. And rightfully so.

After an hour spent massaging things in Interface Builder, here’s the first 1.1 redesign. (I’ll call this 1.1 b2)

Preferences 1.1 b2

I fixed vertical spacing between elements, horizontal alignment of labels and controls, and a few other tweaks. It was primarily a HIG-compatible spacing fix to the 1.1 b1 layout.

Still, the layout just felt wrong. I visited #macdev on IRC to consult some other developers, and two suggestions surfaced. First, a tab-based layout (from ciaren and ccgus), and a boxed layout (a combination of my thinking and ccgus’s view idea). I set out to implement the tab-based layout first.

Preferences 1.1 tabs - panel 1

Preferences 1.1 tabs - panel 2

Preferences 1.1 tabs - panel 3

That’s tabs one, two and three. I split things based on logical separation: general, floater preferences, and color choices. However, as is evident on tab three, I couldn’t find a good layout in that tab that used the space required by tab one. Onward, then, I ventured, to fix another layout shortcoming.

The separations from the tabs made logical sense, so I wanted to keep those while junking the extra whitespace of the tab layout. So next up was a box-separated (NSBox) layout.

Preferences 1.1 final

This is the current leader in the window design, and most likely what I’ll be shipping tomorrow. It had the right mix between an all-in-one window, which removed whitespace issues with tabs, and clear splits between controls of different types.


Posted by
22 June 2008 @ 7am

I think that preferences windows can be some of the most challenging interfaces to design, especially when one has a small number of preferences. I know that the preferences window in my app will def. be getting some attention in the next release and it was great seeing someone go through the process.

Posted by
3 July 2008 @ 12pm

Uli Kusterer recently wrote a bit bout spacing in interfaces, you might find it useful:

Posted by
Matthieu Cormier
7 July 2008 @ 4pm


I think you were on the right track with the second to last one. Take a look at the preferences for Safari. See how it resizes for each tab. Well guess what! So does transmission, which is an open source bit torrent client for mac.

Posted by
John Muir
7 July 2008 @ 4pm

The “every 1.0 sec” label seems out of place. How about integrating that update frequency idea into the labels of the slider itself? The others move from “small” to “large”, so that slider could be labelled with its limits in a similar way and get to fully align at last.

Posted by
7 July 2008 @ 4pm

A few critiques on the last one: 1. The word “floater” has negative connotations. :-) 2. “.0″ is redundant if you want to say “1 second”, and “sec.” should probably be spelled as “second” instead. Yes, I know it’s a pain in the ass and it requires a plural form every now and then, but who said software development should be easy?

Posted by
Nathan Duran
7 July 2008 @ 5pm

In addition to the rhythm ruining wrapping of “every 1.0 sec”, the fact that all the slider labels are all lowercase is not helping matters.

Posted by
7 July 2008 @ 6pm

A very nice job on the redesign — it flows neatly and is well organized.

I have one suggestion: Instead of Refresh Rate with a scale from “no label” to “every 1.0 sec.”, how about calling it Refresh Interval and label the leftmost point “10 seconds” (or whatever the max interval is) and the rightmost point 1 second (or 1.0 if you have that kind of granularity in the setting). Sometimes refresh intervals are linear which makes it easy to infer the actual setting from a graphic slider and sometimes they are something else (exponential or quadratic for example). I’m not sure which these are but it may affect how you would best label the setting.

Posted by
Jesse Wilson
7 July 2008 @ 6pm

Do you really need preferences for all of these? I’d prefer that you choose tasteful values (bar width, graph divider) and remove the preferences.

Posted by
7 July 2008 @ 7pm

John Muir is right. Also Refresh Rate is the only slider where the minimum value isn’t labeled. I know that pushing Graph Divider all the way to the left will make the graph divider vanish, just by looking at the screenshot above. But when I do this with Refresh Rate … will it stop updating at all? Or just go really slowly?

As far as the logical groupings are concerned, I’m very pleased with your end result. Now the information comes in chunks of unintimidating size and they’re even ordered by importance. But to me it seems just the grouped layout and the little captions alone would achieve that nicely; I’d suggest you try out losing the actual boxes themselves, maybe they’re just visual clutter with little function?

Posted by
Christopher Bowns
7 July 2008 @ 7pm

I’ve been considering that, actually; that’ll give me more control over the size of the caption text, as well, which I feel is too small at the moment.

I appreciate everyone’s feedback, and I’ll write a follow-up post regarding comments and possible changes in a couple of days.

Posted by
Jamie Curmi
7 July 2008 @ 7pm

An interesting article, but I’d point out that it is a good idea to avoid the word “Color” in windows where possible, since you only upset people if you don’t internationalise it (i.e. it should be “Colour” everywhere other than North America). Or you need to localise it for British/Australian/New Zealand users, say, which most developers don’t do.

I note that Apple took it out of the context menus in the finder for Leopard — now it is titled “Label:” instead.

Posted by
Michael Llaneza
7 July 2008 @ 8pm

Speaking of preferences, is anyone else tired of application crashes that can be cured by throwing away the preferences file ?

So my suggestion is, as long as you’re looking at preferences, how can you validate the preferences before relying on them ? What happens if you can’t get a handle to the prefs ? Or if you can’t write to it. Or if it’s sitting on a bad sector ? Could the user possibly have last opened the file on January 1, 1970 ? Is a text color of [255, 255, 257} ok ? Should any setting have a value anywhere near $MAXINT –1 ?

This goes for the rest of you too.

Posted by
Nicholas Riley
7 July 2008 @ 10pm

You might consider getting rid of all the labels under the sliders to reduce clutter, or replacing them with icons (e.g. the Finder’s View Options). Also, Capitalizing Every Word looks weird: if you don’t, it helps users to read labels like sentences.

When I redid the AntiRSI pref dialog, which has a bunch of the same controls, I had to deal with some of the same decisions.



Posted by
David K.
8 July 2008 @ 1am

Kudos for taking the time to improve your UI even for a preference window. These attention to details are what make Mac programmers better than those other guys :)

@Jamie Curmi — If people get upset because they don’t like the spelling of color i’d say they have some anger management issues.

Posted by
Martin Pilkington
8 July 2008 @ 1am

There is one big advantage to the tabbed preferences, it allows you to grow your preferences without massively increasing the size of the window. In order to get round the issue of not being able to fill the tabs, make the tab view tabless and put the sections in a toolbar, then resize the window height when you click on another tab. This is used quite frequently (eg Safari’s preferences). At the moment the boxed design works but if you plan to increase the size of your preferences at all in the future, you may need to redesign again.

Posted by
Peter Maurer
8 July 2008 @ 3am

Regarding too much whitespace in the tabbed design: I had the exact same problem in one app; and I ended up generalizing the code I use for resizing NSToolbar-controled preference windows to also work on occasions where the NSTabView’s tabs were visible and controling what got displayed.

So it’s still an automatic process, and it works just fine. If you want to see this in action, send me an e-mail — it doesn’t feel right to hijack this comments thread by advertising my apps. I’d be happy to share that code with you.

Posted by
8 July 2008 @ 4am

Nice re-design!

One other option could be a resizable tab view (like the preferences panel of Mail).

Posted by
Jared Earle
8 July 2008 @ 5am

If I were you, I’d remove at least the ability to change colours. It’s a very visual part of the pane and why would anyone need to ever change colours?

Posted by
8 July 2008 @ 6am

@Jared Earle—customizing the colors I have to constantly look at is very important to me in whether I want to use an application or not. That shade of red would be gone in a heartbeat, before I even got through the trial period. Uh, so would the green. And probably the blue. In the current setup, it’s easy enough for people to ignore the entire section, so it’s not really cluttering anything.

But now I’m thinking maybe you were joking as a riff on the other comments.

@CB—I’m no developer, but these type of “before, during, and after” posts are very interesting.

Posted by
8 July 2008 @ 9am

I’d like to second what Peter Maurer and Martin Pilkington said. And I’d like to add that most Cocoa Apps by Apple itself (Safari and Mail i.e.) don’t have buttons like “OK” or “Apply” ruling over preference windows — which you did right. Very Happy about this. But the “Revert to defaults” Button kind of disturbs the otherwise clean design. If the functionality really is needed, I’d put it into the General-Tab or provide individual Buttons to reset the reset worthy settings. Labels would be an obvious choice i.e.


Posted by
8 July 2008 @ 11am

Tweet! Five yard penalty! Overuse of NSBoxs!

Actually, I think your design is still way off the mark. You were closer with the tabbed layout, and there are simple ways to resize the window to accomodate different sized sections. You also ignored the de facto preference design standard of using an icon shelf to select different sections.

The final design is truly awful; other people have pointed out the twisted language (what the hell is a “floater”?) and inconsistent slider feedback (“every 1 sec”).

If you’re going to stuff all the preferences in one pane, your initial views were a better approach, with some tweaking to the wording and alignment. The real problem with a single pane is that it already is pretty busy, and that will likely only get worse as time goes on and you find other preference options to add.

Posted by
Mark Damon Hughes
8 July 2008 @ 1pm

The tabbed layout was much cleaner than the final one.

Floater should be “Window”. A floater is a dead body that’s been in the water.

The refresh rate slider is entirely wrong. The durations should be marked on the slider; see the duration sliders in the Screen Saver preference pane.

Posted by
8 July 2008 @ 6pm

Here’s my quick feedback… probably not all that valuable, since I don’t know your product.

My recommendation is to open it up a bit with some extra space. Use space as your friend, instead of cramming things together. Analyze the space between every single control to make sure it’s consistent. Increase the width of the dialog so there is some breathing room around the controls.

I would remove the boxes on all three areas, and put divider lines between them instead (if you’re not going to move them into separate tab panes with the new tab bar on top). Slide the checkboxes to be aligned with the left side of all the sliders. Does the first checkbox control the second one and the graph size slider? if so, those need to indented. Lose all the extra caps on words and make them read more like a sentence. e.g. “Size in dock:” and “Show separate graph”. Also test to see how it looks with the labels on the right side of the color pickers. ([picker] Label) Not sure why the refresh rate slider differs from the others in style. I don’t know how the refresh rate works. It might be better as “Refresh every [field] seconds” instead of a slider, depending on how it works. I don’t think you need labels on the other sliders, if you can see the effect they have as you are sliding them. Should “graph divider” be “Divider width”? And should Bar width be in pixels like the other? Should “graph size” be chanced to just “Size”? And should the size labels on the slider be “16x16” or “16px”? Lastly, I wonder if the button on the bottom could be located on the left, so it’s not in the default location of a button in a dialog/sheet. Oh, and maybe “Restore Defaults” would be a better label for the button.

I am also a fan of adding some small descriptive text under controls that are not immediately understood by their label, to help explain what they do.

Oh, sorry, also, you might want to use the regular size slider controls, instead of the small. With extra space added in and around them, they won’t look as huge as they would jammed together. They should match the size of the labels.

Good luck!

Posted by
Philip (flip) Kromer
8 July 2008 @ 8pm


Consider using desaturated (pastel) colors by default: (see Tufte’s “Visual Explanations” p 76 or “Envisioning Information” p 91: ) Professional maps use muted pastel colors for areas of large coverage, and so should we.

There are three fundamental dimensions of color, and they are not Redness/Blueness/Greenness. Humans find meaning in transitions along Hue (red-green-blue), saturation (bright-pastel-gray) and value (white — earthy — black), and it’s best to constrain each data dimension thoughtfully to a color dimension.

This is a beautiful tool: The three bars on the top far right control Hue, Saturation and Value respectively — mess around with them and see how the colors change. I made a sample palette: My reasoning * “Idle time” is empty — it should be transparent, or the background color. * “nice” time is “background, innocuous, calm” — it should be a very desaturated sky blue. * “User time” is what you care about. It’s assumedly spent doing what you want it do do, so go with green. It should be prominent but not pushy, so make it semi-saturated * “System time” is usually a problem — you bought your machine to run programs, not kernel. So it’s red, and it’s a bit louder. * We want to see the competition between user time and system time, so start with two well-separated colors. So that’s hue and saturation: two axes, conveying two variables (hue=segment, sat=urgency). As for value: if this thing sits in front of you it should be audible but not deafening. Let’s give each color the same value (brightness), and let’s set it to 70%, which is the foreground color of a safari window (90%, the background color, seemed intense).

This won’t be your actual palette, but if you start thinking of the colors in perceptual rather than RGB terms your program will be prettier and more meaningful. Someone with a better eye than mine could certainly fix the balance of hues…

So all that blather and we still have red/green/blue: my point is that you should choose three tasteful shades that bear meaning and chuck the color controls. A future version could intensify each segment’s color saturation as its system burden climbs.…


  • I don’t find “Size in dock” or “Bar Width” that interesting. A principle of information design is to “Maximize your data ink”. The graph can fill its full dock slot, so it should; and the bar gaps carry no information (the bottom of each waterfall shows its axis) so they should be omitted altogether. Now, a control to occupy two or three dock slots would be interesting, but I bet there’s better uses of your time than crawling through the underbelly of the API.

For resizing in general, however, the best interfaces are direct interfaces: You can toss out that whole dialog box if you put a dashboard-style (i)nformation-please button in the corner to expose adjustment handles.

The dock actually does both: the preference panel gives you a slider which resizes the dock in-flight, while the little ribbed section between file and app gives you an expert feature — it resizes the dock with immediate feedback.

For direct manipulation of the time: the faster you sample the more space one second occupies on the screen: at 30 chunks and 0.5 S/s the graph is 60 seconds wide, and at 30 chunks and 0.5 S/s sampling the graph is 15 seconds wide. So, show a ‘scale bar’ that is 10s long, with handles to resize it, and report on the sampling rate: 0.5 S/s |—-| 2 S/s |—————-| Something like that… The intutive variables are, I think, “How much time does this graph show” and “How often does it move over a slot”: so, not “Bar Width” but “Graph Duration”.

This adjustment should be discrete: snap to exact rates so I can map graph to a number. 0.1, 0.5, 1s, 2s, 5s, 10s…, with graph duration ranging from “one minute” through “ten minutes” to “1 hour” or something.

If you’re showing a refresh rate (my vote) then report a rate: “2 S/s” or “2 Samples per second” — if you’re showing “sample duration” then report a period: “every 0.5 seconds” (right now you say rate but show period.)


  • You should redraw the graph when its scale (refresh rate) changes.
  • An experiment: draw system time down from the top, user time up from the bottom, and nice time atop that. (“Enforce Comparisons” — Tufte.) As the graph is currently set up you can’t directly compare user time. Dunno if this will be more or less clear.

  • I have a quad-core machine, and I hear there are folks out ther with octo-cores — I don’t think the stacked graphs stay meaningful at that point.

What do we really want to know? I’d like to know 1) The overall system load; 2) user time vs system time within overall load 3) the variance across CPUs (a 25% load: one 100% process and 3 idle cores, or 4 25% processes?) 4) how much of the overall load is coming from the piggiest process (judging pigginess based on “fraction of the total integrated non-idle time shown on the graph” — basically, how much of the ink is each little piggie’s fault?)

I don’t really know how to do #4, but we do have a couple ways to do 1–3 and maximize data ink. Draw ONE waterfall graph, and segment each User, System, Nice bar into (#cores) segments (so, four segments for my quadcore). Then experiment: you can draw each core with alternating shades (remember, we still have the ‘value’ dimension on the shelf), or you could put a 1px bar separating each segment. You could even just alternate (user-system-nice#1)/(user-system-nice#2)/(user-system-nice#3)/(user-system-nice#4) — the different colors mark the cores — but I bet that looks soupy in the end.

I hope you don’t mind this ridiculously nitpicky post — I only went into this detail because I think what you’re doing is neat.

Posted by
10 July 2008 @ 6am

just a small detail: the official abbreviation for second is simply “s”. “sec(s)” hurts my eyes.

Posted by
Christopher Bowns
10 July 2008 @ 3pm

I’m writing a response post (with new GUI mockups) tomorrow morning at the iPhone 3G launch; hopefully I’ll have it up shortly before the doors open at 8 AM.

Thanks again for all the comments and suggestions: it’s always useful to have new pairs of eyes take a look at a design.