feat(ui): let a widget opt out of the pressed style
A custom node that paints its own key highlight does not want the whole node marked dirty on every press.
This commit is contained in:
+8
-2
@@ -28,6 +28,7 @@ local ui = {}
|
||||
---@field on_exit? UiHandler
|
||||
---@field on_click? UiHandler
|
||||
---@field paint? fun(id: NodeId, x: integer, y: integer, w: integer, h: integer)
|
||||
---@field press_style? boolean False for a widget that paints its own press feedback.
|
||||
|
||||
---@class UiConfirmSpec
|
||||
---@field title string
|
||||
@@ -49,6 +50,9 @@ local THEMES = {
|
||||
}
|
||||
|
||||
local enterHandlers, exitHandlers, clickHandlers, painters = {}, {}, {}, {}
|
||||
-- A widget that paints its own press feedback opts out, so pressing one key does not
|
||||
-- repaint the whole node the way a pressed style would.
|
||||
local pressStyles = {}
|
||||
local laidOut = false
|
||||
local themeName
|
||||
local activeScreen
|
||||
@@ -119,6 +123,7 @@ loadTheme(savedTheme and savedTheme:match("^%s*(.-)%s*$") or "light")
|
||||
|
||||
local function clearState()
|
||||
enterHandlers, exitHandlers, clickHandlers, painters = {}, {}, {}, {}
|
||||
pressStyles = {}
|
||||
end
|
||||
|
||||
node.setPainter(function(id, x, y, w, h)
|
||||
@@ -164,6 +169,7 @@ local function build(spec, kind)
|
||||
exitHandlers[id] = spec.on_exit
|
||||
clickHandlers[id] = spec.on_click
|
||||
painters[id] = spec.paint
|
||||
pressStyles[id] = spec.press_style ~= false
|
||||
return id
|
||||
end
|
||||
|
||||
@@ -340,13 +346,13 @@ local function inside(id, x, y)
|
||||
end
|
||||
|
||||
local function enter(id, x, y)
|
||||
node.setPressed(id, true)
|
||||
if pressStyles[id] then node.setPressed(id, true) end
|
||||
local handler = enterHandlers[id]
|
||||
if handler then handler(id, x, y) end
|
||||
end
|
||||
|
||||
local function exit(id, x, y)
|
||||
node.setPressed(id, false)
|
||||
if pressStyles[id] then node.setPressed(id, false) end
|
||||
local handler = exitHandlers[id]
|
||||
if handler then handler(id, x, y) end
|
||||
end
|
||||
|
||||
@@ -194,4 +194,24 @@ assert(columns == 3 and side == 93, "width is the binding constraint in portrait
|
||||
-- Five cards are two rows, so a reserve that eats the height budget shrinks the card.
|
||||
assert(select(1, ui.cardSide(5, 12, 8, 300)) == 74, "height binds once the reserve is large")
|
||||
|
||||
-- A widget painting its own feedback is never given a pressed style, while an ordinary one
|
||||
-- still is. Which node was hit is geometry, so the test names the target directly.
|
||||
ui.reset()
|
||||
local pressedCalls = {}
|
||||
node.setPressed = function(_, on) pressedCalls[#pressedCalls + 1] = on end
|
||||
local own = ui.custom{h = 20, press_style = false, on_click = function() end}
|
||||
local styled = ui.button{h = 20, label = "ok", on_click = function() end}
|
||||
local board = ui.screen(ui.box{own, styled})
|
||||
local target
|
||||
node.hit = function() return target end
|
||||
|
||||
target = own
|
||||
board:down(0, 0)
|
||||
board:up(0, 0)
|
||||
assert(#pressedCalls == 0, "a self-painting widget is not styled on press")
|
||||
|
||||
target = styled
|
||||
board:down(0, 0)
|
||||
assert(pressedCalls[1] == true, "an ordinary widget still gets its pressed style")
|
||||
|
||||
print("ok")
|
||||
|
||||
Reference in New Issue
Block a user