From 886b6c2f3facdd07a77ad7dddf865556930f0d18 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Mon, 14 Jul 2025 17:23:49 +0200 Subject: [PATCH] refactored groups, separators and delays --- src/core/draw/delay.typ | 27 ++++++++ src/core/draw/group.typ | 120 ++++++++++++++++++++++++++++++++++++ src/core/draw/separator.typ | 46 ++++++++++++++ src/core/renderer.typ | 77 ----------------------- src/core/setup.typ | 2 + src/group.typ | 60 +----------------- src/separator.typ | 50 ++------------- 7 files changed, 202 insertions(+), 180 deletions(-) create mode 100644 src/core/draw/delay.typ create mode 100644 src/core/draw/group.typ create mode 100644 src/core/draw/separator.typ diff --git a/src/core/draw/delay.typ b/src/core/draw/delay.typ new file mode 100644 index 0000000..9a204ea --- /dev/null +++ b/src/core/draw/delay.typ @@ -0,0 +1,27 @@ +#import "../utils.typ": get-ctx, set-ctx +#import "../../cetz.typ": draw + +#let render(delay) = get-ctx(ctx => { + let y0 = ctx.y + let y1 = ctx.y - delay.size + for (i, line) in ctx.lifelines.enumerate() { + line.lines.push(("delay-start", y0)) + line.lines.push(("delay-end", y1)) + ctx.lifelines.at(i) = line + } + if delay.name != none { + let x0 = ctx.x-pos.first() + let x1 = ctx.x-pos.last() + draw.content( + ((x0 + x1) / 2, (y0 + y1) / 2), + anchor: "center", + delay.name + ) + } + ctx.y = y1 + set-ctx(c => { + c.y = ctx.y + c.lifelines = ctx.lifelines + return c + }) +}) \ No newline at end of file diff --git a/src/core/draw/group.typ b/src/core/draw/group.typ new file mode 100644 index 0000000..631091a --- /dev/null +++ b/src/core/draw/group.typ @@ -0,0 +1,120 @@ +#import "../utils.typ": get-ctx, set-ctx +#import "../../consts.typ": * +#import "../../cetz.typ": draw + +#let render-start(grp) = get-ctx(ctx => { + let grp = grp + ctx.y -= Y-SPACE + let m = measure( + box( + grp.name, + inset: ( + left: 5pt, + right: 5pt, + top: 3pt, + bottom: 3pt + ), + ) + ) + ctx.groups = ctx.groups.map(g => { + if g.at(1).min-i == grp.min-i { g.at(2) += 1 } + if g.at(1).max-i == grp.max-i { g.at(3) += 1 } + g + }) + if grp.grp-type == "alt" { + grp.insert("elses", ()) + } + ctx.groups.push((ctx.y, grp, 0, 0)) + ctx.y -= m.height / 1pt + + set-ctx(c => { + c.y = ctx.y + c.groups = ctx.groups + return c + }) +}) + + +#let draw-group(x0, x1, y0, y1, group) = { + let name = text(group.name, weight: "bold") + let m = measure(box(name)) + let w = m.width / 1pt + 15 + let h = m.height / 1pt + 6 + draw.rect( + (x0, y0), + (x1, y1) + ) + draw.merge-path( + fill: COL-GRP-NAME, + close: true, + { + draw.line( + (x0, y0), + (x0 + w, y0), + (x0 + w, y0 - h / 2), + (x0 + w - 5, y0 - h), + (x0, y0 - h) + ) + } + ) + draw.content( + (x0, y0), + name, + anchor: "north-west", + padding: (left: 5pt, right: 10pt, top: 3pt, bottom: 3pt) + ) + + if group.desc != none { + draw.content( + (x0 + w, y0), + text([\[#group.desc\]], weight: "bold", size: .8em), + anchor: "north-west", + padding: 3pt + ) + } +} + +#let draw-else(x0, x1, y, elmt) = { + draw.line( + (x0, y), + (x1, y), + stroke: (dash: (2pt, 1pt), thickness: .5pt) + ) + draw.content( + (x0, y), + text([\[#elmt.desc\]], weight: "bold", size: .8em), + anchor: "north-west", + padding: 3pt + ) +} + +#let render-end(group) = get-ctx(ctx => { + ctx.y -= Y-SPACE + let (start-y, group, start-lvl, end-lvl) = ctx.groups.pop() + let x0 = ctx.x-pos.at(group.min-i) - start-lvl * 10 - 20 + let x1 = ctx.x-pos.at(group.max-i) + end-lvl * 10 + 20 + + draw-group(x0, x1, start-y, ctx.y, group) + + if group.grp-type == "alt" { + for (else-y, else-elmt) in group.elses { + draw-else(x0, x1, else-y, else-elmt) + } + } + + set-ctx(c => { + c.y = ctx.y + c.groups = ctx.groups + return c + }) +}) + +#let render-else(else_) = set-ctx(ctx => { + ctx.y -= Y-SPACE + let m = measure(text([\[#else_.desc\]], weight: "bold", size: .8em)) + ctx.groups.last().at(1).elses.push(( + ctx.y, else_ + )) + ctx.y -= m.height / 1pt + return ctx +}) \ No newline at end of file diff --git a/src/core/draw/separator.typ b/src/core/draw/separator.typ new file mode 100644 index 0000000..44b0f23 --- /dev/null +++ b/src/core/draw/separator.typ @@ -0,0 +1,46 @@ +#import "../utils.typ": get-ctx, set-ctx +#import "../../consts.typ": * +#import "../../cetz.typ": draw + +#let render(sep) = get-ctx(ctx => { + ctx.y -= Y-SPACE + + let x0 = ctx.x-pos.first() - 20 + let x1 = ctx.x-pos.last() + 20 + let m = measure( + box( + sep.name, + inset: (left: 3pt, right: 3pt, top: 5pt, bottom: 5pt) + ) + ) + let w = m.width / 1pt + let h = m.height / 1pt + let cx = (x0 + x1) / 2 + let xl = cx - w / 2 + let xr = cx + w / 2 + + ctx.y -= h / 2 + draw.rect( + (x0, ctx.y), + (x1, ctx.y - 3), + stroke: none, + fill: white + ) + draw.line((x0, ctx.y), (x1, ctx.y)) + ctx.y -= 3 + draw.line((x0, ctx.y), (x1, ctx.y)) + draw.content( + ((x0 + x1) / 2, ctx.y + 1.5), + sep.name, + anchor: "center", + padding: (5pt, 3pt), + frame: "rect", + fill: COL-SEP-NAME + ) + ctx.y -= h / 2 + + set-ctx(c => { + c.y = ctx.y + return c + }) +}) diff --git a/src/core/renderer.typ b/src/core/renderer.typ index b09e9b7..8081885 100644 --- a/src/core/renderer.typ +++ b/src/core/renderer.typ @@ -354,7 +354,6 @@ },) #let render(participants, elements) = context canvas(length: 1pt, { - let shapes = () setup-ctx(participants, elements) // Draw participants (start) @@ -372,80 +371,6 @@ (elmt,) } else if "draw" in elmt and elmt.type != "par" { (elmt.draw)(elmt) - - // Groups (start) -> reserve space for labels + store position - } else if elmt.type == "grp" { - y -= Y-SPACE - let m = measure( - box( - elmt.name, - inset: ( - left: 5pt, - right: 5pt, - top: 3pt, - bottom: 3pt - ), - ) - ) - groups = groups.map(g => { - if g.at(1).min-i == elmt.min-i { g.at(2) += 1 } - if g.at(1).max-i == elmt.max-i { g.at(3) += 1 } - g - }) - if elmt.grp-type == "alt" { - elmt.insert("elses", ()) - } - groups.push((y, elmt, 0, 0)) - y -= m.height / 1pt - - // Groups (end) -> actual drawing - } else if elmt.type == "grp-end" { - y -= Y-SPACE - let (start-y, group, start-lvl, end-lvl) = groups.pop() - let x0 = x-pos.at(group.min-i) - start-lvl * 10 - 20 - let x1 = x-pos.at(group.max-i) + end-lvl * 10 + 20 - shapes += draw-group(x0, x1, start-y, y, group) - - if group.grp-type == "alt" { - for (else-y, else-elmt) in group.elses { - shapes += draw-else(x0, x1, else-y, else-elmt) - } - } - - // Alt's elses -> reserve space for label + store position - } else if elmt.type == "else" { - y -= Y-SPACE - let m = measure(text([\[#elmt.desc\]], weight: "bold", size: .8em)) - groups.last().at(1).elses.push(( - y, elmt - )) - y -= m.height / 1pt - - // Separator - } else if elmt.type == "sep" { - let shps - (y, shps) = draw-sep(elmt, y) - shapes += shps - - // Delay - } else if elmt.type == "delay" { - let y0 = y - let y1 = y - elmt.size - for (i, line) in lifelines.enumerate() { - line.lines.push(("delay-start", y0)) - line.lines.push(("delay-end", y1)) - lifelines.at(i) = line - } - if elmt.name != none { - let x0 = x-pos.first() - let x1 = x-pos.last() - shapes += draw.content( - ((x0 + x1) / 2, (y0 + y1) / 2), - anchor: "center", - elmt.name - ) - } - y = y1 } } @@ -476,6 +401,4 @@ participant.render-lifelines() }) - - shapes }) \ No newline at end of file diff --git a/src/core/setup.typ b/src/core/setup.typ index bc899e7..85b9444 100644 --- a/src/core/setup.typ +++ b/src/core/setup.typ @@ -1,5 +1,6 @@ #import "utils.typ": is-elmt, get-group-span #import "../participant.typ": _exists as par-exists, _par +#import "draw/group.typ": render-end as grp-render-end #let flatten-group(elmts, i) = { let group = elmts.at(i) @@ -9,6 +10,7 @@ group.elmts + (( type: "grp-end", + draw: grp-render-end, start-i: i ),) + elmts.slice(i+1) diff --git a/src/group.typ b/src/group.typ index db0933b..fcaa43d 100644 --- a/src/group.typ +++ b/src/group.typ @@ -1,9 +1,11 @@ #import "/src/cetz.typ": draw #import "consts.typ": * +#import "core/draw/group.typ" #let _grp(name, desc: none, type: "default", elmts) = { return (( type: "grp", + draw: group.render-start, name: name, desc: desc, grp-type: type, @@ -20,6 +22,7 @@ let else-elmts = args.at(i + 1, default: ()) all-elmts.push(( type: "else", + draw: group.render-else, desc: else-desc )) all-elmts += else-elmts @@ -40,60 +43,3 @@ } #let _opt(desc, elmts) = grp("opt", desc: desc, type: "opt", elmts) #let _break(desc, elmts) = grp("break", desc: desc, type: "break", elmts) - -#let render(x0, x1, y0, y1, group) = { - let shapes = () - let name = text(group.name, weight: "bold") - let m = measure(box(name)) - let w = m.width / 1pt + 15 - let h = m.height / 1pt + 6 - shapes += draw.rect( - (x0, y0), - (x1, y1) - ) - shapes += draw.merge-path( - fill: COL-GRP-NAME, - close: true, - { - draw.line( - (x0, y0), - (x0 + w, y0), - (x0 + w, y0 - h / 2), - (x0 + w - 5, y0 - h), - (x0, y0 - h) - ) - } - ) - shapes += draw.content( - (x0, y0), - name, - anchor: "north-west", - padding: (left: 5pt, right: 10pt, top: 3pt, bottom: 3pt) - ) - - if group.desc != none { - shapes += draw.content( - (x0 + w, y0), - text([\[#group.desc\]], weight: "bold", size: .8em), - anchor: "north-west", - padding: 3pt - ) - } - - return shapes -} - -#let render-else(x0, x1, y, elmt) = { - let shapes = draw.line( - (x0, y), - (x1, y), - stroke: (dash: (2pt, 1pt), thickness: .5pt) - ) - shapes += draw.content( - (x0, y), - text([\[#elmt.desc\]], weight: "bold", size: .8em), - anchor: "north-west", - padding: 3pt - ) - return shapes -} \ No newline at end of file diff --git a/src/separator.typ b/src/separator.typ index e0d1b71..68de017 100644 --- a/src/separator.typ +++ b/src/separator.typ @@ -1,9 +1,12 @@ #import "/src/cetz.typ": draw #import "consts.typ": * +#import "core/draw/separator.typ" +#import "core/draw/delay.typ" #let _sep(name) = { return (( type: "sep", + draw: separator.render, name: name ),) } @@ -11,53 +14,8 @@ #let _delay(name: none, size: 30) = { return (( type: "delay", + draw: delay.render, name: name, size: size ),) -} - -#let render(x-pos, elmt, y) = { - let shapes = () - y -= Y-SPACE - - let x0 = x-pos.first() - 20 - let x1 = x-pos.last() + 20 - let m = measure( - box( - elmt.name, - inset: (left: 3pt, right: 3pt, top: 5pt, bottom: 5pt) - ) - ) - let w = m.width / 1pt - let h = m.height / 1pt - let cx = (x0 + x1) / 2 - let xl = cx - w / 2 - let xr = cx + w / 2 - - y -= h / 2 - shapes += draw.rect( - (x0, y), - (x1, y - 3), - stroke: none, - fill: white - ) - shapes += draw.line((x0, y), (x1, y)) - //shapes += draw.line((x0, y), (xl, y)) - //shapes += draw.line((xr, y), (x1, y)) - y -= 3 - shapes += draw.line((x0, y), (x1, y)) - //shapes += draw.line((x0, y), (xl, y)) - //shapes += draw.line((xr, y), (x1, y)) - shapes += draw.content( - ((x0 + x1) / 2, y + 1.5), - elmt.name, - anchor: "center", - padding: (5pt, 3pt), - frame: "rect", - fill: COL-SEP-NAME - ) - y -= h / 2 - - let r = (y, shapes) - return r } \ No newline at end of file