190 lines
3.6 KiB
Typst
190 lines
3.6 KiB
Typst
#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
|
|
})
|
|
}) |