Thursday, January 14, 2010

Colors: A Good GUI for Selecting Colors

This article explores the question: what is a good GUI for picking a color?

Dialogs


The first instinct of many developers will be to use a dialog. And there is a dialog that comes standard with Java that does the trick. It takes one line to invoke:

Color newColor = JColorChooser.showDialog(component, title, initialColor)



I have several complaints about this dialog:
  • The default tab is poorly designed. Look at all that wasted vertical space! And I don't like the strong shadows that surrounds each cell.
  • The colorful components are not keyboard accessible. You can navigate the dialog using the keyboard if you eventually tab to a text field or spinner: but then you have to choose your color by numbers. Do you like choosing a color by numbers? It seems more natural to choose a color from a set of colors.
  • The dialog uses tabs. This is perhaps acceptable on the grounds that this is intended to be a universal component. But a better design would only present one suitable model. The user's goal here is to select a color. In this dialog they can get distracted with all the different components. Depending on how you count them, I see at least 23 different components the user can click here: this is overdoing it.

This prompted me to create a new dialog. It's default view features a color wheel. You can navigate it with the keyboard. There are no tabs, but it does offer subtle controls to change the view. This is modeled after what Photoshop uses, and they must know a thing or two about how professional artists want to choose a color, right?

However most users are not professional artists, so this is still overkill. Also when possible it is better to avoid dialogs. The book About Face makes these comments about dialogs:

"A dialog box is another room; have a good reason to go there.

... Build functions into the window where they are used.

... Putting functions in a dialog box emphasizes their separateness from the main task."

Palettes


Instead I would like to focus on palettes. A grid of colors. This could be presented in a small JWindow, or it could be presented in a JPopupMenu.

Here size is everything. The key difference in this concept and the dialogs mentioned before is that this is small. In nuanced jargon: this is a "transient", and the previous two dialogs are more "sovereign". This is one component - not several.

Here is an applet that provides several consecutive drafts of different palettes:


This applet (source included) is available here.

Here is a brief history of each draft:

  1. This was my first reaction to the words "pick a color". Every pixel counts. You have thousands of colors here to choose from. Not every color is represented, but you get light and dark shades that really stand out. (Compared to less saturated, muddy shades.)
  2. But quickly someone pointed out: this doesn't have black and white! Those are very important colors. As are shades of gray. So the second draft included a special column for white/black/gray.
  3. We had this model deployed in a desktop application for a while. Eventually the feedback came back to us: it's too many options. It was nearly impossible to ever pick the same color.

    The previous models were based on my instincts as a developer: if I give you more choices, that gives you more control. More control is better, right? But in fact people don't usually like too many choices. Here is a quote from The Power of Persuasion:

    "The greater the number of choices, the happier the consumer - so it's assumed.

    In a recent series of experiments ... a group of Columbia University chocolate lovers were given a choice between six different flavors of Godiva chocolates. A second group was asked to select between thirty different flavors. Subjects given the extensive flavor choices rated their selection as less tasty, less satisfying and less enjoyable than did the limited-choice group. The thirty-flavor subjects expressed more regrets about their selection and were less likely to choose chocolate as payment for participating in the experiment."

    In other words: suppose a user goes off in search of the color green. But then they quickly see that there are 300 different shades to choose from! This is a source of stress to the user. Give them a few tasteful options and they'll actually be happier.
  4. Then we designed a product for a younger audience. We wanted to thin the color pool down even more. Also a common complaint was that users needed brown. So we added a second special column for brown.
  5. But for graphic designers and other artists: they really might want more than 60 colors. This model uses keyboard modifiers to let the user get thousands of more choices. There are modifiers for "flesh tones" and "earth tones", as well as to toggle to a continuous spectrum of colors.
  6. Another way to give more options is to add scrollbars. A color is generally considered to have three dimensions (RGB, HSB, RYB, HSL, etc.). A rectangle will only present two of these dimensions. If you add a scrollbar, though: you can represent another dimension. Also you can add a scrollbar for opacity. And because I still like the modifier idea: you can press a modifier key to toggle between a continuous spectrum and a grid. In theory this model offers every color conceivable to the user. (In practice it is subject to rounding, though.)
  7. But the HSB model is not very aesthetic. Rob Camick has a nice article about using the hue-saturation-luminance model instead. Isn't it just all-around better looking?
  8. Lastly: yellow. In HSB or HSL: the hue is still abstractly based on an RGB model (that is: the primary colors of light). The problem here is if you split the RGB model into 6ths, you'll get: red, yellow, green, cyan, blue, purple. What about orange? You'll have to split the model into 12ths to see orange: it's a tiny sliver in an RGB-based spectrum. Instead I added a special class called HueDistribution, and I use it to give each of these colors equal weight: red, orange, yellow, green, cyan, blue, purple.

You'll notice in the applet these drafts all have funny names: the list presents them as ColorPaletteUIs. The component shown is a com.bric.swing.ColorPalette, and it can be configured with several different look-and-feels.

Also the controls at the top of the applet are client properties that affect the look of the UI. They are purely aesthetic - they make no functional difference. Personally I hate selecting a color from uniform cells due to the contrast effect of placing the cells side-by-side. These options provide a stylized way to break up that effect.

I'd like to add this sidenote: these were intended for (and tested against) use in desktop apps: not applets. I'd recommend downloading and running these jars as applications to really observe their behavior. So far my limited testing shows these bugs:

  • On Vista in IE the alt modifier doesn't work. (Well, it toggles IE's menu bar... so it is technically working...)
  • On OpenSUSE in Firefox the popup color well (shown below) doesn't work.


... there are probably many more. But if these bugs only reproduce in applet form: I'm not too worried about them.

Integrating Into A Window


Almost done. But not quite. Where should the ColorPalette component live? It is possible to put in in your main window, but you would only want to do that if your user constantly needed to select a color. In a painting program, for example.

Or I'm developing a graphics application where I put two ColorPalettes side-by-side: one contains the usual spectrum of colors, and the other contains translucent shades of white/black. You might also want to provide a separate set of themed colors (if you were working on, say, a PowerPoint-like program). Or a set of recently-used colors.

However in several applications you can't devote that much window space to the act of choosing a color. Consider iWeb, for example: for your text, shadows, and other effects you need to choose a color, but the inspector is already crammed full of useful odds and ends

In this case what I'd want is a ColorWell. This is about the height of a JLabel (and the width is arbitrary). I gave it an Aqua-ish border to blend in on my Mac.

In order to keep it abstract I defined 4 client properties that are associated with an ActionListener. By default these are what these actions do:

  1. downKeyAction: displays a ColorPalette below the ColorWell.
  2. spaceKeyAction: provides a ColorPicker dialog for your advanced user.
  3. singleClickAction: same as downKeyAction
  4. doubleClickAction: same as spaceKeyAction

So in conclusion: here is applet that contains everything: the ColorWell, the ColorPalette, and the ColorPicker:



This applet (source included) is available here.