base for CeTZ integration

migrated contextual variables to CeTZ context shared-state
adapted participant rendering
This commit is contained in:
2025-07-14 15:40:21 +02:00
parent 6970e59413
commit 12fb144039
3 changed files with 74 additions and 425 deletions

View File

@ -1,8 +1,9 @@
#import "/src/cetz.typ" as cetz: canvas, draw
#import "utils.typ": get-participants-i, get-style, normalize-units, is-elmt
#import "utils.typ": *
#import "../group.typ"
#import "../participant.typ"
#import participant: PAR-SPECIALS
//#import "../participant.typ"
//#import participant: PAR-SPECIALS
#import "draw/participant.typ"
#import "../sequence.typ"
#import "../separator.typ"
#import "../sync.typ"
@ -317,45 +318,65 @@
return widths
}
#let render(participants, elements) = context canvas(length: 1pt, {
let participants = participants
let elements = elements
#let setup-ctx(participants, elements) = (ctx => {
let state = ctx.at("shared-state", default: (:))
let shapes = ()
participants = init-lifelines(participants)
let pars-i = get-participants-i(participants)
let widths = compute-columns-width(participants, elements, pars-i)
let chronos-ctx = (
participants: init-lifelines(participants),
pars-i: get-participants-i(participants),
y: 0,
groups: (),
lifelines: participants.map(_ => (
level: 0,
lines: ()
))
)
chronos-ctx.insert(
"widths",
compute-columns-width(
chronos-ctx.participants,
elements,
chronos-ctx.pars-i
)
)
// Compute each column's X position
let x-pos = (0,)
for width in widths {
for width in chronos-ctx.widths {
x-pos.push(x-pos.last() + width)
}
chronos-ctx.insert("x-pos", x-pos)
state.insert("chronos", chronos-ctx)
ctx.shared-state = state
return (
ctx: ctx
)
},)
#let render(participants, elements) = context canvas(length: 1pt, {
let shapes = ()
setup-ctx(participants, elements)
/*
let draw-seq = sequence.render.with(pars-i, x-pos, participants)
let draw-group = group.render.with()
let draw-else = group.render-else.with()
let draw-sep = separator.render.with(x-pos)
let draw-par = participant.render.with(x-pos)
//let draw-par = participant.render.with(x-pos)
let draw-note = note.render.with(pars-i, x-pos)
let draw-sync = sync.render.with(pars-i, x-pos, participants)
*/
// Draw participants (start)
for p in participants {
if p.from-start and not p.invisible and p.show-top {
shapes += draw-par(p)
get-ctx(ctx => {
for p in ctx.participants {
if p.from-start and not p.invisible and p.show-top {
(p.draw)(p)
}
}
}
})
let y = 0
let groups = ()
let lifelines = participants.map(_ => (
level: 0,
lines: ()
))
// Draw elemnts
// Draw elements
for elmt in elements {
if not is-elmt(elmt) {
shapes.push(elmt)
@ -372,7 +393,12 @@
let m = measure(
box(
elmt.name,
inset: (left: 5pt, right: 5pt, top: 3pt, bottom: 3pt),
inset: (
left: 5pt,
right: 5pt,
top: 3pt,
bottom: 3pt
),
)
)
groups = groups.map(g => {
@ -482,10 +508,13 @@
}
}
y -= Y-SPACE
set-ctx(ctx => {
ctx.y -= Y-SPACE
return ctx
})
// Draw vertical lines + lifelines + end participants
shapes += draw.on-layer(-1, {
draw.on-layer(-1, {
if DEBUG-INVISIBLE {
for p in participants.filter(p => p.invisible) {
let color = if p.name.starts-with("?") {green} else if p.name.ends-with("?") {red} else {blue}
@ -504,99 +533,7 @@
}
}
for p in participants.filter(p => not p.invisible) {
let x = x-pos.at(p.i)
// Draw vertical line
let last-y = 0
let rects = ()
let destructions = ()
let lines = ()
// Compute lifeline rectangles + destruction positions
for line in lifelines.at(p.i).lines {
let event = line.first()
if event == "create" {
last-y = line.at(1)
} else if event == "enable" {
if lines.len() == 0 {
draw.line(
(x, last-y),
(x, line.at(1)),
stroke: p.line-stroke
)
}
lines.push(line)
} else if event == "disable" or event == "destroy" {
let lvl = 0
if lines.len() != 0 {
let l = lines.pop()
lvl = lines.len()
rects.push((
x + lvl * LIFELINE-W / 2,
l.at(1),
line.at(1),
l.at(2)
))
last-y = line.at(1)
}
if event == "destroy" {
destructions.push((x + lvl * LIFELINE-W / 2, line.at(1)))
}
} else if event == "delay-start" {
draw.line(
(x, last-y),
(x, line.at(1)),
stroke: p.line-stroke
)
last-y = line.at(1)
} else if event == "delay-end" {
draw.line(
(x, last-y),
(x, line.at(1)),
stroke: (
dash: "loosely-dotted",
paint: gray.darken(40%),
thickness: .8pt
)
)
last-y = line.at(1)
}
}
draw.line(
(x, last-y),
(x, y),
stroke: p.line-stroke
)
// Draw lifeline rectangles (reverse for bottom to top)
for rect in rects.rev() {
let (cx, y0, y1, style) = rect
let style = get-style("lifeline", style)
draw.rect(
(cx - LIFELINE-W / 2, y0),
(cx + LIFELINE-W / 2, y1),
..style
)
}
// Draw lifeline destructions
for dest in destructions {
let (cx, cy) = dest
draw.line((cx - 8, cy - 8), (cx + 8, cy + 8), stroke: COL-DESTRUCTION + 2pt)
draw.line((cx - 8, cy + 8), (cx + 8, cy - 8), stroke: COL-DESTRUCTION + 2pt)
}
// Draw participants (end)
if p.show-bottom {
draw-par(p, y: y, bottom: true)
}
}
participant.render-lifelines()
})
shapes

View File

@ -1,3 +1,5 @@
#import "../cetz.typ": draw
#let is-elmt(elmt) = {
if type(elmt) != dictionary {
return false
@ -89,4 +91,16 @@
height: new-h,
scale(x: r, y: r, reflow: true, canvas)
)
})
#let set-ctx(func) = draw.set-ctx(c => {
let ctx = c.shared-state.chronos
ctx = func(ctx)
c.shared-state.chronos = ctx
return c
})
#let get-ctx(func) = draw.get-ctx(c => {
let ctx = c.shared-state.chronos
func(ctx)
})