Compare commits

...

2 Commits

Author SHA1 Message Date
a9b467152a
added participant creation 2024-06-18 23:01:53 +02:00
4dd940f584
added lifeline-style 2024-06-18 23:00:41 +02:00
8 changed files with 139 additions and 52 deletions

Binary file not shown.

Binary file not shown.

View File

@ -6,15 +6,15 @@
_seq("User", "A", comment: "DoWork", enable-dst: true) _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("A", "B", comment: [#sym.quote.angle.l createRequest #sym.quote.angle.r], enable-dst: true)
_seq("B", "C", comment: "DoWork", enable-dst: true) _seq("B", "C", comment: "DoWork", enable-dst: true)
_seq("C", "B", comment: "WorkDone", destroy-src: true, dashed: true) _seq("C", "B", comment: "WorkDone", destroy-src: true, disable-src: true, dashed: true)
_seq("B", "A", comment: "RequestCreated", disable-src: true, dashed: true) _seq("B", "A", comment: "RequestCreated", disable-src: true, dashed: true)
_seq("A", "User", comment: "Done", disable-src: true) _seq("A", "User", comment: "Done", disable-src: true)
}) })
#chronos.diagram({ #chronos.diagram({
import chronos: * import chronos: *
_seq("User", "A", comment: "DoWork", enable-dst: true) _seq("User", "A", comment: "DoWork", enable-dst: true, lifeline-style: (fill: rgb("#FFBBBB")))
_seq("A", "A", comment: "Internal call", enable-dst: true) _seq("A", "A", comment: "Internal call", enable-dst: true, lifeline-style: (fill: rgb("#E9967A")))
_seq("A", "B", comment: [#sym.quote.angle.l createRequest #sym.quote.angle.r], 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("B", "A", comment: "RequestCreated", disable-src: true, disable-dst: true, dashed: true)
_seq("A", "User", comment: "Done", disable-src: true) _seq("A", "User", comment: "Done", disable-src: true)
@ -24,8 +24,8 @@
import chronos: * import chronos: *
_seq("alice", "bob", comment: "hello", enable-dst: true) _seq("alice", "bob", comment: "hello", enable-dst: true)
_seq("bob", "bob", comment: "self call", enable-dst: true) _seq("bob", "bob", comment: "self call", enable-dst: true)
_seq("bill", "bob", comment: "hello from thread 2", enable-dst: true) _seq("bill", "bob", comment: "hello from thread 2", enable-dst: true, lifeline-style: (fill: rgb("#005500")))
_seq("bob", "george", comment: "create", enable-dst: true) _seq("bob", "george", comment: "create", create-dst: true)
_seq("bob", "bill", comment: "done in thread 2", disable-src: true, dashed: 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", "bob", comment: "rc", disable-src: true, dashed: true)
_seq("bob", "george", comment: "delete", destroy-dst: true) _seq("bob", "george", comment: "delete", destroy-dst: true)
@ -38,3 +38,4 @@
_seq("bob", "charlie", comment: "hello2", enable-dst: true, disable-src: true) _seq("bob", "charlie", comment: "hello2", enable-dst: true, disable-src: true)
_seq("charlie", "alice", comment: "ok", dashed: true, disable-src: true) _seq("charlie", "alice", comment: "ok", dashed: true, disable-src: true)
}) })

View File

@ -39,11 +39,18 @@
participants.push(_par(elmt.p1).first()) participants.push(_par(elmt.p1).first())
} }
if not participant._exists(participants, elmt.p2) { if not participant._exists(participants, elmt.p2) {
participants.push(_par(elmt.p2).first()) let par = _par(elmt.p2, from-start: not elmt.create-dst).first()
participants.push(par)
} }
} }
} }
// Add index to participant
for (i, p) in participants.enumerate() {
p.insert("i", i)
participants.at(i) = p
}
// Compute groups spans (horizontal) // Compute groups spans (horizontal)
for (i, elmt) in elmts.enumerate() { for (i, elmt) in elmts.enumerate() {
if elmt.type == "grp" { if elmt.type == "grp" {

View File

@ -1,9 +1,12 @@
#let _par(name, display-name: auto, start-at: 0) = { #import "@preview/cetz:0.2.2": draw
#import "consts.typ": *
#let _par(name, display-name: auto, from-start: true) = {
return (( return ((
type: "par", type: "par",
name: name, name: name,
display-name: if display-name == auto {name} else {display-name}, display-name: if display-name == auto {name} else {display-name},
start-at: start-at from-start: from-start
),) ),)
} }
@ -15,3 +18,14 @@
} }
return false return false
} }
#let render(x-pos, p, y: 0) = {
draw.content(
(x-pos.at(p.i), y),
p.display-name,
name: p.name,
frame: "rect",
padding: PAR-PAD,
anchor: "south"
)
}

