57ZOMM2ZRAIPPRSRBXMUYNKJ2IPLRDHXH7A3WCHHQ7VPHRWKUPEAC FTM3CSOAZMHEWXORH2GG3XJZWHCVG6EAUDI4MSGM6IEU2NN5RNPQC NFWJCNMOR3BP7SZEOCJWUBHZOO4AFSYAJCKGCZZ4O52ILICF6DBQC 5P6W7BLDSLTBFPPM6QU4R4T2PY5MH4T3BBCBKAMVI3MRMT764MDAC Q5AQE4P3GYW3KLTK7AB2TLOKP6KCLD54K54J3R7RB6CTATV64TNAC MU5W6A35USV3OPXIVGGY5FXC55KCIRQXOFHAGXMTOKCIL4MSQZ4AC O6D22PJBXFE5XGW27UD7NDIMQYL4NXH4C4T2E73F2NXUSEB4W7QQC R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC WKMW7PCE75A5CFXF5GPL5HQ4ZNASFOFQFHASOQ7LABSQKWU3KEGAC 6KFND4SU2O7UDJVSS74YI3PI453ZFCBM72P6TWLI7DSKFEVUQVFQC PPVABNGQTQMPYILHDNSNXBI5IOCBSIYO45NIHUR4LYPABQZE6PAQC K6ZDYZKXSLTLCCHWYK6K6WOCNXBZOXEDKDVNNJVCZUFOLLSUO5UAC 7IJQIPGG4G2DJAS2W4MUHB2TTJ75ZST6VNAMUYZXEYOVRIV4FZ5QC TBB7GHINPHDTKI3B6U3M2OF7UGQ5V5DUHODB7UNKNZMBA4NWKUFAC HTAB35N62YXTFGITVQAK6DNEKKAUKJQQ27RYO7BBVQKIHXBH6NMQC AUZQ7ULP65IGCJYIT3U6R42HEJT35R33TQHA7XNK242KWCV6IKMAC TZNPEHB3BRUHATVYAODURZUR45TYV62HYWQK5SUXHAOLVGYJVP7AC TBPJ5WSRM5IKQH7FTAVYTWWUBWW7G2CLT5M6FN7CMPLD6Y77YIWQC TTMMK6S6ILBQ6YN6H2DR5I5PH4ZUITWAGG72AJWLKLKGO5AATT2AC H2KZUAWHQXTRUFDPDH4AUG6EP3OR5U3GGFPVGTCY2XJB3WOEO7TQC LHKEZDWPB5KDA5NYEBT4XCAP3CEBRXKIAT7FX4NFKOLAQL7BU7XAC HMH2GYB6BLH4HE7N6J6ZK57RKFICWXSU3KJL7EGYTXJ5DC5XHBIQC 3RLPFCICVQARJBY26A4SX3JZCQWMGPOZC5TDIKHJ75M4EPKJVAWQC QDXO357AHOOUH3RHQFIF6XHLWOEGZFCSGUHPIL6QIQNY53CPNXFAC JIBCE66ZTWM5WEHEHNKKTRWBJQSQWBDDWPMOJIJR5Q676OSHYCNAC KAGTD334AIWFI34VE34OARC44BZDUJRP5R3ZTT6JCQGSYYC3GTVQC X5BLWVNLV62LDMYMC2BYZ44BIY4MJSWJCQERUUIL5ZSVO6EH7WMQC TK73HJVXQCBEEN4ATMLSSG4DI2XZJAQEJICJ472E3YAW55EFAT5AC BF7TW3EKRIDYC6J2Q2J4YOBAVQF55Y3H6KGZIHNXMH4N72MR6GXQC TQUVV6ZZAXGVEFRBUHRXFUIZYVBT5VFGUKSM25MYWS3QF6OB4VEQC XRAQBRS4CZ6T6TSQLCMTS4OENCCGWYEBZ52RK42PV6NMMNZZPKUAC F5BF4M6KKVFYOO65BMF3TNRTYIOHNVVMPLEQSSX6UCNOOEQMKIIAC LIWKX2BUGJ2S3JBILVBQ23FBBGKGOIWPILVZSFESSDSHAPYA5POQC NP3LZH44LOWL2RPT7MOXWX5HJADZRFT7YFZKXSTEQ4JMFQDZPE7QC X7HYGAL2QVKG7M5EMZ2VSH37UYWGE3EPUXYQBJOVL6IGJFZ2I5AAC ZANGJNNX6EITFBOF6NWCF2EM5BDQDEIOD4UPWMF5I6SKAURRTIHAC FBDRJ53NJ5BWDQGU2GWZ6NEYHKCCRD7RODMIG7QQZBRFUB4HR7OAC Page2 = {x=500, y=300,-- pagetype='text',data={},width=400, bg={r=0,g=0.8,b=0}}"Call me Ishmael. Some years ago--never mind how long precisely--having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off--then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.",'1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60',
love.graphics.setFont(love.graphics.newFont(scale(20))) -- editor objects implicitly depend on current font-- continue the pipeline-- TODO: ugly that we're manipulating editor objects twiceendB(skip_updating_screen_top_for)-- translate Page and Page2 to SurfaceSurface = {}local red = falsefor x=-1000,2000,300 dofor y=-10000,10000,200 doadd_thick_line({type='line', data={x,y, x+200,y+200, x,y+400}, r=red and 1 or 0,g=red and 0 or 0.5,b=0}, 10)red = not redendendcompute_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)A = function(skip_updating_screen_top_for)
compute_layout = function(node, x,y, nodes_to_render, skip_updating_screen_top_for)subx,suby = compute_layout(child, subx,y, nodes_to_render, skip_updating_screen_top_for)w = w + child.wif h < child.h thenh = child.hendendnode.w = wnode.h = hif node_to_render thennode_to_render.w = wnode_to_render.h = hendendsubx,suby = compute_layout(child, x,suby, nodes_to_render, skip_updating_screen_top_for)if w < child.w thenw = child.wendh = h+child.hendnode.w = wnode.h = hif node_to_render thennode_to_render.w = wnode_to_render.h = hendelseif node.type == 'cols' thennode.x = xnode.y = y-- lay out children left to rightlocal node_to_renderif node.bg thennode_to_render = {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y}table.insert(nodes_to_render, node_to_render)endlocal subx,suby = x,ylocal w,h = 0,0for _,child in ipairs(node.data) doif child.margin thensubx = subx+child.marginw = w+child.marginendupdate_editor_box(node, skip_updating_screen_top_for)end-- 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-- leaf node containing raw textnode.x = xnode.y = y-- render background if necessary
-- a table on the right{ type='rows', name='searches', margin=50, data={{ type='text', data={''},},{ type='cols', data={{ type='text', data={'search:'},},{ type='text', name='search', bg={r=0.8,g=0.8,b=0.8}, data={''}, width=90,},}},{ type='text', data={'table:'},},{ type='cols', bg={r=0.8,g=0.8,b=0.8}, data={{ type='rows', width=90, data={{type='text', data={'abc'},},{type='text', data={'abc'},},}},{ type='rows', width=90, data={{type='text', data={'def'},},{type='text', data={'def'},},}},}},}},},width=400, bg={r=1,g=1,b=0}},"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",'1','2','3','mno','Acb','g','hij','klm','nop',},}
-- 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}},
love.graphics.setColor(0,0,0)love.graphics.line(50, 0, 50, App.screen.height)for i=0,100 dolove.graphics.print(tostring(i), 30, i*100)endlocal vy0 = vy(0)love.graphics.line(100, vy0, 100, App.screen.height)for i=0,100 dolove.graphics.print(tostring(i), 80, vy0+i*100)endlove.graphics.line(vx(0), vy(0), vx(0), vy(1000000))love.graphics.line(vx(0), vy(0), vx(1000000), vy(0))for i=0,100 dolove.graphics.print(tostring(i), vx(0)-20, vy(i*100))end
elseif chord == 'C-v' then-- load new URLif Major_version >= 12 then -- requires LÖVE with https-- ignore stuff in the clipboard that doesn't look like a urllocal cb = App.get_clipboard()if #cb > 300 thenprint('clipboard: '..cb:sub(1,300)..'...')elseprint('clipboard: '..cb)endif cb:match('^%s*https://[^%s]*%s*$') thenprint('clipboard contains a URL')Url = trim(cb)
endendelseif chord == 'C-up' thenif Cursor_node.in_reply_to_id thenCursor_node = Nodes[Cursor_node.in_reply_to_id]ensure_cursor_node_within_viewport()endelseif chord == 'C-down' thenif Cursor_node.children and #Cursor_node.children > 0 thenCursor_node = Nodes[Cursor_node.children[1]]ensure_cursor_node_within_viewport()endelseif chord == 'C-left' thenif Cursor_node.in_reply_to_id thenlocal parent = Nodes[Cursor_node.in_reply_to_id]assert(parent.children)if #parent.children > 1 thenlocal idx = array.find(parent.children, Cursor_node.id)if idx > 1 thenCursor_node = Nodes[parent.children[idx-1]]ensure_cursor_node_within_viewport()endend
A()elseif chord == 'C-z' thendump_state()-- 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-- 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)returnA()
end