#import "@preview/cetz:0.2.2": canvas, draw #let X-SPACE = 2 #let Y-SPACE = 20 #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)) let style = ( mark: (end: "straight"), stroke: ( dash: if elmt.dashed {"dashed"} else {"solid"}, paint: elmt.color ) ) draw.line( (x1, y), (x2, y), ..style ) 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" ) } }) })