Softanza
StartFrançais
Softanza
Visual & spatial

GUI & reactive

A young RmlUi plane with standout right-to-left and accessibility; the reactive runtime is not yet wired to the view.

2 Strong · 6 Solid · 4 Partial · 0 Emerging

Measured against: Qt · GTK · Flutter · React · Folders: base/gui(opens in a new tab) · base/reactive(opens in a new tab) · base/app(opens in a new tab) · For programmers: this area's reference

a window laid out by the GUI plane: tiles, wrapped text, alignment and right-to-left
a window laid out by the GUI plane: tiles, wrapped text, alignment and right-to-left. rendered by the plane's own guard, committed in the library at 0fbaa692a as base/test/gui/gui_gallery.png, read at commit 4a184e6f0 · the source(opens in a new tab)

Rethought from first principles

What Softanza kept from what works, and what it rethought, as the library wrote it down in its design documents and narrations.

The Softanza waySoftanza declarations are the contract; the markup a UI engine reads is only one projection of them, generated and never written by hand.

Kept from the best practice

  • Layout and input come from RmlUi rather than a home-made toolkit. It was chosen for its permissive licence, host-supplied rendering, no JavaScript engine and a real input model. source(opens in a new tab)
  • The authoring format keeps an idea from QML: each item is a name with a bag of typed properties. Anonymous nested items were refused, so every box has a name. source(opens in a new tab)
  • Asynchronous work rests on libuv, the proven cross-platform event loop, instead of a hand-rolled reactor. Scripts submit work and collect results, and are never called back. source(opens in a new tab)

Rethought

  • Markup is generated, never hand-written. A .panel file is the contract, and RmlUi markup or HTML are its projections, because hand-written markup escapes every check. source(opens in a new tab)
  • The accessibility tree is generated from declared intent, not guessed from markup, which gives screen readers better information. Every focusable element must have a role and a name. source(opens in a new tab)
  • Reactive code is named in plain words, such as functions that wait and values that update themselves, instead of borrowed metaphors like callbacks and subscribers, which hide a simple flow. source(opens in a new tab)
  • An application is modelled as a living world of meaning, a domain, a life with goals, and a body, because files, database and interface are its plumbing, not its being. source(opens in a new tab)

A young but genuinely coherent GUI plane, built on vendored RmlUi and actually running — windows open, events flow, it renders through the GPU plane and an SVG tier. Two standouts reflect the library's DNA: RTL/bidi fully owned and accessibility built in from the grammar up. The rest is early: a four-primitive vocabulary, flexbox-only layout, imperative view-binding, and a full reactive runtime that ships but is not yet wired to the GUI. The whole plane is on local main only, not yet pushed.

What a crafter does with it, and what stands out

  • RTL/bidi fully owned end to end
  • accessibility mandatory at authoring time, exposed via AccessKit
  • a recorder-not-painter render model with a deviceless SVG tier
  • an event surface that counts dropped events

What is owed

  • wire the reactive runtime to the GUI (G5 clause 2)
  • a richer widget set
  • the semantic theme system (G6)
  • IME & two-way text editing

The Softanza way, run

What Softanza does differently in this area, shown by code taken from its narrations and guards, and run for this page.

One declared word, rtl, is emitted as the engine's own direction property, so an author never writes the engine's markup by hand.

Softanza
oRtl = new stzUiDocument(
	'DEFINE PANEL p ( FONT "app", CHILDREN [r] ) RATIONALE "x"' + char(10) +
	'DEFINE BOX r ( TEXT_DIRECTION rtl, HEIGHT 20 ) RATIONALE "x"')
chk("TEXT_DIRECTION rtl becomes --rmlui-direction",
    StzFindFirst("--rmlui-direction: rtl", oRtl.ToRml()) > 0)
chk("...and never the CSS spelling RCSS rejects",
    StzFindFirst("; direction:", oRtl.ToRml()) = 0)
