|
|
|
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:
InputMethodListener
interface to
handle incoming InputMethodEvents
generated by the
current input method, and register the listener.
InputMethodRequests
interface and
override getInputMethodRequests
to return the request
handler.
InputMethodHighlight
attributes along with
composed text and pass them on to the drawing routines.
Optionally, the client component can also use the following functionality:
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.
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).
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
Copyright © 2004 Sun Microsystems, Inc. All Rights Reserved. |
|