75b3a2c490
Namespaces were shared across features: `settings` was written by core, the
panel and touch, and `input` by touch and buttons. That made "does this
firmware implement the whole feature?" a question no pointer could answer.
Each namespace now belongs to exactly one feature or to core, so a feature is
a provider pointer and the compiler validates completeness:
gui, node -> screen, tree, under the screen feature
settings -> screen (rotation, theme), sys (timezone),
touch (calibration)
input -> touch, buttons
Runtime::open() no longer requires a GuiProvider; a firmware without one runs
with no screen/tree globals and reports sys.hasFeature("screen") false.
Rotation is one value again: GuiProvider::setRotation applies and persists, so
an app rotating the panel transiently puts the old value back itself.
52 lines
1.7 KiB
Lua
52 lines
1.7 KiB
Lua
-- Button hints as a shared module rather than a firmware paint routine: what the strip looks
|
|
-- like is composition, and only the device knows which roles exist to label.
|
|
|
|
local hints = {}
|
|
|
|
-- Reading order across the strip, so a device showing three of them still reads left to right.
|
|
local ORDER = { "back", "left", "up", "down", "right", "confirm" }
|
|
|
|
local function available()
|
|
local roles = {}
|
|
if buttons and buttons.getAll then
|
|
for _, role in ipairs(buttons.getAll()) do
|
|
roles[role] = true
|
|
end
|
|
end
|
|
return roles
|
|
end
|
|
|
|
---Paints the labels this device can actually act on, and returns the height it used.
|
|
---@param actions table<string, string> Label per Button role; roles the device lacks are skipped.
|
|
---@param options table|nil `y`, `font`, `color`, and `background` overrides.
|
|
function hints.draw(actions, options)
|
|
options = options or {}
|
|
local font = options.font or screen.FONT_SMALL
|
|
local color = options.color or screen.color(0, 0, 0)
|
|
local background = options.background or screen.color(255, 255, 255)
|
|
local height = screen.getFontHeight(font) + 6
|
|
local y = options.y or (screen.getHeight() - height)
|
|
|
|
local roles = available()
|
|
local labels = {}
|
|
for _, role in ipairs(ORDER) do
|
|
if roles[role] and actions[role] then
|
|
labels[#labels + 1] = actions[role]
|
|
end
|
|
end
|
|
|
|
screen.fillRect(0, y, screen.getWidth(), height, background)
|
|
if #labels == 0 then
|
|
return height
|
|
end
|
|
|
|
local slot = screen.getWidth() // #labels
|
|
for index, label in ipairs(labels) do
|
|
local left = slot * (index - 1) + (slot - screen.getTextWidth(font, label)) // 2
|
|
screen.drawText(font, left, y + 3, label, color, screen.STYLE_NORMAL, background)
|
|
end
|
|
return height
|
|
end
|
|
|
|
return hints
|