A Select Few
Volume Number: 16
Issue Number: 10
Column Tag: Carbon Development
A Select Few...
by Daniel Jalkut
Taking advantage of Apple's standardized Type
Selection API
Introduction
A feature frequently overlooked by new Mac OS users is the ability to select items
from a list by typing part of its name. Apple calls this functionality "type selection.
Seasoned Mac users are accustomed to type selection and navigate rapidly through
Finder hierarchies and StandardFile dialogs without ever letting their hands leave the
keyboard. When a user discovers this feature, it is probably with some disappointment
that they find support for type selection varies widely amongst third-party
applications. Every application that uses StandardFile and Navigation Services dialogs
gets type selection for free in those portions of their program. For custom application
dialogs and views, developers have been required to write their own, custom type
selection code. The result is that some applications don't support type selection at all,
some support it to varying extents, and almost none support it in a way that mimics
every last nuance of Apple's own type selection algorithm. The opportunity to end
these inconsistencies is before us, for Apple's Type Selection APIs have made their
public debut.
Without fanfare, Apple included their time-tested internal Type Selection APIs in the
first public releases of the CarbonLib extension for Mac OS. As of this writing, the
latest version is CarbonLib 1.0.4, and it is available from Apple's web site at
http://asu.info.apple.com/swupdates.nsf/artnum/n11673. CarbonLib is the library
that enables applications ported to Mac OS X's Carbon APIs to continue running on Mac
OS 9 and earlier (as early as 8.1) systems. There is no shortage of compelling reasons
to port your application to Carbon. Apple's decision to support two platforms with a
nearly identical API set provides an irresistibly easy way of adding Mac OS X to the list
of your supported platforms, without losing your existing customer base. Access to
standardized type selection is by no means the greatest benefit of porting to Carbon,
but it has the potential of causing a vast improvement in the user's experience on the
Mac.
What's The Big Deal?
You might be wondering why something as seemingly straightforward as selecting list
items with the keyboard should require a standardized API. The user hits a key, you
select a matching item, and we're done - right? Actually, the apparent simplicity of
type selection is a testament to its internal complexity. You may not have even
considered much of the functionality Apple's TypeSelect APIs provide unless you have
spent a great deal of time focusing only on the dynamics of type selection. Most
developers do not have the time to become type selection experts, so they implement
something that makes sense to them, yet lacks the subtle elegance of Apple's code.
Some of the features of Apple's API are:
International Support
Support for international scripts, which Apple has always promoted, is becoming
more and more important as the customer base for Apple outside of the United States
continues to grow. As a developer, anything that provides international support for
free is a big win for your product, because it is one fewer thing you need to worry
about when pushing to make a localized release available. Apple's type selection APIs
use script-aware string comparison functions, which in turn guarantee that every
selection made by the user causes a match as expected for the appropriate script.
Multi-Character Matching
A major shortcoming of some third-party implementations of type selection is that
only the last key pressed is ever used as a criterion for matching against items. If you
type characters in a Finder view, you will notice that the active selection changes as
the characters you type grow into a more specific match with the item you're seeking.
For instance, if there are three icons in a view, "Belize", "Biafra", and "Burundi",
typing just "B" will select the first, "Bi" the second, and "Bu" the third. In an
implementation that didn't support multi-character matching, the user would be
forced to type "B" to locate the first item, and then navigate with arrow keys to the
desired item. No amount of typing would select either "Biafra," or "Burundi" without
moving a hand from the keyboard to the mouse.
Time-Out and Cancellation
One unexpectedly complicated aspect of a proper type selection implementation is
elegantly guessing the train of thought a user has embarked on: knowing when to stop
one selection and begin another. This task is impossible to do correctly every time, but
Apple comes close with comfortable and consistent behavior that gives the user a great
deal of control.
The type selection APIs keep a running tab of the keys that have been pressed, and
when no keys have been pressed for a duration of time, that buffer is flushed, with the
assumption that the user has finished typing the fragment they were seeking. To
accommodate the user who knows they have mistyped, or who has quickly changed their
mind, the APIs also respond to the escape key, which forces type selection to clear its
buffers and begin matching keys as a new string.
Implementing Type Selection In A List
To demonstrate the use of the type selection APIs, I have included with this article a
sample application, "ListSample", which simply displays a list of selectable items in a
dialog. The applications responds to keyDown events by passing them to the Type
Selection API, "TypeSelectNewKey", which determines whether the key pressed
justifies searching for a new match. If it does, another API, "TypeSelectFindItem" is
called, which uses the state of the key buffer and a list of items provided by the client
to determine the most appropriate selection.
Application Prerequisites
Before I could implement type selection in ListSample, I first had to ensure that the
application had been carbonized and compiled with Apple's latest Universal Headers. If
you have already carbonized your application, then you're ready to go. If you haven't,
then you will need to do so before you can call any of the Type Selection APIs described
in this article.
ListSample Implementation
The easiest way to demonstrate the use of the Type Selection APIs is to explain the
three pieces of code in ListSample which interact with the APIs:
• A TypeSelectRecord is initialized before any type selection can occur.
• Key down events are passed to Type Selection, and a new match is found if
appropriate.
• A callback routine for finding matches is implemented.
First, initialize a TypeSelectRecord. This is done by calling TypeSelectClear() with an
empty TypeSelectRecord as its parameter. In ListSample, this is done in main()
Listing 1: main
Main