Last active
November 7, 2022 05:22
-
-
Save stillwwater/9e30d4962c455a6729cb3a12f8642e85 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| spacing=1 | |
| id=1 | |
| nodes={} | |
| rects={} | |
| parent=nil | |
| child=nil | |
| function setpos(node) | |
| local d=0 | |
| local p=node.p | |
| node.abs={x=node.dst.x, | |
| y=node.dst.y, | |
| w=node.dst.w, | |
| h=node.dst.h} | |
| if p then | |
| node.abs.x+=p.abs.x | |
| node.abs.y+=p.abs.y | |
| end | |
| while p do | |
| p=p.p -- pp | |
| d+=1 | |
| end | |
| rects[node.id]={node.abs.x, | |
| node.abs.y, | |
| node.abs.x+node.abs.w, | |
| node.abs.y+node.abs.h,d} | |
| end | |
| function measure(node,dst) | |
| local spc=spacing | |
| node.dst={x=node.x+spc, | |
| y=node.y+spc, | |
| w=node.w,h=node.h} | |
| dst=node.dst | |
| -- fixed layout? | |
| if node.b and not node.p.fix then | |
| if node.p.horz then | |
| -- horizontal stack layout | |
| dst.x+=node.b.dst.x+node.b.dst.w+spc | |
| else | |
| -- vertical stack layout | |
| dst.y+=node.b.dst.y+node.b.dst.h+spc | |
| end | |
| end | |
| -- w in (0,1] size node | |
| -- relative to parent width. | |
| if node.w>0 and node.w<=1.0 then | |
| -- only works if parent width | |
| -- doesn't depend on children. | |
| assert(node.p.w>0) | |
| dst.w=node.p.dst.w*node.w-spc*2 | |
| -- calculate space remaining | |
| -- in parent to make sure we fit. | |
| local rs=node.p.dst.w-node.dst.x-spc | |
| if rs<=dst.w and node.p.horz | |
| and not node.p.fix then | |
| -- node doesn't fit, measure | |
| -- the remaining children | |
| -- and size this node accordingly. | |
| local a=node.a | |
| while a do | |
| measure(a) | |
| rs-=a.dst.w+2*spc | |
| a=a.a | |
| end | |
| end | |
| dst.w=min(dst.w,rs) | |
| end | |
| -- h in (0,1] size node | |
| -- relative to parent height | |
| if node.h>0 and node.h<=1.0 then | |
| -- only works if parent width | |
| -- doesn't depend on children | |
| assert(node.p.h>0) | |
| -- same as before | |
| dst.h=node.p.dst.h*node.h-spc*2 | |
| local rs=node.p.dst.h-node.dst.y-spc | |
| if rs<=dst.h and not node.p.horz | |
| and not node.p.fix then | |
| local a=node.a | |
| while a do | |
| measure(a) | |
| rs-=a.dst.h+2*spc | |
| a=a.a | |
| end | |
| end | |
| dst.h=min(dst.h,rs) | |
| end | |
| -- measure children | |
| local c=node.c | |
| local last=c | |
| while c do | |
| measure(c) | |
| last=c | |
| c=c.a | |
| if node.col then | |
| -- node is collapsed, node | |
| -- size matches first child. | |
| break | |
| end | |
| end | |
| if last then | |
| c=last | |
| -- h=0 size node based on | |
| -- its children. | |
| -- collapsing parent only | |
| -- works for vertical layout. | |
| if node.h == 0 or node.col then | |
| dst.h=c.dst.y+c.dst.h+spc | |
| end | |
| -- w=0 size node based on | |
| -- its children. | |
| if node.w == 0 then | |
| dst.w=c.dst.x+c.dst.w+spc | |
| end | |
| end | |
| -- x in (0,1] position node | |
| -- relative to parent width | |
| if node.x>0 and node.x<=1 then | |
| node.dst.x=(node.p.dst.w*node.x)-(node.dst.w*node.x)-spc*flr(node.x) | |
| end | |
| -- y in (0,1] position node | |
| -- relative to parent height | |
| if node.y>0 and node.y<=1 then | |
| node.dst.y=(node.p.dst.h*node.y)-(node.dst.h*node.y)-spc*flr(node.y) | |
| end | |
| end | |
| function layout(node) | |
| setpos(node) | |
| local c=node.c | |
| while c do | |
| layout(c) | |
| c=c.a | |
| if node.col then | |
| -- node is collapsed, | |
| -- rest is not visible. | |
| break | |
| end | |
| end | |
| end | |
| function window(node) | |
| id+=1 | |
| node.id=id | |
| node.p=parent | |
| if parent.c==nil then | |
| parent.c=node | |
| elseif child then | |
| node.b=child | |
| child.a=node | |
| end | |
| parent=node | |
| child=nil | |
| add(nodes,node) | |
| end | |
| function pop() | |
| assert(parent) | |
| parent=parent.p | |
| child=parent.c | |
| while child.a do | |
| child=child.a | |
| end | |
| end | |
| function control(node) | |
| assert(parent) | |
| id+=1 | |
| node.id=id | |
| node.p=parent | |
| node.b=child | |
| if child then | |
| child.a=node | |
| end | |
| if parent.c==nil then | |
| parent.c=node | |
| end | |
| child=node | |
| end | |
| function _init() | |
| add(nodes,{id=1, | |
| x=0,y=0,w=128,h=128, | |
| p=nil,c=nil,b=nil,a=nil}) | |
| parent=nodes[1] | |
| -- user code | |
| window{x=0,y=0,w=124,h=124,fix=true} | |
| window{x=1,y=0,w=64,h=1.0} | |
| window{x=0,y=0,w=1.0,h=0} | |
| control{x=0,y=0,w=1.0,h=5} | |
| control{x=0,y=0,w=1.0,h=3} | |
| window{x=0,y=0,w=1,h=0,horz=true} | |
| control{x=0,y=0,w=0.5,h=3} | |
| control{x=0,y=0,w=0.5,h=3} | |
| pop() | |
| window{x=0,y=0,w=1.0,h=0,horz=true} | |
| control{x=0,y=0,w=1,h=3} | |
| control{x=0,y=0,w=10,h=3} | |
| control{x=0,y=0,w=8,h=3} | |
| pop() | |
| pop() | |
| window{x=0,y=0,w=1.0,h=1.0} | |
| window{x=0,y=0,w=1.0,h=0,horz=true} | |
| control{x=0,y=0,w=6,h=6} | |
| control{x=0,y=0,w=1.0,h=6} | |
| control{x=0,y=0,w=6,h=6} | |
| pop() | |
| -- middle | |
| window{x=0,y=0,w=1.0,h=1.0,fix=true} | |
| control{x=0,y=0,w=6,h=6} | |
| control{x=1,y=0,w=6,h=6} | |
| control{x=0,y=1,w=6,h=6} | |
| control{x=1,y=1,w=6,h=6} | |
| control{x=0.5,y=0.5,w=6,h=6} | |
| control{x=0,y=0.5,w=6,h=6} | |
| control{x=1,y=0.5,w=6,h=6} | |
| control{x=0.5,y=0,w=6,h=6} | |
| control{x=0.5,y=1,w=6,h=6} | |
| pop() | |
| window{x=0,y=0,w=1.0,h=0,horz=true} | |
| control{x=0,y=0,w=6,h=6} | |
| control{x=0,y=0,w=1.0,h=6} | |
| control{x=0,y=0,w=6,h=6} | |
| pop() | |
| pop() | |
| pop() | |
| -- dialog | |
| window{x=0.5,y=0.5,w=64,h=32} | |
| control{x=0,y=0,w=1,h=1} | |
| window{x=0,y=0,w=1,h=0,horz=true} | |
| control{x=0,y=0,w=1,h=5} | |
| control{x=0,y=0,w=12,h=5} | |
| control{x=0,y=0,w=12,h=5} | |
| pop() | |
| pop() | |
| -- collapse window | |
| window{x=0,y=0,w=50,h=0,col=true} | |
| control{x=0,y=0,w=1,h=4} | |
| control{x=0,y=0,w=1,h=4} | |
| control{x=0,y=0,w=1,h=4} | |
| control{x=0,y=0,w=1,h=4} | |
| control{x=0,y=0,w=1,h=4} | |
| pop() | |
| pop() | |
| measure(nodes[1]) | |
| layout(nodes[1]) | |
| end | |
| -- renderer | |
| function _draw() | |
| cls(0) | |
| for r in all(rects) do | |
| rectfill(r[1],r[2],r[3],r[4],3+r[5]) | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment