114c8c5f72
The bar is host-owned chrome: the firmware clips apps into a viewport below it, so no app can paint over it, while /lib/statusbar.lua owns the height, repaint interval and painting. gui.fullscreen() lets touch calibration take the physical panel back. Launcher and settings become grids of square cards (3 across landscape, 2 portrait) via the new gui.setTextSize, ui.label and ui.cardSide. The one function on the `app` table moves to sys.setTickInterval, alongside the new sys.appName the bar needs.
119 lines
4.0 KiB
Lua
119 lines
4.0 KiB
Lua
-- Stand-in for the firmware bindings, so host tests exercise the real ui.lua.
|
|
--
|
|
-- One definition of the binding surface: when a binding is added or renamed, this is
|
|
-- the file that changes. Tests mutate the returned table to steer the device, and may
|
|
-- overwrite any stub function outright for a single assertion.
|
|
|
|
local device = {
|
|
-- Text metrics chosen to match the firmware's default GLCD font, since layout
|
|
-- assertions are written in real pixels.
|
|
fontHeight = 8,
|
|
charWidth = 6,
|
|
now = 0,
|
|
rotation = 0,
|
|
theme = "light",
|
|
clockSynced = false,
|
|
tickInterval = 0,
|
|
appName = "test",
|
|
textSize = 1,
|
|
fullscreen = false,
|
|
timezone = "UTC0",
|
|
raw = nil, -- pending raw touch reading, {x, y} or nil
|
|
networks = {}, -- what wifi.scan() returns
|
|
status = {state = "disconnected", ssid = "", ip = "", rssi = 0},
|
|
painted = {}, -- every drawText call, in order
|
|
calibration = nil, -- last sys.setCalibration()
|
|
connected = nil, -- last wifi.connect()
|
|
exited = false,
|
|
launched = nil,
|
|
saveFails = false, -- make every persisting call report failure
|
|
}
|
|
|
|
local function saved()
|
|
return not device.saveFails
|
|
end
|
|
|
|
function device.install()
|
|
device.painted = {}
|
|
|
|
gui = {
|
|
color = function(r, g, b) return r * 65536 + g * 256 + b end,
|
|
-- Rotation swaps the frame, exactly as TFT_eSPI reports it.
|
|
width = function() return device.rotation % 180 == 0 and 320 or 480 end,
|
|
height = function() return device.rotation % 180 == 0 and 480 or 320 end,
|
|
clear = function() end,
|
|
fillRect = function() end,
|
|
drawRect = function() end,
|
|
fillCircle = function() end,
|
|
drawLine = function() end,
|
|
roundRect = function() end,
|
|
drawText = function(label, x, y)
|
|
device.painted[#device.painted + 1] = {label = label, x = x, y = y}
|
|
end,
|
|
setTextSize = function(size) device.textSize = size end,
|
|
fontHeight = function() return device.fontHeight * device.textSize end,
|
|
textWidth = function(text) return #text * device.charWidth * device.textSize end,
|
|
setRotation = function() end,
|
|
fullscreen = function(on) device.fullscreen = on and true or false end,
|
|
}
|
|
|
|
sys = {
|
|
millis = function() return device.now end,
|
|
exit = function() device.exited = true end,
|
|
appName = function() return device.appName end,
|
|
setTickInterval = function(ms)
|
|
assert(ms == 0 or on_tick, "setTickInterval without on_tick")
|
|
device.tickInterval = ms
|
|
end,
|
|
launch = function(path) device.launched = path end,
|
|
getRotation = function() return device.rotation end,
|
|
setRotation = function(degrees)
|
|
if degrees % 90 ~= 0 or degrees < 0 or degrees > 270 then return false end
|
|
device.rotation = degrees
|
|
return saved()
|
|
end,
|
|
getTheme = function() return device.theme end,
|
|
setTheme = function(name) device.theme = name return saved() end,
|
|
setCalibration = function(...) device.calibration = {...} return saved() end,
|
|
clockSynced = function() return device.clockSynced end,
|
|
getTimezone = function() return device.timezone end,
|
|
setTimezone = function(tz) device.timezone = tz return saved() end,
|
|
}
|
|
|
|
input = {
|
|
touched = function() return device.raw ~= nil end,
|
|
getTouch = function()
|
|
if not device.raw then return nil end
|
|
return device.raw[1], device.raw[2]
|
|
end,
|
|
getRawTouch = function()
|
|
if not device.raw then return nil end
|
|
return device.raw[1], device.raw[2]
|
|
end,
|
|
}
|
|
|
|
fs = {
|
|
readFile = function() return nil end,
|
|
writeFile = function() return saved() end,
|
|
exists = function() return false end,
|
|
listFiles = function() return {} end,
|
|
listDirs = function() return {} end,
|
|
}
|
|
|
|
wifi = {
|
|
scan = function() return device.networks end,
|
|
status = function() return device.status end,
|
|
connect = function(ssid, password)
|
|
device.connected = {ssid, password}
|
|
return saved()
|
|
end,
|
|
forget = function() device.connected = nil return saved() end,
|
|
}
|
|
|
|
log = {debug = function() end, info = function() end, error = function() end}
|
|
|
|
return device
|
|
end
|
|
|
|
return device
|