|
Design Details
This page explains how the Synclast UI toolkit works, and is intended for advanced developers who wish to add their own widgets and functionality.
Widget
A widget is a user interface element that can be applied to a
SynclastCanvas or Container. The Widget base class provides functionality
that is common for all types of elements. As such most of the methods
and fields here provide lifecycle management.
showNotify/hideNotify
The showNotify() and hideNotify() events are generated by the MIDP
application when the current displayable is set to or from a
SynclastCanvas. At these times the appropriate method is called down
the widget hierarchy.
showNotify() can also be called when a widget is added to an already
active display. hideNotify() can be called when a widget is removed
from an active display.
X/Y Positioning
Each widget has fields for its X and Y coordinates, though these may
be managed by its container. These specify the position of the
widget's top left corner. The X/Y coordinates are relative to the
most directly referenced container, similar to the notion of a Layer
in the MIDP 2.0 Game API. Therefore, a widget at (0,0) is only in the
upper left corner of the on-screen display if its container (and its
container's container, and so on) also have their origins at (0,0).
Width and Height
Each widget is responsible for providing its own width and height.
The member variables "w" and "h" track these in units of pixels. All
Synclast widgets occupy a rectangular area, though other shapes can of
course be simulated. Width and height are queried by the container
after the widget's setContainer() method is called, which occurs after
all style sheet properties have been applied. Widgets may change their
size at any time, but must call invalidate() if they do so.
Implementation note: For simplicity, we have chosen to avoid having a
separate notion of "preferred" width and height.
Invalidate()/validate()
Widgets are responsible for calling the validate() method if they
make changes that may require their container to re-layout its
components. The validate() method may be overridden to be notified
when the container is preparing to layout the component.
Properties
Widgets have a set of properties that can be applied via StyleSheets
or directly set using the set(property, value) method. The set of
available properties varies based on the specific Widget subclass.
Alignment
Every widget has an ALIGN property that specifies how it is positioned
by its parent container, using the alignment constants from the MIDP
Graphics class (the value zero indicates that the container should
apply whatever its default behavior is). The ALIGN value should not
be confused with any additional properties a Widget may use to align
its internal contents (working within the space allocated by its
width and height).
The paint() Method
A widget's paint(Graphics) method is called whenever its area of the screen is repainted. Before paint() is called, the Graphics context is translated so that (0,0) is the top left corner of the widget. The context is also set with a clipping rectangle equal to the widget's width and height.
Key Events
Widgets that respond to key events must implement the KeyEventListener
interface. A widget enters a state where it may receive key event
callbacks when its focus() method is called (see below).
Pointer Events
Similarly, widgets that wish to respond to pointer events must
implement the PointerEventListener interface. The pointer event
mechanism is currently very open-ended.
Focus
A SynclastCanvas has the notion of user focus. Focus can be assigned
to any widget that implements the KeyEventListener interface. Only
one widget can be focused at a time.
A widget can request to be passed focus by calling
Container.requestFocus(this). It can also pass the focus in the
forward or reverse direction. The container is free to assign its own
meaning to forward (+1) and reverse (-1); generally forward should
mean the "next" widget, either in add order or in visual order.
Focus is first assigned when a canvas is shown on the display. The
first focusable item will have its focus() method called immediately
after showNotify() is called. If no widgets are currently focusable,
but a new focusable widget is added to a canvas, the new widget will
immediately have its focus() method called.
When a canvas is hidden, the focused component will have its blur()
method called prior to hideNotify(). When a canvas is shown, the
component will have its focus() method called again.
Implementation note: As pointer-based devices mature, we may break out
a Focusable interface as a superinterface of both KeyEventListener and
PointerEventListener.
|