View File

@ -1,6 +1,7 @@
#import "@preview/cetz:0.2.2": canvas, draw #import "@preview/cetz:0.2.2": canvas, draw
#import "utils.typ": get-participants-i #import "utils.typ": get-participants-i, get-style
#import "group.typ" #import "group.typ"
#import "participant.typ"
#import "sequence.typ" #import "sequence.typ"
#import "separator.typ" #import "separator.typ"
#import "consts.typ": * #import "consts.typ": *
@ -107,16 +108,16 @@
x-pos.push(x-pos.last() + width) x-pos.push(x-pos.last() + width)
} }
let draw-seq = sequence.render.with(pars-i, x-pos, participants)
let draw-group = group.render.with()
let draw-sep = separator.render.with(x-pos)
let draw-par = participant.render.with(x-pos)
// Draw participants (start) // Draw participants (start)
for (i, p) in participants.enumerate() { for p in participants {
shapes += draw.content( if p.from-start {
(x-pos.at(i), 0), shapes += draw-par(p)
p.display-name, }
name: p.name,
frame: "rect",
padding: PAR-PAD,
anchor: "south"
)
} }
let y = -Y-SPACE let y = -Y-SPACE
@ -126,10 +127,6 @@
lines: () lines: ()
)) ))
let draw-seq = sequence.render.with(pars-i, x-pos)
let draw-group = group.render.with()
let draw-sep = separator.render.with(x-pos)
// Draw elemnts // Draw elemnts
for elmt in elements { for elmt in elements {
// Sequences // Sequences
@ -181,11 +178,7 @@
let x = x-pos.at(i) let x = x-pos.at(i)
// Draw vertical line // Draw vertical line
draw.line( let last-y = 0
(x, 0),
(x, y),
stroke: (dash: "dashed", paint: gray.darken(40%))
)
let rects = () let rects = ()
let destructions = () let destructions = ()
@ -194,25 +187,53 @@
// Compute lifeline rectangles + destruction positions // Compute lifeline rectangles + destruction positions
for line in lifelines.at(i).lines { for line in lifelines.at(i).lines {
let event = line.first() let event = line.first()
if event == "enable" { 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: (dash: "dashed", paint: gray.darken(40%))
)
}
lines.push(line) lines.push(line)
} else if event == "disable" or event == "destroy" { } else if event == "disable" or event == "destroy" {
let lvl = 0
if lines.len() != 0 {
let l = lines.pop() let l = lines.pop()
let lvl = lines.len() lvl = lines.len()
rects.push((x + lvl * LIFELINE-W / 2, l.at(1), line.at(1))) rects.push((
x + lvl * LIFELINE-W / 2,
l.at(1),
line.at(1),
l.at(2)
))
last-y = line.at(1)
}
if event == "destroy" { if event == "destroy" {
destructions.push((x + lvl * LIFELINE-W / 2, line.at(1))) destructions.push((x + lvl * LIFELINE-W / 2, line.at(1)))
} }
} }
} }
draw.line(
(x, last-y),
(x, y),
stroke: (dash: "dashed", paint: gray.darken(40%))
)
// Draw lifeline rectangles (reverse for bottom to top) // Draw lifeline rectangles (reverse for bottom to top)
for rect in rects.rev() { for rect in rects.rev() {
let (cx, y0, y1) = rect let (cx, y0, y1, style) = rect
let style = get-style("lifeline", style)
draw.rect( draw.rect(
(cx - LIFELINE-W / 2, y0), (cx - LIFELINE-W / 2, y0),
(cx + LIFELINE-W / 2, y1) (cx + LIFELINE-W / 2, y1),
..style
) )
} }

View File

