Nextel's MIDP UI Toolkit provides classes for creating user interfaces.

The user interface toolkit bridges the gap between the high-level API and the low-level API. The high-level API promotes portability at the expense of extensibility and customization. With the high-level API all screens with the exception of javax.microedition.lcdui.Form have fixed formats. A Form can have any mix of the components ChoiceGroup, DateField, Gauge, Images, StringItem, and TextField, but you cannot create custom components, such as scroll lists, that can be added to a Form. Additionally, with the high-level API you have little control over the layout of screen – for example, you cannot specify that two TextFields are to be on the same line, as the default layout is that all components that can receive key input are laid out vertically. You also have no control of string size or font.

With the low-level API you can display on the screen anything you like, with complete control over placement and string attributes. However, the low-level API does not provide any visual components, such as text fields or radio buttons, and so you have to create your own.

The UI Toolkit provides a framework for creating custom components that display on the screen and respond to key presses, and also contains a number of pre-defined components. It lets you specify the placement and attributes (e.g., font size) of components, and provides navigation between components.

The UI Toolkit does not ensure portability, which is left to the developer to address. Also, in order to keep the toolkit’s size relatively small a number of restrictions and constraints exist, such as minimal validation of method arguments. These restrictions and constraints are documented in the javadoc of the appropriate classes.


Components

A component is a distinct visual element, such as a radio button, a string, or a scroll list. All components extend class {@link com.nextel.ui.OComponent} or it’s subclasses. Components that respond to key presses are said to be focusable; when the component is active (i.e., it will respond to key presses) the component is said to have focus. Focusable components extend {@link com.nextel.ui.OFocusableComponent}. Not all components are focusable; for example, labels are components that do not respond to key presses.

A custom component must implement the following methods:

