Merge driver.love
This commit is contained in:
commit
45c32104a8
|
@ -45,5 +45,5 @@ on.mouse_press = function(x,y, mouse_button)
|
|||
A()
|
||||
end
|
||||
-- pan surface
|
||||
Pan = {x=Viewport.x+x/Viewport.zoom,y=Viewport.y+y/Viewport.zoom}
|
||||
Pan = {x=Viewport.x+x/Viewport.zoom, y=Viewport.y+y/Viewport.zoom}
|
||||
end
|
||||
|
|
|
@ -9,8 +9,8 @@ box_height = function(node)
|
|||
node.editor.line_cache[i].fragments = nil
|
||||
node.editor.line_cache[i].screen_line_starting_pos = nil
|
||||
Text.populate_screen_line_starting_pos(node.editor, i)
|
||||
y = y + 20*1.3*#node.editor.line_cache[i].screen_line_starting_pos
|
||||
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
|
||||
Text.clear_screen_line_cache(node.editor, i)
|
||||
end
|
||||
return y
|
||||
return y/Viewport.zoom
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
y_of_schema1 = function(editor, loc)
|
||||
local result = 0
|
||||
loc = {line=loc.line, pos=Text.pos_at_start_of_screen_line(editor, loc)}
|
||||
if loc.line == 1 and loc.pos == 1 then
|
||||
return result
|
||||
end
|
||||
|
@ -15,4 +16,4 @@ y_of_schema1 = function(editor, loc)
|
|||
result = result + editor.line_height
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
|
5
0019-B
5
0019-B
|
@ -1,7 +1,6 @@
|
|||
B = function()
|
||||
B = function(skip_updating_screen_top_for)
|
||||
-- print('B')
|
||||
-- recompute various aspects based on the current viewport settings
|
||||
love.graphics.setFont(love.graphics.newFont(scale(20))) -- editor objects implicitly depend on current font so update it
|
||||
for _,obj in ipairs(Surface) do
|
||||
if obj.type == 'line' then
|
||||
obj.zdata = {}
|
||||
|
@ -18,7 +17,7 @@ B = function()
|
|||
obj.zdata = love.math.newBezierCurve(zdata):render()
|
||||
elseif obj.type == 'text' then
|
||||
if obj.w then
|
||||
update_editor_box(obj)
|
||||
update_editor_box(obj, skip_updating_screen_top_for)
|
||||
else
|
||||
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
compute_layout = function(node, x,y, nodes_to_render)
|
||||
compute_layout = function(node, x,y, nodes_to_render, skip_updating_screen_top_for)
|
||||
--[[ --debug prints when modifying the DOM
|
||||
if node.type == 'rows' or node.type == 'cols' then
|
||||
print(node.type, node.button, #node.data)
|
||||
|
@ -38,7 +38,7 @@ compute_layout = function(node, x,y, nodes_to_render)
|
|||
if node.editor == nil then
|
||||
initialize_editor(node)
|
||||
else
|
||||
update_editor_box(node)
|
||||
update_editor_box(node, skip_updating_screen_top_for)
|
||||
end
|
||||
node.h = box_height(node)
|
||||
table.insert(nodes_to_render, node)
|
||||
|
@ -66,7 +66,7 @@ compute_layout = function(node, x,y, nodes_to_render)
|
|||
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)
|
||||
subx,suby = compute_layout(child, x,suby, nodes_to_render, skip_updating_screen_top_for)
|
||||
if w < child.w then
|
||||
w = child.w
|
||||
end
|
||||
|
@ -94,7 +94,7 @@ compute_layout = function(node, x,y, nodes_to_render)
|
|||
subx = subx+child.margin
|
||||
w = w+child.margin
|
||||
end
|
||||
subx,suby = compute_layout(child, subx,y, nodes_to_render)
|
||||
subx,suby = compute_layout(child, subx,y, nodes_to_render, skip_updating_screen_top_for)
|
||||
w = w + child.w
|
||||
if h < child.h then
|
||||
h = child.h
|
||||
|
|
|
@ -5,6 +5,19 @@ on.text_input = function(t)
|
|||
edit.text_input(Cursor_node.editor, t)
|
||||
if not eq(Cursor_node.editor.screen_top1, old_top) then
|
||||
Viewport.y = Cursor_node.y + y_of_schema1(Cursor_node.editor, Cursor_node.editor.screen_top1)
|
||||
-- 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
|
||||
B()
|
||||
end
|
||||
|
|
|
@ -8,22 +8,35 @@ on.keychord_press = function(chord, key)
|
|||
elseif chord == 'C-=' then
|
||||
-- zoom in
|
||||
Viewport.zoom = Viewport.zoom+0.1
|
||||
B()
|
||||
A()
|
||||
elseif chord == 'C--' then
|
||||
-- zoom out
|
||||
if (Viewport.zoom-0.1)*20 >= 1 then -- disallow font size of 0
|
||||
Viewport.zoom = Viewport.zoom-0.1
|
||||
B()
|
||||
A()
|
||||
end
|
||||
elseif chord == 'C-0' then
|
||||
-- reset zoom
|
||||
Viewport.zoom = 1.0
|
||||
B()
|
||||
elseif Cursor_node then
|
||||
A()
|
||||
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}
|
||||
edit.keychord_press(Cursor_node.editor, chord, key)
|
||||
if not eq(Cursor_node.editor.screen_top1, old_top) then
|
||||
Viewport.y = Cursor_node.y + y_of_schema1(Cursor_node.editor, Cursor_node.editor.screen_top1)
|
||||
-- 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
|
||||
if chord == 'return' then
|
||||
A()
|
||||
|
|
7
0028-A
7
0028-A
|
@ -1,4 +1,4 @@
|
|||
A = function()
|
||||
A = function(skip_updating_screen_top_for)
|
||||
-- print('A')
|
||||
love.graphics.setFont(love.graphics.newFont(scale(20))) -- editor objects implicitly depend on current font
|
||||
-- translate some page in Global_state to Surface
|
||||
|
@ -6,9 +6,10 @@ A = function()
|
|||
if Global_state.thread == nil then
|
||||
lay_out_file_picker()
|
||||
else
|
||||
compute_layout(Global_state.thread, 0,0, Surface)
|
||||
compute_layout(Global_state.thread, 0,0, Surface, skip_updating_screen_top_for)
|
||||
end
|
||||
compute_viewport_bounds()
|
||||
B()
|
||||
-- continue the pipeline
|
||||
B(skip_updating_screen_top_for)
|
||||
-- TODO: ugly that we're manipulating editor objects twice
|
||||
end
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
update_editor_box = function(node)
|
||||
update_editor_box = function(node, skip_updating_screen_top_for)
|
||||
if node.editor == nil then return end
|
||||
if node.editor.font_height ~= scale(20) then
|
||||
edit.update_font_settings(node.editor, scale(20))
|
||||
Text.redraw_all(node.editor)
|
||||
end
|
||||
if node.y > Viewport.y then
|
||||
if node ~= Cursor_node then
|
||||
if node ~= skip_updating_screen_top_for then
|
||||
node.editor.screen_top1.line = 1
|
||||
node.editor.screen_top1.pos = 1
|
||||
end
|
||||
node.editor.top = vy(node.y)
|
||||
else
|
||||
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, scale(Viewport.y-node.y)) -- scale y because editor's font is scaled
|
||||
node.editor.top = node.editor.top + Menu_bar_height
|
||||
end
|
||||
if node.editor.font_height ~= scale(20) then
|
||||
edit.update_font_settings(node.editor, scale(20))
|
||||
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)) -- scale y because editor's font is scaled
|
||||
node.editor.top = node.editor.top + Menu_bar_height
|
||||
end
|
||||
end
|
||||
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
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
test_y_of_schema1 = function()
|
||||
local state = edit.initialize_test_state()
|
||||
state.lines = load_array{'1', '2', '3'}
|
||||
Text.redraw_all(state)
|
||||
check_eq(y_of_schema1(state, {line=1, pos=1}), 0, 'start of first line')
|
||||
check_eq(y_of_schema1(state, {line=1, pos=2}), 0, 'middle of first line')
|
||||
check_eq(y_of_schema1(state, {line=2, pos=2}), state.line_height, 'middle of second line')
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
dump_state = function()
|
||||
print('===')
|
||||
print('zoom', Viewport.zoom)
|
||||
print('viewport', Viewport.y, 'spx')
|
||||
local node = Page.data[1]
|
||||
print('node', node.y, 'spx')
|
||||
print('line height', node.editor.line_height, 'vpx')
|
||||
print('node renders from', node.editor.top, 'vpx')
|
||||
print('screen top', node.editor.screen_top1.line)
|
||||
print('invariant', Viewport.y-node.y+node.editor.top - y_of_schema1(node.editor, node.editor.screen_top1))
|
||||
local l = 25
|
||||
print('y of line', l, y_of_schema1(node.editor, {line=l, pos=1}), 'spx')
|
||||
end
|
|
@ -19,7 +19,9 @@ Panning (test these at multiple zoom levels):
|
|||
* When a node has cursor in viewport, arrow keys move the cursor within the node, keeping cursor visible, panning surface if scrolling is needed
|
||||
* Pageup/pagedown scroll a whole viewport height at a time if possible, but keep cursor visible if not possible.
|
||||
* When a node has cursor, pageup/pagedown pan surface around
|
||||
* Position a node with some area above viewport. Position cursor at topmost row on screen. Hit up arrow. Surface pans. Cursor doesn't hide behind menu bar.
|
||||
* Position a node with some of its area above (outside) viewport. Position cursor at topmost row on screen. Hit up arrow. Surface pans. Cursor doesn't hide behind menu bar.
|
||||
* Increase/decrease zoom, pan around using cursor inside node. The box for the editor surrounds the entire editor.
|
||||
* Increase/decrease zoom, pan around using cursor outside node. The box for the editor surrounds the entire editor. (not perfect yet)
|
||||
|
||||
### Protocol with driver; error-handling
|
||||
|
||||
|
|
Loading…
Reference in New Issue