@ -1,5 +1,6 @@
#import "consts.typ": *
#import "@preview/cetz:0.2.2": draw #import "@preview/cetz:0.2.2": draw
#import "consts.typ": *
#import "participant.typ"
#let _seq( #let _seq(
p1, p1,
@ -10,10 +11,12 @@
color: black, color: black,
flip: false, flip: false,
enable-dst: false, enable-dst: false,
create-dst: false,
disable-dst: false, disable-dst: false,
destroy-dst: false, destroy-dst: false,
disable-src: false, disable-src: false,
destroy-src: false, destroy-src: false,
lifeline-style: auto
) = { ) = {
return (( return ((
type: "seq", type: "seq",
@ -25,48 +28,64 @@
color: color, color: color,
flip: flip, flip: flip,
enable-dst: enable-dst, enable-dst: enable-dst,
create-dst: create-dst,
disable-dst: disable-dst, disable-dst: disable-dst,
destroy-dst: destroy-dst, destroy-dst: destroy-dst,
disable-src: disable-src, disable-src: disable-src,
destroy-src: destroy-src, destroy-src: destroy-src,
lifeline-style: lifeline-style,
),) ),)
} }
#let render(pars-i, x-pos, elmt, y, lifelines) = { #let render(pars-i, x-pos, participants, elmt, y, lifelines) = {
let shapes = () let shapes = ()
let i1 = pars-i.at(elmt.p1) // Reserve space for comment
let i2 = pars-i.at(elmt.p2)
if elmt.comment != none { if elmt.comment != none {
y -= measure(box(elmt.comment)).height / 1pt + 6 y -= measure(box(elmt.comment)).height / 1pt + 6
} }
let i1 = pars-i.at(elmt.p1)
let i2 = pars-i.at(elmt.p2)
let start-info = (
i: i1,
x: x-pos.at(i1),
y: y,
ll-lvl: lifelines.at(i1).level * LIFELINE-W / 2
)
let end-info = (
i: i2,
x: x-pos.at(i2),
y: y,
ll-lvl: lifelines.at(i2).level * LIFELINE-W / 2
)
let ll-lvl1 = lifelines.at(i1).level * LIFELINE-W / 2
let x1 = x-pos.at(i1)
let x2 = x-pos.at(i2)
if elmt.disable-src { if elmt.disable-src {
let src-line = lifelines.at(i1) let src-line = lifelines.at(i1)
src-line.level -= 1 src-line.level -= 1
src-line.lines.push(("disable", y, auto)) src-line.lines.push(("disable", y))
lifelines.at(i1) = src-line lifelines.at(i1) = src-line
} }
if elmt.destroy-src { if elmt.destroy-src {
let src-line = lifelines.at(i1) let src-line = lifelines.at(i1)
src-line.level -= 1 src-line.lines.push(("destroy", y))
src-line.lines.push(("destroy", y, auto))
lifelines.at(i1) = src-line lifelines.at(i1) = src-line
} }
let ll-lvl1 = lifelines.at(i1).level * LIFELINE-W / 2
if elmt.disable-dst { if elmt.disable-dst {
let dst-line = lifelines.at(i2) let dst-line = lifelines.at(i2)
dst-line.level -= 1 dst-line.level -= 1
dst-line.lines.push(("disable", y, auto)) dst-line.lines.push(("disable", y))
lifelines.at(i2) = dst-line lifelines.at(i2) = dst-line
} }
if elmt.destroy-dst { if elmt.destroy-dst {
let dst-line = lifelines.at(i2) let dst-line = lifelines.at(i2)
dst-line.level -= 1 dst-line.lines.push(("destroy", y))
dst-line.lines.push(("destroy", y, auto))
lifelines.at(i2) = dst-line lifelines.at(i2) = dst-line
} }
if elmt.enable-dst { if elmt.enable-dst {
@ -74,10 +93,14 @@
dst-line.level += 1 dst-line.level += 1
lifelines.at(i2) = dst-line lifelines.at(i2) = dst-line
} }
if elmt.create-dst {
let par = participants.at(i2)
let m = measure(box(par.display-name))
x2 -= (m.width + PAR-PAD.last() * 2) / 2pt
shapes += participant.render(x-pos, par, y: y)
}
let x1 = x-pos.at(i1) end-info.ll-lvl = lifelines.at(i2).level * LIFELINE-W / 2
let x2 = x-pos.at(i2)
let ll-lvl2 = lifelines.at(i2).level * LIFELINE-W / 2 let ll-lvl2 = lifelines.at(i2).level * LIFELINE-W / 2
let f = if elmt.flip {-1} else {1} let f = if elmt.flip {-1} else {1}
@ -142,7 +165,12 @@
} }
if elmt.enable-dst { if elmt.enable-dst {
let dst-line = lifelines.at(i2) let dst-line = lifelines.at(i2)
dst-line.lines.push(("enable", y, auto)) dst-line.lines.push(("enable", y, elmt.lifeline-style))
lifelines.at(i2) = dst-line
}
if elmt.create-dst {
let dst-line = lifelines.at(i2)
dst-line.lines.push(("create", y))
lifelines.at(i2) = dst-line lifelines.at(i2) = dst-line
} }
y -= Y-SPACE y -= Y-SPACE

View File

@ -25,3 +25,19 @@
} }
return (min-i, max-i) return (min-i, max-i)
} }
#let get-style(base-name, mods) = {
let style = if base-name == "lifeline" {(
fill: white,
stroke: black + 1pt
)}
if mods == auto {
return style
}
if type(mods) == dictionary {
return style + mods
}
panic("Invalid type for parameter mods, expected auto or dictionary, got " + str(type(mods)))
}