From 1031f474965b5cce4cb195b274a566b9ba7abc86 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 15:48:45 -0700 Subject: [PATCH 1/8] snapshot: a whole new approach to panning Basic idea: If the goal is for the cursor to be on the viewport, focus the code on ensuring that constraint by construction. Motivation: The downstream driver.love fork still has persistent bugs. And I'm seeing some inconclusive signs that edit.lua might be failing to change screen_top some of the time when it needs to. But this only happens in driver.love, never in lines.love. So the null hypothesis is that there's some subtle assumption in lines.love that we're violating when rendering it on a surface. What do you do with such subtleties? It might actually be counterproductive to fix them at source. You end up with complexity upstream that won't actually matter there if it breaks. Which is a recipe for it to break silently and far away from the downstream fork that might actually care about it. Or it might confuse people in future who don't care about the downstream forks, just lines.love. Maybe it makes sense to modify edit.lua here and take the hit on all possible future merge conflicts. But considering the cost of tracking this down, it seems simplest to: a) come up with the constraint I care about, and b) modify outside edit.lua, either what it sees or its results, to preserve the new constraint. Long ago I used to have this assertion in pensieve.love that the cursor must be within the viewport, but I ended up taking it out because it kept breaking for me when I was trying to do real work. It seems clear that there are possible assertions that are useful and yet counterproductive. If you can't keep it out of the product in the course of testing, then it annoys users where ignoring it would be a more graceful experience. Even when the user is just yourself! So it turns out this is not a problem only for large teams of extrinsically motivated people who don't eat their own dog food. No, for some things you have to fix the problem by construction, not just verify it with an assertion. This plan isn't fully working yet in this commit. I've only fixed cases for down-arrow. I need to address up arrow, and there might also be changes for left/right arrows. Hmm, I'm going to try to follow the implementation of bring_cursor_of_cursor_node_in_view() in pensieve.love. In the process of doing this I also noticed a bug with page-up/down. It already existed, but this approach has made it more obvious. --- 0019-B | 4 ++-- 0021-compute_layout | 8 ++++---- 0023-on.keychord_press | 23 +++------------------ 0028-A | 8 ++++---- 0030-update_editor_box | 23 +++++---------------- 0035-pan_viewport_to_contain_cursor | 31 +++++++++++++++++++++++++++++ 6 files changed, 49 insertions(+), 48 deletions(-) create mode 100644 0035-pan_viewport_to_contain_cursor diff --git a/0019-B b/0019-B index 43c72b6..7e7d0c7 100644 --- a/0019-B +++ b/0019-B @@ -1,4 +1,4 @@ -B = function(skip_updating_screen_top_for) +B = function() -- recompute various aspects based on the current viewport settings for _,obj in ipairs(Surface) do if obj.type == 'line' then @@ -16,7 +16,7 @@ B = function(skip_updating_screen_top_for) obj.zdata = love.math.newBezierCurve(zdata):render() elseif obj.type == 'text' then if obj.w then - update_editor_box(obj, skip_updating_screen_top_for) + update_editor_box(obj) else obj.text = love.graphics.newText(love.graphics.getFont(), obj.data) end diff --git a/0021-compute_layout b/0021-compute_layout index 4d025f3..eb74338 100644 --- a/0021-compute_layout +++ b/0021-compute_layout @@ -1,4 +1,4 @@ -compute_layout = function(node, x,y, nodes_to_render, skip_updating_screen_top_for) +compute_layout = function(node, x,y, nodes_to_render) -- append to nodes_to_render flattened instructions to render a hierarchy of nodes -- return x,y rendered until (surface coordinates) if node.type == 'text' then @@ -31,7 +31,7 @@ compute_layout = function(node, x,y, nodes_to_render, skip_updating_screen_top_f if node.editor == nil then initialize_editor(node) else - update_editor_box(node, skip_updating_screen_top_for) + update_editor_box(node) end node.h = box_height(node) table.insert(nodes_to_render, node) @@ -59,7 +59,7 @@ compute_layout = function(node, x,y, nodes_to_render, skip_updating_screen_top_f if not child.width then child.width = node.width -- HACK: should we set child.w or child.width? Neither is quite satisfactory. end - subx,suby = compute_layout(child, x,suby, nodes_to_render, skip_updating_screen_top_for) + subx,suby = compute_layout(child, x,suby, nodes_to_render) if w < child.w then w = child.w end @@ -87,7 +87,7 @@ compute_layout = function(node, x,y, nodes_to_render, skip_updating_screen_top_f subx = subx+child.margin w = w+child.margin end - subx,suby = compute_layout(child, subx,y, nodes_to_render, skip_updating_screen_top_for) + subx,suby = compute_layout(child, subx,y, nodes_to_render) w = w + child.w if h < child.h then h = child.h diff --git a/0023-on.keychord_press b/0023-on.keychord_press index f81a332..ba8c5a7 100644 --- a/0023-on.keychord_press +++ b/0023-on.keychord_press @@ -17,27 +17,10 @@ on.keychord_press = function(chord, key) elseif chord == 'C-z' then dump_state() elseif Cursor_node and Cursor_node.editor.cursor_x then - local old_top = {line=Cursor_node.editor.screen_top1.line, pos=Cursor_node.editor.screen_top1.pos} + print('cursor before', Cursor_node.editor.cursor1.line, Cursor_node.editor.cursor1.pos) edit.keychord_press(Cursor_node.editor, chord, key) ---? print('edit', old_top.line, '=>', Cursor_node.editor.screen_top1.line) - if not eq(Cursor_node.editor.screen_top1, old_top) then ---? print('modifying Viewport', Viewport.y, 'based on', Cursor_node.y, Cursor_node.editor.screen_top1.line, Cursor_node.editor.line_height) - Viewport.y = Cursor_node.y + y_of_schema1(Cursor_node.editor, Cursor_node.editor.screen_top1)/Viewport.zoom ---? print('modified Viewport', Viewport.y) - -- Most of the time, we update the screen_top of nodes from Viewport.y. - -- But here we went the other way. - -- It's very important to avoid creating a recurrence, to avoid running - -- both sides of this feedback loop in a single frame. These apps are - -- not very numerically precise (e.g. we force text lines to start at - -- integer pixels regardless of zoom, because that keeps text crisp), - -- and the computations of Viewport.y and node.top will almost certainly - -- not converge. The resulting bugs are extremely difficult to chase - -- down. - -- The optional skip_updating_screen_top_for arg ensures we don't run - -- the other side of the feedback loop. - A(--[[skip updating screen_top for]] Cursor_node) - return - end + print('cursor after', Cursor_node.editor.cursor1.line, Cursor_node.editor.cursor1.pos) + pan_viewport_to_contain_cursor(Cursor_node) A() else if chord == 'up' then diff --git a/0028-A b/0028-A index eee11f4..120d1c4 100644 --- a/0028-A +++ b/0028-A @@ -1,4 +1,4 @@ -A = function(skip_updating_screen_top_for) +A = function() love.graphics.setFont(love.graphics.newFont(scale(20))) -- editor objects implicitly depend on current font -- translate Page and Page2 to Surface Surface = {} @@ -9,9 +9,9 @@ A = function(skip_updating_screen_top_for) red = not red end end - compute_layout(Page, Page.x,Page.y, Surface, skip_updating_screen_top_for) - compute_layout(Page2, Page2.x,Page2.y, Surface, skip_updating_screen_top_for) + compute_layout(Page, Page.x,Page.y, Surface) + compute_layout(Page2, Page2.x,Page2.y, Surface) -- continue the pipeline - B(skip_updating_screen_top_for) + B() -- TODO: ugly that we're manipulating editor objects twice end diff --git a/0030-update_editor_box b/0030-update_editor_box index 6da4daa..3a7906b 100644 --- a/0030-update_editor_box +++ b/0030-update_editor_box @@ -1,29 +1,16 @@ -update_editor_box = function(node, skip_updating_screen_top_for) +update_editor_box = function(node, skip_updating) if node.editor == nil then return end + if node == skip_updating then return end edit.update_font_settings(node.editor, scale(20)) node.editor.left = math.floor(vx(node.x)) node.editor.right = math.ceil(vx(node.x+node.w)) node.editor.width = node.editor.right - node.editor.left Text.redraw_all(node.editor) ---? print('update', node.y, Viewport.y, 'spx', node.editor.screen_top1.line, node.editor.top, 'vpx') if node.y > Viewport.y then - if node ~= skip_updating_screen_top_for then ---? print('modifying screen_top to 1') - node.editor.screen_top1.line = 1 - node.editor.screen_top1.pos = 1 - end + node.editor.screen_top1.line = 1 + node.editor.screen_top1.pos = 1 node.editor.top = vy(node.y) else ---? print('<=', node, skip_updating_screen_top_for) - if node ~= skip_updating_screen_top_for then - node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, scale(Viewport.y-node.y)) - print('modified screen_top to', node.editor.screen_top1.line, 'at', node.editor.top, 'vpx') - else - -- adjust editor to start rendering near top of viewport ---? print(Viewport.y) - node.editor.top = Viewport.y%node.editor.line_height - if node.editor.top > 0 then node.editor.top = node.editor.top - node.editor.line_height end ---? print('top', node.editor.top) - end + node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, scale(Viewport.y-node.y)) end end diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor new file mode 100644 index 0000000..8ff4de1 --- /dev/null +++ b/0035-pan_viewport_to_contain_cursor @@ -0,0 +1,31 @@ +function pan_viewport_to_contain_cursor(node) + print('viewport', Viewport.y) + local safety_margin = 2*node.editor.line_height + print('safety margin', screen_top_y, 'dvpx') + print('node', node.y) + local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) + print('cursor', cursor_y, 'dvpx') + if Viewport.y < node.y then + -- node starts within Viewport + print('node starts within viewport') + local max_cursor_y = App.screen.height - scale(node.y - Viewport.y) - safety_margin + if cursor_y > max_cursor_y then + -- set Viewport.y so cursor_y == max_cursor_y + -- equation: cursor_y == App.screen.height - (node.y - Viewport.y)*Viewport.zoom - safety_margin + -- solve for Viewport.y + Viewport.y = node.y - (App.screen.height - cursor_y - safety_margin)/Viewport.zoom + print('adjusting Viewport to', Viewport.y) + end + else + -- node extends above Viewport + print('node extends above viewport') + local screen_top_y = y_of_schema1(node.editor, node.editor.screen_top1) + print('screen top', screen_top_y, 'dvpx') + local min_screen_top_y = cursor_y + safety_margin - App.screen.height + if screen_top_y < min_screen_top_y then + screen_top_y = min_screen_top_y + Viewport.y = node.y + screen_top_y/Viewport.zoom + print('adjusting Viewport to', Viewport.y) + end + end +end From feee7895e99250c8f669b2bbb7b41a4603d1e681 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 16:09:04 -0700 Subject: [PATCH 2/8] use the current implementation in just down-arrow Now we have a skeleton to support up-arrow. This is probably not a good final organization, but will hopefully be a good incremental stepping stone. --- 0035-pan_viewport_to_contain_cursor | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor index 8ff4de1..588f57e 100644 --- a/0035-pan_viewport_to_contain_cursor +++ b/0035-pan_viewport_to_contain_cursor @@ -3,6 +3,8 @@ function pan_viewport_to_contain_cursor(node) local safety_margin = 2*node.editor.line_height print('safety margin', screen_top_y, 'dvpx') print('node', node.y) + local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1) + if cursor_sy > Viewport.y + App.screen.height/Viewport.zoom - safety_margin then local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) print('cursor', cursor_y, 'dvpx') if Viewport.y < node.y then @@ -28,4 +30,6 @@ function pan_viewport_to_contain_cursor(node) print('adjusting Viewport to', Viewport.y) end end + elseif cursor_sy < Viewport.y + safety_margin then + end end From 92c23595325ecb802c8d904b33d675873e4affef Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 16:20:22 -0700 Subject: [PATCH 3/8] indent --- 0035-pan_viewport_to_contain_cursor | 48 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor index 588f57e..7cd424d 100644 --- a/0035-pan_viewport_to_contain_cursor +++ b/0035-pan_viewport_to_contain_cursor @@ -5,31 +5,31 @@ function pan_viewport_to_contain_cursor(node) print('node', node.y) local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1) if cursor_sy > Viewport.y + App.screen.height/Viewport.zoom - safety_margin then - local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) - print('cursor', cursor_y, 'dvpx') - if Viewport.y < node.y then - -- node starts within Viewport - print('node starts within viewport') - local max_cursor_y = App.screen.height - scale(node.y - Viewport.y) - safety_margin - if cursor_y > max_cursor_y then - -- set Viewport.y so cursor_y == max_cursor_y - -- equation: cursor_y == App.screen.height - (node.y - Viewport.y)*Viewport.zoom - safety_margin - -- solve for Viewport.y - Viewport.y = node.y - (App.screen.height - cursor_y - safety_margin)/Viewport.zoom - print('adjusting Viewport to', Viewport.y) + local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) + print('cursor', cursor_y, 'dvpx') + if Viewport.y < node.y then + -- node starts within Viewport + print('node starts within viewport') + local max_cursor_y = App.screen.height - scale(node.y - Viewport.y) - safety_margin + if cursor_y > max_cursor_y then + -- set Viewport.y so cursor_y == max_cursor_y + -- equation: cursor_y == App.screen.height - (node.y - Viewport.y)*Viewport.zoom - safety_margin + -- solve for Viewport.y + Viewport.y = node.y - (App.screen.height - cursor_y - safety_margin)/Viewport.zoom + print('adjusting Viewport to', Viewport.y) + end + else + -- node extends above Viewport + print('node extends above viewport') + local screen_top_y = y_of_schema1(node.editor, node.editor.screen_top1) + print('screen top', screen_top_y, 'dvpx') + local min_screen_top_y = cursor_y + safety_margin - App.screen.height + if screen_top_y < min_screen_top_y then + screen_top_y = min_screen_top_y + Viewport.y = node.y + screen_top_y/Viewport.zoom + print('adjusting Viewport to', Viewport.y) + end end - else - -- node extends above Viewport - print('node extends above viewport') - local screen_top_y = y_of_schema1(node.editor, node.editor.screen_top1) - print('screen top', screen_top_y, 'dvpx') - local min_screen_top_y = cursor_y + safety_margin - App.screen.height - if screen_top_y < min_screen_top_y then - screen_top_y = min_screen_top_y - Viewport.y = node.y + screen_top_y/Viewport.zoom - print('adjusting Viewport to', Viewport.y) - end - end elseif cursor_sy < Viewport.y + safety_margin then end end From d1c65b90a3d5418804d80278cc18a01b442424c6 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 16:41:56 -0700 Subject: [PATCH 4/8] snapshot: fix up arrow at Zoom = 1 --- 0035-pan_viewport_to_contain_cursor | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor index 7cd424d..b78af22 100644 --- a/0035-pan_viewport_to_contain_cursor +++ b/0035-pan_viewport_to_contain_cursor @@ -1,7 +1,7 @@ function pan_viewport_to_contain_cursor(node) print('viewport', Viewport.y) local safety_margin = 2*node.editor.line_height - print('safety margin', screen_top_y, 'dvpx') + print('safety margin', safety_margin, 'dvpx') print('node', node.y) local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1) if cursor_sy > Viewport.y + App.screen.height/Viewport.zoom - safety_margin then @@ -31,5 +31,30 @@ function pan_viewport_to_contain_cursor(node) end end elseif cursor_sy < Viewport.y + safety_margin then + local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) + print('cursor', cursor_y, 'dvpx') + if Viewport.y < node.y then + -- node starts within Viewport + print('node starts within viewport') + local max_cursor_y = App.screen.height - scale(node.y - Viewport.y) - safety_margin + if cursor_y > max_cursor_y then + -- set Viewport.y so cursor_y == max_cursor_y + -- equation: cursor_y == App.screen.height - (node.y - Viewport.y)*Viewport.zoom - safety_margin + -- solve for Viewport.y + Viewport.y = node.y - (App.screen.height - cursor_y - safety_margin)/Viewport.zoom + print('adjusting Viewport to', Viewport.y) + end + else + -- node extends above Viewport + print('node extends above viewport') + local screen_top_y = y_of_schema1(node.editor, node.editor.screen_top1) + print('screen top', screen_top_y, 'dvpx') + local max_screen_top_y = cursor_y - safety_margin + if screen_top_y > max_screen_top_y then + screen_top_y = max_screen_top_y + Viewport.y = node.y + screen_top_y/Viewport.zoom + print('adjusting Viewport to', Viewport.y) + end + end end end From 27733025a2929d8e77026ba355e6b440d2c69052 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 17:13:28 -0700 Subject: [PATCH 5/8] up and down arrow working at all 3 zoom levels I don't know why I have such an almighty struggle with this stuff. --- 0026-on.draw | 1 + 0035-pan_viewport_to_contain_cursor | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/0026-on.draw b/0026-on.draw index ef22e0f..6f3c4df 100644 --- a/0026-on.draw +++ b/0026-on.draw @@ -3,6 +3,7 @@ on.draw = function() love.graphics.line(50, 0, 50, App.screen.height) for i=0,100 do love.graphics.print(tostring(i), 30, i*100) + love.graphics.line(25, i*100, 75, i*100) end local vy0 = vy(0) love.graphics.line(100, vy0, 100, App.screen.height) diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor index b78af22..9cada2c 100644 --- a/0035-pan_viewport_to_contain_cursor +++ b/0035-pan_viewport_to_contain_cursor @@ -1,10 +1,15 @@ function pan_viewport_to_contain_cursor(node) print('viewport', Viewport.y) local safety_margin = 2*node.editor.line_height + cursor1 = {39, 1} print('safety margin', safety_margin, 'dvpx') - print('node', node.y) - local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1) + print('node', node.y, node.y/Viewport.zoom) +--? 0 608 vs 38*20 = 760 + local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1)/Viewport.zoom +--? 608 0 775 968.75 968.75 928.75 + print(cursor_sy, Viewport.y, App.screen.height, App.screen.height/Viewport.zoom, Viewport.y + App.screen.height/Viewport.zoom, Viewport.y + App.screen.height/Viewport.zoom - safety_margin) if cursor_sy > Viewport.y + App.screen.height/Viewport.zoom - safety_margin then + print('cursor below viewport') local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) print('cursor', cursor_y, 'dvpx') if Viewport.y < node.y then @@ -31,6 +36,7 @@ function pan_viewport_to_contain_cursor(node) end end elseif cursor_sy < Viewport.y + safety_margin then + print('cursor above viewport') local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) print('cursor', cursor_y, 'dvpx') if Viewport.y < node.y then From 74db6ac95ee4c845b2ef52dc762f23b8c5ecd56a Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 17:15:04 -0700 Subject: [PATCH 6/8] clean up --- 0035-pan_viewport_to_contain_cursor | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor index 9cada2c..675dded 100644 --- a/0035-pan_viewport_to_contain_cursor +++ b/0035-pan_viewport_to_contain_cursor @@ -3,15 +3,11 @@ function pan_viewport_to_contain_cursor(node) local safety_margin = 2*node.editor.line_height cursor1 = {39, 1} print('safety margin', safety_margin, 'dvpx') - print('node', node.y, node.y/Viewport.zoom) ---? 0 608 vs 38*20 = 760 + print('node', node.y) local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1)/Viewport.zoom ---? 608 0 775 968.75 968.75 928.75 - print(cursor_sy, Viewport.y, App.screen.height, App.screen.height/Viewport.zoom, Viewport.y + App.screen.height/Viewport.zoom, Viewport.y + App.screen.height/Viewport.zoom - safety_margin) if cursor_sy > Viewport.y + App.screen.height/Viewport.zoom - safety_margin then print('cursor below viewport') local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) - print('cursor', cursor_y, 'dvpx') if Viewport.y < node.y then -- node starts within Viewport print('node starts within viewport') @@ -27,7 +23,6 @@ function pan_viewport_to_contain_cursor(node) -- node extends above Viewport print('node extends above viewport') local screen_top_y = y_of_schema1(node.editor, node.editor.screen_top1) - print('screen top', screen_top_y, 'dvpx') local min_screen_top_y = cursor_y + safety_margin - App.screen.height if screen_top_y < min_screen_top_y then screen_top_y = min_screen_top_y @@ -38,7 +33,6 @@ function pan_viewport_to_contain_cursor(node) elseif cursor_sy < Viewport.y + safety_margin then print('cursor above viewport') local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) - print('cursor', cursor_y, 'dvpx') if Viewport.y < node.y then -- node starts within Viewport print('node starts within viewport') @@ -54,7 +48,6 @@ function pan_viewport_to_contain_cursor(node) -- node extends above Viewport print('node extends above viewport') local screen_top_y = y_of_schema1(node.editor, node.editor.screen_top1) - print('screen top', screen_top_y, 'dvpx') local max_screen_top_y = cursor_y - safety_margin if screen_top_y > max_screen_top_y then screen_top_y = max_screen_top_y From 69d3af9ca4d104471a5fde1be92fa0c1d8c8575f Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 17:25:06 -0700 Subject: [PATCH 7/8] recheck manual tests Just the pagedown bug remaining. --- Manual_tests.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Manual_tests.md b/Manual_tests.md index e5db2a0..783bae6 100644 --- a/Manual_tests.md +++ b/Manual_tests.md @@ -24,14 +24,14 @@ Panning: ✓ repeated down arrow near bottom pans down ✓ repeated up arrow ✓ repeated down arrow - ✓ repeated pagedown - ✓ repeated pageup + x repeated pagedown + ✓ pageup ✓ mouse panning tall node extending above viewport ✓ repeated up arrow near top pans up ✓ repeated down arrow ✓ repeated up arrow - ✓ repeated pagedown + ✓ pagedown ✓ repeated pageup ✓ mouse panning tall node extending both below and above viewport @@ -39,7 +39,7 @@ Panning: ✓ repeated down arrow ✓ repeated down arrow near bottom pans down ✓ repeated up arrow - ✓ repeated pagedown + x repeated pagedown ✓ repeated pageup ✓ mouse panning @@ -47,20 +47,20 @@ Panning: short node entirely within viewer, cursor in middle of screen ✓ arrow keys ✓ page-up positions cursor on top line - x page-down positions cursor on bottom line + ✓ page-down positions cursor on bottom line ✓ mouse panning tall node extending below viewport - x repeated down arrow near bottom pans down + ✓ repeated down arrow near bottom pans down ✓ repeated up arrow ✓ repeated down arrow x repeated pagedown - ✓ repeated pageup + ✓ pageup ✓ mouse panning tall node extending above viewport ✓ repeated up arrow near top pans up ✓ repeated down arrow ✓ repeated up arrow - ✓ repeated pagedown + ✓ pagedown ✓ repeated pageup ✓ mouse panning tall node extending both below and above viewport @@ -68,7 +68,7 @@ Panning: ✓ repeated down arrow ✓ repeated down arrow near bottom pans down ✓ repeated up arrow - ✓ repeated pagedown + x repeated pagedown ✓ repeated pageup ✓ mouse panning @@ -76,10 +76,10 @@ Panning: short node entirely within viewer, cursor in middle of screen ✓ arrow keys ✓ page-up positions cursor on top line - x page-down positions cursor on bottom line + ✓ page-down positions cursor on bottom line ✓ mouse panning tall node extending below viewport - x repeated down arrow near bottom pans down + ✓ repeated down arrow near bottom pans down ✓ repeated up arrow ✓ repeated down arrow x repeated pagedown @@ -97,7 +97,7 @@ Panning: ✓ repeated down arrow ✓ repeated down arrow near bottom pans down ✓ repeated up arrow - ✓ repeated pagedown + x repeated pagedown ✓ repeated pageup ✓ mouse panning From f78557e5e5a440457b319df0513622ad3e07838d Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 27 Oct 2023 17:57:09 -0700 Subject: [PATCH 8/8] this seems to pass all manual tests It's an interesting blend with my old solution; the new solution acts as just a safety net. It makes a couple of situations more jarring, where the screen moves more than strictly necessary. But the core vibe of my apps is preserved: the screen only updates when you do something. --- 0035-pan_viewport_to_contain_cursor | 3 +++ Manual_tests.md | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/0035-pan_viewport_to_contain_cursor b/0035-pan_viewport_to_contain_cursor index 675dded..c498f82 100644 --- a/0035-pan_viewport_to_contain_cursor +++ b/0035-pan_viewport_to_contain_cursor @@ -5,6 +5,9 @@ function pan_viewport_to_contain_cursor(node) print('safety margin', safety_margin, 'dvpx') print('node', node.y) local cursor_sy = node.y + y_of_schema1(node.editor, node.editor.cursor1)/Viewport.zoom + if Text.lt1({line=1, pos=1}, node.editor.screen_top1) then + Viewport.y = node.y + y_of_schema1(node.editor, node.editor.screen_top1)/Viewport.zoom + end if cursor_sy > Viewport.y + App.screen.height/Viewport.zoom - safety_margin then print('cursor below viewport') local cursor_y = y_of_schema1(node.editor, node.editor.cursor1) diff --git a/Manual_tests.md b/Manual_tests.md index 783bae6..84b4ac3 100644 --- a/Manual_tests.md +++ b/Manual_tests.md @@ -24,7 +24,7 @@ Panning: ✓ repeated down arrow near bottom pans down ✓ repeated up arrow ✓ repeated down arrow - x repeated pagedown + ✓ repeated pagedown ✓ pageup ✓ mouse panning tall node extending above viewport @@ -39,7 +39,7 @@ Panning: ✓ repeated down arrow ✓ repeated down arrow near bottom pans down ✓ repeated up arrow - x repeated pagedown + ✓ repeated pagedown ✓ repeated pageup ✓ mouse panning @@ -53,7 +53,7 @@ Panning: ✓ repeated down arrow near bottom pans down ✓ repeated up arrow ✓ repeated down arrow - x repeated pagedown + ✓ repeated pagedown ✓ pageup ✓ mouse panning tall node extending above viewport @@ -68,7 +68,7 @@ Panning: ✓ repeated down arrow ✓ repeated down arrow near bottom pans down ✓ repeated up arrow - x repeated pagedown + ✓ repeated pagedown ✓ repeated pageup ✓ mouse panning @@ -82,7 +82,7 @@ Panning: ✓ repeated down arrow near bottom pans down ✓ repeated up arrow ✓ repeated down arrow - x repeated pagedown + ✓ repeated pagedown ✓ repeated pageup ✓ mouse panning tall node extending above viewport @@ -97,7 +97,7 @@ Panning: ✓ repeated down arrow ✓ repeated down arrow near bottom pans down ✓ repeated up arrow - x repeated pagedown + ✓ repeated pagedown ✓ repeated pageup ✓ mouse panning