From 94d0eb286e84b4a899b1eabd027065be9b0cf002 Mon Sep 17 00:00:00 2001 From: LordBaryhobal <lordbaryhobal@gmail.com> Date: Tue, 18 Jun 2024 20:32:39 +0200 Subject: [PATCH] added basis for lifelines --- gallery/example2.pdf | Bin 0 -> 18349 bytes gallery/example2.typ | 33 +++++++++++ src/diagram.typ | 14 ++++- src/renderer.typ | 134 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 gallery/example2.pdf create mode 100644 gallery/example2.typ diff --git a/gallery/example2.pdf b/gallery/example2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..364a2eea2447d33dadc38c2d2a73bb77043156ff GIT binary patch literal 18349 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 literal 0 HcmV?d00001 diff --git a/gallery/example2.typ b/gallery/example2.typ new file mode 100644 index 0000000..8f0e5fb --- /dev/null +++ b/gallery/example2.typ @@ -0,0 +1,33 @@ +#import "/src/lib.typ" as chronos + + +#chronos.diagram({ + import "/src/diagram.typ": * + _seq("User", "A", comment: "DoWork", enable-dst: true) + _seq("A", "B", comment: [#sym.quote.angle.l createRequest #sym.quote.angle.r], enable-dst: true) + _seq("B", "C", comment: "DoWork", enable-dst: true) + _seq("C", "B", comment: "WorkDone", destroy-src: true, dashed: true) + _seq("B", "A", comment: "RequestCreated", disable-src: true, dashed: true) + _seq("A", "User", comment: "Done", disable-src: true) +}) + +#chronos.diagram({ + import "/src/diagram.typ": * + _seq("User", "A", comment: "DoWork", enable-dst: true) + _seq("A", "A", comment: "Internal call", enable-dst: true) + _seq("A", "B", comment: [#sym.quote.angle.l createRequest #sym.quote.angle.r], enable-dst: true) + _seq("B", "A", comment: "RequestCreated", disable-src: true, disable-dst: true, dashed: true) + _seq("A", "User", comment: "Done", disable-src: true) +}) + +#chronos.diagram({ + import "/src/diagram.typ": * + _seq("alice", "bob", comment: "hello", enable-dst: true) + _seq("bob", "bob", comment: "self call", enable-dst: true) + _seq("bill", "bob", comment: "hello from thread 2", enable-dst: true) + _seq("bob", "george", comment: "create", enable-dst: true) + _seq("bob", "bill", comment: "done in thread 2", disable-src: true, dashed: true) + _seq("bob", "bob", comment: "rc", disable-src: true, dashed: true) + _seq("bob", "george", comment: "delete", destroy-dst: true) + _seq("bob", "alice", comment: "success", disable-src: true, dashed: true) +}) \ No newline at end of file diff --git a/src/diagram.typ b/src/diagram.typ index 31312c9..cd4c168 100644 --- a/src/diagram.typ +++ b/src/diagram.typ @@ -8,7 +8,12 @@ dashed: false, tip: "default", color: black, - flip: false + flip: false, + enable-dst: false, + disable-dst: false, + destroy-dst: false, + disable-src: false, + destroy-src: false, ) = { return (( type: "seq", @@ -18,7 +23,12 @@ dashed: dashed, tip: tip, color: color, - flip: flip + flip: flip, + enable-dst: enable-dst, + disable-dst: disable-dst, + destroy-dst: destroy-dst, + disable-src: disable-src, + destroy-src: destroy-src, ),) } diff --git a/src/renderer.typ b/src/renderer.typ index 0c4a00c..7bf0f10 100644 --- a/src/renderer.typ +++ b/src/renderer.typ @@ -5,9 +5,15 @@ #let PAR-PAD = (5pt, 3pt) #let PAR-SPACE = 10 #let COMMENT-PAD = 8 +#let LIFELINE-W = 10 #let get-columns-width(participants, elements) = { + participants = participants.map(p => { + p.insert("lifeline-lvl", 0) + p.insert("max-lifelines", 0) + p + }) let pars-i = get-participants-i(participants) let cells = () for elmt in elements { @@ -23,6 +29,23 @@ cell: box(com, inset: 3pt) ) ) + + if elmt.disable-src or elmt.destroy-src { + let p = participants.at(i1) + p.lifeline-lvl -= 1 + participants.at(i1) = p + } + if elmt.disable-dst { + let p = participants.at(i2) + p.lifeline-lvl -= 1 + participants.at(i2) = p + } + if elmt.enable-dst { + let p = participants.at(i2) + p.lifeline-lvl += 1 + p.max-lifelines = calc.max(p.max-lifelines, p.lifeline-lvl) + participants.at(i2) = p + } } } @@ -54,6 +77,15 @@ m.width / 1pt - widths.slice(0, cell.i2 - 1).sum() ) } + for (i, w) in widths.enumerate() { + let p1 = participants.at(i) + let p2 = participants.at(i + 1) + let w = w + p1.max-lifelines * LIFELINE-W / 2 + if p2.max-lifelines != 0 { + w += LIFELINE-W / 2 + } + widths.at(i) = w + } return widths } @@ -119,12 +151,68 @@ let y = -Y-SPACE let groups = () + let lifelines = participants.map(_ => ( + level: 0, + lines: () + )) // 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 i1 = pars-i.at(elmt.p1) + let i2 = pars-i.at(elmt.p2) + + if elmt.comment != none { + y -= measure(box(elmt.comment)).height / 1pt + 6 + } + + if elmt.disable-src { + let src-line = lifelines.at(i1) + src-line.level -= 1 + src-line.lines.push(("disable", y, auto)) + lifelines.at(i1) = src-line + } + if elmt.destroy-src { + let src-line = lifelines.at(i1) + src-line.level -= 1 + src-line.lines.push(("destroy", y, auto)) + lifelines.at(i1) = src-line + } + + let ll-lvl1 = lifelines.at(i1).level * LIFELINE-W / 2 + + if elmt.disable-dst { + let dst-line = lifelines.at(i2) + dst-line.level -= 1 + dst-line.lines.push(("disable", y, auto)) + lifelines.at(i2) = dst-line + } + if elmt.destroy-dst { + let dst-line = lifelines.at(i2) + dst-line.level -= 1 + dst-line.lines.push(("destroy", y, auto)) + lifelines.at(i2) = dst-line + } + if elmt.enable-dst { + let dst-line = lifelines.at(i2) + dst-line.level += 1 + lifelines.at(i2) = dst-line + } + + let x1 = x-pos.at(i1) + let x2 = x-pos.at(i2) + + let ll-lvl2 = lifelines.at(i2).level * LIFELINE-W / 2 + + let f = if elmt.flip {-1} else {1} + if i1 <= i2 { + x1 += ll-lvl1 * f + x2 -= ll-lvl2 * f + } else { + x1 -= ll-lvl1 * f + x2 += ll-lvl2 * f + } + let style = ( mark: (end: "straight"), stroke: ( @@ -134,10 +222,11 @@ ) if elmt.p1 == elmt.p2 { + let x3 = x1 - ll-lvl1 + ll-lvl2 + x2 = if elmt.flip {x1 - 20} else {x1 + 20} if elmt.comment != none { - y -= measure(box(elmt.comment)).height / 1pt + 6 draw.content( (x1, y), elmt.comment, @@ -150,7 +239,7 @@ (x1, y), (x2, y), (x2, y - 10), - (x1, y - 10), + (x3, y - 10), ..style ) y -= 10 @@ -161,7 +250,6 @@ if x2 < x1 { x += COMMENT-PAD } - y -= measure(box(elmt.comment)).height / 1pt + 6 draw.content( (x, y), elmt.comment, @@ -176,6 +264,11 @@ ..style ) } + if elmt.enable-dst { + let dst-line = lifelines.at(i2) + dst-line.lines.push(("enable", y, auto)) + lifelines.at(i2) = dst-line + } y -= Y-SPACE } else if elmt.type == "grp" { @@ -244,6 +337,37 @@ (x, y), stroke: (dash: "dashed", paint: gray.darken(40%)) ) + + let rects = () + let destructions = () + let lines = () + for line in lifelines.at(i).lines { + let event = line.first() + if event == "enable" { + lines.push(line) + } else if event == "disable" or event == "destroy" { + let l = lines.pop() + let lvl = lines.len() + rects.push((x + lvl * LIFELINE-W / 2, l.at(1), line.at(1))) + if event == "destroy" { + destructions.push((x + lvl * LIFELINE-W / 2, line.at(1))) + } + } + } + + for rect in rects.rev() { + let (cx, y0, y1) = rect + draw.rect( + (cx - LIFELINE-W / 2, y0), + (cx + LIFELINE-W / 2, y1), + ) + } + for dest in destructions { + let (cx, cy) = dest + draw.line((cx - 8, cy - 8), (cx + 8, cy + 8), stroke: red + 2pt) + draw.line((cx - 8, cy + 8), (cx + 8, cy - 8), stroke: red + 2pt) + } + draw.content( (x, y), p.display-name,