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' thenGlobal_state = {}elseif Cursor_node thenlocal 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) thenViewport.y = Cursor_node.y + y_of_schema1(Cursor_node.editor, Cursor_node.editor.screen_top1)endif chord == 'return' thenA(--[[preserve screen_top of cursor node]] true)elseB(--[[preserve screen_top of cursor node]] true)endelseif chord == 'up' thenViewport.y = Viewport.y - scale(20)B()elseif chord == 'down' thenViewport.y = Viewport.y + scale(20)B()elseif chord == 'left' thenViewport.x = Viewport.x - scale(50)B()elseif chord == 'right' thenViewport.x = Viewport.x + scale(50)B()elseif chord == 'pageup' thenViewport.y = Viewport.y - App.screen.height/Viewport.zoomB()elseif chord == 'S-up' thenViewport.y = Viewport.y - App.screen.height/Viewport.zoomB()elseif chord == 'pagedown' thenViewport.y = Viewport.y + App.screen.height/Viewport.zoomB()elseif chord == 'S-down' thenViewport.y = Viewport.y + App.screen.height/Viewport.zoomB()elseif chord == 'S-left' thenViewport.x = Viewport.x - App.screen.width/Viewport.zoomB()elseif chord == 'S-right' thenViewport.x = Viewport.x + App.screen.width/Viewport.zoomB()endendendlove.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,0for _,n in ipairs(Global_state.file_picker) dolocal x2,y2 = compute_layout(n, x,y, Surface)if x2 < 1000 thenx = x2 + File_picker_marginelsex,y = 0,y2+File_picker_marginendendend
initialize_file_picker = function()Files = love.filesystem.getDirectoryItems('data')for i=#Files,1,-1 doif (not Files[i]:match('%.md$')) or Files[i]:match('%-%d+.md$') thentable.remove(Files, i)endendtable.sort(Files)Global_state.file_picker = {}for _,f in ipairs(Files) dotable.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}})endend
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 thenlay_out_file_picker()elseif Global_state.thread thencompute_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 welldraw_file_picker()elsedraw_surface()
for _,obj in ipairs(Surface) dolove.graphics.setColor(obj.r or 0, obj.g or 0, obj.b or 0)if obj.type == 'rectangle' thenlove.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' thenlove.graphics.line(unpack(obj.zdata))elseif obj.type == 'circle' thenlove.graphics.circle(obj.drawmode or 'fill', vx(obj.x), vy(obj.y), scale(obj.radius))elseif obj.type == 'arc' thenlove.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' thenlove.graphics.ellipse(obj.drawmode or 'fill', vx(obj.x), vy(obj.y), scale(obj.radiusx), scale(obj.radiusy))elseif obj.type == 'bezier' thenlove.graphics.line(unpack(obj.zdata))elseif obj.type == 'text' thenif obj.w == nil thenlove.graphics.draw(obj.text, vx(obj.x), vy(obj.y))elseedit.draw(obj.editor, obj.fg, not obj.show_cursor)endend
-- a little weird that zoom works even in file picker modeif chord == 'C-=' then
if Global_state.thread and chord == 'C-o' thenGlobal_state.thread = nilreset_viewport()elseif chord == 'C-=' then
elseif Global_state.root thenkeychord_press_on_surface(chord, key)
elseif Cursor_node thenlocal 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) thenViewport.y = Cursor_node.y + y_of_schema1(Cursor_node.editor, Cursor_node.editor.screen_top1)endif chord == 'return' thenA(--[[preserve screen_top of cursor node]] true)elseB(--[[preserve screen_top of cursor node]] true)endelseif chord == 'up' thenViewport.y = Viewport.y - scale(20)B()elseif chord == 'down' thenViewport.y = Viewport.y + scale(20)B()elseif chord == 'left' thenViewport.x = Viewport.x - scale(50)B()elseif chord == 'right' thenViewport.x = Viewport.x + scale(50)B()elseif chord == 'pageup' thenViewport.y = Viewport.y - App.screen.height/Viewport.zoomB()elseif chord == 'S-up' thenViewport.y = Viewport.y - App.screen.height/Viewport.zoomB()elseif chord == 'pagedown' thenViewport.y = Viewport.y + App.screen.height/Viewport.zoomB()elseif chord == 'S-down' thenViewport.y = Viewport.y + App.screen.height/Viewport.zoomB()elseif chord == 'S-left' thenViewport.x = Viewport.x - App.screen.width/Viewport.zoomB()elseif chord == 'S-right' thenViewport.x = Viewport.x + App.screen.width/Viewport.zoomB()end
if Global_state.root thenmouse_press_on_surface(x,y, mouse_button)
local node = on_text(x,y)if node then-- position cursor in nodeCursor_node = nodeedit.mouse_press(node.editor, x,y, mouse_button)return