User interface definitions and interaction
The user interface protocol is perhaps the most subject-to-change part of the whole system. It is a client-server protocol, similar in spirit to X-Windows, where clients request display and input services from a server, to which is attached a display and input devices.
At present, it is a simple system with a fixed set of widget types, a TeX-inspired box-and-glue layout model, and a very limited set of event types. In future, a NeWS/Display-PostScript-inspired model could dovetail very nicely with the capability and dataspace features of Syndicate.
Implementation. The SqueakPhone Smalltalk image includes the initial implementation of the
protocol, in classes
WidgetWindow, and so on.
Creating a window
A client observes
Window assertions with an
id of its choice. The server notices the
client's interest, and in response, creates a fresh dataspace for configuration and interaction
relating to the new window, and asserts a
Window record mapping the
id to the new
Window = <window @id WidgetId @space #!any> . WidgetId = any .
Configuring a window
Within the dataspace referred to by a
Window assertion—henceforth the window dataspace—the
client may assert
WindowCloseable to add a close button to the window decoration, and may
WindowTitle to give the window a name.
WindowCloseable = <window-closeable> . WindowTitle = <window-title @title string> .
Creating widget trees
The client may place
Widget assertions within the window dataspace to create new widgets
within the window. The window is hidden until the first
Widget is asserted.
Parent assertions connect new widgets to the overall window layout tree. A
assertion places the widget directly in the containing window, while a
Parent assertion marks
a widget as child of another widget. In both cases, the
order sort key is used when multiple
children are present within a container that supports widget ordering.
Widget = <widget @id WidgetId @type WidgetType> . Parent = <parent @id WidgetId @parentId WidgetId @order SortKey> . Root = <root @id WidgetId @order SortKey> . SortKey = @double double / @string string .
Widgets acting as containers for other widgets may be of either
row type. Leaf
widgets may be
blank (for spacing/padding/layout),
text (a label or editable field), a
slider, or a FontAwesome
WidgetType = NodeType / LeafType . NodeType = =column / =row . LeafType = =blank / =text / =slider / =icon .
Widgets have attributes attached to them. An attribute is a pair of a symbol
key and a
key-specific type) attached to a particular widget. Most attribute keys are
expected to have either zero or one
Attribute records for any given widget, but the
Syndicated Actor Model naturally supports multiple values for a given attribute, and some
attribute keys take advantage of this. See below for more on the available
Attribute = <attribute @id WidgetId @key symbol @value any> .
Events and Widget State
Widgets marked with the
interactive attribute generate events in response to
Clients can observe
Touch assertions to receive information about when the user has a finger
touching the displayed widget on a touchscreen. The assertion for a given widget will appear
when the touch starts, and disappear when the touch ends. Multiple touches, uniquely
identified, may be active simultaneously.
Touch = <touch @widget WidgetId @touchId any> .
Clients can observe
Click messages to receive information about when the user removes a
touching finger from a widget while the finger is within the widget's bounds.
Click = <click @widget WidgetId> .
Finally, whether a widget is marked interactive or not, the UI server actor asserts
assertions containing facts about a given widget's state. For example, a text widget asserts a
State assertion with the symbol
text as its
key and a string as its
value; a slider
State; and a scrollable widget asserts a
State with a
State = <state @widget WidgetId @key any @value any> . VisibleScrollRange = / =none / @visibleScrollRange <visible-scroll-range <min @minId WidgetId @minSortKey SortKey> <max @maxId WidgetId @maxSortKey SortKey>> .
Accessing widget instances
Within the current implementation, access to the raw
Morphic object representing the widget can be gained
WidgetInstance assertions. (This is not a sustainable technique, and it will be
replaced in future by an entity-reference-based system.)
WidgetInstance = <widget-instance @id WidgetId @instance #!any> .
General attributes, for any widget type
|size||Layout: explicit widget size|
|backgroundColor||The background color of the widget|
|foregroundColor||Text color in a label or editable field; icon color for FontAwesome icons|
|cornerStyle||The widget's corner style. Defaults to |
|cornerRadius||number||The widget's corner radius (where |
|interactive||boolean||If true, enables touch and click events|
|name||string||Sets the Morphic "name" for the widget|
|icon||symbol||The FontAwesome icon name for icons|
|icon-style||symbol||The FontAwesome icon style name for icons|
|fontSize||number||The font size, measured in points|
|readOnly||boolean||If true or absent, a label; if false, an editable text field|
Row and column attributes
|cells||integer||Number of cells per row (column) in a grid; if absent, just one row (column)|
|scrollable||boolean||Whether the container is a scrollable viewport or fixed-size|
Widget value types
Color type describes an RGBA color value where the components are
doubles in the range
Color = <rgba @red double @green double @blue double @alpha double> .
BoxSize: layout sizes
BoxSize type is a pair of
Sizings, one for the horizontal and one for the vertical
Sizing describes an ideal size, measured in points, plus a "stretch" and a
"shrink" specification of
Fill type, loosely modelled on the TeX concept of "boxes and glue".
Fill = @fixed double / <fill @weight int @rank int> . Sizing = <sizing @ideal double @stretch Fill @shrink Fill> . BoxSize = <box-size @horizontal Sizing @vertical Sizing> .