J62CVGNGJZSN7TMTE2SG53O47YG4SJGJFTUFKVOZY4TM4KAC566QC
AB5WZZKYX4HAWSO25E7DPU2DTAE2TWY3HOZE6V74OF5SQDMYZC7AC
QSFUGJRQ3I6WMKXUPY6TYMTGWDVONXY7A3EJ4SH5E32DEZFA5B4AC
QXJ3HUDHKPVZNC4LF6IC5VWQWDT7XRKASM2PLFMTSM3NGJKSHDPQC
S5KEQNTQJ5K5NS2NZUQ37SKQM6XOVI5OHLZUGBED553RPCHJ3KQQC
NDP75JUBOFE5AWPWGNMCZUOTLM4CYXG3WHOSEFJPPSS4QNLG5CKQC
VYVZXEKURUING6SYXEB2LP4QQSSM3II7JZ5ZMGC2BF2LWTMXYONAC
MFBZCXOUHS7ELP3SRTA7VDO32CUSRDIX44LXSMBPIAE5JXKFWXOQC
R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC
WA5RXMGA4V7BAL3QEW6BNYCOM4BAGKZJCKBZWCXYBC2VLDV7Z27QC
JBYPLGW2C3JYDIEYAUIRYGI33CWQJXUW2BTXYQWVK7FNMAL6FGUAC
VF2FRNK5O53KGL47ECLLXIF6PKX4ZMH54WALEKLNPVNDPUTLLUMQC
XH2FW3YDKFHC6KKCAJ5LE6EAEUUJZ23BIGNYG37PMUPHFW5KTFKAC
EHVOKKDTAH4ED432LZCX2Y4BK63BP6YAIL2U7WXWBNWJRIACY7WQC
ACEWU2ORP2QPYQQL2MXWLOQGAG4XBU5YWOO57K6KJBPJU4VDNH5AC
C3DUID2HUFDX5WXG4YZX2TUHJ5OBVEAOPSBUSGZTJW7RB4SGK46QC
U4DYD4L2LZQ4U4ZNBVA4E5DMHCWTF25A6Q4GS35B3FKB74MPIQ4AC
CKGWLO67CSR67ZO6CZAICVAC4FNCO2QBQWOBQA6CU6ISUAXLBDYAC
OZNETUSGD7GQD3XDGBFEQBSXYE4UM6G5D6OBFVNQW3XLJERHU5WQC
6QK4TD73S6BE3KJGEZG2APZKSPENEZSJ22EZUTL5GFQEJ6EBXEDQC
35W3XPSDT72C3DGWNEWRF5A42SV6PDQ3ZAWVGCA3U42EYWDVKK7QC
U3YIPNIJ6JBWKXZOKDFZFUDL3USFDIMDDVGP2JZMXGPZQ7ELKF6QC
YUQ4YINAT5YTK3CAY4VK3HSYQ4D63FXLLPMC4R3DUFHIZIUQO7WQC
S4QPRGGMVRDOB5FINBVTWSXMSOX4HA2GPRFQ5UIXRHTIHUUGZIZQC
3MH6NUDYVAVUVGBI6KC3P4FVNKBJ6EIHC2H5UPLEVGTIZJDGYCRQC
UJ2RZ43LIVRIBWIXHXMLIQIQTL32VVEN4CVU7PEBTITQFPO4EXXQC
4GXHYH5IYHUBCNQVJMXYJMVU5BF6C6TEOQEMGFFYYAL7GRCZX4XQC
2GOAQOS3LSYMBT2H6SFEN23EV6F47BDQQY2G2IENB5CGE6SF7PKAC
NNIKYLOXQHZ6TZ7SDOA2OPNVTBJGNZRVXPVFLUTKIABM7XPAPB5AC
HJQFU6IFL4WBNSG4KINMYAWNYE7GEPCXW7FM5CLNLFFA46QHTQKAC
K3TL4FPX65XC7EKRQEF4YYZVVP242NRSR4BGGBJ4H5LXVLN44ECAC
GMDEH4RHOR6DJABQ5WVGY4GVUU3QPWFTPFUHYUOULTVJZA2FTPAQC
LFAROW2YSPM7534MX4G4BM6GSIHEQWQJH4QTGP4EGYQKRX5FP27AC
FS2ITYYHBLFT66YUC3ENPFYI2HOYHOVEPQIN7NQR6KF5MEK4NKZAC
5TDFTJBI6I633A4W2NWMMP3YRYOTLRSBJU7XBU5H45UETXSPGSBQC
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
if x >= vx(node.x) and node.w and x < vx(node.x + node.w) then
if y >= vy(node.y) and node.h and y < vy(node.y + node.h) then
return node
end
end
end
end
end
{"on.text_input":388,"font":353,"scale":7,"Cursor_node":172,"on.draw":418,"A":426,"vx":5,"add_thick_line":400,"Viewport":303,"Surface":422,"update_editor_box":430,"vy":8,"line_height":365,"to_text":180,"copy_shape":396,"fw_parent":429,"on.mouse_press":179,"Page2":429,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"y_of_schema1":364,"on.code_change":306,"Page":381,"on":1,"schema1_of_y":366,"B":379}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node 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, Viewport.y - node.y)
end
node.editor.left = math.floor(vx(node.x))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
A(--[[preserve screen_top of cursor node]] true)
end
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
obj.editor = edit.initialize_state(vy(obj.y), math.floor(vx(obj.x)), math.ceil(vx(obj.x+obj.w)), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
schema1_of_y = function(editor, y)
-- return line/pos of screen line starting near a given y offset,
-- and the (negative) offset remaining after the calculation
-- invariants:
-- - 0 >= y_offset >= -Line_height
-- - let loc, y_offset = schema1_of_y(pane, y)
-- y + y_offset == y_of_schema1(pane, loc)
assert(y >= 0)
local y_offset = y
for i=1,#editor.lines do
Text.populate_screen_line_starting_pos(editor, i)
local height = line_height(editor, i)
if y_offset < height then
local line = editor.lines[i]
local nlines = math.floor(y_offset/editor.line_height)
assert(nlines >= 0 and nlines < #editor.line_cache[i].screen_line_starting_pos)
local pos = editor.line_cache[i].screen_line_starting_pos[nlines+1] -- switch to 1-indexing
y_offset = y_offset - nlines*editor.line_height
return {line=i, pos=pos}, -y_offset
end
y_offset = y_offset - height
end
-- y is below the pane
return {line=#editor.lines+1, pos=1}, y_offset -- positive value
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"on.text_input":388,"vy":8,"scale":7,"y_of_schema1":364,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.code_change":306,"on":1,"Page":381,"Page2":429,"vx":5,"font":353,"fw_parent":428,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"A":426,"on.draw":418,"Cursor_node":172}
on.update = function(dt)
if Pan then
end
if App.mouse_down(1) then
B()
end
end
Viewport.x = Pan.x - App.mouse_x()
Viewport.y = Pan.y - App.mouse_y()
B = function()
-- 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 = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
initialize_editor(obj)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
B = function()
-- 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 = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
update_editor_box(obj)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
box_height = function(node)
-- return the height of a node. The result is scaled.
print('computing box height based on font size', node.scaled_fontsize, node.editor.font_height, node.editor.line_height)
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
table.insert(Box_heights, y)
end
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
on.update = function(dt)
if Pan then
end
if App.mouse_down(1) then
B()
clip_all()
end
end
Viewport.x = Pan.x - App.mouse_x()
Viewport.y = Pan.y - App.mouse_y()
update_editor_box = function(obj)
if obj.editor == nil then return end
obj.editor.top = vy(obj.y)
obj.editor.left = math.floor(vx(obj.x))
obj.editor.right = math.ceil(vx(obj.x+obj.w))
edit.update_font_settings(obj.editor, scale(20))
Text.redraw_all(obj.editor)
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"on.text_input":388,"vy":8,"scale":7,"y_of_schema1":364,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.code_change":306,"on":1,"Page":381,"Page2":428,"vx":5,"font":353,"fw_parent":427,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"A":426,"on.draw":418,"Cursor_node":172}
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
A(--[[preserve screen_top of cursor node]] true)
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
on.text_input = function(t)
if Cursor_node then
local old_top = {line=Cursor_node.editor.screen_top1.line, pos=Cursor_node.editor.screen_top1.pos}
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)
end
A(--[[preserve screen_top of cursor node]] true)
end
end
Page2 = {
x=500, y=300,
-- page
type='text',
data={
"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."
},
width=400, bg={r=0,g=0.8,b=0}
}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
----[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), math.floor(vx(obj.x)), math.ceil(vx(obj.x+obj.w)), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"on.text_input":388,"vy":8,"scale":7,"y_of_schema1":364,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.code_change":306,"on":1,"Page":381,"Page2":427,"vx":5,"font":353,"fw_parent":426,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"A":426,"on.draw":418,"Cursor_node":172}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"on.text_input":388,"vy":8,"scale":7,"y_of_schema1":364,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.code_change":306,"on":1,"Page":381,"Page2":425,"vx":5,"font":353,"fw_parent":425,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"A":426,"on.draw":418,"Cursor_node":172}
y_of_schema1 = function(editor, loc)
local result = 0
if loc.line == 1 and loc.pos == 1 then
return result
end
for i=1,loc.line-1 do
Text.populate_screen_line_starting_pos(editor, i)
result = result + line_height(editor, i)
end
Text.populate_screen_line_starting_pos(editor, loc.line)
for i,screen_line_starting_pos in ipairs(editor.line_cache[loc.line].screen_line_starting_pos) do
if screen_line_starting_pos >= loc.pos then
break
end
result = result + editor.line_height
end
return result
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(20), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
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)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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 == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
elseif obj.type == 'bezier' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
end
end
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(20), node.data)
local width = text:getWidth()
print(node.data[i], 'has width', width)
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
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)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
B = function()
-- editor objects implicitly depend on current font so update it
love.graphics.setFont(love.graphics.newFont(scale(20)))
for _,obj in ipairs(Surface) do
if obj.type == 'line' then
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
initialize_editor(obj)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
----[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), math.ceil(vx(obj.x+obj.w)), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"on.text_input":388,"vy":8,"scale":7,"y_of_schema1":364,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.code_change":306,"on":1,"Page":381,"Page2":425,"vx":5,"font":353,"fw_parent":424,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"A":421,"on.draw":418,"Cursor_node":172}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
Page2 = {
x=500, y=300,
-- page
type='text',
data={
"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."
},
width=400, bg={r=0.8,g=0,b=0.8}
}
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
A(--[[preserve screen_top of cursor node]] true)
else
if chord == 'up' then
Viewport.y = Viewport.y - scale(20)
elseif chord == 'down' then
Viewport.y = Viewport.y + scale(20)
elseif chord == 'left' then
Viewport.x = Viewport.x - scale(50)
elseif chord == 'right' then
Viewport.x = Viewport.x + scale(50)
elseif chord == 'pageup' then
Viewport.y = Viewport.y - App.screen.height/Viewport.zoom
elseif chord == 'S-up' then
Viewport.y = Viewport.y - App.screen.height/Viewport.zoom
elseif chord == 'pagedown' then
Viewport.y = Viewport.y + App.screen.height/Viewport.zoom
elseif chord == 'S-down' then
Viewport.y = Viewport.y + App.screen.height/Viewport.zoom
elseif chord == 'S-left' then
Viewport.x = Viewport.x - App.screen.width/Viewport.zoom
elseif chord == 'S-right' then
Viewport.x = Viewport.x + App.screen.width/Viewport.zoom
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"on.text_input":388,"vy":8,"scale":7,"y_of_schema1":364,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.code_change":306,"on":1,"Page":381,"Page2":424,"vx":5,"font":353,"fw_parent":422,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"A":421,"on.draw":418,"Cursor_node":172}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B()
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print('init', obj.data[1], obj.w)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
Page = {
-- page
type='rows', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
schema1_of_y = function(editor, y)
-- return line/pos of screen line starting near a given y offset,
-- and the (negative) offset remaining after the calculation
-- invariants:
-- - 0 >= y_offset >= -Line_height
-- - let loc, y_offset = schema1_of_y(pane, y)
-- y + y_offset == y_of_schema1(pane, loc)
assert(y >= 0)
local y_offset = y
for i=1,#editor.lines do
Text.populate_screen_line_starting_pos(editor, i)
local height = line_height(editor, i)
if y_offset < height then
local line = editor.lines[i]
local nlines = math.floor(y_offset/editor.line_height)
assert(nlines >= 0 and nlines < #editor.line_cache[i].screen_line_starting_pos)
local pos = editor.line_cache[i].screen_line_starting_pos[nlines+1] -- switch to 1-indexing
y_offset = y_offset - nlines*editor.line_height
return {line=i, pos=pos}, -y_offset
end
y_offset = y_offset - height
end
-- y is below the pane
return {line=#pane.lines+1, pos=1}, y_offset -- positive value
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"B":379,"vy":8,"scale":7,"A":421,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"Page2":423,"vx":5,"font":353,"fw_parent":422,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"y_of_schema1":364,"on.draw":418,"Cursor_node":172}
box_height = function(node)
-- return the height of a node. The result is scaled.
print('computing box height based on font size', node.scaled_fontsize, node.editor.font_height, node.editor.line_height)
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
table.insert(Box_heights, y)
end
end
return y
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":421,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":421,"to_text":180,"line_height":365,"Surface":422,"add_thick_line":400,"y_of_schema1":364,"on.draw":418,"Cursor_node":172}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
on.draw = function()
for _,obj in ipairs(Surface) do
love.graphics.setColor(obj.r or 1, obj.g or 1, obj.b or 1)
if obj.type == 'rectangle' then
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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 == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
elseif obj.type == 'bezier' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":421,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":420,"to_text":180,"line_height":365,"Surface":420,"add_thick_line":400,"y_of_schema1":364,"on.draw":418,"Cursor_node":172}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
Page2 = {
x=400, y=400,
-- page
type='text',
data={
"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."
},
width=400, bg={r=0.8,g=0,b=0.8}
}
B = function(preserve_screen_top_of_cursor_node)
-- 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 = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
update_editor_box(obj, preserve_screen_top_of_cursor_node)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":417,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":419,"to_text":180,"line_height":365,"Surface":420,"add_thick_line":400,"y_of_schema1":364,"on.draw":418,"Cursor_node":172}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(20), node.data)
local width = text:getWidth()
print(node.data[i], 'has width', width)
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
if node.width and 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)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(20), node.data)
local width = text:getWidth()
print(node.data[i], 'has width', width)
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
box_height = function(node)
-- return the height of a node. The result is scaled.
print('computing box height based on font size', node.scaled_fontsize, node.editor.font_height, node.editor.line_height)
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
table.insert(Box_heights, y)
end
end
return y
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":417,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":418,"to_text":180,"line_height":365,"Surface":419,"add_thick_line":400,"y_of_schema1":364,"on.draw":418,"Cursor_node":172}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
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, preserve_screen_top_of_cursor_node)
compute_layout(Page2, Page2.x,Page2.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":417,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":417,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":418,"Cursor_node":172}
compute_layout = function(node, x,y, nodes_to_render, preserve_screen_top_of_cursor_node)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(20), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
if node.editor == nil then
initialize_editor(node)
else
update_editor_box(node, preserve_screen_top_of_cursor_node)
end
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
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)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
B = function(preserve_screen_top_of_cursor_node)
-- 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 = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
update_editor_box(obj, preserve_screen_top_of_cursor_node)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
schema1_of_y = function(editor, y)
-- return line/pos of screen line starting near a given y offset,
-- and the (negative) offset remaining after the calculation
-- invariants:
-- - 0 >= y_offset >= -Line_height
-- - let loc, y_offset = schema1_of_y(pane, y)
-- y + y_offset == y_of_schema1(pane, loc)
assert(y >= 0)
local y_offset = y
for i=1,#editor.lines do
Text.populate_screen_line_starting_pos(editor, i)
local height = line_height(editor, i, editor.left, editor.right)
if y_offset < height then
local line = editor.lines[i]
local nlines = math.floor(y_offset/editor.line_height)
assert(nlines >= 0 and nlines < #editor.line_cache[i].screen_line_starting_pos)
local pos = editor.line_cache[i].screen_line_starting_pos[nlines+1] -- switch to 1-indexing
y_offset = y_offset - nlines*editor.line_height
return {line=i, pos=pos}, -y_offset
end
y_offset = y_offset - height
end
-- y is below the pane
return {line=#pane.lines+1, pos=1}, y_offset -- positive value
end
on.draw = function()
for _,obj in ipairs(Surface) do
color(obj.r or 1, obj.g or 1, obj.b or 1)
if obj.type == 'rectangle' then
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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 == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
elseif obj.type == 'bezier' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":417,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":416,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
print(x, y, node.data[1], node.x, node.y, node.w, node.h)
if x >= vx(node.x) and node.w and x < vx(node.x + node.w) then
if y >= vy(node.y) and node.h and y < vy(node.y + node.h) then
return node
end
end
end
end
end
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node 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, Viewport.y - node.y)
end
print('top', node.editor.top)
print('screen_top1', node.editor.screen_top1.line, node.editor.screen_top1.pos)
node.editor.left = math.floor(vx(node.x))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
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))
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 or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":416,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":415,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
Page2 = {
x=800, y=400,
-- page
type='text',
data={
"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."
},
width=400, bg={r=0.8,g=0,b=0.8}
}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in ipairs(Box_heights) do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
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 or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":415,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":414,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
schema1_of_y = function(editor, y)
-- return line/pos of screen line starting near a given y offset,
-- and the (negative) offset remaining after the calculation
-- invariants:
-- - 0 >= y_offset >= -Line_height
-- - let loc, y_offset = schema1_of_y(pane, y)
-- y + y_offset == y_of_schema1(pane, loc)
return {line=1, pos=1}, 0
assert(y >= 0)
local y_offset = y
for i=1,#editor.lines do
Text.populate_screen_line_starting_pos(editor, i)
local height = line_height(editor, i, editor.left, editor.right)
if y_offset < height then
local line = editor.lines[i]
local nlines = math.floor(y_offset/editor.line_height)
assert(nlines >= 0 and nlines < #editor.line_cache[i].screen_line_starting_pos)
local pos = editor.line_cache[i].screen_line_starting_pos[nlines+1] -- switch to 1-indexing
y_offset = y_offset - nlines*editor.line_height
return {line=i, pos=pos}, -y_offset
end
y_offset = y_offset - height
end
-- y is below the pane
return {line=#pane.lines+1, pos=1}, y_offset -- positive value
end
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in ipairs(Box_heights) do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
B(--[[skip_cursor_node]] true)
end
end
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
print(x, y, node.data[1], node.x, node.y, node.w, node.h)
if x >= node.x and node.w and x < node.x + node.w then
if y >= node.y and node.h and y < node.y + node.h then
return node
end
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":414,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":413,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(20, node.data)
local width = text:getWidth()
print(node.data[i], 'has width', width)
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
box_height = function(node)
-- return the height of a node. The result is scaled.
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
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 + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":413,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":412,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
update_editor_box = function(obj)
if obj.editor == nil then return end
if obj.y > Viewport.y then
obj.editor.screen_top1.line = 1
obj.editor.screen_top1.pos = 1
obj.editor.top = vy(obj.y)
else
obj.editor.screen_top1, obj.editor.top = schema1_of_y(obj.editor, Viewport.y - obj.y)
end
print('top', obj.editor.top)
print('screen_top1', obj.editor.screen_top1.line, obj.editor.screen_top1.pos)
obj.editor.left = math.floor(vx(obj.x))
obj.editor.right = math.ceil(vx(obj.x+obj.w))
edit.update_font_settings(obj.editor, scale(20))
Text.redraw_all(obj.editor)
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":412,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":411,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
compute_layout = function(node, x,y, nodes_to_render, preserve_screen_top_of_cursor_node)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(20), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
if node.editor == nil then
initialize_editor(node)
else
update_editor_box(obj, preserve_screen_top_of_cursor_node)
end
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
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)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
----[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
print('before', Viewport.y)
Viewport.y = Cursor_node.y + y_of_schema1(Cursor_node.editor, Cursor_node.editor.screen_top1)
print('after', Viewport.y)
end
B(--[[skip_cursor_node]] true)
end
end
Surface = {
-- test data
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data={'0'}, x=-20,y=-20},
{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}},
}
Page2 = {
-- page
type='text',
data={
"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."
},
width=400, bg={r=0.8,g=0,b=0.8}
}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
print(x,y, node.data[1])
node.x = x
node.y = y
-- render background if necessary
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
on.draw = function()
for _,obj in ipairs(Surface) do
color(obj.r or 1, obj.g or 1, obj.b or 1)
if obj.type == 'rect' then
rect(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
line(unpack(obj.zdata))
elseif obj.type == 'circle' then
circ(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 == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
elseif obj.type == 'bezier' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
line(unpack(obj.zdata))
end
end
end
on.draw = function()
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
print('draw rectangle', obj.x)
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.w),scale(obj.h))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
print(x, y, node.data[1], node.x, node.y, node.w, node.h)
if x >= node.x and x < node.x + node.w then
if y >= node.y and y < node.y + node.h then
return node
end
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":411,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":410,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
B = function()
for _,obj in ipairs(Surface) do
if obj.type == 'line' then
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
initialize_editor(obj)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
B(--[[preserve screen_top of cursor node]] true)
end
end
Surface = {
-- test data
{type='rect', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{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}},
}
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
elseif Cursor_node then
end
end
edit.keychord_press(Cursor_node.editor, chord, key)
on.keychord_press = function(chord, key)
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
print(node.data[1])
if x >= node.x and x < node.x + node.w then
if y >= node.y and y < node.y + node.h then
return node
end
end
end
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":410,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":409,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
----[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
B(--[[skip_cursor_node]] true)
end
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
Surface = {
{type='rect', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{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}},
}
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":409,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":408,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
on.text_input = function(t)
if Cursor_node then
local old_top = {line=Cursor_node.editor.screen_top1.line, pos=Cursor_node.editor.screen_top1.pos}
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)
end
B(--[[preserve screen_top of cursor node]] true)
end
end
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in ipairs(Box_heights) do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
Page2 = {
-- page
type='text',
data={
'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.'
},
width=400, bg={r=0.8,g=0,b=0.8}
}
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":408,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":407,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
----[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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.screen_top1)
end
B(--[[skip_cursor_node]] true)
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":407,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":406,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
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}},
}
print('code changed')
A() -- just in case we edited Page
end
on.code_change = function()
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":406,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":405,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in ipairs(Box_heights) do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
--[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- leaf node containing raw text
node.x = x
node.y = y
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
box_height = function(node)
-- return the height of a node. The result is scaled.
print('computing box height based on font size', node.scaled_fontsize, node.editor.font_height, node.editor.line_height)
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
table.insert(Box_heights, y)
end
end
return y
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
update_editor_box = function(node, skip_cursor_node)
if node.editor == nil then return end
if skip_cursor_node and node == Cursor_node then return end
if node.y > Viewport.y then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
print('top', node.editor.top)
print('screen_top1', node.editor.screen_top1.line, node.editor.screen_top1.pos)
node.editor.left = math.floor(vx(node.x))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":405,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":404,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('Creating text of size', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
print('aaaa', obj.text)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":404,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":403,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
----[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
-- ]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":403,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":402,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
update_editor_box = function(node, skip_cursor_node)
if node.editor == nil then return end
if skip_cursor_node and node == Cursor_node then return end
if node.y > Viewport.y then
node.editor.screen_top1.line = 1
node.editor.screen_top1.pos = 1
node.editor.top = vy(node.y)
else
node.editor.screen_top1, node.editor.top = schema1_of_y(node.editor, Viewport.y - node.y)
end
print('top', node.editor.top)
print('screen_top1', node.editor.screen_top1.line, node.editor.screen_top1.pos)
node.editor.left = math.floor(vx(node.x))
node.editor.right = math.ceil(vx(node.x+obj.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
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=-20},
{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}},
}
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"scale":7,"A":402,"on.text_input":388,"schema1_of_y":366,"on.mouse_press":179,"on.initialize":350,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"on":1,"on.code_change":306,"B":379,"vx":5,"font":353,"fw_parent":400,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"y_of_schema1":364,"on.draw":346,"Cursor_node":172}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
--[[
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
]]
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":401,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":400,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"on.text_input":388,"on.draw":346,"Cursor_node":172}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(Page, Page.x,Page.y, Surface) -- just in case we edited Page
end
on.code_change = function()
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
update_editor_box = function(obj, skip_cursor_node)
if obj.editor == nil then return end
if skip_cursor_node and obj == Cursor_node then return end
if obj.y > Viewport.y then
obj.editor.screen_top1.line = 1
obj.editor.screen_top1.pos = 1
obj.editor.top = vy(obj.y)
else
obj.editor.screen_top1, obj.editor.top = schema1_of_y(obj.editor, Viewport.y - obj.y)
end
print('top', obj.editor.top)
print('screen_top1', obj.editor.screen_top1.line, obj.editor.screen_top1.pos)
obj.editor.left = math.floor(vx(obj.x))
obj.editor.right = math.ceil(vx(obj.x+obj.w))
edit.update_font_settings(obj.editor, scale(20))
Text.redraw_all(obj.editor)
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, obj.show_cursor)
end
end
end
end
Surface = {
-- test data
{type='line', data={0,-1000, 0,1000}},
{type='line', data={0,0, 800,0}},
{type='text', data={'0'}, x=-20,y=-20},
{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}},
}
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":399,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":399,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":400,"on.text_input":388,"on.draw":346,"Cursor_node":172}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
print('left', vx(obj.x))
print('right', vx(obj.x+obj.w))
print('width', vx(obj.x+obj.w)-vx(obj.x))
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":399,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":398,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":397,"on.text_input":388,"on.draw":346,"Cursor_node":172}
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":398,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":397,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":397,"on.text_input":388,"on.draw":346,"Cursor_node":172}
on.draw = function()
love.graphics.setColor(1,0,0)
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))
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 or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
if x >= node.x and x < node.x + node.w then
if y >= node.y and y < node.y + node.h then
return node
end
end
end
end
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('Creating text of size', scaled_fontsize)
love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
print('aaaa', obj.text)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('width', obj.w, 'scales to', scale(obj.w))
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":394,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":396,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":397,"on.text_input":388,"on.draw":346,"Cursor_node":172}
B = function(skip_cursor_node)
-- 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 = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
update_editor_box(obj, skip_cursor_node)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
on.update = function(dt)
if Pan then
B()
end
end
Viewport.x = Pan.x - App.mouse_x()/Viewport.zoom
Viewport.y = Pan.y - App.mouse_y()/Viewport.zoom
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
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
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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 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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
{"update_editor_box":377,"copy_shape":396,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":394,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":395,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":395,"on.text_input":388,"on.draw":346,"Cursor_node":172}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print('init', obj.data[1], obj.w)
print('at zoom', Viewport.zoom)
print('with width', obj.w)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"Viewport":303,"vy":8,"on.code_change":306,"scale":7,"A":394,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":394,"to_text":180,"line_height":365,"Surface":196,"add_thick_line":395,"on.text_input":388,"on.draw":346,"Cursor_node":172}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,2000,300 do
for y=-1000,1000,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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in ipairs(Box_heights) do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for i,s in ipairs(node.data) do
local text = love.graphics.newText(font(scaled_fontsize), node.data)
local width = text:getWidth()
print(node.data[i], 'has width', width)
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
{"update_editor_box":377,"Viewport":303,"vy":8,"scale":7,"A":394,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":393,"to_text":180,"line_height":365,"Surface":196,"on.code_change":306,"on.text_input":388,"on.draw":346,"Cursor_node":172}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(Page, Page.x,Page.y, Surface)
end
on.code_change = function()
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"update_editor_box":377,"Viewport":303,"vy":8,"scale":7,"A":393,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":392,"to_text":180,"line_height":365,"Surface":196,"on.code_change":306,"on.text_input":388,"on.draw":346,"Cursor_node":172}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,300 do
for y=-1000,1000,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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(Page, Page.x,Page.y, Surface)
end
on.code_change = function()
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('Creating text of size', scaled_fontsize)
love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
print(obj.text)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print('init', obj.data[1], obj.w)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"update_editor_box":377,"Viewport":303,"vy":8,"scale":7,"A":392,"schema1_of_y":366,"on.mouse_press":179,"y_of_schema1":364,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"on.initialize":350,"on":1,"Page":381,"B":379,"vx":5,"font":353,"fw_parent":391,"to_text":180,"line_height":365,"Surface":196,"on.code_change":306,"on.text_input":388,"on.draw":346,"Cursor_node":172}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(Page, Page.x,Page.y, Surface)
end
on.code_change = function()
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
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
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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 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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
box_height = function(node)
-- return the height of a node. The result is scaled.
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
print('box height', i, y)
table.insert(Box_heights, y)
end
end
return y
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"on.mouse_press":179,"B":379,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":391,"compute_layout":385,"Page":381,"line_height":365,"update_editor_box":377,"font":353,"on.code_change":306,"on.text_input":388,"Surface":196,"vy":8,"Cursor_node":172,"on.draw":346,"fw_parent":390,"schema1_of_y":366,"vx":5,"Viewport":303,"on":1,"to_text":180,"on.initialize":350,"y_of_schema1":364,"A":387,"scale":7}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,200 do
for y=-1000,1000,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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"on.mouse_press":179,"B":379,"on.mouse_release":367,"initialize_editor":338,"on.update":368,"box_height":345,"on.keychord_press":390,"compute_layout":385,"Page":381,"line_height":365,"update_editor_box":377,"font":353,"on.code_change":306,"on.text_input":388,"Surface":196,"vy":8,"Cursor_node":172,"on.draw":346,"fw_parent":389,"schema1_of_y":366,"vx":5,"Viewport":303,"on":1,"to_text":180,"on.initialize":350,"y_of_schema1":364,"A":387,"scale":7}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"Cursor_node":172,"scale":7,"on.update":368,"to_text":180,"font":353,"on.text_input":388,"on":1,"schema1_of_y":366,"A":387,"initialize_editor":338,"on.initialize":350,"y_of_schema1":364,"Page":381,"B":379,"on.draw":346,"box_height":345,"vx":5,"on.keychord_press":389,"Viewport":303,"compute_layout":385,"on.mouse_release":367,"vy":8,"on.code_change":306,"update_editor_box":377,"Surface":196,"fw_parent":388,"on.mouse_press":179,"line_height":365}
box_height = function(node)
-- return the height of a node. The result is scaled.
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
print('box height', i, y)
table.insert(Box_heights, y)
end
end
return y
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,400 do
for y=-1000,1000,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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"Cursor_node":172,"scale":7,"on.update":368,"to_text":180,"font":353,"on.text_input":388,"on":1,"schema1_of_y":366,"A":387,"initialize_editor":338,"on.initialize":350,"y_of_schema1":364,"Page":381,"B":379,"on.draw":346,"box_height":345,"vx":5,"on.keychord_press":383,"Viewport":303,"compute_layout":385,"on.mouse_release":367,"vy":8,"on.code_change":306,"update_editor_box":377,"Surface":196,"fw_parent":387,"on.mouse_press":179,"line_height":365}
{"Cursor_node":172,"scale":7,"on.update":368,"to_text":180,"font":353,"on.text_input":382,"on":1,"schema1_of_y":366,"A":387,"initialize_editor":338,"on.initialize":350,"y_of_schema1":364,"Page":381,"B":379,"on.draw":346,"box_height":345,"vx":5,"on.keychord_press":383,"Viewport":303,"compute_layout":385,"on.mouse_release":367,"vy":8,"on.code_change":306,"update_editor_box":377,"Surface":196,"fw_parent":386,"on.mouse_press":179,"line_height":365}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
on.draw = function()
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
print('draw rectangle')
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.w),scale(obj.h))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
box_height = function(node)
-- return the height of a node. The result is scaled.
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
print('box height', i, y)
table.insert(Box_heights, y)
end
end
return y
end
{"Cursor_node":172,"scale":7,"on.update":368,"to_text":180,"font":353,"on.text_input":382,"on":1,"schema1_of_y":366,"A":386,"initialize_editor":338,"on.initialize":350,"y_of_schema1":364,"Page":381,"B":379,"on.draw":346,"box_height":345,"vx":5,"on.keychord_press":383,"Viewport":303,"compute_layout":385,"on.mouse_release":367,"vy":8,"on.code_change":306,"update_editor_box":377,"Surface":196,"fw_parent":385,"on.mouse_press":179,"line_height":365}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
print(obj.text)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,1000 do
for y=-1000,1000,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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"on.code_change":306,"fw_parent":384,"Surface":196,"schema1_of_y":366,"on.draw":346,"font":353,"Cursor_node":172,"Viewport":303,"y_of_schema1":364,"update_editor_box":377,"vx":5,"vy":8,"on.text_input":382,"to_text":180,"line_height":365,"scale":7,"on.mouse_press":179,"A":309,"on":1,"on.mouse_release":367,"on.update":368,"B":379,"on.keychord_press":383,"box_height":345,"initialize_editor":338,"compute_layout":385,"Page":381,"on.initialize":350}
{"on.code_change":306,"fw_parent":383,"Surface":196,"schema1_of_y":366,"on.draw":346,"font":353,"Cursor_node":172,"Viewport":303,"y_of_schema1":364,"update_editor_box":377,"vx":5,"vy":8,"on.text_input":382,"to_text":180,"line_height":365,"scale":7,"on.mouse_press":179,"A":309,"on":1,"on.mouse_release":367,"on.update":368,"B":379,"on.keychord_press":383,"box_height":345,"initialize_editor":338,"compute_layout":384,"Page":381,"on.initialize":350}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,1000 do
for y=-1000,1000,100 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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
box_height = function(node)
-- return the height of a node. The result is scaled.
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
print('box height', i, y)
table.insert(Box_heights, y)
end
end
return y
end
{"on.code_change":306,"fw_parent":382,"Surface":196,"schema1_of_y":366,"on.draw":346,"font":353,"Cursor_node":172,"Viewport":303,"y_of_schema1":364,"update_editor_box":377,"vx":5,"vy":8,"on.text_input":382,"to_text":180,"line_height":365,"scale":7,"on.mouse_press":179,"A":309,"on":1,"on.mouse_release":367,"on.update":368,"B":379,"on.keychord_press":383,"box_height":345,"initialize_editor":338,"compute_layout":354,"Page":381,"on.initialize":350}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"on.code_change":306,"fw_parent":381,"Surface":196,"schema1_of_y":366,"on.draw":346,"font":353,"Cursor_node":172,"Viewport":303,"y_of_schema1":364,"update_editor_box":377,"vx":5,"vy":8,"on.text_input":382,"to_text":180,"line_height":365,"scale":7,"on.mouse_press":179,"A":309,"on":1,"on.mouse_release":367,"on.update":368,"B":379,"on.keychord_press":376,"box_height":345,"initialize_editor":338,"compute_layout":354,"Page":381,"on.initialize":350}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,100 do
for y=-1000,1000,100 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, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
on.draw = function()
print('== draw')
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
print('draw rectangle')
love.graphics.rectangle(obj.drawmode or 'fill', vx(obj.x),vy(obj.y), scale(obj.w),scale(obj.h))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
print('draw text', obj.data[1], obj.editor.lines[1].data, obj.editor.line_cache[1].fragments)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"vy":8,"schema1_of_y":366,"on.keychord_press":376,"to_text":180,"initialize_editor":338,"on.update":368,"on.initialize":350,"y_of_schema1":364,"A":309,"box_height":345,"compute_layout":354,"Page":381,"B":379,"on.mouse_release":367,"on":1,"scale":7,"on.mouse_press":179,"on.text_input":177,"Surface":196,"on.code_change":306,"fw_parent":380,"line_height":365,"Cursor_node":172,"vx":5,"update_editor_box":377,"Viewport":303,"on.draw":346,"font":353}
box_height = function(node)
-- return the height of a node. The result is scaled.
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
table.insert(Box_heights, y)
end
end
return y
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"compute_layout":354,"Page":380,"schema1_of_y":366,"fw_parent":379,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":379,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":377,"on.update":368,"box_height":345,"on.keychord_press":376}
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":378,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":379,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":377,"on.update":368,"box_height":345,"on.keychord_press":376}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
local red = false
for x=-1000,1000,100 do
for y=-1000,1000,100 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 1,b=0}, 10)
red = not red
end
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":377,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":378,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":377,"on.update":368,"box_height":345,"on.keychord_press":376}
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":376,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":377,"on.update":368,"box_height":345,"on.keychord_press":376}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for x=-1000,1000,100 do
for y=-1000,1000,100 do
add_thick_line({type='line', data={x,y, x+200,y+200, x,y+400}, r=(x+y)/1000%2,g=((x+y)/1000+1)%2,b=0}, 10)
end
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":375,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":372,"on.update":368,"box_height":345,"on.keychord_press":376}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
print('draw text', obj.data[1], obj.editor.lines[1].data, obj.editor.line_cache[1].fragments)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in ipairs(Box_heights) do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":374,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":372,"on.update":368,"box_height":345,"on.keychord_press":375}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for x=-1000,1000,100 do
for y=-1000,1000,100 do
add_thick_line({type='line', data={x,y, x+200,y+200, x,y+400}, r=(x+y)/1000%2,g=(x+y)/1000%2+1,b=0}, 10)
end
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":373,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":372,"on.update":368,"box_height":345,"on.keychord_press":374}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":372,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":372,"on.update":368,"box_height":345,"on.keychord_press":373}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for x=-1000,1000,100 do
for y=-1000,1000,100 do
add_thick_line({type='line', data={x,y, x+200,y+200, x,y+400}, r=(x+y)/1000%2,g=((x+y)/1000+1)%2,b=0}, 10)
end
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":371,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":372,"on.update":368,"box_height":345,"on.keychord_press":311}
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":370,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":371,"on.update":368,"box_height":345,"on.keychord_press":311}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for x=-1000,1000,100 do
for y=-1000,1000,100 do
add_thick_line({type='line', data={x,y, x+200,y+200, x,y+400}, r=1,g=0,b=0}, 10)
end
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
print('draw text', obj.data[1], obj.editor.lines[1].data, obj.editor.line_cache[1])
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":369,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":370,"on.update":368,"box_height":345,"on.keychord_press":311}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
love.graphics.setColor(0,1,0)
for _,y in Box_heights do
love.graphics.line(vx(0), vy(y), vx(10), vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":368,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":369,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":358,"on.update":368,"box_height":345,"on.keychord_press":311}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
-- love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for x=-1000,1000,100 do
for y=-1000,1000,100 do
add_thick_line({type='line', data={x,y, x+2000,y+2000, x,y+4000}, r=1,g=0,b=0}, 10)
end
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":367,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":352,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":358,"on.update":368,"box_height":345,"on.keychord_press":311}
{"compute_layout":354,"Page":344,"schema1_of_y":366,"fw_parent":366,"Cursor_node":172,"on":1,"on.initialize":350,"y_of_schema1":364,"A":309,"on.draw":346,"font":353,"vx":5,"B":352,"Viewport":303,"initialize_editor":338,"line_height":365,"vy":8,"on.code_change":306,"Surface":196,"on.text_input":177,"to_text":180,"on.mouse_press":179,"scale":7,"on.mouse_release":367,"update_editor_box":358,"on.update":355,"box_height":345,"on.keychord_press":311}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for y=-1000,1000,100 do
add_thick_line({type='line', data={-1000,y, 1000,y+2000, -6000,y+4000}, r=1,g=0,b=0}, 10)
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":366,"y_of_schema1":364,"to_text":180,"Page":344,"line_height":365,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":365,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
box_height = function(node)
-- return the height of a node. The result is scaled.
Box_heights = {}
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
table.insert(Box_heights, y)
end
return y
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
--[[
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
-- "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',
},
width=400, bg={r=1,g=1,b=0}
},
]]
-- 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'},},
}},
}},
}},
},
}
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":363,"y_of_schema1":364,"to_text":180,"Page":344,"line_height":365,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":364,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
print('draw text', obj.data[1], obj.editor.lines[1].data, obj.w)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":363,"y_of_schema1":364,"to_text":180,"Page":344,"line_height":362,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":363,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for y=-1000,1000,100 do
add_thick_line({type='line', data={-6000,y, 6000,y+2000, -6000,y+4000}, r=1,g=0,b=0}, 10)
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":363,"to_text":180,"Page":344,"line_height":362,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":362,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
box_height = function(node)
-- return the height of a node. The result is scaled.
print('computing box height based on font size', node.scaled_fontsize, node.editor.font_height, node.editor.line_height)
if #node.editor.lines > 1 then Box_heights = {} end
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
if #node.editor.lines > 1 then
table.insert(Box_heights, y)
end
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
box_height = function(node)
-- return the height of a node. The result is scaled.
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
end
return y
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":360,"to_text":180,"Page":344,"line_height":362,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":361,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for y=-1000,1000,100 do
add_thick_line({type='line', data={-6000,y, 6000,y+2000}, r=1,g=0,b=0}, 10)
end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":360,"to_text":180,"Page":344,"line_height":361,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":360,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
box_height = function(node)
-- return the height of a node. The result is scaled.
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
end
return y
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":360,"to_text":180,"Page":344,"on.draw":346,"on":1,"A":309,"on.initialize":350,"Viewport":303,"fw_parent":358,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"Surface":196,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
for y=-1000,1000,100 do
add_thick_line({type='line', data={-6000,y, 6000,y+2000}, r=1,g=0,b=0}, 10)
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
print('draw text', obj.data[1], obj.editor.lines[1].data, obj.w)
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"schema1_of_y":359,"Surface":196,"to_text":180,"on.draw":346,"on.initialize":350,"A":309,"on":1,"Viewport":303,"Page":344,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"fw_parent":358,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(scaled_fontsize)
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"box_height":345,"on.keychord_press":311,"compute_layout":354,"on.code_change":306,"Cursor_node":172,"font":353,"Surface":196,"to_text":180,"on.draw":346,"on.initialize":350,"A":309,"on":1,"Viewport":303,"Page":344,"B":352,"vy":8,"scale":7,"on.text_input":177,"update_editor_box":358,"vx":5,"on.mouse_press":179,"fw_parent":357,"on.mouse_release":178,"initialize_editor":338,"on.update":355}
add_thick_line = function(s, thickness)
-- increase the thickness of a horizontal-ish line
table.insert(Surface, s)
for i=1,thickness-1 do
s = copy_shape(s)
for j=2,#s.data, 2 do
s.data[j] = s.data[j]+1
end
table.insert(Surface, s)
end
end
box_height = function(node)
-- return the height of a node. The result is scaled.
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
end
return y
end
{"box_height":345,"on.mouse_release":178,"compute_layout":354,"on.update":355,"on.text_input":177,"A":309,"B":352,"Surface":196,"font":353,"on.code_change":306,"fw_parent":356,"on.initialize":350,"on.draw":346,"Cursor_node":172,"vx":5,"on.keychord_press":311,"Viewport":303,"scale":7,"Page":344,"vy":8,"on.mouse_press":179,"update_editor_box":351,"on":1,"initialize_editor":338,"to_text":180}
{"box_height":345,"on.mouse_release":178,"compute_layout":354,"on.update":355,"on.text_input":177,"A":309,"B":352,"Surface":196,"font":353,"on.code_change":306,"fw_parent":355,"clip":236,"on.initialize":350,"on.draw":346,"Cursor_node":172,"vx":5,"on.keychord_press":311,"Viewport":303,"scale":7,"Page":344,"vy":8,"on.mouse_press":179,"update_editor_box":351,"on":1,"initialize_editor":338,"to_text":180}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
add_thick_line({type='line', data={0,0, 6000,1000}, r=1,g=0,b=0}, 10)
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
box_height = function(node)
-- return the height of a node. The result is scaled.
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
end
return y
end
{"box_height":345,"on.mouse_release":178,"compute_layout":354,"on.update":355,"on.text_input":177,"A":309,"B":352,"Surface":196,"font":353,"clip_all":265,"on.code_change":306,"fw_parent":354,"clip":236,"on.initialize":350,"on.draw":346,"Cursor_node":172,"vx":5,"on.keychord_press":311,"Viewport":303,"scale":7,"Page":344,"vy":8,"on.mouse_press":179,"update_editor_box":351,"on":1,"initialize_editor":338,"to_text":180}
{"on.text_input":177,"vx":5,"to_text":180,"vy":8,"A":309,"fw_parent":353,"on.mouse_press":179,"B":352,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":354,"Viewport":303,"on":1,"Page":344,"on.initialize":350,"font":353,"scale":7,"update_editor_box":351,"Cursor_node":172,"Surface":196,"clip":236,"on.code_change":306,"clip_all":265,"on.draw":346}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
add_thick_line({type='line', data={0,0, 6000,1000}, r=1,g=0,b=0}, 5)
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"on.text_input":177,"vx":5,"to_text":180,"vy":8,"A":309,"fw_parent":352,"on.mouse_press":179,"B":352,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":349,"Viewport":303,"on":1,"Page":344,"on.initialize":350,"font":353,"scale":7,"update_editor_box":351,"Cursor_node":172,"Surface":196,"clip":236,"on.code_change":306,"clip_all":265,"on.draw":346}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(font(obj, scaled_fontsize))
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"Cursor_node":172,"vy":8,"on.mouse_press":179,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":349,"to_text":180,"Page":344,"on.code_change":306,"clip":236,"font":228,"on.text_input":177,"scale":7,"on":1,"clip_all":265,"Surface":196,"update_editor_box":351,"B":352,"on.draw":346,"on.initialize":350,"vx":5,"A":309,"Viewport":303,"fw_parent":351}
add_thick_line = function(s, thickness)
-- increase the thickness of a horizontal-ish line
table.insert(Surface, s)
for i=1,thickness-1 do
local s = copy_shape(s)
for j=2,#s.data, 2 do
s.data[j] = s.data[j]+1
end
table.insert(Surface, s)
end
end
{"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":349,"on.code_change":306,"update_editor_box":351,"on.text_input":177,"on.initialize":350,"scale":7,"Surface":196,"A":309,"vy":8,"on.draw":346,"B":316,"vx":5,"initialize_editor":338,"Viewport":303,"on":1,"fw_parent":350,"Cursor_node":172,"font":228,"clip":236,"Page":344,"clip_all":265}
{"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":349,"on.code_change":306,"on.text_input":177,"on.initialize":350,"scale":7,"Surface":196,"A":309,"vy":8,"on.draw":346,"B":316,"vx":5,"initialize_editor":338,"Viewport":303,"on":1,"fw_parent":349,"Cursor_node":172,"font":228,"clip":236,"Page":344,"clip_all":265}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"on.mouse_press":179,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":349,"Cursor_node":172,"to_text":180,"Page":344,"on.text_input":177,"Surface":196,"clip":236,"on.code_change":306,"on.draw":346,"on":1,"vx":5,"fw_parent":348,"Viewport":303,"on.initialize":304,"clip_all":265,"vy":8,"A":309,"scale":7,"B":316}
add_thick_line = function(s, thickness)
-- increase the thickness of a horizontal-ish line
table.insert(Surface, s)
for i=1,thickness-1 do
for j=2,#s.data, 2 do
s.data[j] = s.data[j]+1
end
table.insert(Surface, s)
end
end
{"on.mouse_press":179,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":348,"Cursor_node":172,"to_text":180,"Page":344,"on.text_input":177,"Surface":196,"clip":236,"on.code_change":306,"on.draw":346,"on":1,"vx":5,"fw_parent":347,"Viewport":303,"on.initialize":304,"clip_all":265,"vy":8,"A":309,"scale":7,"B":316}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
print('draw text', obj.data, obj.data[1], obj.w, obj.fg)
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"on.mouse_press":179,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":335,"Cursor_node":172,"to_text":180,"Page":344,"on.text_input":177,"Surface":196,"clip":236,"on.code_change":306,"on.draw":346,"on":1,"vx":5,"fw_parent":346,"Viewport":303,"on.initialize":304,"clip_all":265,"vy":8,"A":309,"scale":7,"B":316}
{"on.mouse_press":179,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":335,"Cursor_node":172,"to_text":180,"Page":344,"on.text_input":177,"Surface":196,"clip":236,"on.code_change":306,"on.draw":346,"on":1,"vx":5,"fw_parent":345,"Viewport":303,"on.initialize":304,"clip_all":265,"vy":8,"A":309,"Box_heights":277,"scale":7,"B":316}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(font(obj, scaled_fontsize))
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
table.insert(Surface, {type='line', data={0,0, 6000,1000}, r=1,g=0,b=0})
table.insert(Surface, {type='line', data={0,1, 6000,1001}, r=1,g=0,b=0})
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"on.mouse_press":179,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":345,"on.keychord_press":311,"compute_layout":335,"Cursor_node":172,"to_text":180,"Page":344,"on.text_input":177,"Surface":196,"clip":236,"on.code_change":306,"on.draw":310,"on":1,"vx":5,"fw_parent":344,"Viewport":303,"on.initialize":304,"clip_all":265,"vy":8,"A":309,"Box_heights":277,"scale":7,"B":316}
{"Page":344,"on.text_input":177,"Surface":196,"A":309,"on.draw":310,"vx":5,"to_text":180,"on.initialize":304,"compute_layout":335,"Viewport":303,"B":316,"on.code_change":306,"vy":8,"scale":7,"Cursor_node":172,"clip":236,"on.mouse_press":179,"clip_all":265,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":317,"on.keychord_press":311,"on":1,"fw_parent":343,"Box_heights":277}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
table.insert(Surface, {type='line', data={0,0, 6000,1000}, r=1,g=0,b=0})
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{"Page":343,"on.text_input":177,"Surface":196,"A":309,"on.draw":310,"vx":5,"to_text":180,"on.initialize":304,"compute_layout":335,"Viewport":303,"B":316,"on.code_change":306,"vy":8,"scale":7,"Cursor_node":172,"clip":236,"on.mouse_press":179,"clip_all":265,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":317,"on.keychord_press":311,"on":1,"fw_parent":342,"Box_heights":277}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
print('heights', obj.editor.line_height, obj.editor.font_height, obj.scaled_fontsize)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"Page":342,"on.text_input":177,"Surface":196,"A":309,"on.draw":310,"vx":5,"to_text":180,"on.initialize":304,"compute_layout":335,"Viewport":303,"B":316,"on.code_change":306,"vy":8,"scale":7,"Cursor_node":172,"clip":236,"on.mouse_press":179,"clip_all":265,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":317,"on.keychord_press":311,"on":1,"fw_parent":341,"Box_heights":277}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 3 do table.remove(Surface) end -- HACK
table.insert(Surface, {type='line', data={0,0, 100,600}, r=1,g=0,b=0})
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
print('draw text', obj.data, obj.data[1], obj.w)
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"Page":341,"on.text_input":177,"Surface":196,"A":309,"on.draw":310,"vx":5,"to_text":180,"on.initialize":304,"compute_layout":335,"Viewport":303,"B":316,"on.code_change":306,"vy":8,"scale":7,"Cursor_node":172,"clip":236,"on.mouse_press":179,"clip_all":265,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":317,"on.keychord_press":311,"on":1,"fw_parent":340,"Box_heights":277}
{"Page":340,"on.text_input":177,"Surface":196,"A":309,"on.draw":310,"vx":5,"to_text":180,"on.initialize":304,"compute_layout":335,"Viewport":303,"B":316,"on.code_change":306,"vy":8,"scale":7,"Cursor_node":172,"clip":236,"on.mouse_press":179,"clip_all":265,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":317,"on.keychord_press":311,"on":1,"fw_parent":339,"Box_heights":277}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
love.graphics.setFont(font(obj, scaled_fontsize))
-- obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
end
return y
end
{"Page":339,"on.text_input":177,"Surface":196,"A":309,"on.draw":310,"vx":5,"to_text":180,"on.initialize":304,"compute_layout":335,"Viewport":303,"B":316,"on.code_change":306,"vy":8,"scale":7,"Cursor_node":172,"clip":236,"on.mouse_press":179,"clip_all":265,"font":228,"on.mouse_release":178,"initialize_editor":338,"on.update":315,"box_height":317,"on.keychord_press":311,"on":1,"fw_parent":338,"Box_heights":277}
{"on.mouse_release":178,"Box_heights":277,"on":1,"on.keychord_press":311,"Page":324,"A":309,"on.update":315,"on.text_input":177,"clip_all":265,"fw_parent":337,"Surface":196,"scale":7,"on.code_change":306,"on.draw":310,"font":228,"vx":5,"Cursor_node":172,"Viewport":303,"clip":236,"on.mouse_press":179,"vy":8,"initialize_editor":338,"box_height":317,"B":316,"compute_layout":335,"on.initialize":304,"to_text":180}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + math.floor(scale(node.editor.line_height))*#node.editor.line_cache[i].screen_line_starting_pos
end
return y
end
{"on.initialize":304,"Surface":196,"B":316,"on.draw":310,"on":1,"vx":5,"on.mouse_release":178,"Viewport":303,"initialize_editor":337,"box_height":317,"vy":8,"compute_layout":335,"to_text":180,"Page":324,"on.keychord_press":311,"Box_heights":277,"on.mouse_press":179,"on.code_change":306,"Cursor_node":172,"font":228,"clip":236,"fw_parent":336,"clip_all":265,"scale":7,"on.text_input":177,"on.update":315,"A":309}
{"on.mouse_release":178,"initialize_editor":336,"on.update":315,"to_text":180,"compute_layout":335,"A":309,"box_height":317,"Box_heights":277,"Page":324,"clip":236,"on.code_change":306,"on.text_input":177,"Surface":196,"on":1,"on.draw":310,"vx":5,"clip_all":265,"Viewport":303,"B":316,"vy":8,"scale":7,"fw_parent":335,"Cursor_node":172,"font":228,"on.initialize":304,"on.mouse_press":179,"on.keychord_press":311}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(Page, Page.x,Page.y, Surface)
end
on.code_change = function()
{"fw_parent":334,"font":228,"on.mouse_release":178,"on.update":315,"box_height":317,"on.keychord_press":311,"compute_layout":335,"to_text":180,"Page":324,"clip":236,"on.code_change":306,"scale":7,"on.initialize":304,"Surface":196,"A":309,"on.draw":310,"Box_heights":277,"initialize_editor":333,"vx":5,"on.mouse_press":179,"Viewport":303,"on":1,"Cursor_node":172,"vy":8,"B":316,"clip_all":265,"on.text_input":177}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
-- y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
y = y + scale(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, Viewport.zoom, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
{"fw_parent":333,"font":228,"on.mouse_release":178,"on.update":315,"box_height":317,"on.keychord_press":311,"compute_layout":334,"to_text":180,"Page":324,"clip":236,"on.code_change":306,"scale":7,"on.initialize":304,"Surface":196,"A":309,"on.draw":310,"Box_heights":277,"initialize_editor":333,"vx":5,"on.mouse_press":179,"Viewport":303,"on":1,"Cursor_node":172,"vy":8,"B":316,"clip_all":265,"on.text_input":177}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('creating text of size', scaled_fontsize)
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"fw_parent":332,"font":228,"on.mouse_release":178,"on.update":315,"box_height":317,"on.keychord_press":311,"compute_layout":301,"to_text":180,"Page":324,"clip":236,"on.code_change":306,"scale":7,"on.initialize":304,"Surface":196,"A":309,"on.draw":310,"Box_heights":277,"initialize_editor":333,"vx":5,"on.mouse_press":179,"Viewport":303,"on":1,"Cursor_node":172,"vy":8,"B":316,"clip_all":265,"on.text_input":177}
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":331,"box_height":317,"on.mouse_press":179,"initialize_editor":332,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.scaled_fontsize*#node.editor.line_cache[i].screen_line_starting_pos
-- y = y + scale(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, Viewport.zoom, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":330,"box_height":317,"on.mouse_press":179,"initialize_editor":331,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":329,"box_height":317,"on.mouse_press":179,"initialize_editor":330,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":328,"box_height":317,"on.mouse_press":179,"initialize_editor":329,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":327,"box_height":317,"on.mouse_press":179,"initialize_editor":328,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(Page, Page.x,Page.y, Surface)
end
on.code_change = function()
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('updating editor', obj.data[1])
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":326,"box_height":317,"on.mouse_press":179,"initialize_editor":327,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
elseif Cursor_node then
end
end
edit.keychord_press(Cursor_node.editor, chord, key)
on.keychord_press = function(chord, key)
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
print('setting font', scaled_fontsize)
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":325,"box_height":317,"on.mouse_press":179,"initialize_editor":326,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
Page.x,Page.y,
Surface)
end
on.code_change = function()
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":324,"box_height":317,"on.mouse_press":179,"initialize_editor":325,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
Page.x,Page.y,
Surface)
end
on.code_change = function()
{"on.keychord_press":311,"scale":7,"Page":324,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":323,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
{"on.keychord_press":311,"scale":7,"Page":323,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":322,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
{"on.keychord_press":311,"scale":7,"Page":322,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":321,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"on.keychord_press":311,"scale":7,"Page":321,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":320,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
print(x,y, node.data[1])
node.x = x
node.y = y
-- render background if necessary
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
{"on.keychord_press":311,"scale":7,"Page":320,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":319,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
Page.x,Page.y,
Surface)
end
on.code_change = function()
{"on.keychord_press":311,"scale":7,"Page":319,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":318,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
for x=0,1000,100 do
love.graphics.line(vx(x),vy(-5), vx(x),vy(5))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"on.keychord_press":311,"scale":7,"Page":318,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":317,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
while #Surface > 3 do
table.remove(Surface)
end
print('code changed', Page.x,Page.y)
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
Page.x,Page.y,
Surface)
end
on.code_change = function()
{"on.keychord_press":311,"scale":7,"Page":312,"on.code_change":306,"clip":236,"clip_all":265,"on.text_input":177,"Surface":196,"on.initialize":304,"font":228,"A":309,"vx":5,"Box_heights":277,"Viewport":303,"B":316,"compute_layout":301,"vy":8,"Cursor_node":172,"on":1,"fw_parent":316,"box_height":317,"on.mouse_press":179,"initialize_editor":313,"on.mouse_release":178,"to_text":180,"on.update":315,"on.draw":310}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw text', obj.w, obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"clip":236,"on.mouse_release":178,"clip_all":265,"on.update":315,"box_height":297,"on.keychord_press":311,"compute_layout":301,"scale":7,"Page":312,"Box_heights":277,"to_text":180,"B":316,"Surface":196,"Cursor_node":172,"on.draw":310,"font":228,"vx":5,"on.code_change":306,"Viewport":303,"on.text_input":177,"A":309,"vy":8,"fw_parent":315,"on.initialize":304,"on":1,"initialize_editor":313,"on.mouse_press":179}
print('code changed')
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
Page.x,Page.y,
Surface)
end
on.code_change = function()
{"Box_heights":277,"on.text_input":177,"B":314,"on.mouse_press":179,"on":1,"Surface":196,"clip_all":265,"clip":236,"on.draw":310,"Viewport":303,"scale":7,"on.update":315,"on.keychord_press":311,"Page":312,"on.mouse_release":178,"vy":8,"initialize_editor":313,"box_height":297,"to_text":180,"compute_layout":301,"vx":5,"fw_parent":314,"Cursor_node":172,"on.initialize":304,"font":228,"A":309,"on.code_change":306}
Page = {
-- page
type='cols', x=0, y=20,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"Box_heights":277,"on.text_input":177,"B":314,"on.mouse_press":179,"on":1,"Surface":196,"clip_all":265,"clip":236,"on.draw":310,"Viewport":303,"scale":7,"on.update":239,"on.keychord_press":311,"Page":312,"on.mouse_release":178,"vy":8,"initialize_editor":313,"box_height":297,"to_text":180,"compute_layout":301,"vx":5,"fw_parent":313,"Cursor_node":172,"on.initialize":304,"font":228,"A":309,"on.code_change":306}
print('code changed')
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"Viewport":303,"Box_heights":277,"vy":8,"A":309,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"B":308,"on.update":239,"fw_parent":312,"on.keychord_press":311,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":313,"Page":312,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":310,"clip":236,"vx":5}
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"Viewport":303,"Box_heights":277,"vy":8,"A":309,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"B":308,"on.update":239,"fw_parent":311,"on.keychord_press":311,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":312,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":310,"clip":236,"vx":5}
{"Viewport":303,"Box_heights":277,"vy":8,"A":309,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"B":308,"on.update":239,"fw_parent":310,"on.keychord_press":311,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":310,"clip":236,"vx":5}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
if Cursor_node then
Cursor_node.show_cursor = nil
Cursor_node = nil
end
local node = to_text(x,y)
if node then
Cursor_node = node
else
end
end
Pan = {x=Viewport.x+x/Viewport.zoom,y=Viewport.y+y/Viewport.zoom}
edit.mouse_press(node.editor, x,y, mouse_button)
on.mouse_press = function(x,y, mouse_button)
{"Viewport":303,"Box_heights":277,"vy":8,"A":309,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"B":308,"on.update":239,"fw_parent":309,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":310,"clip":236,"vx":5}
if Pan then
Pan = nil
elseif Cursor_node then
Cursor_node.show_cursor = true
end
end
edit.mouse_release(Cursor_node.editor, x,y, mouse_button)
on.mouse_release = function(x,y, mouse_button)
{"Viewport":303,"Box_heights":277,"vy":8,"A":309,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"B":308,"on.update":239,"fw_parent":308,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":307,"clip":236,"vx":5}
if Cursor_node then
end
end
edit.text_input(Cursor_node.editor, t)
on.text_input = function(t)
{"Viewport":303,"Box_heights":277,"vy":8,"A":305,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"B":308,"on.update":239,"fw_parent":307,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":307,"clip":236,"vx":5}
on.draw = function()
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(vx(-5),vy(y), vx(5),vy(y))
end
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
elseif Cursor_node then
end
end
edit.keychord_press(Cursor_node.editor, chord, key)
on.keychord_press = function(chord, key)
{"Viewport":303,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"A":305,"on.update":239,"fw_parent":306,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":307,"clip":236,"vx":5}
if Pan then
Pan = nil
elseif Cursor_node then
end
end
edit.mouse_release(Cursor_node.editor, x,y, mouse_button)
on.mouse_release = function(x,y, mouse_button)
{"Viewport":303,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"A":305,"on.update":239,"fw_parent":305,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":306,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":293,"clip":236,"vx":5}
if Cursor_node then
Cursor_node.show_cursor = nil
Cursor_node = nil
end
local node = to_text(x,y)
if node then
Cursor_node = node
node.show_cursor = true
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
edit.mouse_press(node.editor, x,y, mouse_button)
on.mouse_press = function(x,y, mouse_button)
{"Viewport":303,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"A":305,"on.update":239,"fw_parent":304,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":293,"clip":236,"vx":5}
local node = to_text(x,y)
if node then
Cursor_node = node
node.show_cursor = true
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
edit.mouse_press(node.editor, x,y, mouse_button)
on.mouse_press = function(x,y, mouse_button)
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
assert(obj.w)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"Viewport":303,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":239,"fw_parent":303,"on.keychord_press":200,"compute_layout":301,"clip_all":265,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"on.initialize":304,"on.draw":293,"clip":236,"vx":5}
if Pan then
Pan = nil
else
local node = to_text(x,y)
if node then
end
end
end
edit.mouse_release(node.editor, x,y, mouse_button)
on.mouse_release = function(x,y, mouse_button)
{"Viewport":303,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":239,"fw_parent":302,"on.keychord_press":200,"compute_layout":301,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"clip_all":265,"on.draw":293,"clip":236,"vx":5}
if Pan then
Pan = nil
else
local node = to_text(x,y)
if node then
end
end
edit.mouse_release(node.editor, x,y, mouse_button)
on.mouse_release = function(x,y, mouse_button)
{"Viewport":302,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":239,"fw_parent":301,"on.keychord_press":200,"compute_layout":301,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"clip_all":265,"on.draw":293,"clip":236,"vx":5}
Page = {
-- page
type='cols', x=0, y=20,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
local node = to_text(x,y)
if node then
node.show_cursor = true
print('show cursor')
else
print('pan')
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
edit.mouse_press(node.editor, x,y, mouse_button)
on.mouse_press = function(x,y, mouse_button)
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(obj.editor.left,vy(y), obj.editor.right,vy(y))
end
end
end
end
end
{"Viewport":298,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":239,"fw_parent":300,"on.keychord_press":200,"compute_layout":301,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"clip_all":265,"on.draw":293,"clip":236,"vx":5}
{"Viewport":298,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":239,"fw_parent":299,"on.keychord_press":200,"compute_layout":235,"box_height":297,"Cursor_node":172,"initialize_editor":300,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"clip_all":265,"on.draw":293,"clip":236,"vx":5}
local node = to_text(x,y)
if node then
node.show_cursor = true
print('show cursor')
else
print('pan')
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
on.mouse_press = function(x,y, mouse_button)
Surface = {
-- test data
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data={'0'}, x=-20,y=-20},
{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}},
}
{"Viewport":298,"Box_heights":277,"vy":8,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"on.update":239,"fw_parent":298,"on.keychord_press":200,"compute_layout":235,"box_height":297,"Cursor_node":172,"initialize_editor":290,"Page":296,"font":228,"on.code_change":299,"scale":7,"on.text_input":177,"Surface":196,"on":1,"clip_all":265,"on.draw":293,"clip":236,"vx":5}
{"Page":296,"Cursor_node":172,"on.code_change":289,"to_text":180,"on.draw":293,"on.mouse_press":179,"vx":5,"clip":236,"Viewport":298,"clip_all":265,"on":1,"vy":8,"scale":7,"Surface":196,"fw_parent":297,"Box_heights":277,"font":228,"on.update":239,"on.mouse_release":178,"on.text_input":177,"initialize_editor":290,"box_height":297,"on.keychord_press":200,"compute_layout":235}
{"box_height":297,"on.keychord_press":200,"compute_layout":235,"Cursor_node":172,"on.code_change":289,"on.text_input":177,"Surface":196,"to_text":180,"on.draw":293,"vx":5,"scale":7,"Viewport":233,"clip":236,"initialize_editor":290,"clip_all":265,"Page":296,"vy":8,"font":228,"on.update":239,"on.mouse_press":179,"fw_parent":296,"on.mouse_release":178,"on":1,"Box_heights":277}
{"box_height":295,"on.keychord_press":200,"compute_layout":235,"Cursor_node":172,"on.code_change":289,"on.text_input":177,"Surface":196,"to_text":180,"on.draw":293,"vx":5,"scale":7,"Viewport":233,"clip":236,"initialize_editor":290,"clip_all":265,"Page":296,"vy":8,"font":228,"on.update":239,"on.mouse_press":179,"fw_parent":295,"on.mouse_release":178,"on":1,"Box_heights":277}
on.draw = function()
print('on.draw')
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
print('initializing editor')
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
initialize_editor(obj)
print('updating editor', obj.editor)
end
print('editor', obj.editor)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"box_height":295,"on.keychord_press":200,"compute_layout":235,"Cursor_node":172,"on.code_change":289,"on.text_input":177,"Surface":196,"to_text":180,"on.draw":293,"vx":5,"scale":7,"Viewport":233,"clip":236,"initialize_editor":290,"clip_all":265,"Page":263,"vy":8,"font":228,"on.update":239,"on.mouse_press":179,"fw_parent":294,"on.mouse_release":178,"on":1,"Box_heights":277}
local node = to_text(x,y)
if node then
node.show_cursor = true
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
on.mouse_press = function(x,y, mouse_button)
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
love.graphics.setColor(1,0,0)
for y=0,1000,100 do
love.graphics.line(obj.editor.left,y, obj.editor.right,y)
end
end
end
end
end
{"box_height":294,"on.keychord_press":200,"compute_layout":235,"Cursor_node":172,"on.code_change":289,"on.text_input":177,"Surface":196,"to_text":180,"on.draw":293,"vx":5,"scale":7,"Viewport":233,"clip":236,"initialize_editor":290,"clip_all":265,"Page":263,"vy":8,"font":228,"on.update":239,"on.mouse_press":179,"fw_parent":293,"on.mouse_release":178,"on":1,"Box_heights":277}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 15)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
{"Surface":196,"on.draw":293,"vx":5,"Viewport":233,"fw_parent":292,"on":1,"clip":236,"clip_all":265,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"font":228,"on.update":239,"on.keychord_press":200,"Cursor_node":172,"Box_heights":277,"vy":8,"Page":263,"on.code_change":289,"initialize_editor":290,"on.text_input":177,"box_height":291,"compute_layout":235,"scale":7}
{"fw_parent":291,"on.text_input":177,"to_text":180,"on.mouse_press":179,"on.mouse_release":178,"font":228,"on.update":239,"Page":263,"initialize_editor":290,"box_height":291,"on.keychord_press":200,"compute_layout":235,"clip":236,"clip_all":265,"Surface":196,"Box_heights":277,"on":1,"on.draw":292,"on.code_change":289,"Cursor_node":172,"vy":8,"Viewport":233,"vx":5,"scale":7}
{"fw_parent":290,"on.text_input":177,"to_text":180,"on.mouse_press":179,"on.mouse_release":178,"font":228,"on.update":239,"Page":263,"initialize_editor":290,"box_height":291,"on.keychord_press":200,"compute_layout":235,"clip":236,"clip_all":265,"Surface":196,"Box_heights":277,"on":1,"on.draw":286,"on.code_change":289,"Cursor_node":172,"vy":8,"Viewport":233,"vx":5,"scale":7}
{"on.code_change":289,"font":228,"Surface":196,"to_text":180,"clip_all":265,"on.draw":286,"on.text_input":177,"vx":5,"on":1,"Viewport":233,"fw_parent":289,"vy":8,"scale":7,"on.mouse_press":179,"Cursor_node":172,"on.mouse_release":178,"Box_heights":277,"on.update":239,"box_height":285,"on.keychord_press":200,"compute_layout":235,"clip":236,"initialize_editor":290,"Page":263}
on.draw = function()
print('on.draw')
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
print('initializing editor')
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
initialize_editor(obj)
print('updating editor', obj.editor)
end
print('editor', obj.editor)
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"Surface":196,"on.draw":286,"vx":5,"Viewport":233,"vy":8,"to_text":180,"on":1,"on.mouse_press":179,"scale":7,"on.mouse_release":178,"fw_parent":288,"clip_all":265,"box_height":285,"on.keychord_press":200,"compute_layout":235,"on.update":239,"initialize_editor":254,"Page":263,"clip":236,"on.text_input":177,"Box_heights":277,"on.code_change":289,"font":228,"Cursor_node":172}
{"Surface":196,"on.draw":286,"vx":5,"Viewport":233,"vy":8,"to_text":180,"on":1,"on.mouse_press":179,"scale":7,"on.mouse_release":178,"fw_parent":287,"clip_all":265,"box_height":285,"on.keychord_press":200,"compute_layout":235,"on.update":239,"initialize_editor":254,"Page":263,"clip":236,"on.text_input":177,"Box_heights":277,"on.code_change":288,"font":228,"Cursor_node":172}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
love.graphics.setColor(1,0,0)
for i=1,#obj.editor.lines do
local y = obj.y + obj.editor.line_cache[i].starty
love.graphics.line(obj.editor.left,y, obj.editor.right,y)
end
end
end
end
end
{"on.code_change":287,"Surface":196,"clip_all":265,"on.draw":286,"on.text_input":177,"vx":5,"Viewport":233,"vy":8,"fw_parent":286,"on.mouse_press":179,"Box_heights":277,"on.mouse_release":178,"scale":7,"on.update":239,"initialize_editor":254,"box_height":285,"clip":236,"compute_layout":235,"on.keychord_press":200,"Page":263,"Cursor_node":172,"font":228,"on":1,"to_text":180}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
print(x,y, node.data[1])
node.x = x
node.y = y
-- render background if necessary
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 15)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":286,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":285,"box_height":285,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":280,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":284,"box_height":285,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":280,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":283,"box_height":284,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
on.draw = function()
print('on.draw')
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
initialize_editor(obj)
print('updating editor', obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":280,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":282,"box_height":283,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":280,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":281,"box_height":282,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"on.code_change":212,"font":228,"Surface":196,"on.draw":280,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":280,"box_height":281,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 15)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
end
end
end
end
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
love.graphics.setColor(1,0,0)
for i=1,#obj.editor.lines do
local y = obj.y + obj.editor.line_cache[i].starty
love.graphics.line(0,y, 800,y)
end
end
end
end
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":280,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":279,"box_height":278,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":279,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":278,"box_height":278,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":277,"box_height":278,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
print('on.code_change')
compute_layout = function(node, x,y, nodes_to_render)
print('compute_layout')
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
print('node editor', node.editor)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on":1,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":276,"box_height":276,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"Box_heights":277}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":275,"box_height":276,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":274,"box_height":275,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":273,"box_height":274,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
print('on.code_change')
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
love.graphics.setColor(1,0,0)
for i=1,#obj.editor.lines do
local y = vy(obj.editor.line_cache[i].starty)
love.graphics.line(0,y, 800,y)
end
end
end
end
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":272,"box_height":273,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":272,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":271,"box_height":270,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":271,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":270,"box_height":270,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
Page = {
-- page
type='cols', x=0, y=200,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":266,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":269,"box_height":270,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":266,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":268,"box_height":269,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
initialize_editor(obj)
print('updating editor', obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":266,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":267,"box_height":268,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":266,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":266,"box_height":267,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
love.graphics.setFont(font(scaled_fontsize))
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
love.graphics.setColor(1,0,0)
for i=1,#obj.editor.lines do
local y = vy(obj.editor.lines[i].starty)
love.graphics.line(0,y, 800,y)
end
end
end
end
end
{"on.code_change":212,"font":228,"Surface":196,"on.draw":266,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":265,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":264,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":265,"on.mouse_release":178,"Cursor_node":172,"fw_parent":264,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":264,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":241,"on.mouse_release":178,"Cursor_node":172,"fw_parent":263,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":262,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":241,"on.mouse_release":178,"Cursor_node":172,"fw_parent":262,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":263,"clip":236,"scale":7,"on":1}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + scale(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, Viewport.zoom, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
print('node editor', node.editor)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
Page = {
-- page
type='cols', x=0, y=400,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"on.code_change":212,"font":228,"Surface":196,"on.draw":262,"vx":5,"Viewport":233,"to_text":180,"vy":8,"initialize_editor":254,"on.mouse_press":179,"clip_all":241,"on.mouse_release":178,"Cursor_node":172,"fw_parent":261,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on.update":239,"Page":243,"clip":236,"scale":7,"on":1}
{"on.code_change":212,"scale":7,"on.text_input":177,"Surface":196,"clip":236,"on.draw":261,"vx":5,"font":228,"Viewport":233,"on":1,"vy":8,"to_text":180,"on.mouse_press":179,"fw_parent":260,"on.mouse_release":178,"initialize_editor":254,"box_height":255,"on.keychord_press":200,"compute_layout":235,"Page":243,"on.update":239,"Cursor_node":172,"clip_all":241}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print(obj.fontsize, scaled_fontsize, scaled_lineheight)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"on.code_change":212,"scale":7,"on.text_input":177,"Surface":196,"clip":236,"on.draw":260,"vx":5,"font":228,"Viewport":233,"on":1,"vy":8,"to_text":180,"on.mouse_press":179,"fw_parent":259,"on.mouse_release":178,"initialize_editor":254,"box_height":255,"on.keychord_press":200,"compute_layout":235,"Page":243,"on.update":239,"Cursor_node":172,"clip_all":241}
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"Page":243,"on.code_change":212,"Surface":196,"to_text":180,"vx":5,"Viewport":233,"font":228,"initialize_editor":254,"vy":8,"Cursor_node":172,"on.mouse_press":179,"clip":236,"scale":7,"clip_all":241,"on.draw":259,"on.mouse_release":178,"fw_parent":258,"on.update":239,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on":1}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print(obj.fontsize, scaled_fontsize, scaled_lineheight)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"Page":243,"on.code_change":212,"Surface":196,"to_text":180,"vx":5,"Viewport":233,"font":228,"initialize_editor":254,"vy":8,"Cursor_node":172,"on.mouse_press":179,"clip":236,"scale":7,"clip_all":241,"on.draw":258,"on.mouse_release":178,"fw_parent":257,"on.update":239,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on":1}
{"Page":243,"on.code_change":212,"Surface":196,"to_text":180,"vx":5,"Viewport":233,"font":228,"initialize_editor":254,"vy":8,"Cursor_node":172,"on.mouse_press":179,"clip":236,"scale":7,"clip_all":241,"on.draw":257,"on.mouse_release":178,"fw_parent":256,"on.update":239,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on":1}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
print(node.editor)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
{"Page":243,"on.code_change":212,"Surface":196,"to_text":180,"vx":5,"Viewport":233,"font":228,"initialize_editor":254,"vy":8,"Cursor_node":172,"on.mouse_press":179,"clip":236,"scale":7,"clip_all":241,"on.draw":256,"on.mouse_release":178,"fw_parent":255,"on.update":239,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on":1}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print(obj.fontsize, scaled_fontsize, scaled_lineheight)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"Page":243,"on.code_change":212,"Surface":196,"to_text":180,"vx":5,"Viewport":233,"font":228,"initialize_editor":254,"vy":8,"Cursor_node":172,"on.mouse_press":179,"clip":236,"scale":7,"clip_all":241,"on.draw":234,"on.mouse_release":178,"fw_parent":254,"on.update":239,"box_height":255,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"on":1}
{"on.code_change":212,"on.text_input":177,"Surface":196,"to_text":180,"scale":7,"vx":5,"Viewport":233,"vy":8,"on":1,"Page":243,"fw_parent":253,"on.draw":234,"on.mouse_press":179,"clip":236,"on.mouse_release":178,"clip_all":241,"on.update":239,"box_height":250,"on.keychord_press":200,"compute_layout":235,"font":228,"initialize_editor":254,"Cursor_node":172}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
print(scaled_fontsize, scaled_lineheight)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, scaled_lineheight)
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
{"font":228,"initialize_editor":253,"Surface":196,"Cursor_node":172,"on.draw":234,"fw_parent":252,"vx":5,"on":1,"on.text_input":177,"to_text":180,"on.mouse_release":178,"vy":8,"on.update":239,"box_height":250,"on.keychord_press":200,"compute_layout":235,"on.mouse_press":179,"clip_all":241,"Page":243,"Viewport":233,"clip":236,"on.code_change":212,"scale":7}
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"initialize_editor":252,"on.mouse_press":179,"on.mouse_release":178,"Cursor_node":172,"on.update":239,"box_height":250,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"Page":243,"to_text":180,"on.code_change":212,"scale":7,"Surface":196,"on.draw":234,"vx":5,"font":228,"clip":236,"Viewport":233,"clip_all":241,"on":1,"vy":8,"fw_parent":251}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
print(x,y, node.data[1])
node.x = x
node.y = y
-- render background if necessary
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
-- --[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
{"initialize_editor":251,"on.mouse_press":179,"on.mouse_release":178,"Cursor_node":172,"on.update":239,"box_height":250,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"Page":243,"to_text":180,"on.code_change":212,"scale":7,"Surface":196,"on.draw":234,"vx":5,"font":228,"clip":236,"Viewport":233,"clip_all":241,"on":1,"vy":8,"fw_parent":250}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + scale(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, Viewport.zoom, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
while #Surface > 3 do
table.remove(Surface)
end
compute_layout(
Page,
-- --[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"initialize_editor":74,"on.mouse_press":179,"on.mouse_release":178,"Cursor_node":172,"on.update":239,"box_height":250,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"Page":243,"to_text":180,"on.code_change":212,"scale":7,"Surface":196,"on.draw":234,"vx":5,"font":228,"clip":236,"Viewport":233,"clip_all":241,"on":1,"vy":8,"fw_parent":249}
while #Surface > 3 do
table.remove(Surface)
end
local node = compute_layout(
Page,
-- --[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0,
Surface)
end
on.code_change = function()
{"initialize_editor":74,"on.mouse_press":179,"on.mouse_release":178,"Cursor_node":172,"on.update":239,"box_height":249,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"Page":243,"to_text":180,"on.code_change":212,"scale":7,"Surface":196,"on.draw":234,"vx":5,"font":228,"clip":236,"Viewport":233,"clip_all":241,"on":1,"vy":8,"fw_parent":248}
{"initialize_editor":74,"on.mouse_press":179,"on.mouse_release":178,"Cursor_node":172,"on.update":239,"box_height":248,"on.keychord_press":200,"compute_layout":235,"on.text_input":177,"Page":243,"to_text":180,"on.code_change":212,"scale":7,"Surface":196,"on.draw":234,"vx":5,"font":228,"clip":236,"Viewport":233,"clip_all":241,"on":1,"vy":8,"fw_parent":247}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + scale(node.editor.line_height)*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
{"on.mouse_release":178,"on.update":239,"box_height":247,"on.keychord_press":200,"compute_layout":235,"fw_parent":246,"Page":243,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":239,"box_height":246,"on.keychord_press":200,"compute_layout":235,"fw_parent":245,"Page":243,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
local node = compute_layout(
Page,
-- --[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
{"on.mouse_release":178,"on.update":239,"box_height":245,"on.keychord_press":200,"compute_layout":235,"fw_parent":244,"Page":243,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page,
-- --[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1], obj.fg)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
compute_layout = function(node, x,y, nodes_to_render)
-- 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
print(node.data[1])
node.x = x
node.y = y
-- render background if necessary
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
-- render contents
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
if node_to_render then
node_to_render.w = node.w
node_to_render.h = node.h
end
elseif node.type == 'rows' then
node.x = x
node.y = y
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
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
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
return x+node.w,y+node.h
end
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
--Page,
-- --[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
{"on.mouse_release":178,"on.update":239,"box_height":244,"on.keychord_press":200,"compute_layout":235,"fw_parent":243,"Page":243,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
--Page,
-- [[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- ]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
{"on.mouse_release":178,"on.update":239,"box_height":44,"on.keychord_press":200,"compute_layout":235,"fw_parent":242,"Page":243,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
print('height', i, node.editor.line_height, #node.editor.line_cache[i].screen_line_starting_pos, y)
Text.clear_screen_line_cache(node.editor, i)
end
return y
end
{"on.mouse_release":178,"on.update":239,"box_height":44,"on.keychord_press":200,"compute_layout":235,"fw_parent":241,"Page":242,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
{"on.mouse_release":178,"on.update":239,"box_height":44,"on.keychord_press":200,"compute_layout":235,"fw_parent":240,"Page":202,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":241,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page,
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
{"on.mouse_release":178,"on.update":239,"box_height":44,"on.keychord_press":200,"compute_layout":235,"fw_parent":239,"Page":202,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":240,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
Text.clear_screen_line_cache(node.editor, i)
print('height', i, node.editor.line_height, #node.editor.line_cache[i].screen_line_starting_pos, y)
end
return y
end
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
{"on.mouse_release":178,"on.update":239,"box_height":44,"on.keychord_press":200,"compute_layout":235,"fw_parent":238,"Page":202,"on.text_input":177,"on.code_change":212,"Surface":196,"on":1,"font":228,"to_text":180,"on.draw":234,"Viewport":233,"scale":7,"clip":236,"vy":8,"initialize_editor":74,"clip_all":237,"Cursor_node":172,"vx":5,"on.mouse_press":179}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
{"vx":5,"on.text_input":177,"Viewport":233,"vy":8,"on.mouse_press":179,"on.mouse_release":178,"scale":7,"on.update":238,"to_text":180,"on.keychord_press":200,"compute_layout":235,"fw_parent":237,"Page":202,"clip_all":237,"box_height":44,"on.code_change":212,"Cursor_node":172,"initialize_editor":74,"on":1,"clip":236,"Surface":196,"on.draw":234,"font":228}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('draw', obj.data[1])
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
]]
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
end
on.code_change = function()
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
Text.clear_screen_line_cache(node.editor, i)
print('height', i, y)
end
return y
end
{"vx":5,"on.text_input":177,"Viewport":233,"vy":8,"on.mouse_press":179,"on.mouse_release":178,"scale":7,"on.update":14,"to_text":180,"on.keychord_press":200,"compute_layout":235,"fw_parent":236,"Page":202,"clip_all":237,"box_height":44,"on.code_change":212,"Cursor_node":172,"initialize_editor":74,"on":1,"clip":236,"Surface":196,"on.draw":234,"font":228}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
]]
print('AAA', #Surface)
end
on.code_change = function()
Page = {
-- page
type='cols', x=0, y=400,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"vx":5,"on.text_input":177,"Viewport":233,"vy":8,"on.mouse_press":179,"on.mouse_release":178,"scale":7,"on.update":14,"to_text":180,"on.keychord_press":200,"compute_layout":235,"fw_parent":235,"Page":202,"box_height":44,"on.code_change":212,"Cursor_node":172,"initialize_editor":74,"on":1,"clip":236,"Surface":196,"on.draw":234,"font":228}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
Page)
--[[
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
]]
print('AAA', #Surface)
end
on.code_change = function()
{"vx":5,"Viewport":233,"initialize_editor":74,"vy":8,"compute_layout":235,"scale":7,"on.mouse_press":179,"on.mouse_release":178,"on.text_input":177,"on.update":14,"font":228,"on.keychord_press":200,"to_text":180,"Page":202,"fw_parent":234,"on":1,"Surface":196,"box_height":44,"on.code_change":212,"on.draw":234,"Cursor_node":172}
box_height = function(node)
local y = 0
for i=1,#node.editor.lines do
local line = node.editor.lines[i]
if node.editor.line_cache[i] == nil then
node.editor.line_cache[i] = {}
end
node.editor.line_cache[i].fragments = nil
node.editor.line_cache[i].screen_line_starting_pos = nil
Text.compute_fragments(node.editor, i)
Text.populate_screen_line_starting_pos(node.editor, i)
y = y + node.editor.line_height*#node.editor.line_cache[i].screen_line_starting_pos
Text.clear_screen_line_cache(node.editor, i)
print('height', i, y)
end
return y
end
{"vx":5,"Viewport":233,"initialize_editor":74,"vy":8,"compute_layout":229,"scale":7,"on.mouse_press":179,"on.mouse_release":178,"on.text_input":177,"on.update":14,"font":228,"on.keychord_press":200,"to_text":180,"Page":202,"fw_parent":233,"on":1,"Surface":196,"box_height":44,"on.code_change":212,"on.draw":234,"Cursor_node":172}
{"vx":5,"Viewport":233,"initialize_editor":74,"vy":8,"compute_layout":229,"scale":7,"on.mouse_press":179,"on.mouse_release":178,"on.text_input":177,"on.update":14,"font":228,"on.keychord_press":200,"to_text":180,"Page":202,"fw_parent":232,"on":1,"Surface":196,"box_height":44,"on.code_change":212,"on.draw":225,"Cursor_node":172}
{"vx":5,"Viewport":232,"initialize_editor":74,"vy":8,"compute_layout":229,"scale":7,"on.mouse_press":179,"on.mouse_release":178,"on.text_input":177,"on.update":14,"font":228,"on.keychord_press":200,"to_text":180,"Page":202,"fw_parent":231,"on":1,"Surface":196,"box_height":44,"on.code_change":212,"on.draw":225,"Cursor_node":172}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.w = 0
for _,s in ipairs(node.data) do
local text = love.graphics.newText(font(node, scaled_fontsize), node.data)
local width = text:getWidth()
if node.w < width then node.w = width end
end
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
{"vx":5,"Viewport":231,"initialize_editor":74,"vy":8,"compute_layout":229,"scale":7,"on.mouse_press":179,"on.mouse_release":178,"on.text_input":177,"on.update":14,"font":228,"on.keychord_press":200,"to_text":180,"Page":202,"fw_parent":230,"on":1,"Surface":196,"box_height":44,"on.code_change":212,"on.draw":225,"Cursor_node":172}
{"vx":5,"Viewport":230,"initialize_editor":74,"vy":8,"compute_layout":229,"scale":7,"on.mouse_press":179,"on.mouse_release":178,"on.text_input":177,"on.update":14,"font":228,"on.keychord_press":200,"to_text":180,"Page":202,"fw_parent":229,"on":1,"Surface":196,"box_height":44,"on.code_change":212,"on.draw":225,"Cursor_node":172}
{"on.draw":225,"compute_layout":229,"vx":5,"font":228,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":228,"scale":7,"Viewport":227,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
Page = {
-- page
type='cols', x=0, y=20,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"on.draw":225,"compute_layout":205,"vx":5,"font":228,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":227,"scale":7,"Viewport":227,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":225,"compute_layout":205,"vx":5,"font":224,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":226,"scale":7,"Viewport":227,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":225,"compute_layout":205,"vx":5,"font":224,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":225,"scale":7,"Viewport":226,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
print(node.data[1], node.w)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
print('AAA', #Surface)
end
on.code_change = function()
{"on.draw":225,"compute_layout":205,"vx":5,"font":224,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":224,"scale":7,"Viewport":221,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
Page = {
-- page
type='cols', x=0, y=300,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
{"on.draw":223,"compute_layout":205,"vx":5,"font":224,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":223,"scale":7,"Viewport":221,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
Page = {
-- page
type='cols', x=0, y=20,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"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',
},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node,
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
}
print('AAA', #Surface)
end
on.code_change = function()
{"on.draw":223,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":222,"scale":7,"Viewport":221,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node}
print('AAA', #Surface)
end
on.code_change = function()
{"on.draw":222,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":221,"scale":7,"Viewport":221,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":220,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":220,"scale":7,"Viewport":221,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
print('AAAAAAAAAAAAAAAAA')
local node = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node}
print('AAA', #Surface)
end
on.code_change = function()
{"on.draw":220,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":219,"scale":7,"Viewport":217,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
local node = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node}
print('AAA', #Surface)
end
on.code_change = function()
on.update = function(dt)
if Pan then
end
if App.mouse_down(1) then
clip_all()
end
end
Viewport.x = Pan.x - App.mouse_x()
Viewport.y = Pan.y - App.mouse_y()
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
print(node.w)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
local node = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node}
print('AAA')
end
on.code_change = function()
{"on.draw":219,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":218,"scale":7,"Viewport":217,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
local node = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
Surface = {node}
end
on.code_change = function()
{"on.draw":218,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":217,"scale":7,"Viewport":217,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":216,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":216,"scale":7,"Viewport":217,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
Surface = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
end
on.code_change = function()
{"on.draw":216,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":215,"scale":7,"Viewport":215,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":211,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":214,"scale":7,"Viewport":215,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":211,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":213,"scale":7,"Viewport":214,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"on.draw":211,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":212,"scale":7,"Viewport":213,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":211,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":212,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":211,"scale":7,"Viewport":204,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":211,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":201,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":210,"scale":7,"Viewport":204,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":210,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":201,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":209,"scale":7,"Viewport":204,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"on.draw":209,"compute_layout":205,"vx":5,"font":104,"Cursor_node":172,"vy":8,"on.code_change":201,"on.text_input":177,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":200,"Page":202,"fw_parent":208,"scale":7,"Viewport":204,"on":1,"to_text":180,"Surface":196,"initialize_editor":74,"box_height":44}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":208,"vx":5,"Viewport":204,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":207,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":205,"on.text_input":177,"Page":202}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":207,"vx":5,"Viewport":204,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":206,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":205,"on.text_input":177,"Page":202}
on.draw = function()
for _,obj in ipairs(Surface) do
print(obj.type, obj.data)
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":206,"vx":5,"Viewport":204,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":205,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":205,"on.text_input":177,"Page":202}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":204,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":204,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":205,"on.text_input":177,"Page":202}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":204,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":203,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":194,"on.text_input":177,"Page":202}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":203,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":202,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":194,"on.text_input":177,"Page":202}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":29,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":201,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":194,"on.text_input":177,"Page":202}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":29,"vy":8,"initialize_editor":74,"on":1,"on.code_change":201,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":200,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":194,"on.text_input":177,"Page":197}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":29,"vy":8,"initialize_editor":74,"on":1,"on.code_change":199,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":199,"on.update":14,"box_height":44,"on.keychord_press":200,"scale":7,"compute_layout":194,"on.text_input":177,"Page":197}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":29,"vy":8,"initialize_editor":74,"on":1,"on.code_change":199,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":198,"on.update":14,"box_height":44,"on.keychord_press":176,"scale":7,"compute_layout":194,"on.text_input":177,"Page":197}
{"Cursor_node":172,"font":104,"Surface":196,"on.draw":195,"vx":5,"Viewport":29,"vy":8,"initialize_editor":74,"on":1,"on.code_change":198,"on.mouse_press":179,"to_text":180,"on.mouse_release":178,"fw_parent":197,"on.update":14,"box_height":44,"on.keychord_press":176,"scale":7,"compute_layout":194,"on.text_input":177,"Page":197}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":194,"Page":197,"on.code_change":190,"on.text_input":177,"Surface":196,"on":1,"on.draw":195,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":196,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":194,"Page":192,"on.code_change":190,"on.text_input":177,"Surface":196,"on":1,"on.draw":195,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":195,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":194,"Page":192,"on.code_change":190,"on.text_input":177,"Surface":165,"on":1,"on.draw":195,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":194,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":194,"Page":192,"on.code_change":190,"on.text_input":177,"Surface":165,"on":1,"on.draw":193,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":193,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":187,"Page":192,"on.code_change":190,"on.text_input":177,"Surface":165,"on":1,"on.draw":193,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":192,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":187,"Page":192,"on.code_change":190,"on.text_input":177,"Surface":165,"on":1,"on.draw":162,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":191,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.mouse_release":178,"on.update":14,"box_height":44,"font":104,"compute_layout":187,"Page":191,"on.code_change":190,"on.text_input":177,"Surface":165,"on":1,"on.draw":162,"vx":5,"scale":7,"Viewport":29,"Cursor_node":172,"vy":8,"fw_parent":190,"to_text":180,"initialize_editor":74,"on.keychord_press":176,"on.mouse_press":179}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":187,"Page":189,"on.update":14,"scale":7,"on":1,"on.code_change":190,"fw_parent":189,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":187,"Page":189,"on.update":14,"scale":7,"on":1,"on.code_change":188,"fw_parent":188,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":187,"Page":184,"on.update":14,"scale":7,"on":1,"on.code_change":188,"fw_parent":187,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":187,"Page":184,"on.update":14,"scale":7,"on":1,"on.code_change":185,"fw_parent":186,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":186,"Page":184,"on.update":14,"scale":7,"on":1,"on.code_change":185,"fw_parent":185,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":157,"Page":184,"on.update":14,"scale":7,"on":1,"on.code_change":185,"fw_parent":184,"on.mouse_press":179,"Surface":165}
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
end
end
on.keychord_press = function(chord, key)
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":157,"Page":184,"on.update":14,"scale":7,"on":1,"on.code_change":183,"fw_parent":183,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":157,"Page":181,"on.update":14,"scale":7,"on":1,"on.code_change":183,"fw_parent":182,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":157,"Page":181,"on.update":14,"scale":7,"on":1,"on.code_change":182,"fw_parent":181,"on.mouse_press":179,"Surface":165}
{"on.draw":162,"to_text":180,"vx":5,"Viewport":29,"vy":8,"Cursor_node":172,"font":104,"on.mouse_release":178,"on.text_input":177,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"compute_layout":157,"Page":181,"on.update":14,"scale":7,"on":1,"on.code_change":140,"fw_parent":180,"on.mouse_press":179,"Surface":165}
{"to_text":180,"on.mouse_press":179,"on.mouse_release":178,"initialize_editor":74,"box_height":44,"on.keychord_press":176,"on":1,"on.text_input":177,"font":104,"on.code_change":140,"fw_parent":179,"Surface":165,"on.draw":162,"vx":5,"Page":111,"Viewport":29,"compute_layout":157,"scale":7,"vy":8,"Cursor_node":172,"on.update":14}
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"on.text_input":177,"vy":8,"on.mouse_press":179,"on.mouse_release":178,"on.update":14,"on.keychord_press":176,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":178}
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
end
end
on.keychord_press = function(chord, key)
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"on.text_input":177,"vy":8,"on.mouse_press":174,"on.mouse_release":178,"on.update":14,"on.keychord_press":176,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":177}
on.draw = function()
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))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"on.text_input":177,"vy":8,"on.mouse_press":174,"on.mouse_release":175,"on.update":14,"on.keychord_press":176,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":176}
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"vy":8,"on.mouse_press":174,"on.mouse_release":175,"on.update":14,"on.keychord_press":176,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":175}
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"vy":8,"on.mouse_press":174,"on.mouse_release":175,"on.update":14,"on.keychord_press":17,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":174}
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"vy":8,"on.mouse_press":174,"on.mouse_release":171,"on.update":14,"on.keychord_press":17,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":173}
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"vy":8,"on.mouse_press":173,"on.mouse_release":171,"on.update":14,"on.keychord_press":17,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":172}
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"vy":8,"on.mouse_press":169,"on.mouse_release":171,"on.update":14,"on.keychord_press":17,"Cursor_node":172,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":171}
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
end
end
on.keychord_press = function(chord, key)
{"Surface":165,"to_text":168,"on.code_change":140,"vx":5,"on":1,"Viewport":29,"vy":8,"on.mouse_press":169,"on.mouse_release":171,"on.update":14,"on.keychord_press":17,"on.draw":162,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"Page":111,"font":104,"fw_parent":169}
{"Surface":165,"to_text":168,"on.code_change":140,"fw_parent":169,"on":1,"Viewport":29,"vy":8,"on.mouse_press":169,"on.mouse_release":170,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":165,"to_text":168,"on.code_change":140,"fw_parent":168,"on":1,"Viewport":29,"vy":8,"on.mouse_press":169,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":165,"to_text":168,"on.code_change":140,"fw_parent":167,"on":1,"Viewport":29,"vy":8,"on.mouse_press":167,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":165,"to_text":166,"on.code_change":140,"fw_parent":166,"on":1,"Viewport":29,"vy":8,"on.mouse_press":167,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":165,"to_text":166,"on.code_change":140,"fw_parent":165,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":165,"to_text":164,"on.code_change":140,"fw_parent":164,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":116,"to_text":164,"on.code_change":140,"fw_parent":163,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":116,"to_text":163,"on.code_change":140,"fw_parent":162,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":116,"to_text":159,"on.code_change":140,"fw_parent":161,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":162}
{"Surface":116,"to_text":159,"on.code_change":140,"fw_parent":160,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":161}
{"Surface":116,"to_text":159,"on.code_change":140,"fw_parent":159,"on":1,"Viewport":29,"vy":8,"on.mouse_press":160,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":158}
{"Surface":116,"to_text":159,"on.code_change":140,"fw_parent":158,"on":1,"Viewport":29,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"vx":5,"initialize_editor":74,"box_height":44,"scale":7,"compute_layout":157,"font":104,"Page":111,"on.draw":158}
{"compute_layout":157,"on.keychord_press":17,"Page":111,"on.code_change":140,"scale":7,"Surface":116,"font":104,"on.draw":158,"vx":5,"Viewport":29,"fw_parent":157,"vy":8,"initialize_editor":74,"on.mouse_press":12,"on":1,"on.mouse_release":13,"box_height":44,"on.update":14}
{"compute_layout":157,"on.keychord_press":17,"Page":111,"on.code_change":140,"scale":7,"Surface":116,"font":104,"on.draw":155,"vx":5,"Viewport":29,"fw_parent":156,"vy":8,"initialize_editor":74,"on.mouse_press":12,"on":1,"on.mouse_release":13,"box_height":44,"on.update":14}
{"Viewport":29,"fw_parent":155,"vy":8,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":156,"Page":111,"on.code_change":140,"Surface":116,"scale":7,"on.draw":155,"font":104,"vx":5,"initialize_editor":74}
{"Viewport":29,"fw_parent":154,"vy":8,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":154,"Page":111,"on.code_change":140,"Surface":116,"scale":7,"on.draw":155,"font":104,"vx":5,"initialize_editor":74}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":150,"vx":5,"Viewport":29,"vy":8,"fw_parent":153,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":154,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":150,"vx":5,"Viewport":29,"vy":8,"fw_parent":152,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":153,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":150,"vx":5,"Viewport":29,"vy":8,"fw_parent":151,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":152,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":150,"vx":5,"Viewport":29,"vy":8,"fw_parent":150,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":151,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":150,"vx":5,"Viewport":29,"vy":8,"fw_parent":149,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
Surface = {
-- test data
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{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}},
}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":149,"vx":5,"Viewport":29,"vy":8,"fw_parent":148,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":148,"vx":5,"Viewport":29,"vy":8,"fw_parent":147,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":147,"vx":5,"Viewport":29,"vy":8,"fw_parent":146,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":146,"vx":5,"Viewport":29,"vy":8,"fw_parent":145,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":145,"vx":5,"Viewport":29,"vy":8,"fw_parent":144,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":144,"vx":5,"Viewport":29,"vy":8,"fw_parent":143,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":143,"vx":5,"Viewport":29,"vy":8,"fw_parent":142,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"Page":111,"on.code_change":140,"Surface":116,"on":1,"on.draw":142,"vx":5,"Viewport":29,"vy":8,"fw_parent":141,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"font":104,"scale":7}
{"font":104,"initialize_editor":74,"on.mouse_press":12,"fw_parent":140,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"vy":8,"on.code_change":140,"Page":111,"on":1,"scale":7,"Viewport":29,"vx":5,"on.draw":141,"Surface":116,"compute_layout":122}
{"Surface":116,"on.code_change":140,"on.draw":139,"vx":5,"Viewport":29,"vy":8,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"initialize_editor":74,"Page":111,"fw_parent":139,"compute_layout":122,"scale":7,"font":104}
{"vy":8,"scale":7,"on.mouse_press":12,"Surface":116,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":122,"Page":111,"on.code_change":109,"fw_parent":138,"font":104,"vx":5,"on.update":14,"Viewport":29,"on.draw":139,"on":1}
{"font":104,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":122,"Page":111,"Surface":116,"on.code_change":109,"on.draw":138,"fw_parent":137,"Viewport":29,"vy":8,"on":1,"initialize_editor":74,"vx":5,"on.mouse_press":12,"scale":7,"on.mouse_release":13}
{"font":104,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":122,"Page":111,"Surface":116,"on.code_change":109,"on.draw":137,"fw_parent":136,"Viewport":29,"vy":8,"on":1,"initialize_editor":74,"vx":5,"on.mouse_press":12,"scale":7,"on.mouse_release":13}
{"font":104,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":122,"Page":111,"Surface":116,"on.code_change":109,"on.draw":136,"fw_parent":135,"Viewport":29,"vy":8,"on":1,"initialize_editor":74,"vx":5,"on.mouse_press":12,"scale":7,"on.mouse_release":13}
{"font":104,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":122,"Page":111,"Surface":116,"on.code_change":109,"on.draw":135,"fw_parent":125,"Viewport":29,"vy":8,"on":1,"initialize_editor":74,"vx":5,"on.mouse_press":12,"scale":7,"on.mouse_release":13}
{"on.mouse_release":13,"scale":7,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":130,"Page":111,"on.code_change":134,"on.draw":133,"vx":5,"Viewport":29,"on.update":14,"vy":8,"font":104,"Surface":116,"on":1,"fw_parent":133,"on.mouse_press":12}
{"on.mouse_release":13,"scale":7,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":130,"Page":111,"on.code_change":129,"on.draw":133,"vx":5,"Viewport":29,"on.update":14,"vy":8,"font":104,"Surface":116,"on":1,"fw_parent":132,"on.mouse_press":12}
{"on.mouse_release":13,"scale":7,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":130,"Page":111,"on.code_change":129,"on.draw":132,"vx":5,"Viewport":29,"on.update":14,"vy":8,"font":104,"Surface":116,"on":1,"fw_parent":131,"on.mouse_press":12}
{"on.draw":131,"vx":5,"Viewport":29,"vy":8,"fw_parent":130,"font":104,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":130,"on":1,"scale":7,"on.code_change":129,"Page":111,"Surface":116,"on.update":14}
{"on.draw":128,"vx":5,"Viewport":29,"vy":8,"fw_parent":129,"font":104,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":130,"on":1,"scale":7,"on.code_change":129,"Page":111,"Surface":116,"on.update":14}
{"on.draw":128,"vx":5,"Viewport":29,"vy":8,"fw_parent":128,"font":104,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":127,"on":1,"scale":7,"on.code_change":129,"Page":111,"Surface":116,"on.update":14}
{"vx":5,"Viewport":29,"on":1,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"Page":111,"Surface":116,"on.draw":128,"fw_parent":127,"scale":7,"on.code_change":109,"initialize_editor":74,"box_height":44,"font":104,"compute_layout":127}
{"vx":5,"Viewport":29,"on":1,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"Page":111,"Surface":116,"on.draw":125,"fw_parent":126,"scale":7,"on.code_change":109,"initialize_editor":74,"box_height":44,"font":104,"compute_layout":127}
{"vx":5,"Viewport":29,"on":1,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"Page":111,"Surface":116,"on.draw":125,"fw_parent":125,"scale":7,"on.code_change":109,"initialize_editor":74,"box_height":44,"font":104,"compute_layout":126}
{"on.code_change":109,"on.draw":125,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":122,"fw_parent":124,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":124,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":122,"fw_parent":123,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":123,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":122,"fw_parent":122,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":119,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":122,"fw_parent":121,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":119,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":121,"fw_parent":120,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":119,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":120,"fw_parent":119,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":119,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":115,"fw_parent":118,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":118,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":115,"fw_parent":117,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":117,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":115,"fw_parent":116,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":113,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":115,"fw_parent":115,"box_height":44,"on":1,"Surface":116}
{"on.code_change":109,"on.draw":113,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":115,"fw_parent":114,"box_height":44,"on":1,"Surface":93}
{"on.code_change":109,"on.draw":113,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":114,"fw_parent":113,"box_height":44,"on":1,"Surface":93}
{"on.code_change":109,"on.draw":113,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":112,"fw_parent":112,"box_height":44,"on":1,"Surface":93}
{"on.code_change":109,"on.draw":105,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":112,"fw_parent":111,"box_height":44,"on":1,"Surface":93}
{"on.code_change":109,"on.draw":105,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":111,"compute_layout":107,"fw_parent":110,"box_height":44,"on":1,"Surface":93}
{"on.code_change":109,"on.draw":105,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":110,"compute_layout":107,"fw_parent":109,"box_height":44,"on":1,"Surface":93}
{"on.code_change":109,"on.draw":105,"font":104,"vx":5,"Viewport":29,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"initialize_editor":74,"on.keychord_press":17,"Page":76,"compute_layout":107,"fw_parent":108,"box_height":44,"on":1,"Surface":93}
{"vy":8,"compute_layout":107,"on.mouse_press":12,"on.mouse_release":13,"on.code_change":108,"scale":7,"on.keychord_press":17,"Page":76,"on":1,"Surface":93,"on.update":14,"on.draw":105,"font":104,"vx":5,"fw_parent":107,"Viewport":29,"initialize_editor":74,"box_height":44}
{"vy":8,"compute_layout":107,"on.mouse_press":12,"on.mouse_release":13,"on.code_change":103,"scale":7,"on.keychord_press":17,"Page":76,"on":1,"Surface":93,"on.update":14,"on.draw":105,"font":104,"vx":5,"fw_parent":106,"Viewport":29,"initialize_editor":74,"box_height":44}
{"on.draw":105,"vx":5,"Viewport":29,"vy":8,"on":1,"fw_parent":105,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":106,"Page":76,"font":104,"on.code_change":103,"scale":7,"Surface":93,"on.update":14}
{"on.draw":105,"vx":5,"Viewport":29,"vy":8,"on":1,"fw_parent":104,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":102,"Page":76,"font":104,"on.code_change":103,"scale":7,"Surface":93,"on.update":14}
{"on.draw":91,"vx":5,"Viewport":29,"vy":8,"on":1,"fw_parent":103,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":102,"Page":76,"font":104,"on.code_change":103,"scale":7,"Surface":93,"on.update":14}
{"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"Page":76,"scale":7,"initialize_editor":74,"Surface":93,"compute_layout":102,"on.draw":91,"vx":5,"on":1,"Viewport":29,"on.code_change":103,"vy":8,"fw_parent":102,"on.mouse_press":12}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":102,"scale":7,"Page":76,"on.code_change":98,"Surface":93,"fw_parent":101,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":101,"scale":7,"Page":76,"on.code_change":98,"Surface":93,"fw_parent":100,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":100,"scale":7,"Page":76,"on.code_change":98,"Surface":93,"fw_parent":99,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":99,"scale":7,"Page":76,"on.code_change":98,"Surface":93,"fw_parent":98,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
if node.bg then
table.insert(nodes_to_render, {type='rectangle', r=node.bg.r, g=node.bg.g, b=node.bg.b, x=node.x, y=node.y, w=node.w, h=node.h})
end
end
return x+node.w,y+node.h
end
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":95,"scale":7,"Page":76,"on.code_change":98,"Surface":93,"fw_parent":97,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":95,"scale":7,"Page":76,"on.code_change":97,"Surface":93,"fw_parent":96,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":95,"scale":7,"Page":76,"on.code_change":96,"Surface":93,"fw_parent":95,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":95,"scale":7,"Page":76,"on.code_change":94,"Surface":93,"fw_parent":94,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":92,"scale":7,"Page":76,"on.code_change":94,"Surface":93,"fw_parent":93,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":92,"scale":7,"Page":76,"on.code_change":89,"Surface":93,"fw_parent":92,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":92,"scale":7,"Page":76,"on.code_change":89,"Surface":70,"fw_parent":91,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":75,"scale":7,"Page":76,"on.code_change":89,"Surface":70,"fw_parent":90,"on.draw":91,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":75,"scale":7,"Page":76,"on.code_change":89,"Surface":70,"fw_parent":89,"on.draw":90,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":75,"scale":7,"Page":76,"on.code_change":89,"Surface":70,"fw_parent":88,"on.draw":72,"vx":5,"Viewport":29,"on":1,"vy":8,"initialize_editor":74}
{"on":1,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":88,"scale":7,"Surface":70,"on.draw":72,"vx":5,"Viewport":29,"on.update":14,"vy":8,"fw_parent":87}
{"on":1,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":87,"scale":7,"Surface":70,"on.draw":72,"vx":5,"Viewport":29,"on.update":14,"vy":8,"fw_parent":86}
{"on":1,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":86,"scale":7,"Surface":70,"on.draw":72,"vx":5,"Viewport":29,"on.update":14,"vy":8,"fw_parent":85}
{"on":1,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":85,"scale":7,"Surface":70,"on.draw":72,"vx":5,"Viewport":29,"on.update":14,"vy":8,"fw_parent":83}
{"on":1,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":84,"scale":7,"Surface":70,"on.draw":72,"vx":5,"Viewport":29,"on.update":14,"vy":8,"fw_parent":83}
{"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on":1,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":83,"Surface":70,"on.draw":72,"vx":5,"fw_parent":81,"Viewport":29,"initialize_editor":74,"scale":7}
{"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on":1,"on.update":14,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":82,"Surface":70,"on.draw":72,"vx":5,"fw_parent":81,"Viewport":29,"initialize_editor":74,"scale":7}
{"Viewport":29,"fw_parent":80,"vy":8,"scale":7,"on.mouse_press":12,"on.mouse_release":13,"initialize_editor":74,"box_height":44,"on.keychord_press":17,"compute_layout":75,"Page":76,"on.code_change":81,"Surface":70,"on":1,"on.draw":72,"on.update":14,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":78,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":75,"Page":76,"on.code_change":80,"Surface":70,"on.draw":72,"scale":7,"initialize_editor":74,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":78,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":75,"Page":76,"on.code_change":79,"Surface":70,"initialize_editor":74,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":77,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":75,"Page":76,"on.code_change":78,"Surface":70,"initialize_editor":74,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":76,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":75,"Page":76,"on.code_change":77,"Surface":70,"initialize_editor":74,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":75,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":75,"Page":76,"on.code_change":61,"Surface":70,"initialize_editor":74,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":74,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":75,"Page":39,"on.code_change":61,"Surface":70,"initialize_editor":74,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":73,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":73,"Page":39,"on.code_change":61,"Surface":70,"initialize_editor":74,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":72,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":73,"Page":39,"on.code_change":61,"Surface":70,"initialize_editor":71,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":71,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":66,"Page":39,"on.code_change":61,"Surface":70,"initialize_editor":71,"on.draw":72,"scale":7,"vx":5}
{"Viewport":29,"vy":8,"fw_parent":70,"on":1,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"on.keychord_press":17,"box_height":44,"compute_layout":66,"Page":39,"on.code_change":61,"Surface":70,"initialize_editor":71,"on.draw":69,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":66,"Page":39,"vy":8,"fw_parent":69,"on":1,"on.draw":69,"on.keychord_press":17,"on.code_change":61,"Surface":70,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":66,"Page":39,"vy":8,"fw_parent":68,"on":1,"on.draw":69,"on.keychord_press":17,"on.code_change":61,"Surface":68,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":66,"Page":39,"vy":8,"fw_parent":67,"on":1,"on.draw":67,"on.keychord_press":17,"on.code_change":61,"Surface":68,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":66,"Page":39,"vy":8,"fw_parent":66,"on":1,"on.draw":67,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":66,"Page":39,"vy":8,"fw_parent":65,"on":1,"on.draw":62,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":65,"Page":39,"vy":8,"fw_parent":64,"on":1,"on.draw":62,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":64,"Page":39,"vy":8,"fw_parent":63,"on":1,"on.draw":62,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":63,"Page":39,"vy":8,"fw_parent":62,"on":1,"on.draw":62,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":60,"Page":39,"vy":8,"fw_parent":61,"on":1,"on.draw":62,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":60,"Page":39,"vy":8,"fw_parent":60,"on":1,"on.draw":59,"on.keychord_press":17,"on.code_change":61,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":60,"Page":39,"vy":8,"fw_parent":59,"on":1,"on.draw":59,"on.keychord_press":17,"on.code_change":58,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":51,"Page":39,"vy":8,"fw_parent":58,"on":1,"on.draw":59,"on.keychord_press":17,"on.code_change":58,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":51,"Page":39,"vy":8,"fw_parent":57,"on":1,"on.draw":43,"on.keychord_press":17,"on.code_change":58,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"box_height":44,"Viewport":29,"compute_layout":51,"Page":39,"vy":8,"fw_parent":56,"on":1,"on.draw":43,"on.keychord_press":17,"on.code_change":57,"Surface":42,"on.mouse_release":13,"on.mouse_press":12,"on.update":14,"scale":7,"vx":5}
{"scale":7,"vx":5,"Viewport":29,"on.code_change":55,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":51,"on":1,"fw_parent":55,"Page":39,"on.draw":43,"box_height":44}
{"scale":7,"vx":5,"Viewport":29,"on.code_change":55,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":51,"on":1,"on.code_change":49,"fw_parent":54,"Page":39,"on.draw":43,"box_height":44}
compute_layout = function(node, x,y, nodes_to_render)
-- 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
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
table.insert(nodes_to_render, node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
{"scale":7,"vx":5,"Viewport":29,"on.code_change":54,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":51,"on":1,"on.code_change":49,"fw_parent":53,"Page":39,"on.draw":43,"box_height":44}
{"scale":7,"vx":5,"Viewport":29,"on.code_change":53,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":51,"on":1,"on.code_change":49,"fw_parent":52,"Page":39,"on.draw":43,"box_height":44}
{"scale":7,"vx":5,"Viewport":29,"on.code_change":52,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":51,"on":1,"on.code_change":49,"fw_parent":51,"Page":39,"on.draw":43,"box_height":44}
{"scale":7,"vx":5,"Viewport":29,"on.code_change":50,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":51,"on":1,"on.code_change":49,"fw_parent":50,"Page":39,"on.draw":43,"box_height":44}
{"scale":7,"vx":5,"Viewport":29,"on.code_change":50,"vy":8,"on.mouse_press":12,"on.mouse_release":13,"on.update":14,"Surface":42,"on.keychord_press":17,"compute_layout":46,"on":1,"on.code_change":49,"fw_parent":49,"Page":39,"on.draw":43,"box_height":44}
{"compute_layout":46,"vy":8,"on.code_change":49,"on.update":14,"on":1,"scale":7,"on.mouse_press":12,"fw_parent":48,"on.mouse_release":13,"Page":39,"on.draw":43,"on.keychord_press":17,"vx":5,"Viewport":29,"box_height":44,"Surface":42}
{"compute_layout":46,"vy":8,"on.code_change":48,"on.update":14,"on":1,"scale":7,"on.mouse_press":12,"fw_parent":47,"on.mouse_release":13,"Page":39,"on.draw":43,"on.keychord_press":17,"vx":5,"Viewport":29,"box_height":44,"Surface":42}
{"compute_layout":46,"vy":8,"on.code_change":47,"on.update":14,"on":1,"scale":7,"on.mouse_press":12,"fw_parent":46,"on.mouse_release":13,"Page":39,"on.draw":43,"on.keychord_press":17,"vx":5,"Viewport":29,"box_height":44,"Surface":42}
{"fw_parent":45,"box_height":44,"on.mouse_press":12,"Surface":42,"on.mouse_release":13,"on.draw":43,"compute_layout":46,"vx":5,"on":1,"Viewport":29,"on.keychord_press":17,"Page":39,"vy":8,"scale":7,"on.update":14}
{"fw_parent":44,"box_height":44,"on.mouse_press":12,"Surface":42,"on.mouse_release":13,"on.draw":43,"compute_layout":45,"vx":5,"on":1,"Viewport":29,"on.keychord_press":17,"Page":39,"vy":8,"scale":7,"on.update":14}
{"fw_parent":43,"box_height":44,"on.mouse_press":12,"Surface":42,"on.mouse_release":13,"on.draw":43,"vx":5,"on":1,"Viewport":29,"on.keychord_press":17,"Page":39,"vy":8,"scale":7,"on.update":14}
{"Viewport":29,"Page":39,"vy":8,"vx":5,"Surface":42,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":43,"on.update":14,"scale":7,"fw_parent":42,"on.keychord_press":17}
{"Viewport":29,"Page":39,"vy":8,"vx":5,"Surface":42,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":41,"on.update":14,"scale":7,"fw_parent":41,"on.keychord_press":17}
{"Viewport":29,"Page":39,"vy":8,"vx":5,"Surface":38,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":41,"on.update":14,"scale":7,"fw_parent":40,"on.keychord_press":17}
{"Viewport":29,"Page":39,"vy":8,"vx":5,"Surface":38,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":40,"on.update":14,"scale":7,"fw_parent":39,"on.keychord_press":17}
{"Viewport":29,"Page":39,"vy":8,"vx":5,"Surface":38,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":35,"on.update":14,"scale":7,"fw_parent":38,"on.keychord_press":17}
{"Viewport":29,"Page":19,"vy":8,"vx":5,"Surface":38,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":35,"on.update":14,"scale":7,"fw_parent":37,"on.keychord_press":17}
{"Viewport":29,"Page":19,"vy":8,"vx":5,"Surface":37,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":35,"on.update":14,"scale":7,"fw_parent":36,"on.keychord_press":17}
{"Viewport":29,"Page":19,"vy":8,"vx":5,"Surface":36,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":35,"on.update":14,"scale":7,"fw_parent":35,"on.keychord_press":17}
{"Viewport":29,"Page":19,"vy":8,"vx":5,"Surface":33,"on.mouse_press":12,"on":1,"on.mouse_release":13,"on.draw":35,"on.update":14,"scale":7,"fw_parent":34,"on.keychord_press":17}
{"on.keychord_press":17,"Viewport":29,"scale":7,"vy":8,"Page":19,"on.draw":34,"fw_parent":33,"on.mouse_press":12,"Surface":33,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":29,"scale":7,"vy":8,"Page":19,"on.draw":32,"fw_parent":32,"on.mouse_press":12,"Surface":33,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":29,"scale":7,"vy":8,"Page":19,"on.draw":32,"fw_parent":31,"on.mouse_press":12,"Surface":30,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":29,"scale":7,"vy":8,"Page":19,"on.draw":31,"fw_parent":30,"on.mouse_press":12,"Surface":30,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":29,"scale":7,"vy":8,"Page":19,"on.draw":27,"fw_parent":29,"on.mouse_press":12,"Surface":30,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":29,"scale":7,"vy":8,"Page":19,"on.draw":27,"fw_parent":28,"on.mouse_press":12,"Surface":28,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":27,"fw_parent":27,"on.mouse_press":12,"Surface":28,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":27,"fw_parent":26,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":26,"fw_parent":25,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":25,"fw_parent":24,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":24,"fw_parent":23,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":23,"fw_parent":22,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":22,"fw_parent":21,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":21,"fw_parent":20,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":11,"fw_parent":19,"on.mouse_press":12,"Surface":20,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":19,"on.draw":11,"fw_parent":18,"on.mouse_press":12,"Surface":3,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"Viewport":6,"scale":7,"vy":8,"Page":18,"on.draw":11,"fw_parent":17,"on.mouse_press":12,"Surface":3,"on.mouse_release":13,"on":1,"on.update":14,"vx":5}
{"on.keychord_press":17,"on.mouse_press":12,"Surface":3,"on.mouse_release":13,"scale":7,"on.update":14,"on":1,"vx":5,"Viewport":6,"vy":8,"fw_parent":16,"on.draw":11}
{"on.keychord_press":16,"on.mouse_press":12,"Surface":3,"on.mouse_release":13,"scale":7,"on.update":14,"on":1,"vx":5,"Viewport":6,"vy":8,"fw_parent":15,"on.draw":11}
{"on.keychord_press":15,"on.mouse_press":12,"Surface":3,"on.mouse_release":13,"scale":7,"on.update":14,"on":1,"vx":5,"Viewport":6,"vy":8,"fw_parent":14,"on.draw":11}
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
table.insert(nodes_to_render, node)
if node.type == 'text' then
-- leaf node containing raw text
node.x = x
node.y = y
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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'},},
}},
}},
}},
},
}
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- 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={
{data={'abc'},},
{data={'abc'},},
}},
{ type='rows', width=90, data={
{data={'def'},},
{data={'def'},},
}},
}},
}},
},
}
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
print('compute_layout: node of type', node.type, 'at', x,y)
table.insert(nodes_to_render, node)
if node.type == 'text' then
-- leaf node containing raw text
node.x = x
node.y = y
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
print('compute_layout: node of type', node.type, 'at', x,y)
table.insert(nodes_to_render, node)
if node.type == 'text' then
-- leaf node containing raw text
node.x = x
node.y = y
if node.width then
node.w = node.width
else
local scaled_fontsize = scale(node.fontsize or 20)
node.text = love.graphics.newText(font(node, scaled_fontsize), node.data)
node.w = node.text:getWidth()
end
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
on.draw = function()
for i,obj in ipairs(Surface) do
print(i, obj.type)
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
obj.text = love.graphics.newText(font(obj, scaled_fontsize), obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
print('compute_layout: node of type', node.type, 'at', x,y)
table.insert(nodes_to_render, node)
if node.type == 'text' and node.width then
-- leaf node containing raw text
node.x = x
node.y = y
node.w = node.width
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
print('compute_layout: node of type', node.type)
table.insert(nodes_to_render, node)
if node.type == 'text' and node.width then
-- leaf node containing raw text
node.x = x
node.y = y
node.w = node.width
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
print(node.type)
table.insert(nodes_to_render, node)
if node.type == 'text' and node.width then
-- leaf node containing raw text
node.x = x
node.y = y
node.w = node.width
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
table.insert(nodes_to_render, node)
if node.type == 'text' and node.width then
-- leaf node containing raw text
node.x = x
node.y = y
node.w = node.width
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
table.insert(nodes_to_render, node)
if node.type == 'text' and node.width then
-- leaf node containing raw text
node.x = x
node.y = y
node.w = node.width
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = dom.compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = dom.compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
Surface = {
-- test data
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='rectangle', x=50,y=50, width=20,height=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}},
}
compute_layout = function(node, x,y, nodes_to_render)
-- append to nodes_to_render flattened instructions to render a hierarchy of nodes
-- return x,y rendered until (surface coordinates)
table.insert(nodes_to_render, node)
if node.type == 'text' and node.width then
-- leaf node containing raw text
node.x = x
node.y = y
node.w = node.width
initialize_editor(node)
node.h = box_height(node)
elseif node.type == 'rows' then
node.x = x
node.y = y
-- lay out children top to bottom
local subx,suby = x,y
local w,h = 0,0
local subnodes
for _,child in ipairs(node.data) do
if child.margin then
suby = suby+child.margin
h = h+child.margin
end
subx,suby = dom.compute_layout(child, x,suby, nodes_to_render)
if w < child.w then
w = child.w
end
h = h+child.h
end
node.w = w
node.h = h
elseif node.type == 'cols' then
node.x = x
node.y = y
-- lay out children left to right
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
subx,suby = dom.compute_layout(child, subx,y, nodes_to_render)
w = w + child.w
if h < child.h then
h = child.h
end
end
node.w = w
node.h = h
end
return x+node.w,y+node.h
end
on.draw = function()
for i,obj in ipairs(Surface) do
print(i, obj.type)
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print(obj.data)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print(obj.data)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='text',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- a table on the right
{ type='rows', name='searches', margin=50, data={
{ type='text', data={''},},
{ type='cols', data={
{ type='text', data={'search:'},},
{ type='edit', 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={
{data={'abc'},},
{data={'abc'},},
}},
{ type='rows', width=90, data={
{data={'def'},},
{data={'def'},},
}},
}},
}},
},
}
initialize_editor = function(obj)
if obj.w then
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
initialize_editor(obj)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
Surface = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{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}},
}
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
if obj.w then
-- use an editor to wrap the text
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
Surface = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{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}},
}
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
if obj.w then
-- use an editor to wrap the text
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
compute_layout = function(node, x,y)
if node.type == 'text' and node.width then
node.x = x
node.y = y
node.w = node.width
node.h = box_height(node)
end
return node
end
--[[
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
]]
compute_layout = function(node, x,y)
if node.type == 'text' and node.width then
node.x = x
node.y = y
node.editor = edit.initialize
node.editor.top = y
node.editor.left = x
node.editor.right = x + node.w
node.w = node.width
node.h = box_height(node)
end
return node
end
--[[
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
]]
compute_layout = function(node, x,y)
if node.type == 'text' and node.width then
node.x = x
node.y = y
node.editor = edit.initialize
node.editor.top = y
node.editor.left = x
node.editor.right = x + node.w
node.w = node.width
node.h = dom.height(node)
end
return node
end
--[[
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
]]
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
compute_layout = function(node, x,y)
if node.type == 'text' and node.width then
node.x = x
node.y = y
node.editor.top = y
node.editor.left = x
node.editor.right = x + node.w
node.w = node.width
node.h = dom.height(node)
end
return node
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
print('rendering', obj.data)
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
compute_layout = function(node, x,y)
if node.type == 'text' and node.width then
node.x = x
node.y = y
node.editor.top = y
node.editor.left = x
node.editor.right = x + node.w
node.h = dom.height(node)
end
return node
end
on.code_change = function()
print('AAA')
Surface = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
end
on.code_change = function()
Surface = compute_layout(
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
0,0)
end
compute_layout = function(node, x,y)
if node.type == 'text' and node.width then
node.x = x
node.y = y
node.editor.top = y
node.editor.left = x
node.editor.right = x + node.w
node.h = dom.height(node)
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
if obj.width == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
-- use an editor to wrap the text
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true) -- hide cursor
end
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
-- for now the editor is just a way to line-wrap text. Hide the cursor.
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, true)
end
end
end
Page = {
-- page
type='cols', x=0, y=0,
width=800, data={
-- editor covering left side
{
type='edit',
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- a table on the right
{ type='rows', name='searches', margin=50, data={
{ type='text', data={''},},
{ type='cols', data={
{ type='text', data={'search:'},},
{ type='edit', 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={
{data={'abc'},},
{data={'abc'},},
}},
{ type='rows', width=90, data={
{data={'def'},},
{data={'def'},},
}},
}},
}},
},
}
Surface = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='edit', 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 = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='edit', data={'abc', 'def'}, x=100, 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 = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='edit', data={'abc', 'def'}, x=100, y=50, w=50,h=50, fg={r=0,g=0, 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}},
}
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
end
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
Surface = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
--{type='edit', data={'abc', 'def'}, x=100, y=50, w=50,h=50, fg={r=0,g=0, 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}},
}
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y or obj.scaled_fontsize ~= scaled_fontsize then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.editor == nil or obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
Surface = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='edit', data={'abc', 'def'}, x=100, y=50, w=50,h=50, fg={r=0,g=0, 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 = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='edit', data={'abc', 'def'}, x=100, y=50, w=50,h=50, fg={r=0,g=0, b=0.5}},
{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}},
}
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.editor == nil or obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize_state(obj.y, obj.x, obj.x+obj.w, scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.editor == nil or obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
print(edit)
obj.editor = edit.initialize(obj.y, obj.x, obj.x+obj.w, scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.editor == nil or obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize(obj.y, obj.x, obj.x+obj.w, scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize(obj.y, obj.x, obj.x+obj.w, scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.editor = edit.initialize(obj.y, obj.x, obj.x+obj.w, scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
end
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0})
end
end
end
on.draw = function()
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.width),scale(obj.height))
elseif obj.type == 'line' then
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
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
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
end
end
end
Surface = {
-- test data
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{type='edit', data={'abc', 'def'}, x=100, y=50, w=50,h=50,},
{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}},
}
Page = {
-- page
x=0, y=0,
width=800, cols={
-- editor covering left side
{
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
width=400, bg={r=1,g=1,b=0}
},
-- a table on the right
{ name='searches', margin=50, rows={
{ data={''},},
{ cols={
{ data={'search:'},},
{ name='search', bg={r=0.8,g=0.8,b=0.8}, data={''}, width=90,},
}},
{ data={'table:'},},
{ bg={r=0.8,g=0.8,b=0.8}, cols={
{ width=90, rows={
{data={'abc'},},
{data={'abc'},},
}},
{ width=90, rows={
{data={'def'},},
{data={'def'},},
}},
}},
}},
},
}
Page = {
-- page
x=0, y=0,
w=800, cols={
-- editor covering left side
{
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={"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.",},
w=400, bg={r=1,g=1,b=0}
},
-- a table on the right
{ name='searches', margin=50, rows={
{ data={''}, w=90,},
{ cols={
{ data={'search:'}, w=90,},
{ name='search', bg={r=0.8,g=0.8,b=0.8}, data={''}, w=90,},
}},
{ data={''}, w=90,},
{ data={'table:'}, w=90,},
{ bg={r=0.8,g=0.8,b=0.8}, rows={
{ cols={
{data={'abc'}, w=90,},
{data={'def'}, w=90,},
}},
{ cols={
{data={'abc'}, w=90,},
{data={'def'}, w=90,},
}},
}},
}},
},
}
update_editor_box = function(node, preserve_screen_top_of_cursor_node)
if node.editor == nil then return end
if node.y > Viewport.y then
if not preserve_screen_top_of_cursor_node or node ~= Cursor_node 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, Viewport.y - node.y)
end
node.editor.left = math.floor(vx(node.x))
node.editor.right = math.ceil(vx(node.x+node.w))
edit.update_font_settings(node.editor, scale(20))
Text.redraw_all(node.editor)
end
Page2 = {
x=500, y=300,
-- page
type='text',
data={
"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."
},
width=400, bg={r=0,g=0.8,b=0}
}
A = function(preserve_screen_top_of_cursor_node)
-- translate Page to Surface
while #Surface > 0 do table.remove(Surface) end
compute_layout(Page, Page.x,Page.y, Surface, preserve_screen_top_of_cursor_node)
-- continue the pipeline
B(preserve_screen_top_of_cursor_node)
-- TODO: ugly that we're manipulating editor objects twice
end
{type='rectangle', x=50,y=50, width=20,height=80, r=1,g=0,b=0},
{type='line', data={0,0, 0,600}},
{type='line', data={0,0, 800,0}},
{type='text', data='0', x=-20,y=-20},
{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},
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
obj.zdata = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
end
if obj.saved_zoom ~= Viewport.zoom or obj.saved_x ~= Viewport.x or obj.saved_y ~= Viewport.y then
obj.saved_zoom = Viewport.zoom
obj.saved_x = Viewport.x
obj.saved_y = Viewport.y
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
love.graphics.line(unpack(obj.zdata))
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
obj.text = love.graphics.newText(Font[scaled_fontsize], obj.data)
end
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
end
love.graphics.line(unpack(obj.zdata))
elseif obj.type == 'edit' then
local scaled_fontsize = scale(obj.fontsize or 20)
if obj.editor == nil or obj.scaled_fontsize ~= scaled_fontsize then
obj.scaled_fontsize = scaled_fontsize
if Font == nil then Font = {} end
if Font[scaled_fontsize] == nil then
Font[scaled_fontsize] = love.graphics.newFont(scaled_fontsize)
end
print(edit, edit.initialize)
obj.editor = edit.initialize(obj.y, obj.x, obj.x+obj.w, scaled_fontsize, math.floor(scaled_fontsize*1.3))
obj.editor.lines = load_array(obj.data)
Text.redraw_all(obj.editor)
if obj.w == nil then
love.graphics.draw(obj.text, vx(obj.x), vy(obj.y))
else
edit.draw(obj.editor, obj.fg or {r=0,g=0,b=0}, not obj.show_cursor)
add_thick_line = function(s, thickness)
-- increase the thickness of a horizontal-ish line
table.insert(Surface, s)
for i=1,thickness-1 do
s = copy_shape(s)
for j=2,#s.data, 2 do
s.data[j] = s.data[j]+1
end
table.insert(Surface, s)
end
end
copy_shape = function(s)
local result = {}
for k,v in pairs(s) do
result[k] = v
end
result.data = {}
for _,d in ipairs(s.data) do
table.insert(result.data, d)
end
return result
end
on.keychord_press = function(chord, key)
if chord == 'C-=' then
-- zoom in
Viewport.zoom = Viewport.zoom+0.1
B()
elseif chord == 'C--' then
-- zoom out
Viewport.zoom = Viewport.zoom-0.1
B()
elseif chord == 'C-0' then
-- reset zoom
Viewport.zoom = 1.0
B()
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
A(--[[preserve screen_top of cursor node]] true)
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
on.text_input = function(t)
if Cursor_node then
local old_top = {line=Cursor_node.editor.screen_top1.line, pos=Cursor_node.editor.screen_top1.pos}
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)
end
A(--[[preserve screen_top of cursor node]] true)
end
end
Page = {
type='text', x=0, y=0,
name='editor',
doc='prose goes here, on the left half of the window',
margin=Margin_left,
data={
"Lorem Ipsum",
'1',
'2',
'3',
'mno',
'Acb',
'g',
'hij',
'klm',
'nop',
},
width=400,
}
B = function(preserve_screen_top_of_cursor_node)
-- 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 = {}
for i=1,#obj.data,2 do
table.insert(obj.zdata, vx(obj.data[i]))
table.insert(obj.zdata, vy(obj.data[i+1]))
end
elseif obj.type == 'bezier' then
zdata = {}
for i=1,#obj.data,2 do
table.insert(zdata, vx(obj.data[i]))
table.insert(zdata, vy(obj.data[i+1]))
end
obj.zdata = love.math.newBezierCurve(zdata):render()
elseif obj.type == 'text' then
if obj.w then
update_editor_box(obj, preserve_screen_top_of_cursor_node)
else
obj.text = love.graphics.newText(love.graphics.getFont(), obj.data)
end
end
end
end
schema1_of_y = function(editor, y)
-- return line/pos of screen line starting near a given y offset,
-- and the (negative) offset remaining after the calculation
-- invariants:
-- - 0 >= y_offset >= -Line_height
-- - let loc, y_offset = schema1_of_y(pane, y)
-- y + y_offset == y_of_schema1(pane, loc)
assert(y >= 0)
local y_offset = y
for i=1,#editor.lines do
Text.populate_screen_line_starting_pos(editor, i)
local height = line_height(editor, i)
if y_offset < height then
local line = editor.lines[i]
local nlines = math.floor(y_offset/editor.line_height)
assert(nlines >= 0 and nlines < #editor.line_cache[i].screen_line_starting_pos)
local pos = editor.line_cache[i].screen_line_starting_pos[nlines+1] -- switch to 1-indexing
y_offset = y_offset - nlines*editor.line_height
return {line=i, pos=pos}, -y_offset
end
y_offset = y_offset - height
end
-- y is below the pane
return {line=#editor.lines+1, pos=1}, y_offset -- positive value
end
line_height = function(editor, line_index)
local line = editor.lines[line_index]
local line_cache = editor.line_cache[line_index]
return editor.line_height*#line_cache.screen_line_starting_pos
end
y_of_schema1 = function(editor, loc)
local result = 0
if loc.line == 1 and loc.pos == 1 then
return result
end
for i=1,loc.line-1 do
Text.populate_screen_line_starting_pos(editor, i)
result = result + line_height(editor, i)
end
Text.populate_screen_line_starting_pos(editor, loc.line)
for i,screen_line_starting_pos in ipairs(editor.line_cache[loc.line].screen_line_starting_pos) do
if screen_line_starting_pos >= loc.pos then
break
end
result = result + editor.line_height
end
return result
end
on.initialize = function()
A()
end
obj.editor = edit.initialize_state(vy(obj.y), vx(obj.x), vx(obj.x+obj.w), scaled_fontsize, math.floor(scaled_fontsize*1.3))
local scaled_fontsize = scale(20)
local scaled_lineheight = math.floor(scaled_fontsize*1.3)
obj.editor = edit.initialize_state(vy(obj.y), math.floor(vx(obj.x)), math.ceil(vx(obj.x+obj.w)), scaled_fontsize, scaled_lineheight)
Viewport = {x=-50, y=-50, w=800,h=600, zoom=1.0}
to_text = function(x,y)
for _,node in ipairs(Surface) do
if node.type == 'text' then
if x >= vx(node.x) and node.w and x < vx(node.x + node.w) then
if y >= vy(node.y) and node.h and y < vy(node.y + node.h) then
return node
end
end
end
end
end
on.mouse_press = function(x,y, mouse_button)
if Cursor_node then
Cursor_node.show_cursor = nil
Cursor_node = nil
end
local node = to_text(x,y)
if node then
Cursor_node = node
edit.mouse_press(node.editor, x,y, mouse_button)
else
Pan = {x=Viewport.x+x/Viewport.zoom,y=Viewport.y+y/Viewport.zoom}
end
end
Cursor_node = nil
This file contains no definition, but is used as a marker in the save dir to
indicate all definitions have been copied from the repo to the save dir.
This file contains no definition, but is used as a marker in the save dir to indicate all definitions have been copied from the repo to the save dir.