Output
  [OK] TEXT_DIRECTION rtl becomes --rmlui-direction
  [OK] ...and never the CSS spelling RCSS rejects

run on 2026-10-01 21:18 inside the library at commit 0e72e2e2c; taken from base/test/gui/gui_stzui_narrated.ring(opens in a new tab)

An application is declared as a world of things, truths and relations, and it explains itself in plain text.

Softanza
oApp = new stzApp("SonibankVisits")
oApp {
    AddThingQ(:Account) { Has([ :number, :chapter, :balance ])  IsTrue(:balance, "@ >= 0") }
    AddThingQ(:Client)  { Has([ :code, :name, :city ])  Owns(:Account) }
    AddThingQ(:Visit)   { Of(:Client)  Has([ :agent, :date, :subject ]) }
    AddRelation(:Account, :belongsTo, :Client)
}
oApp.Explain()
Output
WORLD SonibankVisits   lives in: memory (not persisted)
  BEING
    account (number, chapter, balance)
        true when balance @ >= 0
    client (code, name, city)
    visit (agent, date, subject)
  RELATIONS
    client owns account
    visit of client
    account belongsto client

run on 2026-10-01 21:18 inside the library at commit 0e72e2e2c; taken from base/test/app/00_stzapp_narrated.ring(opens in a new tab)

The lanes, one by one

Lanes and their notes are quoted as they were read at the source, on Read from the source on 2026-09-16, from a read-only main worktree.

RTL & bidirectional text
Strong
Fully owned (RmlUi does no bidi): stzUiDocument reverses flex rows under RTL; gpu_text.zig reorders with SheenBidi (UAX#9) and shapes Arabic with HarfBuzzstzUiDocument / gpu_text.zig; test/gui RTL suite
Accessibility
Strong
G4a: a mandatory RATIONALE on every element emits an ARIA-role tree; G4b: a11y.zig hands that tree to AccessKit (UIA / NSAccessibility / AT-SPI)stzAccessibilityTree / a11y.zig
Declarative authoring (.panel)
Solid
A closed four-kind grammar PANEL/BOX/TEXT/STYLE, a diagnostics court, a .panel->RML->.panel round-trip fixpoint; far narrower than peer component modelsstzUiDocument
Layout
Solid
RmlUi flexbox via RCSS: direction, wrap, gap, align, justify, px/%/fill sizing; CSS Grid refused by decision, no constraint or custom layoutstzUiDocument::ToRml()
Rendering backend
Solid
RmlUi's render interface is a recorder, not a painter (stz_rmlui.cpp): one flat display list drawn by the GPU tier or an SVG tier; PNG needs a GPU devicestz_rmlui.cpp
Event handling
Solid
Pointer, key, text-input, focus and directional focus move, hit-testing (element_at), an event recorder that counts dropped events; no gesture recognitionstzPanel
Reactive runtime & signals
Solid
stzReactiveObject with Watch / Computed(deps) / BindTo / SetAttribute, streams, timers, HTTP, event bus on a libuv reactor; not yet reaching the viewbase/reactive; reactor.zig
App shell & windowing
Solid
Native windows via vendored GLFW (window.zig); stzApp is a declarative living world; no multi-window orchestration, dialogs, menus or system-traywindow.zig / stzApp
Widget / element toolkit
Partial
RmlUi's own form controls (input, select, textarea, progress, tabset, button); no tables, trees, menus, dialogs, pickers, toolbars, docking
State->view binding
Partial
{placeholder} templates and Set/SetStyle/Apply mutate a live document preserving focus, values escaped as data; imperative, not reactivestzUiBindings (G5 clause 1)
Text input & IME
Partial
Single-line text input works (stz_gui_text_input); no IME, composition input for CJK and complex scripts deferred (costed at 1-3 engineer-years)
Theming & animation
Partial
Inline styling (BACKGROUND, COLOR, STYLE bags -> RCSS) and a profile layer; no semantic theme system (G6 not started) and no animation/transitions