From 6ba10b4de61f1bce61bb946a0d023cf4969fdefe Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 9 Jun 2022 15:49:16 -0700 Subject: fix a corner case when selecting text The hard part here is keeping click-drag selection working (without pressing and holding shift). --- main.lua | 30 +++++++++++++++++++++--------- text_tests.lua | 30 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/main.lua b/main.lua index b318fb8..24d6f00 100644 --- a/main.lua +++ b/main.lua @@ -55,6 +55,7 @@ Cursor1 = {line=1, pos=1} -- position of cursor Screen_bottom1 = {line=1, pos=1} -- position of start of screen line at bottom of screen Selection1 = {} +Old_cursor1, Old_selection1, Mousepress_shift = nil -- some extra state to compute selection between mousepress and mouserelease Recent_mouse = {} -- when selecting text, avoid recomputing some state on every single frame Cursor_x, Cursor_y = 0, 0 -- in pixels @@ -271,13 +272,19 @@ function App.mousepressed(x,y, mouse_button) for line_index,line in ipairs(Lines) do if line.mode == 'text' then if Text.in_line(line, x,y) then - if App.shift_down() then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} - end - Cursor1 = {line=line_index, pos=Text.to_pos_on_line(line, x, y)} - if not App.shift_down() then - Selection1 = {line=Cursor1.line, pos=Cursor1.pos} - end + -- delicate dance between cursor, selection and old cursor + -- manual tests: + -- regular press+release: sets cursor, clears selection + -- shift press+release: + -- sets selection to old cursor if not set otherwise leaves it untouched + -- sets cursor + -- press and hold to start a selection: sets selection on press, cursor on release + -- press and hold, then press shift: ignore shift + -- i.e. mousereleased should never look at shift state + Old_cursor1 = Cursor1 + Old_selection1 = Selection1 + Mousepress_shift = App.shift_down() + Selection1 = {line=line_index, pos=Text.to_pos_on_line(line, x, y)} end elseif line.mode == 'drawing' then if Drawing.in_drawing(line, x, y) then @@ -296,9 +303,14 @@ function App.mousereleased(x,y, button) if line.mode == 'text' then if Text.in_line(line, x,y) then Cursor1 = {line=line_index, pos=Text.to_pos_on_line(line, x, y)} - if Text.eq1(Cursor1, Selection1) and not App.shift_down() then - Selection1 = {} + if Mousepress_shift then + if Old_selection1.line == nil then + Selection1 = Old_cursor1 + else + Selection1 = Old_selection1 + end end + Old_cursor1, Old_selection1, Mousepress_shift = nil end end end diff --git a/text_tests.lua b/text_tests.lua index 85b301a..ab7ac10 100644 --- a/text_tests.lua +++ b/text_tests.lua @@ -224,6 +224,36 @@ function test_select_text_using_mouse_and_shift() check_eq(Cursor1.pos, 4, 'F - test_select_text_using_mouse_and_shift/cursor:pos') end +function test_select_text_repeatedly_using_mouse_and_shift() + io.write('\ntest_select_text_repeatedly_using_mouse_and_shift') + App.screen.init{width=50, height=60} + Lines = load_array{'abc', 'def', 'xyz'} + Line_width = App.screen.width + Cursor1 = {line=1, pos=1} + Screen_top1 = {line=1, pos=1} + Screen_bottom1 = {} + Selection1 = {} + App.draw() -- populate line.y for each line in Lines + local screen_left_margin = 25 -- pixels + -- click on first location + App.run_after_mousepress(screen_left_margin+8,Margin_top+5, '1') + App.run_after_mouserelease(screen_left_margin+8,Margin_top+5, '1') + -- hold down shift and click on a second location + App.keypress('lshift') + App.run_after_mousepress(screen_left_margin+20,Margin_top+5, '1') + App.run_after_mouserelease(screen_left_margin+20,Margin_top+Line_height+5, '1') + -- hold down shift and click at a third location + App.keypress('lshift') + App.run_after_mousepress(screen_left_margin+20,Margin_top+5, '1') + App.run_after_mouserelease(screen_left_margin+8,Margin_top+Line_height+5, '1') + App.keyrelease('lshift') + -- selection is between first and third location. forget the second location, not the first. + check_eq(Selection1.line, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:line') + check_eq(Selection1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos') + check_eq(Cursor1.line, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:line') + check_eq(Cursor1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos') +end + function test_pagedown() io.write('\ntest_pagedown') App.screen.init{width=120, height=45} -- cgit 1.4.1-2-gfad0