97abf037b8
Follows the submodule: on_touch_down and friends become onTouchDown, the last snake_case left in the surface now that handlers are table fields rather than globals. main.lua declares SlateApp, this card's contract with its apps, and every app composes what it fills -- PaintApp is SlateApp plus TouchHandlers, Home is SlateApp alone -- which is also the only static record of the features an app needs.
74 lines
1.8 KiB
Lua
74 lines
1.8 KiB
Lua
local ui = require "ui"
|
|
|
|
-- One node for the whole canvas: every pixel is content, so the app takes the touch
|
|
-- callbacks raw rather than asking the tree what was hit. It wants the firmware's noise
|
|
-- threshold and no gesture slop -- a three pixel stroke is a stroke, not a mis-tap.
|
|
local BRUSH = 2
|
|
|
|
---@class PaintApp : SlateApp, TouchHandlers
|
|
local M = {}
|
|
local canvas, area
|
|
local lastX, lastY
|
|
|
|
local function inside(x, y)
|
|
return area and x >= area.x and x < area.x + area.w and y >= area.y and y < area.y + area.h
|
|
end
|
|
|
|
function M.init()
|
|
log.info "paint ready"
|
|
end
|
|
|
|
function M.node()
|
|
-- The painter runs on every repaint, and a repaint is what clearing means here: the
|
|
-- tree fills the box with the background before calling it, so this only has to
|
|
-- remember where the box landed.
|
|
canvas = ui.custom {
|
|
w = "fill",
|
|
h = "fill",
|
|
paint = function(_, x, y, w, h)
|
|
area = { x = x, y = y, w = w, h = h }
|
|
end,
|
|
}
|
|
return ui.box {
|
|
w = "fill",
|
|
h = "fill",
|
|
ui.box {
|
|
row = true,
|
|
pad = 8,
|
|
ui.button {
|
|
label = "clear",
|
|
on_click = function()
|
|
lastX = nil
|
|
ui.invalidate(canvas)
|
|
end,
|
|
},
|
|
},
|
|
canvas,
|
|
}
|
|
end
|
|
|
|
function M.onTouchDown(x, y)
|
|
if not inside(x, y) then
|
|
return
|
|
end
|
|
lastX, lastY = x, y
|
|
screen.fillCircle(x, y, BRUSH, ui.theme.accent)
|
|
end
|
|
|
|
-- Strokes are joined with a line because the poll rate, not the finger, decides the gap:
|
|
-- a fast swipe reports points tens of pixels apart and dots alone would look dotted.
|
|
function M.onTouchMove(x, y)
|
|
if not lastX or not inside(x, y) then
|
|
return
|
|
end
|
|
screen.drawLine(lastX, lastY, x, y, ui.theme.accent)
|
|
screen.fillCircle(x, y, BRUSH, ui.theme.accent)
|
|
lastX, lastY = x, y
|
|
end
|
|
|
|
function M.onTouchUp()
|
|
lastX = nil
|
|
end
|
|
|
|
return M
|