Files
chronos/src/core/utils.typ

139 lines
3.1 KiB
Typst

#import "/src/cetz.typ": draw, styles
#import "/src/consts.typ": default-style
#let is-elmt(elmt) = {
if type(elmt) != dictionary {
return false
}
if "type" not in elmt {
return false
}
return true
}
#let normalize-units(value) = {
if type(value) == int or type(value) == float {
return value
}
if type(value) == length {
return value / 1pt
}
panic("Unsupported type '" + str(type(value)) + "'")
}
#let get-participants-i(participants) = {
let pars-i = (:)
for (i, p) in participants.enumerate() {
pars-i.insert(p.name, i)
}
return pars-i
}
#let get-group-span(participants, group) = {
let min-i = participants.len() - 1
let max-i = 0
let pars-i = get-participants-i(participants)
for elmt in group.elmts {
if elmt.type == "seq" {
let i1 = pars-i.at(elmt.p1)
let i2 = pars-i.at(elmt.p2)
min-i = calc.min(min-i, i1, i2)
max-i = calc.max(max-i, i1, i2)
} else if elmt.type == "grp" {
let (i0, i1) = get-group-span(participants, elmt)
min-i = calc.min(min-i, i0)
max-i = calc.max(max-i, i1)
} else if elmt.type == "sync" {
let (i0, i1) = get-group-span(participants, elmt)
min-i = calc.min(min-i, i0)
max-i = calc.max(max-i, i1)
}
}
if max-i < min-i {
(min-i, max-i) = (max-i, min-i)
}
return (min-i, max-i)
}
#let get-style(base-name, mods) = {
let style = if base-name == "lifeline" {(
fill: white,
stroke: black + 1pt
)}
if mods == auto {
return style
}
if type(mods) == dictionary {
return style + mods
}
panic("Invalid type for parameter mods, expected auto or dictionary, got " + str(type(mods)))
}
#let fit-canvas(canvas, width: auto) = layout(size => {
let m = measure(canvas)
let w = m.width
let h = m.height
let r = if w == 0pt {0} else {
if width == auto {1}
else if type(width) == length {
width / w
} else {
size.width * width / w
}
}
let new-w = w * r
let new-h = h * r
r *= 100%
box(
width: new-w,
height: new-h,
scale(x: r, y: r, reflow: true, canvas)
)
})
#let extract-ctx(cetz-ctx) = {
let state = cetz-ctx.at("shared-state", default: (:))
return state.at("chronos", default: (:))
}
#let set-ctx(func) = draw.set-ctx(c => {
let ctx = extract-ctx(c)
let new-ctx = func(ctx)
assert(new-ctx != none, message: "set-ctx must return a context!")
let state = c.at("shared-state", default: (:))
state.chronos = new-ctx
c.shared-state = state
return c
})
#let get-ctx(func) = draw.get-ctx(c => {
let ctx = extract-ctx(c)
ctx.style = styles.resolve(
c.style,
root: "chronos",
base: default-style
)
// Normalize because it is used very frequently
ctx.style.y-space = normalize-units(ctx.style.y-space)
func(ctx)
})
#let set-y(new-y) = set-ctx(c => {
c.y = new-y
return c
})
#let expand-parent-group(x0, x1) = set-ctx(ctx => {
if ctx.groups.len() != 0 {
let group = ctx.groups.last()
group.min-x = calc.min(group.min-x, x0)
group.max-x = calc.max(group.max-x, x1)
ctx.groups.last() = group
}
return ctx
})