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 WidgetDaemon, WidgetBuilder, 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 space.
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
assert 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.
Root and Parent assertions connect new widgets to the overall window layout tree. A Root
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 .
Widget Types
Widgets acting as containers for other widgets may be of either column or row type. Leaf
widgets may be blank (for spacing/padding/layout), text (a label or editable field), a
slider, or a FontAwesome icon.
WidgetType = NodeType / LeafType .
NodeType = =column / =row .
LeafType = =blank / =text / =slider / =icon .
Configuring widgets
Widgets have attributes attached to them. An attribute is a pair of a symbol key and a
value (of 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 keys.
Attribute = <attribute @id WidgetId @key symbol @value any> .
Events and Widget State
Widgets marked with the interactive attribute generate events in response to
user interaction.
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 State
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
asserts a value-keyed State; and a scrollable widget asserts a visible-scroll-range-keyed
State with a VisibleScrollRange value.
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
by monitoring 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> .
Widget attributes
General attributes, for any widget type
| Key | Value type | Description |
|---|---|---|
| padding | BoxSize | Layout: padding |
| spacing | BoxSize | Layout: spacing |
| size | BoxSize | Layout: explicit widget size |
| backgroundColor | Color | The background color of the widget |
| foregroundColor | Color | Text color in a label or editable field; icon color for FontAwesome icons |
| cornerStyle | square or rounded | The widget's corner style. Defaults to square |
| cornerRadius | number | The widget's corner radius (where cornerStyle is rounded), measured in points |
| interactive | boolean | If true, enables touch and click events |
| name | string | Sets the Morphic "name" for the widget |
Icon attributes
| Key | Value type | Description |
|---|---|---|
| icon | symbol | The FontAwesome icon name for icons |
| icon-style | symbol | The FontAwesome icon style name for icons |
Slider attributes
| Key | Value type | Description |
|---|---|---|
| max | number | Maximum value |
| min | number | Minimum value |
| value | number | Initial value |
| orientation | vertical or horizontal | Orientation |
Text attributes
| Key | Value type | Description |
|---|---|---|
| fontSize | number | The font size, measured in points |
| readOnly | boolean | If true or absent, a label; if false, an editable text field |
| value | string | Initial value |
Row and column attributes
| Key | Value type | Description |
|---|---|---|
| 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 values
The Color type describes an RGBA color value where the components are doubles in the range
0.0 to 1.0 (inclusive).
Color = <rgba @red double @green double @blue double @alpha double> .
BoxSize: layout sizes
The BoxSize type is a pair of Sizings, one for the horizontal and one for the vertical
dimension. Each 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> .