bugfix: clear selection when clicking above or below lines
Matt Wynne pointed out that snap.love would crash when a node went off
screen. While debugging it I noticed that selection1 was being set when
it shouldn't be.
Turns out I introduced a bug when I fixed the inscript bug back in June
(commit 9656e13774
). One invariant I want to preserve is: selection1
should be unset after a mouse click (press and release without
intervening drag). This invariant was violated in my bugfix back in
June. I was concerned only with selection back then, and I didn't
realize I was breaking the mouse click case (in a fairly subtle way; you
can have selection set, and when it's set identically to the cursor
everything looks the same).
I think there might still be an issue in snap.love after this fix. I
noticed screen_bottom1.pos was nil, and as far as I recall that should
never happen.
This commit is contained in:
parent
c43d884b6f
commit
bd6f7d48e7
28
edit.lua
28
edit.lua
|
@ -291,7 +291,7 @@ function edit.mouse_press(State, x,y, mouse_button)
|
|||
end
|
||||
end
|
||||
|
||||
-- still here? click is below all screen lines
|
||||
-- still here? mouse press is below all screen lines
|
||||
State.old_cursor1 = State.cursor1
|
||||
State.old_selection1 = State.selection1
|
||||
State.mousepress_shift = App.shift_down()
|
||||
|
@ -313,6 +313,12 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
end
|
||||
else
|
||||
--? print_and_log('edit.mouse_release: no current drawing')
|
||||
if y < State.top then
|
||||
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
|
||||
edit.clean_up_mouse_press(State)
|
||||
return
|
||||
end
|
||||
|
||||
for line_index,line in ipairs(State.lines) do
|
||||
if line.mode == 'text' then
|
||||
if Text.in_line(State, line_index, x,y) then
|
||||
|
@ -322,6 +328,20 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
pos=Text.to_pos_on_line(State, line_index, x, y),
|
||||
}
|
||||
--? print_and_log(('edit.mouse_release: cursor now %d,%d'):format(State.cursor1.line, State.cursor1.pos))
|
||||
edit.clean_up_mouse_press(State)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- still here? mouse release is below all screen lines
|
||||
State.cursor1.line, State.cursor1.pos = State.screen_bottom1.line, Text.pos_at_end_of_screen_line(State, State.screen_bottom1)
|
||||
edit.clean_up_mouse_press(State)
|
||||
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
|
||||
end
|
||||
end
|
||||
|
||||
function edit.clean_up_mouse_press(State)
|
||||
if State.mousepress_shift then
|
||||
if State.old_selection1.line == nil then
|
||||
State.selection1 = State.old_cursor1
|
||||
|
@ -333,12 +353,6 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
if eq(State.cursor1, State.selection1) then
|
||||
State.selection1 = {}
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
|
||||
end
|
||||
end
|
||||
|
||||
function edit.mouse_wheel_move(State, dx,dy)
|
||||
|
|
|
@ -295,7 +295,7 @@ function edit.mouse_press(State, x,y, mouse_button)
|
|||
end
|
||||
end
|
||||
|
||||
-- still here? click is below all screen lines
|
||||
-- still here? mouse press is below all screen lines
|
||||
State.old_cursor1 = State.cursor1
|
||||
State.old_selection1 = State.selection1
|
||||
State.mousepress_shift = App.shift_down()
|
||||
|
@ -317,6 +317,12 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
end
|
||||
else
|
||||
--? print_and_log('edit.mouse_release: no current drawing')
|
||||
if y < State.top then
|
||||
State.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}
|
||||
edit.clean_up_mouse_press(State)
|
||||
return
|
||||
end
|
||||
|
||||
for line_index,line in ipairs(State.lines) do
|
||||
if line.mode == 'text' then
|
||||
if Text.in_line(State, line_index, x,y) then
|
||||
|
@ -326,6 +332,20 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
pos=Text.to_pos_on_line(State, line_index, x, y),
|
||||
}
|
||||
--? print_and_log(('edit.mouse_release: cursor now %d,%d'):format(State.cursor1.line, State.cursor1.pos))
|
||||
edit.clean_up_mouse_press(State)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- still here? mouse release is below all screen lines
|
||||
State.cursor1.line, State.cursor1.pos = State.screen_bottom1.line, Text.pos_at_end_of_screen_line(State, State.screen_bottom1)
|
||||
edit.clean_up_mouse_press(State)
|
||||
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
|
||||
end
|
||||
end
|
||||
|
||||
function edit.clean_up_mouse_press(State)
|
||||
if State.mousepress_shift then
|
||||
if State.old_selection1.line == nil then
|
||||
State.selection1 = State.old_cursor1
|
||||
|
@ -337,12 +357,6 @@ function edit.mouse_release(State, x,y, mouse_button)
|
|||
if eq(State.cursor1, State.selection1) then
|
||||
State.selection1 = {}
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
--? print_and_log(('edit.mouse_release: finally selection %s,%s cursor %d,%d'):format(tostring(State.selection1.line), tostring(State.selection1.pos), State.cursor1.line, State.cursor1.pos))
|
||||
end
|
||||
end
|
||||
|
||||
function edit.mouse_wheel_move(State, dx,dy)
|
||||
|
|
|
@ -275,6 +275,7 @@ function test_click_to_left_of_line()
|
|||
Editor_state.cursor1 = {line=1, pos=3}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click to the left of the line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left-4,Editor_state.top+5, 1)
|
||||
|
@ -294,6 +295,7 @@ function test_click_takes_margins_into_account()
|
|||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click on the other line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
|
@ -312,11 +314,33 @@ function test_click_on_empty_line()
|
|||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click on the empty line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
-- cursor moves
|
||||
check_eq(Editor_state.cursor1.line, 1, 'cursor')
|
||||
-- selection remains empty
|
||||
check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
|
||||
end
|
||||
|
||||
function test_click_below_all_lines()
|
||||
-- display one line
|
||||
App.screen.init{width=50, height=80}
|
||||
Editor_state = edit.initialize_test_state()
|
||||
Editor_state.lines = load_array{'abc'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click below first line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+50, 1)
|
||||
-- cursor doesn't move
|
||||
check_eq(Editor_state.cursor1.line, 1, 'cursor')
|
||||
-- selection remains empty
|
||||
check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
|
||||
end
|
||||
|
||||
function test_draw_text()
|
||||
|
|
|
@ -23,6 +23,7 @@ click on wrapping line rendered from partway at top of screen
|
|||
click past end of wrapping line
|
||||
click past end of wrapping line containing non ascii
|
||||
click past end of word wrapping line
|
||||
click below final line does nothing
|
||||
|
||||
# cursor movement
|
||||
move left
|
||||
|
|
|
@ -275,6 +275,7 @@ function test_click_to_left_of_line()
|
|||
Editor_state.cursor1 = {line=1, pos=3}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click to the left of the line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left-4,Editor_state.top+5, 1)
|
||||
|
@ -294,6 +295,7 @@ function test_click_takes_margins_into_account()
|
|||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click on the other line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
|
@ -312,11 +314,33 @@ function test_click_on_empty_line()
|
|||
Editor_state.cursor1 = {line=2, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click on the empty line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+5, 1)
|
||||
-- cursor moves
|
||||
check_eq(Editor_state.cursor1.line, 1, 'cursor')
|
||||
-- selection remains empty
|
||||
check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
|
||||
end
|
||||
|
||||
function test_click_below_all_lines()
|
||||
-- display one line
|
||||
App.screen.init{width=50, height=80}
|
||||
Editor_state = edit.initialize_test_state()
|
||||
Editor_state.lines = load_array{'abc'}
|
||||
Text.redraw_all(Editor_state)
|
||||
Editor_state.cursor1 = {line=1, pos=1}
|
||||
Editor_state.screen_top1 = {line=1, pos=1}
|
||||
Editor_state.screen_bottom1 = {}
|
||||
Editor_state.selection1 = {}
|
||||
-- click below first line
|
||||
edit.draw(Editor_state)
|
||||
edit.run_after_mouse_click(Editor_state, Editor_state.left+8,Editor_state.top+50, 1)
|
||||
-- cursor doesn't move
|
||||
check_eq(Editor_state.cursor1.line, 1, 'cursor')
|
||||
-- selection remains empty
|
||||
check_nil(Editor_state.selection1.line, 'selection is empty to avoid perturbing future edits')
|
||||
end
|
||||
|
||||
function test_draw_text()
|
||||
|
|
Loading…
Reference in New Issue