f7c5cc09ba
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.
26 lines
982 B
Lua
26 lines
982 B
Lua
-- Run: lua test/settings_busy.lua
|
|
-- The scan and keyboard screens announce themselves before work that blocks the loop for
|
|
-- seconds. on_tick runs before draw in the same pass, so anything left for draw() to paint
|
|
-- appears only after the blocking call returns -- on a panel ui.screen() has already
|
|
-- cleared. These assert the announcement is built and painted by the tap itself.
|
|
--
|
|
-- Where the notice lands is layout: test/ui_layout_test.cpp asserts centring against the
|
|
-- same C++ the panel runs.
|
|
package.path = "sdcard/lib/?.lua;test/?.lua;" .. package.path
|
|
|
|
local device = require("fake_device").install()
|
|
|
|
dofile("sdcard/apps/Settings/main.lua")
|
|
|
|
init()
|
|
device.tap("WiFi")
|
|
|
|
local drawnBefore = device.drawn
|
|
device.tap("scan networks")
|
|
|
|
-- Built and drawn by the tap, with no draw() in between.
|
|
assert(device.labelled("scanning"), "the scan screen did not build its notice")
|
|
assert(device.drawn > drawnBefore, "the scan notice was left for the next draw()")
|
|
|
|
print("ok")
|