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 a bar to grab for moving the node local move_bar = {type='rectangle', r=0.8,g=0.8,b=0.8, x=node.x-10, y=node.y-10-5-10, h=10, id=node.id} table.insert(nodes_to_render, move_bar) -- render bounding box local bounding_box = {type='rectangle', drawmode='line', r=0.5, g=0.5, b=0.5, x=node.x-10, y=node.y-10, rx=5, id=node.id} table.insert(nodes_to_render, bounding_box) -- render contents if node.width then node.w = node.width else node.w = 0 for i,s in ipairs(node.data) do local width = love.graphics.getFont():getWidth(s)/Viewport.zoom 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) move_bar.w = node.w/2 bounding_box.w = node.w+20 local buffer_height = node_height(node) bounding_box.h = buffer_height+20 -- resize affordance table.insert(nodes_to_render, {type='line', r=0.7,g=0.7,b=0.7, data={node.x+node.w+20,node.y, node.x+node.w+20,node.y+buffer_height}, id=node.id}) table.insert(nodes_to_render, {type='line', r=0.7,g=0.7,b=0.7, data={node.x+node.w+20+4,node.y, node.x+node.w+20+4,node.y+buffer_height}, id=node.id}) 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