Mac Java tip: How to create Aqua single and segmented buttons

Technologies: Java 5+, Mac OS X 10.5+

Java's Swing has just one generic notion of a button and just one look for that button. However, Apple's Aqua user interface for the Mac has about a dozen different button types to build stand-alone buttons and bars of adjacent segmented buttons. Each Aqua button type has a specific use, from the purple ? button for help, to glossy OK/Cancel/Open/Save buttons, and recessed scope buttons used to modify search operations. This article shows how to use Apple's "Mac OS X" look and feel for Java to access these hidden button types using Java on a Mac.

Introduction

One reason we have so many different component types is to give the user visual reminders about what a component does. A slider and a scroll bar, for instance, are functionally equivalent but they are drawn differently. The user learns that slider-like things change values, while scroll bar-like things move a page of content back and forth.

Apple's Aqua user interface on the Mac extends this notion to include a large number of different button types. Functionally, they are all the same, but their appearance differs enough to give visual reminders about what the button does. For instance, the purple ? button always gives help information, and segmented side-by-side buttons offer strongly related functionality like forward and back arrows on Safari. (See the Buttons chapter in the Apple Human Interface Guidelines.)

Java applications on a Mac default to using Apple's "Mac OS X" look and feel instead of Sun's "Metal." With Apple's look and feel, you can use special Swing client properties to access Aqua's additional button types. (See Apple's New Control Styles available within J2SE 5.0 on Mac OS X 10.5.)

Setting client properties

Every Swing component has a hash table of client properties that control the component's appearance. To set a client property, call putClientProperty( ) on a component, passing in the property name and value.

component.putClientProperty( name, value );

In most cases, client properties must be set before the component is realized. This is easily done by setting the property after creating the component, but before adding the component to a parent container.

Using client properties for single button types

Java's JButton and JToggleButton default to creating standard glossy rounded Aqua buttons. To create additional Aqua button types, set the "JButton.buttonType" client property on a button. For instance, set the property to "textured" to create the shaded buttons like those in the Finder, and set it to "help" to create the standard purple ? button.

JButton button = new JButton( "Button" );
button.putClientProperty( "JButton.buttonType", "textured" );
Button types
Figure 1. The "JButton.buttonType" client property creates
different single button types in the "Mac OS X" look and feel.

Apple assigns specific meanings to some of these button types:

  • A default glossy push button is intended for instantaneous actions, such as the OK/Cancel/Open/Save buttons on a dialog window.
  • A "recessed" or "roundRect" scope button indicates a choice in limiting the scope of an operation, such as the buttons at the top of a Finder when searching.
  • A "gradient" gradient button selects among options, such as different ways of viewing something.
  • A "help" help button shows help information.

The "Mac OS X" Java look and feel automatically switches between button types depending upon the context, unless you override it with a specific button type property:

  • Buttons with a text label, no icon, and a default size, use the default glossy button type.
  • Buttons with icons, or buttons sized larger than a standard Mac button use the "bevel" button type.
  • Buttons on a tool bar, or buttons smaller than a standard button default to the "square" button type.

The look and feel also recognizes four abstract button types for glossy "text" buttons, beveled "icon" and "toggle" buttons, and borderless "toolbar" buttons.

Abstract button types
Figure 2. The "JButton.buttonType" client property also
supports abstract names for button types.

Note some confusion here. While the rarely-used "toggle" type is presumably a default for toggle buttons, if you create a JToggleButton it actually adopts the appearance of the "text" or "icon" types depending on if it has a text label or an icon.

Note also that the "toolbar" type has no border, but if you add a JButton to a tool bar, it actually defaults to the "square" bordered type instead. Still, there really is no good default style for Apple to use on toolbars. Some Mac toolbars should use shaded buttons (as in the Finder) while others should use borderless icon buttons (as in the iWork applications). Which style to use depends upon your application.

Using client properties for segmented button types

A key idea in user interface design is to group related features to declutter an interface and reduce its apparent complexity. For instance, the forward and back arrow buttons on Web browsers belong together, not on opposite ends of a toolbar.

To group related buttons, you can place them close together, while leaving open space between them and the next group of buttons. If these buttons are tightly-packed together, they become segmented buttons forming a button bar. Such button bars are found throughout the Mac interface, such as the forward/back buttons on Safari, the view style buttons on the Finder, or the text justification buttons on TextEdit. (See the Segmented Controls section in the Selection Controls chapter in the Apple Human Interface Guidelines.)

To create segmented buttons, set the "JButton.buttonType" client property on a button to one of the segmented button types, and the "JButton.segmentPosition" property to "first", "middle", "last", or "only" for the left, middle, right, and stand-alone variants.

JButton first = new JButton( "Button" );
first.putClientProperty( "JButton.buttonType", "segmented" );
first.putClientProperty( "JButton.segmentPosition", "first" );
Segmented button types
Figure 3. The "JButton.buttonType" and "JButton.segmentPosition"
client properties create button bar buttons in the "Mac OS X" look and feel.

Using segmented buttons requires that you adjust your layout to avoid gaps between adjacent buttons. Since these segmented buttons are only available on the Mac, if you are writing cross-platform code, your application will need to check the name of the platform before doing a Mac-specific layout. (See Apple's Identifying Java on Mac OS X.)

if ( System.getSystemProperty( "os.name" ).toLowerCase( ).startsWith( "mac os x" ) )
{
    // On a Mac
}

It isn't necessary to avoid setting client properties on non-Macs. If you set the properties, but run on Windows or Linux with a different look and feel, the Mac-specific client properties are silently ignored.

Using client properties for regular, small, and mini-sized buttons

All of these button types are available in the default regular size, and two smaller sizes for use in tightly-packed user interfaces. (See Mac Java tip: How to create Aqua small-sized components.)

To get Apple's small-sized buttons in the "Mac OS X" look and feel, set a button's "JComponent.sizeVariant" client property to "regular", "small", or "mini".

JButton button = new JButton( "Button" );
button.putClientProperty( "JButton.buttonType", "textured" );
button.putClientProperty( "JComponent.sizeVariant", "mini" );
Smaller button sizes
Figure 4. The "JComponent.sizeVariant" client property creates
smaller button sizes in the "Mac OS X" look and feel.
Smaller segmented button sizes
Figure 5. The "JComponent.sizeVariant" client property also creates
smaller segmented button sizes in the "Mac OS X" look and feel.

Creating other Aqua button types

If you look through Apple's applications, there are other button types in common use. For instance, iTunes has has round gray Play/Rewind/Forward buttons, GarageBand has dark shaded buttons, and Logic Pro has glossy black buttons. Unfortunately, at this time none of these other button types are available from Java. If you need these button types, you'll have to resort to using button-shaped images.

Additionally, all of the button types have fixed colors. Calling setBackground( ) on any of them does nothing.

Further reading

Related articles at NadeauSoftware.com

Web articles and specifications

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

Nadeau software consulting
Nadeau software consulting