Input Method Client API Tutorial

#
Input Method Client API Tutorial

## Contents

1. Implementing an Active Client Component
   - Handling Input Method Events
   - Handling Input Method Highlight Attributes
   - Handling Input Method Requests
   - Ending Input Operations
2. Enhancing an Active Client Component
   - Handling Additional Text Attributes
   - Creating Private Input Contexts
   - Selecting Input Methods
   - Setting an Expected Character Subset
   - Using Engine-Specific Functionality
3. Implementing a Non-Client
4. Sample Code

## 1. Implementing an Active Client Component

The input method client API makes it possible for client components to implement integrated text input user interfaces such as on-the-spot input. The API defines events and methods that facilitate the communication between a client component and an input method. It also lets the client component request an input method for a particular language.

Since the API doesn't make any assumptions about how and where the text is drawn, it can also be used to implement other input styles such as over-the-spot editing. In this style, the composed text is drawn over surrounding text and covers it instead of being integrated and formatted with it.

Any client component class can become an active client of the input method client API and thus support an integrated text input user interface by performing the following steps:

- Implement the `InputMethodListener` interface to handle incoming `InputMethodEvents` generated by the current input method, and register the listener.
- Implement the `InputMethodRequests` interface and override `getInputMethodRequests` to return the request handler.
- Store `InputMethodHighlight` attributes along with composed text and pass them on to the drawing routines.
- End input operations when the user initiates an operation that requires all text to be committed.

Optionally, the client component can also use the following functionality:

- Store other text attributes that are created by input methods, and return them when text is requested.
- Create a private input context (instead of sharing one with other components in the same window).
- Select input methods, for example, based on the language of the text being edited.
- Set an expected character subset.

Client components don't need to deal with setting up input contexts, activating or deactivating contexts, or dispatching events to input methods, since all this is handled automatically by AWT.

### Handling Input Method Events

The input method framework provides an event class, `InputMethodEvent`, to support the communication between input methods and text components. The class has two separate event kinds: text changed and caret changed. An event listener interface, `InputMethodListener`, supports these two events. An active client component must implement the `InputMethodListener` interface, register the listener, and handle both kinds of events.

`InputMethodEvent` instances are sent to the client component when there is a change to the user's input text, its highlighting, or to the caret location within the composed text. The event sent for caret-only changes is a simplified version of the one for text changes (it just doesn't have text information), so the following discussion assumes the text-changed event.

An event reporting a text change has a reference to an instance of `AttributedCharacterIterator` that represents either composed text or committed text or both together. The event's committed character count value specifies how many characters in the iterator's range are committed text; all remaining characters are composed text. Committed text always precedes composed text. If the component has no previous composed text, the committed and composed text replace any selected text or are inserted at the current insertion position of the component's text. If there is previous composed text, the entire previous composed text is replaced with the new committed and composed text. The insertion point moves to the end of the committed text. The client component is responsible for redrawing the updated text.

