Now we also have the plumbing in place to map visual objects to the underlying toots.
V2R4643AZLA2QHR6C6ADAOOQXK5ZKZCR4NMKWPPZHMYTOIOIYJDAC
on.mouse_press = function(x,y, mouse_button)
local node_id = to_node(x,y)
if node_id then
App.setClipboardText(Nodes[node_id].url)
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
{"vy":8,"y_of_schema1":364,"A":582,"to_node":611,"on.mouse_press":612,"B":379,"on.mouse_release":586,"on.update":368,"on.keychord_press":584,"Input_filename":436,"on.text_input":587,"fw_parent":611,"fw_app":"mastodon-luaML","Cursor_node":172,"compute_layout":385,"font":353,"line_height":365,"on.code_change":578,"add_thick_line":400,"render_node_and_descendants":603,"copy_shape":396,"add_edge":575,"load_from_iterator":463,"box_height":345,"scale":7,"on":1,"to_text":180,"Nodes":593,"update_editor_box":430,"initialize_editor":338,"on.initialize":446,"split_lines":469,"Surface":588,"add_node":590,"ntracks":600,"on.draw":418,"compute_ntracks":598,"schema1_of_y":366,"render_thread_to_surface":602,"Viewport":303,"vx":5,"dehtml":456}
to_node = 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.toot_id
end
end
end
end
end
{"vy":8,"y_of_schema1":364,"A":582,"to_node":611,"on.mouse_press":607,"B":379,"on.mouse_release":586,"on.update":368,"on.keychord_press":584,"Input_filename":436,"on.text_input":587,"fw_parent":610,"fw_app":"mastodon-luaML","Cursor_node":172,"compute_layout":385,"font":353,"line_height":365,"on.code_change":578,"add_thick_line":400,"render_node_and_descendants":603,"copy_shape":396,"add_edge":575,"load_from_iterator":463,"box_height":345,"scale":7,"on":1,"to_text":180,"Nodes":593,"update_editor_box":430,"initialize_editor":338,"on.initialize":446,"split_lines":469,"Surface":588,"add_node":590,"ntracks":600,"on.draw":418,"compute_ntracks":598,"schema1_of_y":366,"render_thread_to_surface":602,"Viewport":303,"vx":5,"dehtml":456}
to_node = 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
print('bb', node.toot_id)
return node.toot_id
end
end
end
end
end
{"vy":8,"y_of_schema1":364,"A":582,"to_node":610,"on.mouse_press":607,"B":379,"on.mouse_release":586,"on.update":368,"on.keychord_press":584,"Input_filename":436,"on.text_input":587,"fw_parent":609,"fw_app":"mastodon-luaML","Cursor_node":172,"compute_layout":385,"font":353,"line_height":365,"on.code_change":578,"add_thick_line":400,"render_node_and_descendants":603,"copy_shape":396,"add_edge":575,"load_from_iterator":463,"box_height":345,"scale":7,"on":1,"to_text":180,"Nodes":593,"update_editor_box":430,"initialize_editor":338,"on.initialize":446,"split_lines":469,"Surface":588,"add_node":590,"ntracks":600,"on.draw":418,"compute_ntracks":598,"schema1_of_y":366,"render_thread_to_surface":602,"Viewport":303,"vx":5,"dehtml":456}
to_node = 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
print('bb', node.id)
return node.id
end
end
end
end
end
{"vy":8,"y_of_schema1":364,"A":582,"to_node":609,"on.mouse_press":607,"B":379,"on.mouse_release":586,"on.update":368,"on.keychord_press":584,"Input_filename":436,"on.text_input":587,"fw_parent":608,"fw_app":"mastodon-luaML","Cursor_node":172,"compute_layout":385,"font":353,"line_height":365,"on.code_change":578,"add_thick_line":400,"render_node_and_descendants":603,"copy_shape":396,"add_edge":575,"load_from_iterator":463,"box_height":345,"scale":7,"on":1,"to_text":180,"Nodes":593,"update_editor_box":430,"initialize_editor":338,"on.initialize":446,"split_lines":469,"Surface":588,"add_node":590,"ntracks":600,"on.draw":418,"compute_ntracks":598,"schema1_of_y":366,"render_thread_to_surface":602,"Viewport":303,"vx":5,"dehtml":456}
to_node = 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
print('bb')
return node.id
end
end
end
end
end
{"vy":8,"y_of_schema1":364,"A":582,"to_node":608,"on.mouse_press":607,"B":379,"on.mouse_release":586,"on.update":368,"on.keychord_press":584,"Input_filename":436,"on.text_input":587,"fw_parent":607,"fw_app":"mastodon-luaML","Cursor_node":172,"compute_layout":385,"font":353,"line_height":365,"on.code_change":578,"add_thick_line":400,"render_node_and_descendants":603,"copy_shape":396,"add_edge":575,"load_from_iterator":463,"box_height":345,"scale":7,"on":1,"to_text":180,"Nodes":593,"update_editor_box":430,"initialize_editor":338,"on.initialize":446,"split_lines":469,"Surface":588,"add_node":590,"ntracks":600,"on.draw":418,"compute_ntracks":598,"schema1_of_y":366,"render_thread_to_surface":602,"Viewport":303,"vx":5,"dehtml":456}
on.mouse_press = function(x,y, mouse_button)
local node_id = to_node(x,y)
if node_id then
print('aa', node_id, Nodes[node_id].url)
App.setClipboardText(Nodes[node_id].url)
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
{"vy":8,"y_of_schema1":364,"A":582,"to_node":604,"on.mouse_press":607,"B":379,"on.mouse_release":586,"on.update":368,"on.keychord_press":584,"Input_filename":436,"on.text_input":587,"fw_parent":606,"fw_app":"mastodon-luaML","Cursor_node":172,"compute_layout":385,"font":353,"line_height":365,"on.code_change":578,"add_thick_line":400,"render_node_and_descendants":603,"copy_shape":396,"add_edge":575,"load_from_iterator":463,"box_height":345,"scale":7,"on":1,"to_text":180,"Nodes":593,"update_editor_box":430,"initialize_editor":338,"on.initialize":446,"split_lines":469,"Surface":588,"add_node":590,"ntracks":600,"on.draw":418,"compute_ntracks":598,"schema1_of_y":366,"render_thread_to_surface":602,"Viewport":303,"vx":5,"dehtml":456}
on.mouse_press = function(x,y, mouse_button)
local node_id = to_node(x,y)
if node_id then
App.setClipboardText(Nodes[node_id].url)
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
{"fw_parent":604,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":606,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":603,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"Surface":588,"line_height":365,"on.mouse_release":586,"to_text":180,"to_node":604,"render_thread_to_surface":602,"y_of_schema1":364,"schema1_of_y":366,"ntracks":600,"compute_layout":385,"on.code_change":578,"Cursor_node":172,"A":582,"on.initialize":446,"on":1,"on.keychord_press":584,"initialize_editor":338,"on.draw":418,"B":379,"box_height":345}
on.mouse_press = function(x,y, mouse_button)
local node_id = to_node(x,y)
if node_id then
App.setClipboardText(Nodes[node_id].url
else
Pan = {x=Viewport.x+x,y=Viewport.y+y}
end
end
{"fw_parent":604,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":605,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":603,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"to_node":604,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":600,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":602,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
to_node = 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.id
end
end
end
end
end
{"fw_parent":603,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":603,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"to_node":604,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":600,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":602,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
render_node_and_descendants = function(id, y, xlo, xhi, grandparent_surface_node)
-- draw a parent 'id' and its children
-- also draw an edge from grandparent to parent if provided
-- position the root between xlo and xhi to be closer to children with fewer tracks
local parent = Nodes[id]
if parent.children == nil then
add_node(xlo, y, parent.content, parent.id, grandparent_surface_node)
return
end
local parent_xlo
if #parent.children <= 1 then
parent_xlo = xlo
else
local total_boundaries = 0
local curr_boundary = xlo
for child_idx = 1,#parent.children-1 do
local child_id = parent.children[child_idx]
local child = Nodes[child_id]
curr_boundary = curr_boundary + 620 * child.ntracks
total_boundaries = total_boundaries + curr_boundary
end
local parent_x = total_boundaries / (#parent.children-1)
parent_xlo = parent_x - 620/2
end
local parent_surface_node = add_node(parent_xlo, y, parent.content, parent.id, grandparent_surface_node)
local parent_height = box_height(parent_surface_node)
local curr_boundary = xlo
for _,child_id in ipairs(parent.children) do
local child = Nodes[child_id]
render_node_and_descendants(child_id, y + parent_height + 50, curr_boundary, curr_boundary + 620*child.ntracks, parent_surface_node)
curr_boundary = curr_boundary + 620*child.ntracks
end
end
{"fw_parent":602,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":603,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":600,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":602,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
render_thread_to_surface = function(thread_data)
-- design constraints:
-- trees only, no graphs or DAGs
-- parents above children
-- a child shares its parent's column exactly only if it's an only child
-- parents can overlap columns with children and more distant descendants
-- siblings never share a column
-- siblings never overlap columns
-- siblings always occupy the same row
-- cousins/aunts/nephews never overlap columns
Surface = {}
-- we're going to be computing box heights
love.graphics.setFont(love.graphics.newFont(scale(20)))
-- compute mapping from ids to nodes
Nodes = {} -- id to object
Nodes[thread_data.id] = thread_data
for _,x in ipairs(thread_data.descendants) do
Nodes[x.id] = x
end
local root = thread_data
-- compute children
for _,x in pairs(Nodes) do
parent_id = x.in_reply_to_id
if x.id ~= root.id then
assert(parent_id)
local parent = Nodes[parent_id]
if parent.children == nil then
parent.children = {}
end
table.insert(parent.children, x.id)
end
end
-- sort children by time
for _,x in pairs(Nodes) do
if x.children then
table.sort(x.children)
end
end
-- compute number of tracks needed
for _,x in pairs(Nodes) do
if x.ntracks == nil then
x.ntracks = compute_ntracks(x)
end
end
-- prepare the tracks
-- each track is 600px + 20px of gutter between nodes
render_node_and_descendants(root.id, --[[y]] 0, --[[xlo]] 0, --[[xhi]] 620 * root.ntracks)
end
{"fw_parent":601,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":601,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":600,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":602,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
render_node_and_descendants = function(id, y, xlo, xhi, grandparent_surface_node)
-- draw a parent 'id' and its children
-- also draw an edge from grandparent to parent if provided
-- position the root between xlo and xhi to be closer to children with fewer tracks
local parent = Nodes[id]
if parent.children == nil then
add_node(xlo, y, parent.content, parent.id, grandparent_surface_node)
return
end
local parent_xlo
if #parent.children <= 1 then
parent_xlo = xlo
else
local total_boundaries = 0
local curr_boundary = xlo
for child_idx = 1,#parent.children-1 do
local child_id = parent.children[child_idx]
local child = Nodes[child_id]
curr_boundary = curr_boundary + 620 * child.ntracks
total_boundaries = total_boundaries + curr_boundary
end
local parent_x = total_boundaries / (#parent.children-1)
parent_xlo = parent_x - 620/2
end
local parent_surface_node = add_node(parent_xlo, y, parent.content, parent.id, grandparent_surface_node)
local parent_height = box_height(parent_surface_node)
local curr_boundary = xlo
for _,child_id in ipairs(parent.children) do
local child = Nodes[child_id]
render_node_and_descendants(Nodes, child_id, y + parent_height + 50, curr_boundary, curr_boundary + 620*child.ntracks, parent_surface_node)
curr_boundary = curr_boundary + 620*child.ntracks
end
end
{"fw_parent":600,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":601,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":600,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":597,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
ntracks = function(parent)
-- memoize
if parent.ntracks == nil then
parent.ntracks = compute_ntracks(parent)
end
return parent.ntracks
end
{"fw_parent":599,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":600,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":597,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
ntracks = function(parent)
-- memoize
if parent.ntracks == nil then
parent.ntracks = compute_ntracks(nodes, parent)
end
return parent.ntracks
end
{"fw_parent":598,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":599,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":597,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
{"fw_parent":597,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":598,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":597,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
compute_ntracks = function(parent)
-- leaf nodes need 1 track
if parent.children == nil then
return 1
end
-- otherwise add up the tracks needed by all children (parent will fit in among them)
-- if we have a single child, it will slide into the same track. This is desirable.
local result = 0
for _,child_id in ipairs(parent.children) do
local child = Nodes[child_id]
result = result + ntracks(child)
end
return result
end
render_thread_to_surface = function(thread_data)
-- design constraints:
-- trees only, no graphs or DAGs
-- parents above children
-- a child shares its parent's column exactly only if it's an only child
-- parents can overlap columns with children and more distant descendants
-- siblings never share a column
-- siblings never overlap columns
-- siblings always occupy the same row
-- cousins/aunts/nephews never overlap columns
Surface = {}
-- we're going to be computing box heights
love.graphics.setFont(love.graphics.newFont(scale(20)))
-- compute mapping from ids to nodes
Nodes = {} -- id to object
Nodes[thread_data.id] = thread_data
for _,x in ipairs(thread_data.descendants) do
Nodes[x.id] = x
end
local root = thread_data
-- compute children
for _,x in pairs(Nodes) do
parent_id = x.in_reply_to_id
if x.id ~= root.id then
assert(parent_id)
local parent = Nodes[parent_id]
if parent.children == nil then
parent.children = {}
end
table.insert(parent.children, x.id)
end
end
-- sort children by time
for _,x in pairs(Nodes) do
if x.children then
table.sort(x.children)
end
end
-- compute number of tracks needed
for _,x in pairs(Nodes) do
if x.ntracks == nil then
x.ntracks = compute_ntracks(x)
end
end
-- prepare the tracks
-- each track is 600px + 20px of gutter between nodes
render_node_and_descendants(Nodes, root.id, --[[y]] 0, --[[xlo]] 0, --[[xhi]] 620 * root.ntracks)
end
{"fw_parent":596,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":596,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":597,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
{"fw_parent":595,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":596,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":595,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
compute_ntracks = function(parent)
-- leaf nodes need 1 track
if parent.children == nil then
return 1
end
-- otherwise add up the tracks needed by all children (parent will fit in among them)
-- if we have a single child, it will slide into the same track. This is desirable.
local result = 0
for _,child_id in ipairs(parent.children) do
local child = Nodes[child_id]
result = result + ntracks(Nodes, child)
end
return result
end
render_thread_to_surface = function(thread_data)
-- design constraints:
-- trees only, no graphs or DAGs
-- parents above children
-- a child shares its parent's column exactly only if it's an only child
-- parents can overlap columns with children and more distant descendants
-- siblings never share a column
-- siblings never overlap columns
-- siblings always occupy the same row
-- cousins/aunts/nephews never overlap columns
Surface = {}
-- we're going to be computing box heights
love.graphics.setFont(love.graphics.newFont(scale(20)))
-- compute mapping from ids to nodes
Nodes = {} -- id to object
Nodes[thread_data.id] = thread_data
for _,x in ipairs(thread_data.descendants) do
Nodes[x.id] = x
end
local root = thread_data
-- compute children
for _,x in pairs(Nodes) do
parent_id = x.in_reply_to_id
if x.id ~= root.id then
assert(parent_id)
local parent = Nodes[parent_id]
if parent.children == nil then
parent.children = {}
end
table.insert(parent.children, x.id)
end
end
-- sort children by time
for _,x in pairs(Nodes) do
if x.children then
table.sort(x.children)
end
end
-- compute number of tracks needed
for _,x in pairs(Nodes) do
if x.ntracks == nil then
x.ntracks = compute_ntracks(Nodes, x)
end
end
-- prepare the tracks
-- each track is 600px + 20px of gutter between nodes
render_node_and_descendants(Nodes, root.id, --[[y]] 0, --[[xlo]] 0, --[[xhi]] 620 * root.ntracks)
end
{"fw_parent":594,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":519,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":595,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
render_thread_to_surface = function(thread_data)
-- design constraints:
-- trees only, no graphs or DAGs
-- parents above children
-- a child shares its parent's column exactly only if it's an only child
-- parents can overlap columns with children and more distant descendants
-- siblings never share a column
-- siblings never overlap columns
-- siblings always occupy the same row
-- cousins/aunts/nephews never overlap columns
Surface = {}
-- we're going to be computing box heights
love.graphics.setFont(love.graphics.newFont(scale(20)))
-- compute mapping from ids to nodes
Nodes = {} -- id to object
Nodes[thread_data.id] = thread_data
for _,x in ipairs(thread_data.descendants) do
Nodes[x.id] = x
end
local root = thread_data
-- compute children
for _,x in pairs(nodes) do
parent_id = x.in_reply_to_id
if x.id ~= root.id then
assert(parent_id)
local parent = Nodes[parent_id]
if parent.children == nil then
parent.children = {}
end
table.insert(parent.children, x.id)
end
end
-- sort children by time
for _,x in pairs(Nodes) do
if x.children then
table.sort(x.children)
end
end
-- compute number of tracks needed
for _,x in pairs(Nodes) do
if x.ntracks == nil then
x.ntracks = compute_ntracks(Nodes, x)
end
end
-- prepare the tracks
-- each track is 600px + 20px of gutter between nodes
render_node_and_descendants(Nodes, root.id, --[[y]] 0, --[[xlo]] 0, --[[xhi]] 620 * root.ntracks)
end
{"fw_parent":593,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":519,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":594,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
{"fw_parent":592,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"Nodes":593,"compute_ntracks":519,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":589,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
Nodes = {}
render_node_and_descendants = function(nodes, id, y, xlo, xhi, grandparent_surface_node)
-- draw a parent 'id' and its children
-- also draw an edge from grandparent to parent if provided
-- position the root between xlo and xhi to be closer to children with fewer tracks
local parent = nodes[id]
if parent.children == nil then
add_node(xlo, y, parent.content, parent.id, grandparent_surface_node)
return
end
local parent_xlo
if #parent.children <= 1 then
parent_xlo = xlo
else
local total_boundaries = 0
local curr_boundary = xlo
for child_idx = 1,#parent.children-1 do
local child_id = parent.children[child_idx]
local child = nodes[child_id]
curr_boundary = curr_boundary + 620 * child.ntracks
total_boundaries = total_boundaries + curr_boundary
end
local parent_x = total_boundaries / (#parent.children-1)
parent_xlo = parent_x - 620/2
end
local parent_surface_node = add_node(parent_xlo, y, parent.content, parent.id, grandparent_surface_node)
local parent_height = box_height(parent_surface_node)
local curr_boundary = xlo
for _,child_id in ipairs(parent.children) do
local child = nodes[child_id]
render_node_and_descendants(nodes, child_id, y + parent_height + 50, curr_boundary, curr_boundary + 620*child.ntracks, parent_surface_node)
curr_boundary = curr_boundary + 620*child.ntracks
end
end
{"fw_parent":591,"fw_app":"mastodon-luaML","scale":7,"load_from_iterator":463,"on.text_input":587,"vx":5,"on.mouse_press":585,"Viewport":303,"split_lines":469,"vy":8,"compute_ntracks":519,"Input_filename":436,"on.update":368,"font":353,"add_node":590,"render_node_and_descendants":592,"dehtml":456,"add_edge":575,"add_thick_line":400,"copy_shape":396,"update_editor_box":430,"on.initialize":446,"line_height":365,"initialize_editor":338,"on":1,"on.code_change":578,"on.draw":418,"schema1_of_y":366,"box_height":345,"ntracks":505,"compute_layout":385,"Cursor_node":172,"A":582,"y_of_schema1":364,"render_thread_to_surface":589,"on.keychord_press":584,"to_text":180,"on.mouse_release":586,"B":379,"Surface":588}
render_node_and_descendants = function(nodes, id, y, xlo, xhi, grandparent_surface_node)
-- draw a parent 'id' and its children
-- also draw an edge from grandparent to parent if provided
-- position the root between xlo and xhi to be closer to children with fewer tracks
local parent = nodes[id]
if parent.children == nil then
add_node(xlo, y, parent.content, grandparent_surface_node)
return
end
local parent_xlo
if #parent.children <= 1 then
parent_xlo = xlo
else
local total_boundaries = 0
local curr_boundary = xlo
for child_idx = 1,#parent.children-1 do
local child_id = parent.children[child_idx]
local child = nodes[child_id]
curr_boundary = curr_boundary + 620 * child.ntracks
total_boundaries = total_boundaries + curr_boundary
end
local parent_x = total_boundaries / (#parent.children-1)
parent_xlo = parent_x - 620/2
end
local parent_surface_node = add_node(parent_xlo, y, parent.content, parent.id, grandparent_surface_node)
local parent_height = box_height(parent_surface_node)
local curr_boundary = xlo
for _,child_id in ipairs(parent.children) do
local child = nodes[child_id]
render_node_and_descendants(nodes, child_id, y + parent_height + 50, curr_boundary, curr_boundary + 620*child.ntracks, parent_surface_node)
curr_boundary = curr_boundary + 620*child.ntracks
end
end
{"vy":8,"Cursor_node":172,"on.update":368,"ntracks":505,"render_thread_to_surface":589,"dehtml":456,"add_thick_line":400,"copy_shape":396,"fw_parent":590,"fw_app":"mastodon-luaML","load_from_iterator":463,"on.code_change":578,"font":353,"box_height":345,"split_lines":469,"scale":7,"add_node":590,"on.draw":418,"vx":5,"Viewport":303,"schema1_of_y":366,"on.mouse_release":586,"update_editor_box":430,"to_text":180,"Surface":588,"render_node_and_descendants":591,"y_of_schema1":364,"compute_layout":385,"Input_filename":436,"compute_ntracks":519,"A":582,"B":379,"on.keychord_press":584,"add_edge":575,"on":1,"on.text_input":587,"on.mouse_press":585,"initialize_editor":338,"line_height":365,"on.initialize":446}
{"vy":8,"Cursor_node":172,"on.update":368,"ntracks":505,"render_thread_to_surface":589,"dehtml":456,"add_thick_line":400,"copy_shape":396,"fw_parent":589,"fw_app":"mastodon-luaML","load_from_iterator":463,"on.code_change":578,"font":353,"box_height":345,"split_lines":469,"scale":7,"add_node":590,"on.draw":418,"vx":5,"Viewport":303,"schema1_of_y":366,"on.mouse_release":586,"update_editor_box":430,"to_text":180,"Surface":588,"render_node_and_descendants":579,"y_of_schema1":364,"compute_layout":385,"Input_filename":436,"compute_ntracks":519,"A":582,"B":379,"on.keychord_press":584,"add_edge":575,"on":1,"on.text_input":587,"on.mouse_press":585,"initialize_editor":338,"line_height":365,"on.initialize":446}
add_node = function(x, y, text, id, parent_surface_node)
local surface_node = {
x=x, y=y,
width=600,
type='text',
data=split_lines(dehtml(text)),
bg={r=0.7,g=0.7, b=1.0},
toot_id=id,
}
compute_layout(surface_node, surface_node.x, surface_node.y, Surface)
if parent_surface_node then
add_edge(surface_node, parent_surface_node)
end
return surface_node
end
render_thread_to_surface = function(thread_data)
-- design constraints:
-- trees only, no graphs or DAGs
-- parents above children
-- a child shares its parent's column exactly only if it's an only child
-- parents can overlap columns with children and more distant descendants
-- siblings never share a column
-- siblings never overlap columns
-- siblings always occupy the same row
-- cousins/aunts/nephews never overlap columns
Surface = {}
-- we're going to be computing box heights
love.graphics.setFont(love.graphics.newFont(scale(20)))
-- compute mapping from ids to nodes
local nodes = {} -- id to object
nodes[thread_data.id] = thread_data
for _,x in ipairs(thread_data.descendants) do
nodes[x.id] = x
end
local root = thread_data
-- compute children
for _,x in pairs(nodes) do
parent_id = x.in_reply_to_id
if x.id ~= root.id then
assert(parent_id)
local parent = nodes[parent_id]
if parent.children == nil then
parent.children = {}
end
table.insert(parent.children, x.id)
end
end
-- sort children by time
for _,x in pairs(nodes) do
if x.children then
table.sort(x.children)
end
end
-- compute number of tracks needed
for _,x in pairs(nodes) do
if x.ntracks == nil then
x.ntracks = compute_ntracks(nodes, x)
end
end
-- prepare the tracks
-- each track is 600px + 20px of gutter between nodes
render_node_and_descendants(nodes, root.id, --[[y]] 0, --[[xlo]] 0, --[[xhi]] 620 * root.ntracks)
end
{"schema1_of_y":366,"ntracks":505,"compute_ntracks":519,"y_of_schema1":364,"A":582,"compute_layout":385,"render_node_and_descendants":579,"B":379,"line_height":365,"on.code_change":578,"Surface":588,"Input_filename":436,"on.draw":418,"vx":5,"scale":7,"Viewport":303,"Cursor_node":172,"vy":8,"to_text":180,"on.mouse_press":585,"render_thread_to_surface":589,"initialize_editor":338,"on.update":368,"dehtml":456,"on.keychord_press":584,"copy_shape":396,"on.initialize":446,"fw_app":"mastodon-luaML","on":1,"fw_parent":588,"add_node":576,"load_from_iterator":463,"on.text_input":587,"add_edge":575,"add_thick_line":400,"box_height":345,"update_editor_box":430,"on.mouse_release":586,"split_lines":469,"font":353}