stop putting button state in a global

Symptom: a test (test_click_to_create_drawing) started randomly failing
after I inserted a `return` 2 commits ago.

Cause: my tests call edit.draw, but button handlers only get cleared in
app.draw. So my tests weren't clearing button handlers, and every call
to edit.draw was accumulating states. Still unclear why those were going
to different state objects after the `return`, but anyway. I'm not going
to understand every last thing that happens when things go wrong, just
guarantee they can't go wrong. And the way to do that is to decentralize
button handlers to each state that receives them.

The State object in buttons.lua doesn't have to be Editor_state. It just
has to be some table that provides a Schelling Point for shared state.
This commit is contained in:
Kartik K. Agaram 2022-08-23 10:59:58 -07:00
parent ce79623231
commit 8057f3e8fe
3 changed files with 13 additions and 9 deletions

View File

@ -3,19 +3,23 @@
-- If the handler returns true, it'll prevent any further processing of the -- If the handler returns true, it'll prevent any further processing of the
-- event. -- event.
Button_handlers = {}
-- draw button and queue up event handlers -- draw button and queue up event handlers
function button(name, params) function button(State, name, params)
if State.button_handlers == nil then
State.button_handlers = {}
end
love.graphics.setColor(params.color[1], params.color[2], params.color[3]) love.graphics.setColor(params.color[1], params.color[2], params.color[3])
love.graphics.rectangle('fill', params.x,params.y, params.w,params.h, 5,5) love.graphics.rectangle('fill', params.x,params.y, params.w,params.h, 5,5)
if params.icon then params.icon(params.x, params.y) end if params.icon then params.icon(params.x, params.y) end
table.insert(Button_handlers, params) table.insert(State.button_handlers, params)
end end
-- process button event handlers -- process button event handlers
function propagate_to_button_handlers(x, y, mouse_button) function propagate_to_button_handlers(State, x, y, mouse_button)
for _,ev in ipairs(Button_handlers) do if State.button_handlers == nil then
return
end
for _,ev in ipairs(State.button_handlers) do
if x>ev.x and x<ev.x+ev.w and y>ev.y and y<ev.y+ev.h then if x>ev.x and x<ev.x+ev.w and y>ev.y and y<ev.y+ev.h then
if ev.onpress1 and mouse_button == 1 then if ev.onpress1 and mouse_button == 1 then
return ev.onpress1() return ev.onpress1()

View File

@ -128,6 +128,7 @@ function edit.fixup_cursor(State)
end end
function edit.draw(State) function edit.draw(State)
State.button_handlers = {}
App.color(Text_color) App.color(Text_color)
assert(#State.lines == #State.line_cache) assert(#State.lines == #State.line_cache)
if not Text.le1(State.screen_top1, State.cursor1) then if not Text.le1(State.screen_top1, State.cursor1) then
@ -151,7 +152,7 @@ function edit.draw(State)
end end
if line.data == '' then if line.data == '' then
-- button to insert new drawing -- button to insert new drawing
button('draw', {x=4,y=y+4, w=12,h=12, color={1,1,0}, button(State, 'draw', {x=4,y=y+4, w=12,h=12, color={1,1,0},
icon = icon.insert_drawing, icon = icon.insert_drawing,
onpress1 = function() onpress1 = function()
Drawing.before = snapshot(State, line_index-1, line_index) Drawing.before = snapshot(State, line_index-1, line_index)
@ -208,7 +209,7 @@ end
function edit.mouse_pressed(State, x,y, mouse_button) function edit.mouse_pressed(State, x,y, mouse_button)
if State.search_term then return end if State.search_term then return end
--? print('press', State.selection1.line, State.selection1.pos) --? print('press', State.selection1.line, State.selection1.pos)
if propagate_to_button_handlers(x,y, mouse_button) then if propagate_to_button_handlers(State, x,y, mouse_button) then
-- press on a button and it returned 'true' to short-circuit -- press on a button and it returned 'true' to short-circuit
return return
end end

View File

@ -133,7 +133,6 @@ function App.filedropped(file)
end end
function App.draw() function App.draw()
Button_handlers = {}
edit.draw(Editor_state) edit.draw(Editor_state)
end end