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,
-- page
type='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 twice
end
B(skip_updating_screen_top_for)
-- translate Page and Page2 to Surface
Surface = {}
local red = false
for x=-1000,2000,300 do
for y=-10000,10000,200 do
add_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 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)
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.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node_to_render then
node_to_render.w = w
node_to_render.h = h
end
end
subx,suby = compute_layout(child, x,suby, nodes_to_render, skip_updating_screen_top_for)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node_to_render then
node_to_render.w = w
node_to_render.h = h
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
local node_to_render
if node.bg then
node_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)
end
local subx,suby = x,y
local w,h = 0,0
for _,child in ipairs(node.data) do
if child.margin then
subx = subx+child.margin
w = w+child.margin
end
update_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 text
node.x = x
node.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 do
love.graphics.print(tostring(i), 30, i*100)
end
local vy0 = vy(0)
love.graphics.line(100, vy0, 100, App.screen.height)
for i=0,100 do
love.graphics.print(tostring(i), 80, vy0+i*100)
end
love.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 do
love.graphics.print(tostring(i), vx(0)-20, vy(i*100))
end
elseif chord == 'C-v' then
-- load new URL
if Major_version >= 12 then -- requires LÖVE with https
-- ignore stuff in the clipboard that doesn't look like a url
local cb = App.get_clipboard()
if #cb > 300 then
print('clipboard: '..cb:sub(1,300)..'...')
else
print('clipboard: '..cb)
end
if cb:match('^%s*https://[^%s]*%s*$') then
print('clipboard contains a URL')
Url = trim(cb)
end
end
elseif chord == 'C-up' then
if Cursor_node.in_reply_to_id then
Cursor_node = Nodes[Cursor_node.in_reply_to_id]
ensure_cursor_node_within_viewport()
end
elseif chord == 'C-down' then
if Cursor_node.children and #Cursor_node.children > 0 then
Cursor_node = Nodes[Cursor_node.children[1]]
ensure_cursor_node_within_viewport()
end
elseif chord == 'C-left' then
if Cursor_node.in_reply_to_id then
local parent = Nodes[Cursor_node.in_reply_to_id]
assert(parent.children)
if #parent.children > 1 then
local idx = array.find(parent.children, Cursor_node.id)
if idx > 1 then
Cursor_node = Nodes[parent.children[idx-1]]
ensure_cursor_node_within_viewport()
end
end
A()
elseif chord == 'C-z' then
dump_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)
return
A()
end