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 double
s 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 Sizing
s, 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> .