#import "/src/cetz.typ": draw, styles #import "/src/consts.typ": * #import "/src/core/utils.typ": expand-parent-group, get-ctx, normalize-units, set-ctx #let group-default-style = ( name: ( inset: ( x: 5pt, y: 3pt ), stroke: auto, fill: auto ), desc: ( inset: 3pt ), divider: (dash: (2pt, 1pt), thickness: .5pt), padding: 10pt, stroke: auto ) #let render-start(grp) = get-ctx(ctx => { let style = styles.resolve( ctx.style, merge: grp.style, root: "group", base: group-default-style ) let grp = grp grp.insert("resolved-style", style) ctx.y -= ctx.style.y-space let name = box( text(grp.name, weight: "bold"), inset: style.name.inset ) grp.insert("rendered-name", name) let desc = box( text([\[#grp.desc\]], weight: "bold", size: .8em), inset: style.desc.inset ) grp.insert("rendered-desc", desc) let m = measure(name) ctx.groups = ctx.groups.map(g => { if g.group.min-i == grp.min-i { g.start-lvl += 1 } if g.group.max-i == grp.max-i { g.end-lvl += 1 } g }) if grp.grp-type == "alt" { grp.insert("elses", ()) } ctx.groups.push(( start-y: ctx.y, group: grp, start-lvl: 0, end-lvl: 0, min-x: ctx.x-pos.at(grp.min-i) - 10, max-x: ctx.x-pos.at(grp.max-i) + 10 )) ctx.y -= m.height / 1pt ctx.y += ctx.style.y-space / 2 set-ctx(c => { c.y = ctx.y c.groups = ctx.groups return c }) }) #let draw-group(x0, x1, y0, y1, group) = { let style = group.resolved-style let name = group.rendered-name let desc = group.rendered-desc let m = measure(name) let w = m.width / 1pt let h = m.height / 1pt draw.rect( (x0, y0), (x1, y1), stroke: style.stroke ) let x1 = x0 + w let x2 = x1 + 5 draw.line( (x0, y0), (x2, y0), (x2, y0 - h / 2), (x1, y0 - h), (x0, y0 - h), stroke: style.name.stroke, fill: style.name.fill, close: true ) draw.content( (x0, y0), name, anchor: "north-west" ) if group.desc != none { draw.content( (x2, y0), desc, anchor: "north-west" ) } } #let draw-else(x0, x1, y, elmt) = { let style = elmt.resolved-style draw.line( (x0, y), (x1, y), stroke: style.divider ) draw.content( (x0, y), elmt.rendered-desc, anchor: "north-west" ) } #let render-end(group) = get-ctx(ctx => { let y = ctx.y - ctx.style.y-space / 2 ctx.y -= ctx.style.y-space / 2 let ( start-y, group, start-lvl, end-lvl, min-x, max-x ) = ctx.groups.pop() let padding = normalize-units(group.resolved-style.padding) let x0 = min-x - padding let x1 = max-x + padding draw-group(x0, x1, start-y, y, group) if group.grp-type == "alt" { for (else-y, else-elmt) in group.elses { draw-else(x0, x1, else-y, else-elmt) } } set-ctx(c => { c.y = ctx.y c.groups = ctx.groups return c }) expand-parent-group(x0, x1) }) #let render-else(else_) = get-ctx(ctx => { let group = ctx.groups.last().group let style = styles.resolve( ctx.style, merge: group.style, root: "group", base: group-default-style ) ctx.y -= ctx.style.y-space / 2 let desc = box( text([\[#else_.desc\]], weight: "bold", size: .8em), inset: style.desc.inset ) let m = measure(desc) let else_ = else_ else_.insert("resolved-style", style) else_.insert("rendered-desc", desc) ctx.groups.last().group.elses.push(( ctx.y, else_ )) ctx.y -= m.height / 1pt ctx.y += ctx.style.y-space / 2 set-ctx(c => { c.y = ctx.y c.groups = ctx.groups return c }) })