Ø      {@link com.nextel.ui.OComponent#paint} – to draw the component to the screen

Ø      {@link com.nextel.ui.OComponent#getHeight} and {@link com.nextel.ui.OComponent#getWidth} – to get the component’s dimensions

A component that responds to key presses must also implement method {@link com.nextel.ui.OFocusableComponent#keyPressed}.


Containers

Components are managed within the context of a container. The UI toolkit defines two containers, {@link com.nextel.ui.OCompositeScreen} and {@link com.nextel.ui.OPanel}.

{@link com.nextel.ui.OCompositeScreen} is a subclass of javax.microedition.lcdui.Canvas, and so an {@link com.nextel.ui.OCompositeScreen} object is the representation of a screen display. For a component to be displayed it must be contained within an {@link com.nextel.ui.OCompositeScreen} that is the current visible screen, which is set via a call to the setCurrent method of javax.microedition.lcdui.Display

{@link com.nextel.ui.OPanel} is both a container and a component. Multiple components can be placed in an {@link com.nextel.ui.OPanel}, and the {@link com.nextel.ui.OPanel} can then be placed in an {@link com.nextel.ui.OCompositeScreen}. This allows the construction of composite components, such as a date field that consists of month, day, and year fields. ({@link com.nextel.ui.OPanel}s can not be nested, i.e. an {@link com.nextel.ui.OPanel} can not itself contain an {@link com.nextel.ui.OPanel}).

Components are added to containers via the latter’s add methods.


Screen Layout

The position on the screen where a component is displayed on the handset screen is specified when the component is added to the container. The containers support different layout schemes.

{@link com.nextel.ui.OCompositeScreen} use a grid layout, which allows the developer to specify, when constructing an {@link com.nextel.ui.OCompositeScreen}, the number of columns for the grid. The available screen area is then divided into that number of columns; all columns are the same width.

The number of rows is not set when the {@link com.nextel.ui.OCompositeScreen} is constructed, but depends upon the grid coordinates of the components in the grid. The height of a row is the height of the tallest component in the row.

Within grid cells components may be aligned to either the right or left sides, or the center, of the cell.

For example, consider this screen layout:





When the {@link com.nextel.ui.OCompositeScreen} was constructed three columns were specified. Four components were then added:

Ø      A was added at column 0, row 0 with left alignment.

Ø      B was added at column 1, row 0 with center alignment

Ø      C was added at column 2 with right alignment.

Ø      D was added at column 1, row 1 with right alignment.

Note that although D is wider than the cell, its full width is displayed, which is true of all components with any alignment. It is the responsibility of the developer to ensure that components don’t overwrite one another.

The UI toolkit does not provide horizontal scrolling of the screen, and the initial release does not provide vertical scrolling of the screen, so it is the responsibility of the developer to ensure that components do not display beyond the bounds of the screen.

The default on-screen presentation of an {@link com.nextel.ui.OCompositeScreen} is shown below. The title area is optional, and if present is separated from the body by a line. The body is where the screen’s components are displayed. At the bottom of the screen is an area for soft-button labels, which are discussed in more detail later.




{@link com.nextel.ui.OPanel} has a flow layout, which by default is horizontal but can be set to vertical. Flow means that components are placed adjacent to each other in the specified direction (they are separated by a pre-defined spacing interval).  For example, three components of different sizes added in a horizontal or flow layout would appear as follows:



Alternatively, components may be placed in an {@link com.nextel.ui.OPanel} with pixel coordinates relative to the top left corner of the panel.


Navigation

Since a screen may contain multiple components, a mechanism must exist to allow the user to navigate between components. {@link com.nextel.ui.OCompositeScreen} manages this navigation. With most components the user can move to the next component by pressing the right or bottom side of the 4-way navigation key, and to the previous component by pressing the left or top side of the key. However, some components use only one dimension of the 4-way navigation key to navigate within the component.  For example, when the scroll list has focus, pressing the top or bottom of the 4-way navigation key scrolls the list up or down, so navigation to the next or previous component is performed by pressing the left or right side of the key. Conversely, when a text field has focus the left and right sides of the 4-way navigation key are used to move from character to character within the text, and navigation to the next or previous component is performed by pressing the top or bottom of the key.

Any custom component can override the navigation behavior of the 4-way navigation key via the {@link com.nextel.ui.OFocusableComponent#setTraverseDirections}.


Soft Key Management

Actions upon screens, such as returning to the previous screen or progressing to the next screen, are initiated by pressing the left or right soft key (the soft keys are the keys right below the bottom right and left sides of the screen). Components {@link com.nextel.ui.ORadioButton}, {@link com.nextel.ui.OCheckBox}, and {@link com.nextel.ui.OPushButton} also use the right soft key. For example, when an unset {@link com.nextel.ui.ORadioButton} has focus the word “SET” is displayed above the right soft key and pressing it sets the radio button, and when an {@link com.nextel.ui.OCheckBox} has focus the words “CHECK” or “UNCHECK”, as appropriate, are displayed above the right soft key and pressing it checks or unchecks the radio button.

Because {@link com.nextel.ui.ORadioButton} and {@link com.nextel.ui.OCheckBox} override the right-soft key when they have focus, when a screen contains either component {@link com.nextel.ui.OPushButton} can be used to select an activity to perform on the screen. For example, if an {@link com.nextel.ui.OCompositeScreen} is a data-entry form containing {@link com.nextel.ui.ORadioButton}s and other fields, an {@link com.nextel.ui.OPushButton} labeled “Submit” could be placed at the bottom of the form. When the button has focus the word SUBMIT would appear above the right soft key, and pressing the key would result in the form being processed.

The use of {@link com.nextel.ui.OPushButton} need not be restricted to screens containing radio buttons or checkboxes. For example, if a screen displays a data record that can be edited or deleted, two push buttons labeled Edit and Delete could be placed on the screen.

javax.microedition.lcdui.Command and CommandListener should not be used in any screen that contains an {@link com.nextel.ui.ORadioButton}, {@link com.nextel.ui.OCheckBox}, or {@link com.nextel.ui.OPushButton}, and that screen should not call method addCommand (which is inherited from javax.microedition.lcdui.Displayable via the {@link com.nextel.ui.OCompositeScreen}’s parent Canvas class). This is because Commands are displayed above the left and right soft keys, and their display prevents display of the action labels generated with {@link com.nextel.ui.ORadioButton}, {@link com.nextel.ui.OCheckBox}, and {@link com.nextel.ui.OPushButton}, and prevents the soft-key presses from being delivered to {@link com.nextel.ui.OSoftKey} for performance of the associated {@link com.nextel.ui.OCommandAction}.


Accessing MIDlet Functionality

Some functions, such as changing which is screen is displayed or causing the handset to beep, are only possible via a reference to the running MIDlet object.  Class {@link com.nextel.ui.OHandset} provides a mechanism for all objects to access this functionality.  For this mechanism to be available, each MIDlet should call {@link com.nextel.ui.OHandset}.setMIDlet as part of its initialization. If setMIDlet is never called the MIDlet will still run ok but some functionality will be disabled. For example, if setMIDlet is called then {@link com.nextel.ui.ODateField}s will beep on attempts to enter invalid months, but if setMIDlet is never called {@link com.nextel.ui.ODateField}s will function ok but will never beep. Additionally, if setMIDlet is called you can use class {@link com.nextel.examples.ui.ScreenNavigator} for simple forward and backward traversal of a sequence of screens.


iBoard Input

The iBoard is a collapsible keyboard, available from Motorola, to which Nextel handsets may be attached. Both {@link com.nextel.ui.OTextField} and {@link com.nextel.ui.OTextScreen} support input from the iBoard, with a caveat. The caveat arises becase MIDlets have no way of knowing whether an iBoard is attached, and so can not distinguish the source of presses of the number keys. This means that when an iBoard number key is pressed, if the text field or screen that has focus allows the input of letters the number key on the iBoard will cycle through the same sequence of letters that is assigned to the corresponding number key on the handset. This also applies to the star (*) and pound (#) keys, which are used on the handset for backspace/delete and inserting spaces, respectively – when pressed on the iBoard they will result in backspace/delete and the insertion of a space, and not the insertion of a * or #.


Example Code

MIDlet {@link com.nextel.examples.ui.UIDemo com.nextel.examples.ui.UIDemo} displays the visual components available in the toolkit.

MIDlet {@link com.nextel.examples.ui.InProgress com.nextel.examples.ui.InProgress} demonstrates how you can use {@link com.nextel.ui.OAnimation} to display an in-progress indicator.