The event also contains information about the current caret location within the composed text (null if no caret is to be displayed), and about the part of the composed text that is most important to keep in view (null if the input method doesn't have a recommendation).

### Handling Input Method Highlight Attributes

The text component generally draws the composed text as part of the text being edited, using its regular text layout and drawing functionality. However, it needs to add certain highlight style attributes to the composed text to indicate the current state of the composition. The framework defines these style attributes as abstract styles (for example, "unconverted unselected text" or "converted selected text"), and maps them internally to platform-dependent concrete styles (for example, 2-pixel gray underline).

Highlight attributes are represented by the `InputMethodHighlight` class. Instances of this class are used as attribute values of the AttributedCharacterIterator instances representing composed text. Text components must store these attributes with the composed text and pass them on to the drawing routines when drawing composed text. They can use either the `drawString` methods that accept `AttributedCharacterIterator`, or create a `TextLayout` from the iterator and use its draw method. These drawing methods interact with the input method framework to map abstract to concrete highlight styles. Text components using these methods therefore generally do not need to be concerned with the internal details of the input method highlights. If a text component uses some other mechanism to render the text, it should check the input method highlight for concrete style information, and, if none is provided, use `Toolkit.mapInputMethodHighlight` to map to a concrete style.

Some input methods may treat highlights as "annotations". Annotations are attributes that apply to a specified range of text, but not to subranges or the concatenation of ranges. They are represented by wrapping the `InputMethodHighlight` instance into an `Annotation` instance. Input methods may use annotation highlights to separate text segments that will be converted as separate units. On some platforms, these highlights are rendered so as to make the segments visible, for example, by using underlines with short breaks between the segments. Text components have to be able to handle input method highlights whether they are wrapped in `Annotation` instances or not. If a text component implements line wrapping, special care needs to be taken when the range to which a highlight annotation applies crosses a line boundary: The normal behavior (implemented, for example, in `AttributedString`) would be to discard the attribute because it doesn't apply to subranges. But, since in this case there's only a visual break and not a logical break, the highlight needs to be preserved - it has to be treated as if it applied to the subranges that are rendered on separate lines. One way to do this is by implementing the `AttributedCharacterIterator` in a way that returns highlight annotations even for subranges of the intended range.

### Handling Input Method Requests

An input method needs to access component information to perform input operations. For example, an input method needs to know the location where a list of possible choices can be shown.

An active client component therefore must implement the `InputMethodRequests` interface, and override `getInputMethodRequests` to return the request handler. The interface includes methods to:

- Perform conversions between screen coordinates and offsets within the composed text.
- Obtain specified text of the component.
- Cancel the latest committed text.
- Obtain the insertion position within the component's committed text.

### Ending Input Operations

Input methods typically recognize some user actions that end input operations, for example, an operation that commits all uncommitted text. However, there are also user actions that start operations for which input operations should be ended, but that an input method cannot recognize. Saving the document containing the text is one such example. In these cases, the component has to explicitly call the input context's `endComposition` method.

## 2. Enhancing an Active Client Component

### Handling Additional Text Attributes

In addition to the input method highlight information, input methods may also attach other attributes to the text they send to a text component. These attributes may be useful information for the component. They may also improve the input method's performance if returned by the `InputMethodRequest` methods. For the latter reason, it is recommended that text components keep this attribute information around while the text is being edited, and return it with any text requested.

The `AttributedCharacterIterator.Attribute` class defines the following common attributes:

- `LANGUAGE` - the language of the text, specified as a `Locale` object.
- `READING` - a phonetic representation (yomi in Japanese), specified as a `String` object.
- `INPUT_METHOD_SEGMENT` - segmentation information used by input methods.

Input methods written in the Java programming language may define additional attributes.

### Creating Private Input Contexts

By default, one `InputContext` instance is created per Window instance, and this input context is shared by all components within the window's containment hierarchy. This reduces the number of instances created overall, and lets input methods combine information about all the text entered in this window (input methods often use information about previously entered text to improve their conversion accuracy). It means, however, that only one input operation is possible at any one time within a window, and that the text needs to be committed when moving the focus from one text component to another. If this is not desired, text components can create their own input context instances and override `getInputContext` to return them. A component that doesn't have its own input context uses the one used by its parent.

### Selecting Input Methods

Text components can use the input context's `selectInputMethod` operation to select an input method for a given language or locale. This may be helpful, for example, if the user clicks in text that is written in that language, since it's likely that she wants to continue in the same language. Or, the text component may know that the application only allows text in a certain language to be entered.

### Setting an Expected Character Subset

Text components can use the input context's `setCharacterSubsets` operation to tell input methods which characters can be meaningfully entered. For example, a database application may know that certain fields should only receive input in hiragana (one of the syllabic subscripts used in Japanese), another one only Latin characters, a third one any kind of characters. Passing on this information to input methods may allow the input methods to limit the range of characters that can be entered, or to switch to a different input mode that particularly supports the specified character subsets.

### Using Engine-Specific Functionality

Some input methods may provide functionality to client components that can not be made available through the input method framework API. This is possible through input method control objects. The input method developer must publish an interface for these objects. Client components that want to take advantage of the additional functionality can then call `InputContext.getInputMethodControlObject`, check whether the returned object is an instance of a known control object class, and if it is, call its methods.

## 3. Implementing a Non-Client

By default, all components that process key events are clients of the input method framework, that is, input method support is enabled for them. In some cases, components may not want to have their input processed by input methods. For example, games may want to interpret keyboard events directly. These components should call `enableInputMethods(false)`, so that events do not get forwarded to input methods.

## 4. Sample Code

This sample code shows how to implement the different kinds of input method clients that are possible with the input method framework: an active client, a passive client, a non-client, and a peered text component.

- Applet - run this applet in a Java 2 enabled browser, and you can experiment with the different client components.
- Javadoc
  - LWTextComponent - explains the structure of a lightweight text editing component that can be extended to an active client.
  - ActiveClient - explains the structure of an active client component.
- Source Code
  - IMFDemo.java - the applet/application that contains the different client components.
  - LWTextComponent.java - a lightweight text editing component that doesn't know about input methods, but can be extended to an active client.
  - ActiveClient.java - extends LWTextComponent to become an active client component.
  - PeeredTextArea.java - a peered text component.

Copyright © 1995-99 Sun Microsystems, Inc. All Rights Reserved. Please send comments to: java-intl@java.sun.com | Java Software