chronos/src/renderer.typ

116 lines
2.5 KiB
Typst
Raw Normal View History

2024-06-18 13:39:38 +02:00
#import "@preview/cetz:0.2.2": canvas, draw
#let X-SPACE = 2
2024-06-18 13:51:01 +02:00
#let Y-SPACE = 20
2024-06-18 13:39:38 +02:00
#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-columns-width(participants, elements) = {
let pars-i = get-participants-i(participants)
let cells = ()
for elmt in elements {
if elmt.type == "seq" {
let com = if elmt.comment == none {""} else {elmt.comment}
let i1 = pars-i.at(elmt.p1)
let i2 = pars-i.at(elmt.p2)
cells.push(
(
elmt: elmt,
i1: calc.min(i1, i2),
i2: calc.max(i1, i2),
cell: box(com, inset: 3pt)
)
)
}
}
let widths = participants.slice(0, -1).map(_ => 0)
for cell in cells.filter(c => c.i2 - c.i1 == 1) {
let m = measure(cell.cell)
widths.at(cell.i1) = calc.max(
widths.at(cell.i1),
m.width / 1pt
)
}
return widths
}
#let render(participants, elements) = context canvas(length: 1pt, {
let pars-i = get-participants-i(participants)
let widths = get-columns-width(participants, elements)
let x-pos = (0,)
for width in widths {
x-pos.push(x-pos.last() + width)
}
// Draw participants
for (i, p) in participants.enumerate() {
draw.content(
(x-pos.at(i), 0),
p.display-name,
name: p.name,
frame: "rect",
padding: (5pt, 3pt),
anchor: "south"
)
}
let y = -Y-SPACE
// Draw sequences
for elmt in elements {
if elmt.type == "seq" {
let x1 = x-pos.at(pars-i.at(elmt.p1))
let x2 = x-pos.at(pars-i.at(elmt.p2))
2024-06-18 13:51:01 +02:00
let style = (
mark: (end: "straight"),
stroke: (
dash: if elmt.dashed {"dashed"} else {"solid"},
paint: elmt.color
)
)
2024-06-18 13:39:38 +02:00
draw.line(
(x1, y),
(x2, y),
2024-06-18 13:51:01 +02:00
..style
2024-06-18 13:39:38 +02:00
)
if elmt.comment != none {
draw.content(
(calc.min(x1, x2), y),
elmt.comment,
anchor: "south-west",
padding: 3pt
)
}
y -= Y-SPACE
}
}
// Draw vertical lines + end participants
draw.on-layer(-1, {
for (i, p) in participants.enumerate() {
let x = x-pos.at(i)
draw.line(
(x, 0),
(x, y),
stroke: (dash: "dashed", paint: gray.darken(40%))
)
draw.content(
(x, y),
p.display-name,
name: p.name,
frame: "rect",
padding: (5pt, 3pt),
anchor: "north"
)
}
})
})