From 8e304902a895784849f84e9c4c5bcbb1348924a9 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 12 Oct 2022 21:58:29 +0200 Subject: [PATCH] Flesh out protocol descriptions more --- src/protocols/synit/audio.md | 59 ++++++++ src/protocols/synit/mime.md | 16 +++ src/protocols/synit/modem.md | 117 ++++++++++++++++ src/protocols/synit/network.md | 194 ++++++++++++++++++++++++++ src/protocols/synit/soundEffects.md | 30 ++++ src/protocols/synit/telephony.md | 158 ++++++++++++++++++++++ src/protocols/synit/time.md | 20 +++ src/protocols/synit/ui.md | 203 ++++++++++++++++++++++++++++ src/protocols/synit/userSettings.md | 17 +++ 9 files changed, 814 insertions(+) diff --git a/src/protocols/synit/audio.md b/src/protocols/synit/audio.md index 6338037..14d867d 100644 --- a/src/protocols/synit/audio.md +++ b/src/protocols/synit/audio.md @@ -1 +1,60 @@ # Audio control + + - [`[synit]/protocols/schemas/audio.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/audio.prs) + +The audio control protocol configures sound sources and sinks, for instance for call audio +control on a mobile phone. This protocol is still *experimental*, as configuration of audio +stacks is complex and I have only a few simple examples to work from thus far. As Synit is +ported to new systems (e.g. new mobile handsets, to desktop machines, and so on), this protocol +will be refined. + +**Implementation.** The protocol is (as of October 2022) implemented entirely within the +SqueakPhone Smalltalk image, in class `AudioProfileDaemon`. The audio profile daemon has three +tasks: first, to track Linux input `HEADPHONE_INSERT` and `MICROPHONE_INSERT` events and state, +producing `HeadsetSpeakerPresent` and `HeadsetMicrophonePresent` assertions in response; +second, to track application state such as whether a call is in progress or not; and third, to +respond to changes in device and application state, along with changes in sink/source mapping +configuration, by using the external `amixer` program to enable and disable audio sinks and +sources. The schema definition file contains a few +[comments](https://git.syndicate-lang.org/synit/synit/src/commit/a2babb63d55743ce942562e7ccb9106fdb239cf4/protocols/schemas/audio.prs#L3-L17) +that give some of the flavour of the logic involved. + +## Source/Sink mappings + +Each different kind of device asserts `Mapping` records to connect abstract `Endpoint` names to +concrete ALSA device names. + +``` +Mapping = . +Endpoint = / . +Sink = =speaker / =headset / =earpiece . +Source = =speakerphone / =headset / =handset . +``` + +**Example.** When the Smalltalk code detects that it is running on a PinePhone, it asserts + + - ` "Line Out">` + - ` "Headphone">` + - ` "Earpiece">` + - ` "Mic1">` + - ` "Mic1">` + +## Audio device state + +The current daemon interprets low-level Linux input subsystem events, asserting +`HeadsetSpeakerPresent` and `HeadsetMicrophonePresent` when the relevant hardware is physically +attached to the system. These assertions are in turn used when selecting an audio profile to +enable. + +``` +HeadsetSpeakerPresent = . +HeadsetMicrophonePresent = . +``` + +## Relevant application state + +The current daemon reacts to changes in +[`AlertSoundPlaying`](./soundEffects.md#AlertSoundPlaying), +[`PhoneRinging`](./telephony.md#PhoneRinging), +[`CallInProgress`](./telephony.md#CallInProgress), and +[`Speakerphone`](./telephony.md#Speakerphone) when selecting an audio profile to enable. diff --git a/src/protocols/synit/mime.md b/src/protocols/synit/mime.md index 6d5e909..4f327f7 100644 --- a/src/protocols/synit/mime.md +++ b/src/protocols/synit/mime.md @@ -1 +1,17 @@ # MIME type support + + - [`[synit]/protocols/schemas/mime.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/mime.prs) + +Various protocols (e.g. the [sound effects](./soundEffects.md) protocols) rely on the +definition of a [MIME](https://en.wikipedia.org/wiki/MIME) `Value`, compatible with the +[suggested Preserves +convention](https://preserves.dev/conventions.html#mime-type-tagged-binary-data) for MIME +values. + +The `type` is a symbol describing the MIME type, for example `application/octet-stream` or +`text/plain`. The `data` is the associated binary data, expected to be in the correct format +for the given `type`. + +``` +Value = . +``` diff --git a/src/protocols/synit/modem.md b/src/protocols/synit/modem.md index 885dff6..4ba9d78 100644 --- a/src/protocols/synit/modem.md +++ b/src/protocols/synit/modem.md @@ -1 +1,118 @@ # Modem support + + - [`[synit]/protocols/schemas/hayes.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/hayes.prs) + - [`[synit]/protocols/schemas/samsungGalaxyS7.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/samsungGalaxyS7.prs) + +Each particular class of modem has internal protocols needed for controlling it. So far, Synit +is able to interact with generic Hayes-style ("AT-command") modems, as seen in the PinePhone, +as well as with the modem in the Samsung Galaxy S7. + +Each modem's internal protocol is spoken across the modem's distinguished dataspace, a +reference to which is held in the modem's [`ModemPresent`](./telephony.md#ModemPresent) +assertion. + +## Hayes-style ("AT-command") Modems + +As of October 2022, this protocol is implemented entirely in the SqueakPhone Smalltalk image, +in class `HayesModemActor` and friends. + +### Presence + +Hayes-style modems announce their presence with a subtype of the general `ModemPresent` +assertion schema. + +``` +ModemPresent = . +``` + +(TODO: specify the `InternalProtocol` properly) + +``` +InternalProtocol = any . +``` + +### Unsolicited Result Codes + +An `UnsolicitedResultCode` message is sent when the modem sends us a "URC", an Unsolicited +Result Code. + +``` +UnsolicitedResultCode = . +``` + +### Executing AT commands + +Assert a `CommandRPC` record to request execution of an AT command string. The completion, +along with any responses, will be send to the `replyTo` entity reference. Alternatively, if no +completion notification or response is desired, send a `CommandEvent` message. + +``` +CommandRPC = . +CommandEvent = . +``` + +The result of a command execution is *asserted* as a `CommandResult` record to the `replyTo` +entity in the `CommandRPC`. + +``` +CommandResult = . +``` + +### Responses and Unsolicited Results + +The `Result` type appears in both `UnsolicitedResultCode` and `CommandResult` records. + +``` +Result = . +MaybeString = @present string / @absent #f . +MaybeStrings = @present [string ...] / @absent #f . +``` +**Examples.** + - `>` + - `>` + - `>` + - `>` + - `>` + +## Samsung Galaxy S7 + +The Samsung Galaxy S7 was the first modem supported by Synit, but because of problems with the +relevant PostmarketOS kernel, support for it has languished a bit while development has +proceeded based around the PinePhone. As of October 2022, the Samsung modem support protocols +are implemented entirely in the SqueakPhone Smalltalk image, in class +`SamsungGalaxyS7ModemActor` and friends. + +### Presence + +The modem announces its presence with a subtype of the general `ModemPresent` assertion schema. + +``` +ModemPresent = . +``` + +(TODO: specify the `InternalProtocol` properly) + +``` +InternalProtocol = any . +``` + +### Low-level packet I/O + +``` +ModemPacket = @in / @out . + +; The bodies are instances of SamsungFmtMessage and SamsungRfsMessage, respectively. +FmtPacket = . +RfsPacket = . +``` + +### Executing commands + +Analogous to AT command execution for Hayes-style modems. + +``` +; Assertion. Asks the modem to execute the given command. +CommandRPC = . +; Message. Asks the modem to execute the given command, but not to send back the reply. +CommandEvent = . +``` diff --git a/src/protocols/synit/network.md b/src/protocols/synit/network.md index fe7f54e..d1ca5b6 100644 --- a/src/protocols/synit/network.md +++ b/src/protocols/synit/network.md @@ -1 +1,195 @@ # Network core status and configuration + + - [`[synit]/protocols/schemas/network.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/network.prs) + +[interface monitor]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/usr/lib/synit/python/synit/daemon/interface_monitor.py +[wifi daemon]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/usr/lib/synit/python/synit/daemon/wifi_daemon.py +[network.pr]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/etc/syndicate/services/network.pr +[wifi.pr]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/etc/syndicate/services/wifi.pr +[modem.pr]: https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-config/files/etc/syndicate/services/modem.pr + +The definitions in this protocol are used by the Synit daemons responsible for detecting and +responding to changes in the configuration of network devices. + +**Implementation.** As of October 2022, this protocol is mostly implemented in + - the [interface monitor][], + - the [wifi daemon][], and + - the scripting around [network state changes][network.pr]. + - the scripting around the [wifi subsystem][wifi.pr]. + - the scripting around [mobile data][modem.pr]. + +## Network interface presence and state + +The [interface monitor][] daemon uses the Linux netlink protocol to monitor changes in +interface presence and state. In response to netlink messages, it maintains an `Interface` +assertion for each network interface in the system. + +``` +Interface = . +``` + +The `InterfaceType` is synthesised by the interface monitor daemon based on somewhat ad-hoc +heuristics. + +``` +InterfaceType = +/ ; `lo` and friends + =loopback +/ ; `eth0`, bridges, anything that isn't loopback and isn't wireless + =normal +/ ; 'wlan0' and friends + =wireless +. +``` + +The `AdministrativeState` of an interface describes the state that the operator of the machine +wishes the interface to be in (according to the kernel). + +``` +AdministrativeState = =unknown / =down / =up . +``` + +The `OperationalState` and `CarrierState` taken together, by contrast, describe the *actual* +state of the interface. + +``` +OperationalState = +/ =unknown +/ =down +/ @lowerLayerDown =lower-layer-down +/ =testing +/ =dormant +/ =up +. + +CarrierState = +/ @noCarrier =no-carrier +/ =carrier +. +``` + +## Route presence and state + +The [interface monitor][] daemon also listens for netlink messages describing network route +presence and state changes, maintaining a `Route` assertion for each route present. + +``` +Route = . + +AddressFamily = =ipv4 / =ipv6 / @other int . +RouteDestination = =default / @prefix . +RouteInterface = @name string / @none #f . +Gateway = @addr string / @none #f . +``` + +## Default route presence + +The [network.pr][] scripts respond to presence of `Route` records with a `default` +`destination` field by asserting a `DefaultRoute` record. Applications may use the presence or +absence of a `DefaultRoute` record to decide whether or not internet access is currently +present. + +``` +DefaultRoute = . +``` + +## Wi-fi associations + +The [wifi.pr][] script starts an instance of the [wifi daemon][] and an instance of +[`wpa_supplicant`](https://w1.fi/cgit/hostap/tree/README) for each `Interface` of type +`wireless`. The wifi daemon speaks with the `wpa_supplicant` instance to do network scanning as +well as managing network attachments. It publishes a `WifiAssociation` for each active +connection to a wifi access point. + +``` +WifiAssociation = . +WifiAssociationState = @inProgress =in-progress / =ready . +``` + +## Hotspots + +In future, the software will use `HotspotState` assertions to publish the presence and state of +wifi hotspots hosted by the device. + +``` +HotspotState = . +``` + +## AP scanning + +In future, the software will assert `AvailableAccessPoint` with information it learns from +network scanning. + +``` +AvailableAccessPoint = . +``` + +## Network-related user settings + +A number of user setting assertions control the network. + +### Mobile Data + +Asserting `MobileDataApn` and `MobileDataEnabled` causes the [modem.pr][] script to enable a +cellular data link. + +``` +MobileDataApn = . +MobileDataEnabled = . +``` + +### Wifi network preferences + +``` +WifiAuthentication = +/ ; No authentication necessary: open network + =open +/ ; Pre-shared key (WPA2-PSK etc) + +/ ; Other, not-yet-implemented + @other any +. +``` + +Each [wifi daemon][] responds to `SelectedWifiNetwork` assertions for its interface by trying +to connect to the named SSID using the provided credentials. The daemon asserts a +`WifiAssociation` in response. + +``` +SelectedWifiNetwork = . +``` + +In future, user `Hotspot` assertions will cause setup of a wifi hotspot, hosted by the device. + +``` +Hotspot = . +``` + +In future, `SavedWifiNetwork` assertions will hold records of previously-configured wifi +connection details. + +``` +SavedWifiNetwork = . +``` diff --git a/src/protocols/synit/soundEffects.md b/src/protocols/synit/soundEffects.md index c858fdd..211206a 100644 --- a/src/protocols/synit/soundEffects.md +++ b/src/protocols/synit/soundEffects.md @@ -1 +1,31 @@ # Sound effects + + - [`[synit]/protocols/schemas/soundEffects.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/soundEffects.prs) + +From time to time, it makes sense for the device to use sound to communicate with the user. + +**Implementation.** As of October 2022, the implementation resides within classes +`RingToneDaemon` and `SoundEffectsDaemon` in the SqueakPhone Smalltalk image. + +## Continuous sounds + +Continuous sounds such as a user's ringtone may be produced by asserting `ContinuousSound` with +an appropriately-type-tagged sound file (such as an mp3 file) as `data`. In response, the sound +effects daemon play the file in a loop and will assert `ContinuousSoundPlaying`. + +``` +ContinuousSound = . +ContinuousSoundPlaying = . +``` + +## Alert sounds + +One-off sound effects such as the notification of a received SMS may be produced by sending an +`AlertSound` message with an appropriately-type-tagged sound file (such as an mp3 file) as +`data`. In response, the sound effects daemon will play the file once and will assert +`AlertSoundPlaying` until the playback is complete. + +``` +AlertSound = . +AlertSoundPlaying = . +``` diff --git a/src/protocols/synit/telephony.md b/src/protocols/synit/telephony.md index f1f42f6..e647ff5 100644 --- a/src/protocols/synit/telephony.md +++ b/src/protocols/synit/telephony.md @@ -1 +1,159 @@ # Telephony (call and SMS) support + + - [`[synit]/protocols/schemas/telephony.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/telephony.prs) + +The telephony protocol defines record and message types for non-modem-hardware-specific +telephony interactions. + +**Implementation.** The protocol is (as of October 2022) implemented entirely within the +SqueakPhone Smalltalk image, in class `CallManager`, `HayesModemActor`, +`SamsungGalaxyS7ModemActor`, and so on. + +## Available modem devices + +A `ModemPresent` record is asserted for each modem available to the telephony subsystem. The +`type` field can, for example, be the symbol `hayes` for a Hayes modem, `samsung-galaxy-s7` for +a Samsung Galaxy S7, and so on. Each modem variant speaks a [variant-specific +protocol](./modem.md) across the `dataspace` reference in the `ModemPresent` record. Finally, +the `devicePath` is a Linux device path representative of the modem, for example +`/dev/umts_boot0` or `/dev/EG25.AT`. + +``` +ModemPresent = . +``` + +## Telephony addresses (telephone numbers) + +An `Address` represents a phone number. The `numberType` selects the numbering plan; the +`number` is the actual address. Numbering plans are complex! The GSM specifications are the +place to go for details. In general, using `international` with numbers like `+31 6 ...` is the +best way forward. + +``` +Address =
. +NumberType = =unknown / =international / =national / =gsm0338 . +``` + +## Ongoing calls + +An `ActiveCall` assertion describes an active, ongoing call. + +The `callId` is a modem-specific call identification number. (TODO: if two modems are active, +their `callId`s may clash.) The `direction` is `mo` for calls placed by the local phone +endpoint, i.e. those dialed by the local user, and `mt` for calls placed by a remote phone, +i.e. incoming calls, those answered by the local user. The `type` field describes whether the +call is for voice or data; usually, this will be `voice`, but `data` is reported by some modems +when using mobile data connections. As you might imagine, `fax`-type calls are uncommon. The +`peer` field describes the other phone's network address (phone number). Finally, `state` +describes the state of the call. + +``` +ActiveCall = . +CallId = int . +CallDirection = =mo / =mt . +CallType = =voice / =data / =fax . +CallState = =hold / =original / =connect / =incoming / =waiting / =end / =alerting . +``` + +## Answering an incoming call + +When an `ActiveCall` record is asserted by the modem, if it has direction `mt` and state +`incoming`, the system should let the user choose to answer the call (or ignore it, etc.). If +the user chooses to answer, an `AnswerCall` message tells the modem to do the necessary. The +`callId` is the same value as in the `ActiveCall` assertion. + +``` +; Message. Triggers call answering. +AnswerCall = . +``` + +## Rejecting and/or disconnecting a call + +Sending a `DisconnectCall` message causes the modem to release an active call, either without +answering it (rejection) or while it is established (disconnection). The `callId` is taken from +the `ActiveCall` assertion, or is the symbol `all` to request disconnection of all active +calls. The `cause` field describes the release reason; it should usually be `normal`, but +`busy` or `callRejected` may also be appropriate. + +``` +DisconnectCall = . +CallIdSelector = @specificCall int / @allCalls =all . +ReleaseCause = +/ =unassignedNumber +/ =normal +/ =busy +/ =noUserResponding +/ =callRejected +/ =destinationOutOfOrder +/ =normalUnspecified +/ =incompatibleDestination +. +``` + +## Placing an outbound call + +Sending a `PlaceCall` message causes the matching modem (named by its `devicePath`, which +should match a `ModemPresent` assertion) to place an outbound call to the named `peer` (a phone +number). + +``` +; Message. Starts an outgoing call. +PlaceCall = . +``` + +## Whole-device call state + +Many applications don't care about precise details of individual calls, but only whether or not +some ongoing call is active (alerting, connected, ringing etc.). Those applications may monitor +the `CallInProgress` assertion. + +``` +CallInProgress = . +``` + +## Whole-device ringing state + +A `PhoneRinging` assertion means that an incoming call is signalling the user, asking for a +decision about whether to answer, reject, or ignore the call. + +``` +PhoneRinging = . +``` + +A `PeerRinging` assertion means that, during the establishment phase of an outgoing call, the +remote party's phone should be ringing. + +``` +PeerRinging = . +``` + +## SMS deliveries and transmissions + +An `SmsDelivery` message indicates that an incoming SMS message has been received. The `smsc` +is the message relay server that forwarded the message on to us; this is usually some carrier- +and even plan-specific address, see the GSM specifications for details. The `peer` is the +sender's phone number. The `timestamp` describes the time associated with the SMS, and the +`body` is the message itself. + +``` +SmsDelivery = . +``` + +To send an SMS message, assert an `SmsTransmission` record with the correct `smsc`, the +`peer`'s destination phone number, and the `body` of the message to send. The `continuation` +field should be a reference to an entity that expects the `ok` symbol as a message when the +transmission has been processed by the modem. + +``` +; Assertion. An outgoing SMS should be transmitted. +SmsTransmission = . +``` + +## Speakerphone mode + +The user may choose to assert a `Speakerphone` record in order to request that the local audio +hardware switch profile to speakerphone mode during a call. + +``` +Speakerphone = . +``` diff --git a/src/protocols/synit/time.md b/src/protocols/synit/time.md index 0c86047..ccfb875 100644 --- a/src/protocols/synit/time.md +++ b/src/protocols/synit/time.md @@ -1 +1,21 @@ # Time stamps + + - [`[synit]/protocols/schemas/time.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/time.prs) + +Various protocols rely on the definition of a time stamp type, `Stamp`, compatible with the +[suggested Preserves convention](https://preserves.dev/conventions.html#dates-and-times) for +dates and times. + +``` +Stamp = . +``` + +From the Preserves convention document: + +> Dates, times, moments, and timestamps can be represented with a Record with label `rfc3339` +> having a single field, a `String`, which MUST conform to one of the `full-date`, +> `partial-time`, `full-time`, or `date-time` productions of +> [section 5.6 of RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6). +> (In `date-time`, “T” and +> “Z” MUST be upper-case and “T” MUST be used; a space separating the `full-date` and +> `full-time` MUST NOT be used.) diff --git a/src/protocols/synit/ui.md b/src/protocols/synit/ui.md index 3476991..c37a3c2 100644 --- a/src/protocols/synit/ui.md +++ b/src/protocols/synit/ui.md @@ -1 +1,204 @@ # User interface definitions and interaction + + - [`[synit]/protocols/schemas/ui.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/ui.prs) + +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 = . +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 = . +WindowTitle = . +``` + +## 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 = . + +Parent = . +Root = . + +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`, an `image`, or a [FontAwesome](https://fontawesome.com/) `icon`. + +``` +WidgetType = NodeType / LeafType . +NodeType = =column / =row . +LeafType = =blank / =text / =slider / =image / =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](#attribute-keys) for more on the available +attribute keys. + +``` +Attribute = . +``` + +## Events and Widget State + +Widgets marked with the [`interactive` attribute](#interactive) 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 = . +``` + +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 = . +``` + +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 = . + +VisibleScrollRange = +/ =none +/ @visibleScrollRange + > +. +``` + +## Accessing widget instances + +Within the current implementation, access to the raw +[Morphic](http://wiki.squeak.org/squeak/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 Attributes + +### General attributes + +interactive - boolean - ? +name - string - morphic name for the widget + +### Color and style + +The `Color` type describes an RGBA color value where the components are `double`s in the range +`0.0` to `1.0` (inclusive). + +``` +Color = . +``` + +#### backgroundColor: Color + +Sets 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` + +Sets the widget's corner style. Defaults to `square`. + +#### cornerRadius: number + +Sets the widget's corner radius (where `cornerStyle` is `rounded`), measured in points. + +#### fontSize: number + +Sets the font size, measured in points. + +#### icon: symbol + +Sets the FontAwesome icon name for icons. + +#### icon-style: symbol + +Sets the FontAwesome icon style name for icons. + +### Layout + +``` +; Box-and-glue layout +Fill = @fixed double / . +Sizing = . +BoxSize = . +``` + +padding - BoxSize - layout padding +size - BoxSize +spacing - BoxSize + +### Sliders + +max - number +min - number +orientation - `vertical` or `horizontal` - for sliders +value - number - slider value + +### Text fields (labels and editable fields) + +readOnly - boolean - set to false to turn a label into an editable field +value - string - label or editable field contents + +### Column and row attributes + +cells - integer - number of cells per row (column) of the layout matrix - if none, just one row (column) exists +scrollable - boolean diff --git a/src/protocols/synit/userSettings.md b/src/protocols/synit/userSettings.md index 3f4ada5..ad26a34 100644 --- a/src/protocols/synit/userSettings.md +++ b/src/protocols/synit/userSettings.md @@ -1 +1,18 @@ # User settings + + - [`[synit]/protocols/schemas/userSettings.prs`](https://git.syndicate-lang.org/synit/synit/src/branch/main/protocols/schemas/userSettings.prs) + +``` +version 1 . + +; Assertion. +CommandRPC = . +; Message. +CommandEvent = . + +CommandReply = =done . +Action = / . + +; Assertion. +Value = . +```