Files
chronos/src/core/draw/group.typ

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
})
})