From a24681827e7a0cca5a43c0706c82f68845962682 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Mon, 28 Jul 2025 18:54:04 +0200 Subject: [PATCH] refactored setup-ctx to use CeTZ context --- src/core/draw/participant.typ | 17 ++-- src/core/renderer.typ | 151 +++++++++++++++++++--------------- 2 files changed, 96 insertions(+), 72 deletions(-) diff --git a/src/core/draw/participant.typ b/src/core/draw/participant.typ index c8d78e6..b52a6f1 100644 --- a/src/core/draw/participant.typ +++ b/src/core/draw/participant.typ @@ -54,8 +54,10 @@ return style } -#let pre-resolve-styles(ctx, elements, participants) = { +#let pre-resolve-styles() = get-ctx(ctx => { let idx = (:) + let elements = ctx.setup.elements + let participants = ctx.setup.participants for (i, par) in participants.enumerate() { par.insert("resolved-style", resolve-style(ctx, par)) participants.at(i) = par @@ -65,7 +67,7 @@ if type(elmt) == function { ctx = elmt(ctx).ctx } else if is-elmt(elmt) { - if elmt.type == par { + if elmt.type == "par" { let style = resolve-style(ctx, elmt) elements.at(i).insert("resolved-style", style) let i = idx.at(elmt.name) @@ -73,12 +75,17 @@ } } } - return (elements, participants) -} + + set-ctx(c => { + c.setup.elements = elements + c.setup.participants = participants + return c + }) +}) #let get-size(par) = { if par.invisible { - return (width: 0pt, height: 0pt) + return (width: 0, height: 0) } let style = par.resolved-style let func = shapes.at(style.shape).get-size diff --git a/src/core/renderer.typ b/src/core/renderer.typ index 34b795a..df5cfd5 100644 --- a/src/core/renderer.typ +++ b/src/core/renderer.typ @@ -1,19 +1,28 @@ #import "/src/cetz.typ": canvas, draw -#import "draw/note.typ": get-box as get-note-box, get-size as get-note-size +#import "draw/note.typ" #import "draw/participant.typ" #import "utils.typ": * #import "/src/consts.typ": * #let DEBUG-INVISIBLE = false -#let init-lifelines(participants) = { - return participants.map(p => { +#let init-lifelines() = set-ctx(ctx => { + ctx.setup.participants = ctx.setup.participants.map(p => { p.insert("lifeline-lvl", 0) p.insert("max-lifelines", 0) p }) -} + return ctx +}) + +#let set-participants-i() = set-ctx(ctx => { + ctx.setup.insert( + "pars-i", + get-participants-i(ctx.setup.participants) + ) + return ctx +}) #let unwrap-syncs(elements) = { let i = 0 @@ -78,28 +87,28 @@ return participants } -#let note-get-cell(pars-i, note) = { +#let note-get-cell(pars-i, n) = { let (p1, p2) = (none, none) let cell = none - if note.side == "left" { - p1 = note.pos2 - p2 = note.pos - cell = get-note-box(note) - } else if note.side == "right" { - p1 = note.pos - p2 = note.pos2 - cell = get-note-box(note) - } else if note.side == "over" and note.aligned-with != none { - let box1 = get-note-box(note) - let box2 = get-note-box(note.aligned-with) + if n.side == "left" { + p1 = n.pos2 + p2 = n.pos + cell = note.get-box(n) + } else if n.side == "right" { + p1 = n.pos + p2 = n.pos2 + cell = note.get-box(n) + } else if n.side == "over" and n.aligned-with != none { + let box1 = note.get-box(n) + let box2 = note.get-box(n.aligned-with) let m1 = measure(box1) let m2 = measure(box2) cell = box( width: (m1.width + m2.width) / 2, height: calc.max(m1.height, m2.height) ) - p1 = note.pos - p2 = note.aligned-with.pos + p1 = n.pos + p2 = n.aligned-with.pos } else { return none } @@ -107,7 +116,7 @@ let i1 = pars-i.at(p1) let i2 = pars-i.at(p2) cell = ( - elmt: note, + elmt: n, i1: calc.min(i1, i2), i2: calc.max(i1, i2), cell: cell @@ -116,7 +125,7 @@ return cell } -#let compute-max-lifeline-levels(participants, elements, pars-i) = { +#let compute-max-lifeline-levels(participants, elements, notes, pars-i) = { let cells = () for elmt in elements { if elmt.type == "seq" { @@ -135,14 +144,14 @@ ) } else if elmt.type == "note" { - let cell = note-get-cell(pars-i, elmt) + let cell = note-get-cell(pars-i, notes.at(elmt.id)) if cell != none { cells.push(cell) } } } - return (participants, elements, cells) + return (participants, cells) } /// Compute minimum widths for participant names and shapes @@ -161,13 +170,12 @@ } /// Compute minimum width for over notes -#let notes-min-col-widths(elements, widths, pars-i) = { +#let notes-min-col-widths(notes, widths, pars-i) = { let widths = widths - let notes = elements.filter(e => e.type == "note") for n in notes.filter(e => (e.side == "over" and type(e.pos) == str)) { - let m = get-note-size(n) + let m = note.get-size(n) let i = pars-i.at(n.pos) if i < widths.len() { @@ -306,62 +314,71 @@ return widths } -#let compute-columns-width(participants, elements, pars-i) = { - elements = elements.filter(is-elmt) +#let compute-columns-width() = set-ctx(ctx => { + let elements = ctx.setup.elements.filter(is-elmt) + let participants = ctx.setup.participants + let notes = ctx.setup.notes + let pars-i = ctx.setup.pars-i elements = unwrap-syncs(elements) let cells - (participants, elements, cells) = compute-max-lifeline-levels(participants, elements, pars-i) + (participants, cells) = compute-max-lifeline-levels(participants, elements, notes, pars-i) let widths = participants-min-col-widths(participants) - widths = notes-min-col-widths(elements, widths, pars-i) + widths = notes-min-col-widths(notes, widths, pars-i) widths = simple-seq-min-col-widths(cells, widths) widths = self-seq-min-col-widths(cells, widths) widths = long-seq-min-col-widths(participants, cells, widths) widths = col-widths-add-lifelines(participants, widths) widths = process-col-elements(elements, widths, pars-i) - return widths -} -#let setup-ctx(participants, elements) = (ctx => { - let state = ctx.at("shared-state", default: (:)) + let ctx = ctx + ctx.insert("widths", widths) - let (elements, participants) = participant.pre-resolve-styles( - extract-ctx(ctx, with-style: true), - elements, - participants - ) - - let chronos-ctx = ( - participants: init-lifelines(participants), - pars-i: get-participants-i(participants), - y: 0, - groups: (), - lifelines: participants.map(_ => ( - level: 0, - events: () - )) - ) - 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 chronos-ctx.widths { + for width in 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 - ) + ctx.insert("x-pos", x-pos) + + return ctx +}) + +#let setup-ctx(participants, elements, notes) = draw.get-ctx(_ => { + set-ctx(c => { + c.insert("participants", participants) + c.insert("setup", ( + elements: elements, + participants: participants, + notes: notes + )) + return c + }) + + participant.pre-resolve-styles() + + init-lifelines() + set-participants-i() + + + compute-columns-width() + + set-ctx(c => { + let setup = c.setup + c += ( + participants: setup.participants, + pars-i: setup.pars-i, + y: 0, + groups: (), + lifelines: setup.participants.map(_ => ( + level: 0, + events: () + )), + notes: setup.notes + ) + c.remove("setup") + return c + }) },) #let render-debug() = get-ctx(ctx => { @@ -383,7 +400,7 @@ }) #let render(participants, elements, notes) = context canvas(length: 1pt, { - setup-ctx(participants, elements) + setup-ctx(participants, elements, notes) // Draw participants (start) get-ctx(ctx => {