This will make things more consistent in the long term, but I realize one major cost: our button abstraction doesn't work well with luaML and compute_layout. So we need something to replace it.
R5HNWYMH47LWVHS5VVXNR6TCBDXDURVXZ6RCUNFTTTMIXF275ULQC
ZE4ZEF4NITAK6MMQQ74AYYBGM7NRQZWQY2MW4I2QWAOMTLITCCCAC
6GHRND3MFF6ZDIQO67TPXYNYRTHDTDSC7EPCYF7TCEPCEF7ASO3QC
ND7NVNRKX2ZUTQ35Y324YMBM6R5HML2FC63AT547JUGJ36BQTYMQC
PUAFL2INULSU55YGRH7NCRQ6R7BTAKP3MK6FPWIKJDONNF7FR22AC
PCM5XKH4LESPEN3HIQMHOBGPRJNGVXQ6DFI5PGMFDASKGHY2BACQC
R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC
CWDOQLMNGY6BP3QCSQCQ7NG5XZN3QIKPZ5YMQHS3AC53J6QZ5RUQC
VZ6UKPE6CW7ZUKUBPUY3XAZL37WILDOTUZLNOM7NZGHS7WVQAXLQC
ZXQ2MMPAOIA4TN3TWMFPXZUL7NUE3EWXLV2JHBQXEINE7WCKFSIQC
OF4P6TYQA7SUF4N2KPDN7LRTIRNXME2IZJHRLFGF3EMDTWZSGOYAC
FHHATD2K3LNFNJ4YKTCHAWKBNB5VSASQR4T6TQ5PK4O433P4FOEQC
7TQAF4BYIK75EEYCCK7VEUSZHNCWMWIA3HZGQKIILYESUZ5ZZRVQC
QJAYOFWY7V4BWVLJMEDCCBC2HX4BDAZI6PQVLWCLYRHWGMOBFTVAC
PPVABNGQTQMPYILHDNSNXBI5IOCBSIYO45NIHUR4LYPABQZE6PAQC
SUPHTPXYKS4JBDPASHAYA5OBVJ45QT7ZV2HYNTF7OJYOKKS6DW5QC
JIBCE66ZTWM5WEHEHNKKTRWBJQSQWBDDWPMOJIJR5Q676OSHYCNAC
44XJ7M5LRCOL46CUUTN2ZIOAYQOHPLRNA37S67CH665RAOVI4SJQC
AYUZF67YZY2GQBYJJLHU6LI7KJUTBRPYY46WOD4MBVE3DIGSLM2QC
BF7TW3EKRIDYC6J2Q2J4YOBAVQF55Y3H6KGZIHNXMH4N72MR6GXQC
TBPJ5WSRM5IKQH7FTAVYTWWUBWW7G2CLT5M6FN7CMPLD6Y77YIWQC
X7HYGAL2QVKG7M5EMZ2VSH37UYWGE3EPUXYQBJOVL6IGJFZ2I5AAC
4TL2FLYP36JS4K6QBXZBCFCTIBMIT7OAF7KMAAFGPAF5OWSP4QFAC
Q2C4QGRCXKMCWMEQJT2OJMC5A3OIYKWPQBU4U3QWICEJHFXO6LPQC
OLCKKDVSDTIBX5U3IRCLRL6KQMG2RDWKGDN4OTPI3WMN4FSX6ROQC
FBDRJ53NJ5BWDQGU2GWZ6NEYHKCCRD7RODMIG7QQZBRFUB4HR7OAC
6C3UZDESM2HPFIHAW5YIPUV6VXO4YV5DIEY574HUGP2DGOQNUVOAC
keychord_press_on_surface = function(chord, key)
if chord == 'C-o' then
Global_state = {}
elseif Cursor_node 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)
end
if chord == 'return' then
A(--[[preserve screen_top of cursor node]] true)
else
B(--[[preserve screen_top of cursor node]] true)
end
else
if chord == 'up' then
Viewport.y = Viewport.y - scale(20)
B()
elseif chord == 'down' then
Viewport.y = Viewport.y + scale(20)
B()
elseif chord == 'left' then
Viewport.x = Viewport.x - scale(50)
B()
elseif chord == 'right' then
Viewport.x = Viewport.x + scale(50)
B()
elseif chord == 'pageup' then
Viewport.y = Viewport.y - App.screen.height/Viewport.zoom
B()
elseif chord == 'S-up' then
Viewport.y = Viewport.y - App.screen.height/Viewport.zoom
B()
elseif chord == 'pagedown' then
Viewport.y = Viewport.y + App.screen.height/Viewport.zoom
B()
elseif chord == 'S-down' then
Viewport.y = Viewport.y + App.screen.height/Viewport.zoom
B()
elseif chord == 'S-left' then
Viewport.x = Viewport.x - App.screen.width/Viewport.zoom
B()
elseif chord == 'S-right' then
Viewport.x = Viewport.x + App.screen.width/Viewport.zoom
B()
end
end
end
love.graphics.setFont(love.graphics.newFont(20))
local font = love.graphics.getFont()
font:setLineHeight(1.3)
Viewport = {x=-50, y=-50, w=800,h=600, zoom=1.0}
File_picker_margin = 20 -- around each file button in all directions
lay_out_file_picker = function()
local x,y = 0,0
for _,n in ipairs(Global_state.file_picker) do
local x2,y2 = compute_layout(n, x,y, Surface)
if x2 < 1000 then
x = x2 + File_picker_margin
else
x,y = 0,y2+File_picker_margin
end
end
end
initialize_file_picker = function()
Files = love.filesystem.getDirectoryItems('data')
for i=#Files,1,-1 do
if (not Files[i]:match('%.md$')) or Files[i]:match('%-%d+.md$') then
table.remove(Files, i)
end
end
table.sort(Files)
Global_state.file_picker = {}
for _,f in ipairs(Files) do
table.insert(Global_state.file_picker, {
type='text',
data={{data=f}},
rx=5,
bg={r=0.7, g=0.7, b=1.0},
border={r=0.4, g=0.4, b=0.7}
})
end
end
reset_viewport = function()
Viewport = {x=-50, y=-50, w=800,h=600, zoom=1.0}
end
compute_layout(Global_state.root, 0,0, Surface, preserve_screen_top_of_cursor_node)
if Global_state.file_picker then
lay_out_file_picker()
elseif Global_state.thread then
compute_layout(Global_state.thread, 0,0, Surface, preserve_screen_top_of_cursor_node)
end
Surface = {
-- test data
{type='line', data={0,-1000, 0,1000}},
{type='line', data={-10000,0, 10000,0}},
{type='text', data={'0'}, x=-20,y=-30},
{type='rectangle', x=50,y=50, w=20,h=80, r=1,g=0,b=0},
{type='text', data={'abc', 'def'}, x=150, y=50, w=50,h=50, fg={r=0,g=0.4, b=0.9}},
{type='circle', x=300,y=200, radius=40, r=1,g=0,b=1},
{type='arc', x=0,y=0, radius=50, angle1=0, angle2=math.pi*2/3},
{type='ellipse', x=100,y=100, radiusx=10, radiusy=50},
{type='bezier', data={25,25, 25,125, 75,25, 125,25}},
}
Surface = {}
Global_state.button_handlers = {}
if Global_state.root == nil then
-- TODO: use surface for file picker as well
draw_file_picker()
else
draw_surface()
for _,obj in ipairs(Surface) do
love.graphics.setColor(obj.r or 0, obj.g or 0, obj.b or 0)
if obj.type == 'rectangle' then
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.w),scale(obj.h), scale(obj.rx or 5), scale(obj.rx or obj.ry or 5))
elseif obj.type == 'line' then
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'circle' then
love.graphics.circle(obj.drawmode or 'fill', vx(obj.x), vy(obj.y), scale(obj.radius))
elseif obj.type == 'arc' then
love.graphics.arc(obj.drawmode or 'line', obj.arctype or 'open', vx(obj.x), vy(obj.y), scale(obj.radius), obj.angle1, obj.angle2, obj.segments)
elseif obj.type == 'ellipse' then
love.graphics.ellipse(obj.drawmode or 'fill', vx(obj.x), vy(obj.y), scale(obj.radiusx), scale(obj.radiusy))
elseif obj.type == 'bezier' then
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg, not obj.show_cursor)
end
end
-- a little weird that zoom works even in file picker mode
if chord == 'C-=' then
if Global_state.thread and chord == 'C-o' then
Global_state.thread = nil
reset_viewport()
elseif chord == 'C-=' then
elseif Global_state.root then
keychord_press_on_surface(chord, key)
elseif Cursor_node 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)
end
if chord == 'return' then
A(--[[preserve screen_top of cursor node]] true)
else
B(--[[preserve screen_top of cursor node]] true)
end
else
if chord == 'up' then
Viewport.y = Viewport.y - scale(20)
B()
elseif chord == 'down' then
Viewport.y = Viewport.y + scale(20)
B()
elseif chord == 'left' then
Viewport.x = Viewport.x - scale(50)
B()
elseif chord == 'right' then
Viewport.x = Viewport.x + scale(50)
B()
elseif chord == 'pageup' then
Viewport.y = Viewport.y - App.screen.height/Viewport.zoom
B()
elseif chord == 'S-up' then
Viewport.y = Viewport.y - App.screen.height/Viewport.zoom
B()
elseif chord == 'pagedown' then
Viewport.y = Viewport.y + App.screen.height/Viewport.zoom
B()
elseif chord == 'S-down' then
Viewport.y = Viewport.y + App.screen.height/Viewport.zoom
B()
elseif chord == 'S-left' then
Viewport.x = Viewport.x - App.screen.width/Viewport.zoom
B()
elseif chord == 'S-right' then
Viewport.x = Viewport.x + App.screen.width/Viewport.zoom
B()
end
if Global_state.root then
mouse_press_on_surface(x,y, mouse_button)
local node = on_text(x,y)
if node then
-- position cursor in node
Cursor_node = node
edit.mouse_press(node.editor, x,y, mouse_button)
return