Commit Graph

5 Commits

Author SHA1 Message Date
evan 2cdb7b3702 feat: timezone setting and main-axis justify in the ui toolkit
The launcher clock read UTC and sat next to the title because the toolkit could only
stack children from the start of an axis. justify adds the CSS main-axis modes that
had a caller -- start, end, center, between -- so a header keeps its title left and
its clock right without any app doing arithmetic.

Timezones are stored as POSIX TZ rules rather than offsets, so newlib applies DST
changeovers and os.date() in Lua reports local time with no binding of its own.
/lib/timezones.lua is only the picker list: a zone missing from it still works if its
rule is written into settings, the same split themes already use.

settings_calibration.lua now finds rows by label. Adding the timezone row shifted
every hardcoded y coordinate in it, which is the failure that had been predicted and
would have silently retargeted taps at the wrong control.
2026-08-01 17:03:55 -04:00
evan 393ce3c0ed refactor: split the Lua runtime, share test stubs, add a Makefile
lua_app.cpp had grown to 701 lines holding every binding, the module loader and the
app lifecycle, so new bindings landed wherever the cursor was. Each Lua table now has
its own file under bindings/, and the app is recovered from the lua_State's extra
space instead of a file-static, so a second state cannot reach the wrong app.

Three tests each redeclared the binding surface, which broke twice this session when
a binding changed; test/fake_device.lua is now the single stub. `make test` runs all
four suites and pins Lua 5.4, matching the vendored interpreter rather than the 5.2
the tests had silently been using.
2026-08-01 11:17:42 -04:00
evan 36953bb140 fix(gui): anti-aliased rounded rects from one distance field
Corners were drawn by two disagreeing algorithms: a hand-rolled per-row inset for
the gradient fill and TFT_eSPI's Bresenham arc for the border, so they missed each
other by a pixel and left a halo. The inset was also wrong, truncating the sqrt and
ignoring pixel centres, which over-cut the top row by 2px into a visible chamfer.

gui.roundRect now derives fill and border from the same signed distance, blending
edge pixels by coverage, and replaces fillRoundRect, drawRoundRect and
fillRectGradient. The geometry moved to src/gfx/round_rect.h so round_rect_test.cpp
can check the arc on the host, since only the eye ever checked the old one.
2026-08-01 11:04:35 -04:00
evan 0a27062a70 feat(ui): themes derived from three seed colors
Every app re-declared the same black/white/accent triple, so a palette now lives in
/lib/theme.lua and ui.lua derives muted, contrast, gradients and radius from it.
Deriving rather than listing means a new component costs no theme keys, and a theme
cannot pick text that is unreadable on its own accent.

Components take the palette by inheritance, so the three apps name no colors at all;
ui.theme stays for drawing outside the tree. Settings cycles the installed themes and
stores only the name.
2026-08-01 10:04:52 -04:00
evan 4e5796fd51 feat(ui): layout toolkit, Lua launcher and touch press events
Apps describe nesting instead of coordinates: /lib/ui.lua borrows CSS block flow,
the box model and auto sizing, and owns hit testing, press capture and the pressed
repaint. The runtime gains require backed by the SD card, on_touch_down/on_touch_up,
text metrics and rounded gradient fills, so the launcher becomes an ordinary Lua app
and the firmware keeps only a fallback screen for an unreadable card.
2026-07-31 22:27:34 -04:00