0a27062a70
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.
80 lines
3.2 KiB
Lua
80 lines
3.2 KiB
Lua
-- Run: lua test/ui_theme.lua
|
|
-- Asserts the palette ui.lua derives from a theme's three seed colors.
|
|
package.path = "sdcard/lib/?.lua;" .. package.path
|
|
|
|
local themeName = "light"
|
|
|
|
-- Packing the channels keeps them recoverable, so contrast is checkable.
|
|
gui = {
|
|
color = function(r, g, b) return r * 65536 + g * 256 + b end,
|
|
width = function() return 320 end,
|
|
height = function() return 480 end,
|
|
clear = function() end,
|
|
fillRect = function() end,
|
|
drawText = function() end,
|
|
fillRoundRect = function() end,
|
|
drawRoundRect = function() end,
|
|
fillRectGradient = function() end,
|
|
fontHeight = function() return 8 end,
|
|
textWidth = function(text) return #text * 6 end,
|
|
}
|
|
sys = {millis = function() return 0 end, getTheme = function() return themeName end}
|
|
|
|
local ui = require("ui")
|
|
|
|
local BLACK, WHITE = gui.color(0, 0, 0), gui.color(255, 255, 255)
|
|
|
|
local function reload(name)
|
|
themeName = name
|
|
return ui.reloadTheme()
|
|
end
|
|
|
|
-- Seeds pass through untouched.
|
|
local light = reload("light")
|
|
assert(light.bg == WHITE, "light bg")
|
|
assert(light.fg == BLACK, "light fg")
|
|
assert(light.accent == gui.color(0, 120, 255), "light accent")
|
|
|
|
-- Muted sits between the text and the surface, so it reads as secondary on both.
|
|
assert(light.muted > BLACK and light.muted < WHITE, "muted between fg and bg")
|
|
|
|
-- Contrast is derived, never configured: text on a dark accent must be light.
|
|
assert(light.accent_fg == WHITE, "white text on the blue accent")
|
|
assert(reload("mono").accent_fg == WHITE, "white text on the black accent")
|
|
|
|
-- A pale accent has to flip the label to black; no theme file can get this wrong.
|
|
local pale = ui.themeNames() -- force the module to be loaded before patching it
|
|
assert(#pale >= 3, "expected the canned themes")
|
|
package.loaded["theme"].pale = {bg = {255, 255, 255}, fg = {0, 0, 0}, accent = {255, 235, 120}}
|
|
assert(reload("pale").accent_fg == BLACK, "black text on a pale accent")
|
|
|
|
-- Dark inverts the surface without any per-component configuration.
|
|
local dark = reload("dark")
|
|
assert(dark.bg < dark.fg, "dark theme keeps light text on a dark surface")
|
|
assert(#dark.face == 2 and #dark.face_pressed == 2, "button gradients are pairs")
|
|
|
|
-- Pinned roles win over derived ones, which is the deviation hatch.
|
|
assert(reload("mono").radius == 0, "mono pins radius")
|
|
assert(light.radius == 6, "light keeps the derived radius")
|
|
|
|
-- An unknown name must not leave an app without colors.
|
|
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")
|
|
|
|
-- 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")
|
|
|
|
print("ok")
|