Files
slate32/stubs/slate32.lua
evan f7c5cc09ba feat(ui)!: move the widget tree into C++
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.
2026-08-02 18:48:48 -04:00

455 lines
14 KiB
Lua

---@meta
-- Generated by scripts/gen_lua_stubs.py. Do not edit.
-- Point your editor's Lua language server at this file to get completion for the
-- firmware API inside sdcard/apps and sdcard/lib.
---@class fslib
fs = {}
--- Reads a whole file from the SD card.
---@param path string Absolute path.
---@return string? Contents truncated to 65536 bytes, or nil when missing.
function fs.readFile(path) end
--- Writes a whole file to the SD card, replacing it if it exists.
---@param path string Absolute path.
---@param content string
---@return boolean
function fs.writeFile(path, content) end
--- Whether a path exists.
---@param path string Absolute path.
---@return boolean
function fs.exists(path) end
--- Names of the files in a directory, excluding dotfiles.
---@param path string Absolute path.
---@return string[]
function fs.listFiles(path) end
--- Names of the subdirectories in a directory, excluding dotfiles.
---@param path string Absolute path.
---@return string[]
function fs.listDirs(path) end
---@class guilib
gui = {}
--- Panel width in pixels, for the current rotation.
---@return integer
function gui.getWidth() end
--- Hands the app the whole panel, hiding the status bar, until it is turned off.
---@param on boolean
function gui.setFullscreen(on) end
--- Panel height in pixels, for the current rotation.
---@return integer
function gui.getHeight() end
--- Fills the whole panel with one color.
---@param color integer? Defaults to white.
function gui.clear(color) end
--- Fills a rectangle.
---@param x integer
---@param y integer
---@param w integer
---@param h integer
---@param color integer
function gui.fillRect(x, y, w, h, color) end
--- Strokes a one pixel rectangle outline.
---@param x integer
---@param y integer
---@param w integer
---@param h integer
---@param color integer
function gui.drawRect(x, y, w, h, color) end
--- Fills an anti-aliased circle, blending its rim against the surface behind it.
---@param x integer Center.
---@param y integer Center.
---@param radius integer
---@param color integer
---@param bg integer? Surface color to blend against, defaults to white.
function gui.fillCircle(x, y, radius, color, bg) end
--- Strokes a line.
---@param x1 integer
---@param y1 integer
---@param x2 integer
---@param y2 integer
---@param color integer
function gui.drawLine(x1, y1, x2, y2, color) end
--- Draws text with an opaque background behind its glyphs.
---@param text string
---@param x integer
---@param y integer
---@param color integer? Defaults to black.
---@param bg integer? Omitted draws transparent glyphs, over whatever is behind them.
function gui.drawText(text, x, y, color, bg) end
--- Draws a rounded rectangle: fill, vertical gradient and border from one
--- distance field, so the edges cannot disagree.
---@param x integer
---@param y integer
---@param w integer
---@param h integer
---@param radius integer Clamped to half the shorter side.
---@param bg integer Surface color the anti-aliased edge blends against.
---@param top integer? Fill color, or the top of the gradient.
---@param bottom integer? Bottom of the gradient, defaults to top.
---@param border integer? Border color; omitted draws no border.
function gui.roundRect(x, y, w, h, radius, bg, top, bottom, border) end
--- Scales the built-in font by a whole number, for this app only.
---@param size integer 1 to 8.
function gui.setTextSize(size) end
--- Height of the current font in pixels, at the current text size.
---@return integer
function gui.getFontHeight() end
--- Width the given text would occupy in pixels.
---@param text string
---@return integer
function gui.getTextWidth(text) end
--- Rotates the frame for this draw only; settings.setRotation persists it.
---@param degrees integer 0, 90, 180 or 270.
function gui.setRotation(degrees) end
--- Rotation of the frame being drawn, which is not always the saved preference.
---@return integer Degrees clockwise.
function gui.getRotation() end
--- Packs 8 bit channels into the panel's RGB565 color format.
---@param r integer
---@param g integer
---@param b integer
---@return integer
function gui.color(r, g, b) end
---@class httplib
http = {}
--- Fetches a URL. Certificates are verified against the embedded root bundle.
---@param url string
---@param headers table? Header name to value.
---@return string? Response body, or nil when the status is not 2xx or the body exceeds 50000 bytes.
---@return integer HTTP status, or -1 when the request could not be sent.
function http.get(url, headers) end
--- Fetches a URL, discarding the body.
---@param url string
---@param headers table? Header name to value.
---@return string? Response body, always empty on success.
---@return integer HTTP status, or -1 when the request could not be sent.
function http.head(url, headers) end
--- Deletes a resource.
---@param url string
---@param headers table? Header name to value.
---@return string? Response body.
---@return integer HTTP status, or -1 when the request could not be sent.
function http.delete(url, headers) end
--- Posts a body to a URL.
---@param url string
---@param body string? Request body, empty when omitted.
---@param headers table? Header name to value.
---@return string? Response body.
---@return integer HTTP status, or -1 when the request could not be sent.
function http.post(url, body, headers) end
--- Patches a resource.
---@param url string
---@param body string? Request body, empty when omitted.
---@param headers table? Header name to value.
---@return string? Response body.
---@return integer HTTP status, or -1 when the request could not be sent.
function http.patch(url, body, headers) end
--- Streams an HTTPS URL to a file, checking size and digest before keeping it.
---@param url string Must be https.
---@param destination string Absolute path that must not already exist.
---@param options table maxBytes is required; expectedSize and sha256 are optional.
---@return integer? Bytes written, or nil on failure.
---@return string? Error message when the download failed.
function http.download(url, destination, options) end
--- Percent-encodes a string, keeping the RFC 3986 unreserved characters.
---@param input string
---@return string
function http.urlencode(input) end
---@class inputlib
input = {}
--- Current touch point, calibrated and rotated.
---@return integer? X, or nil when the panel is not touched.
---@return integer? Y.
function input.getTouch() end
--- Current touch point as raw ADC readings, for calibration.
---@return integer? X, or nil when the panel is not touched.
---@return integer? Y.
function input.getRawTouch() end
--- Whether the panel is being touched.
---@return boolean
function input.isTouched() end
---@class loglib
log = {}
--- Writes a debug line to the serial log.
---@param message string
function log.debug(message) end
--- Writes an info line to the serial log.
---@param message string
function log.info(message) end
--- Writes an error line to the serial log.
---@param message string
function log.error(message) end
---@class nodelib
node = {}
--- Drops the whole tree. Every screen is built from scratch, so this is what a
--- rebuild starts with; existing ids are invalid afterwards.
function node.reset() end
--- Adds a node and returns its handle.
---@param parent integer? Nil creates a root.
---@param spec table Fields: type ("box", "text", "button", "custom"), w, h, pad,
---@param spec table gap, align, justify, row, at, capture, interactive, label, size.
---@return integer
function node.create(parent, spec, spec) end
--- Adopts an existing root node as a child, so a container can be built after
--- the things it holds. The child must not already have a parent.
---@param parent integer
---@param child integer
function node.attach(parent, child) end
--- Fills in sizes a node left as "auto". Only meaningful before layout.
---@param id integer
---@param w number|string?
---@param h number|string?
function node.setSize(id, w, h) end
--- Measures and places a tree into the given rectangle.
---@param root integer
---@param x integer
---@param y integer
---@param w integer
---@param h integer
---@return boolean True on success; false plus a message when a size cannot resolve.
function node.layout(root, x, y, w, h) end
--- Frees the layout inputs, which nothing reads once a tree is placed. A screen
--- calls this after layout and rebuilds from Lua if it ever needs placing again.
function node.dropScratch() end
--- Deepest interactive node covering the point, or nil.
---@param root integer
---@param x integer
---@param y integer
---@return integer?
function node.hit(root, x, y) end
--- Placed rectangle of a node.
---@param id integer
---@return integer x
---@return integer y
---@return integer w
---@return integer h
function node.getRect(id) end
--- Replaces a node's text. Re-measuring is the caller's business: the node keeps
--- the box it was placed with until the screen is rebuilt.
---@param id integer
---@param text string
function node.setLabel(id, text) end
--- A node's text, or nil if it has none.
---@param id integer
---@return string?
function node.getLabel(id) end
--- The node that contains this one, or nil at the root.
---@param id integer
---@return integer?
function node.getParent(id) end
--- Sets the colors and metrics a node states for itself. Anything left out is
--- answered by the nearest ancestor that states it, so a node that names nothing
--- costs nothing.
---@param id integer
---@param style table Fields: color, bg, fill, border, press_color, radius, size,
---@param style table and the {top, bottom} pairs face and face_pressed.
function node.setStyle(id, style, style) end
--- Marks a node for repainting on the next draw, along with its children.
---@param id integer
function node.invalidate(id) end
--- Shows or clears a node's pressed face.
---@param id integer
---@param on boolean
function node.setPressed(id, on) end
--- Whether a node is currently showing its pressed face.
---@param id integer
---@return boolean
function node.isPressed(id) end
--- Installs the function that paints "custom" nodes, called with the node id and
--- its placed rectangle. One painter serves the whole tree.
---@param painter function
function node.setPainter(painter) end
--- Repaints every node marked dirty, and everything inside one.
---@param root integer
function node.draw(root) end
--- How many nodes the current tree holds.
---@return integer
function node.getCount() end
--- Bytes the current tree occupies, for the memory the design exists to save.
---@return integer
function node.getFootprint() end
---@class settingslib
settings = {}
--- Saved screen rotation in degrees clockwise.
---@return integer
function settings.getRotation() end
--- Rotates the screen and saves it.
---@param degrees integer 0, 90, 180 or 270.
---@return boolean Whether the setting was saved.
function settings.setRotation(degrees) end
--- Name of the active theme in /lib/theme.lua.
---@return string
function settings.getTheme() end
--- Saves the theme name. Apps call ui.setTheme(), which also reloads the palette.
---@param name string
---@return boolean Whether the setting was saved.
function settings.setTheme(name) end
--- Active POSIX timezone rule.
---@return string
function settings.getTimezone() end
--- Sets the timezone from a POSIX TZ rule and saves it.
---@param tz string For example EST5EDT,M3.2.0,M11.1.0.
---@return boolean Whether the setting was saved.
function settings.setTimezone(tz) end
--- Stores touch calibration, in the panel's unrotated frame.
---@param x0 integer Raw reading at the left edge.
---@param y0 integer Raw reading at the top edge.
---@param x1 integer Raw reading at the right edge.
---@param y1 integer Raw reading at the bottom edge.
---@return boolean Whether the setting was saved.
function settings.setCalibration(x0, y0, x1, y1) end
---@class syslib
sys = {}
--- Milliseconds since boot.
---@return integer
function sys.getMillis() end
--- Blocks for the given time.
---@param ms integer
function sys.delay(ms) end
--- Returns to the previous app, or Home when there is no history.
function sys.back() end
--- Name of the running app, its directory name until sys.setAppName() changes it.
---@return string
function sys.getAppName() end
--- Sets how often on_tick() runs. Errors when on_tick is not defined.
---@param intervalMs integer 0 stops ticking; anything else is clamped to 33..3600000.
function sys.setTickInterval(intervalMs) end
--- Ends this app and starts another one.
---@param path string Absolute path to the app's main.lua.
---@param arg string? Passed to the new app's init(); at most 256 bytes.
function sys.launch(path, arg) end
--- Starts another app without adding this route to history.
---@param path string Absolute path to the app's main.lua.
---@param arg string? Passed to the new app's init(); at most 256 bytes.
function sys.replace(path, arg) end
--- Renames the running app in the status bar.
---@param name string 1 to 32 bytes.
function sys.setAppName(name) end
--- Free and total heap, in bytes.
---@return integer Free bytes.
---@return integer Total bytes.
---@return integer Largest contiguous free block.
function sys.getMemory() end
--- Whether SNTP has answered. Until it has, os.time() is only a build-time floor.
---@return boolean
function sys.isClockSynced() end
---@class wifilib
wifi = {}
--- Scans for networks, blocking until the sweep finishes.
---@return table[] Each entry has ssid, rssi and secure.
function wifi.scan() end
--- Saves credentials and starts connecting. Poll status() for the outcome.
---@param ssid string
---@param password string? Omitted for an open network.
---@return boolean Whether the credentials were saved and the attempt started.
function wifi.connect(ssid, password) end
--- Current connection state.
--- connecting, connected, not_found or failed.
---@return table Fields state, ssid, ip and rssi. state is one of disconnected,
function wifi.getStatus() end
--- Whether the station is associated.
---@return boolean
function wifi.isConnected() end
--- Current IPv4 address.
---@return string The address, or 0.0.0.0 when not connected.
function wifi.getLocalIP() end
--- Drops the connection but keeps the saved credentials.
function wifi.disconnect() end
--- Drops the connection and erases the saved credentials.
---@return boolean Whether the settings were saved.
function wifi.forget() end
-- Callbacks an app may define as globals:
-- init() once, before the first draw (required)
-- draw() every 33 ms while the app runs
-- on_tick() at the interval app.setTickInterval() asked for
-- on_touch_down(x, y) finger down
-- on_touch_move(x, y) finger moved while down
-- on_touch_up(x, y) finger up
-- on_touch(x, y) tap, fired on release like a click