feat(ui)!: move the widget tree into C++
A node was a Lua table of ~625 bytes, of which 21 keys pushed it over a
power-of-two hash boundary and eight were style copies inheritance had
splattered down from its parent. A 400 node screen cost ~250 KB and could not
coexist with wifi's buffers.
The tree now lives in src/ui/layout.h as a 16 byte struct in a flat arena, and
splits by lifetime: Node holds what hit testing and repainting need forever,
Spec holds what only measure/place read and is dropped when layout ends. Style
is sparse and resolved by walking parents, so a node naming no colours costs
nothing. Re-layout rebuilds from Lua rather than retaining the inputs.
401 nodes: 8218 B steady, 21050 B peak
Lua: ~250000 B steady
sdcard/lib/ui.lua stays the toolkit and keeps every constructor signature, but
returns integer handles: 627 lines to 374. Composition, the palette and custom
painters are still Lua on the SD card; only primitives now need a reflash.
BREAKING CHANGE: ui constructors return handles, not tables. Use
ui.setText(id, text) and keep per-node app data in a table keyed by id.
This commit is contained in:
+7
-13
@@ -45,19 +45,13 @@ assert(light.radius == 6, "light keeps the derived radius")
|
||||
local missing = reload("does-not-exist")
|
||||
assert(missing.bg == WHITE and missing.fg == BLACK, "unknown theme falls back to light")
|
||||
|
||||
-- The root seeds the tree, so an app naming no colors still gets themed.
|
||||
reload("dark")
|
||||
local button = ui.button{label = "go", on_press = function() end}
|
||||
local screen = ui.screen(ui.box{pad = 12, button})
|
||||
assert(screen.root.bg == ui.theme.bg, "root takes the theme surface")
|
||||
assert(screen.root.color == ui.theme.fg, "root takes the theme text")
|
||||
screen:draw()
|
||||
assert(button.color == ui.theme.fg, "the button inherited the theme")
|
||||
assert(button.press_bg == ui.theme.accent, "the button inherited the accent")
|
||||
-- Dimming re-derives every role rather than blending pixels, because the panel has no
|
||||
-- alpha to composite a scrim with.
|
||||
reload("light")
|
||||
assert(ui.theme.dim.bg ~= ui.theme.bg, "the dim palette matches the lit one")
|
||||
assert(ui.theme.dim.muted ~= ui.theme.muted, "dimming did not reach derived roles")
|
||||
|
||||
-- An explicit value still wins over the theme.
|
||||
local custom = ui.button{label = "delete", press_bg = 123, on_press = function() end}
|
||||
ui.screen(ui.box{pad = 12, custom}):draw()
|
||||
assert(custom.press_bg == 123, "explicit styling overrides the theme")
|
||||
-- Which node ends up wearing which role is inheritance, and inheritance is the firmware's
|
||||
-- half: test/ui_layout_test.cpp asserts it against the same code the panel runs.
|
||||
|
||||
print("ok")
|
||||
|
||||
Reference in New Issue
Block a user