added notes

This commit is contained in:
2024-06-21 15:59:35 +02:00
parent 81871e2aca
commit f08f30b9e2
9 changed files with 384 additions and 10 deletions

View File

@ -15,6 +15,12 @@
#let COLLECTIONS-DY = 3
#let QUEUE-PAD = (5pt, 3pt)
#let NOTE-PAD = (6, 3)
#let NOTE-CORNER-SIZE = 6
#let NOTE-GAP = 3
#let NOTE-HEX-PAD = (6, 8)
#let COL-DESTRUCTION = rgb("#A80238")
#let COL-GRP-NAME = rgb("#EEEEEE")
#let COL-SEP-NAME = rgb("#EEEEEE")
#let COL-SEP-NAME = rgb("#EEEEEE")
#let COL-NOTE = rgb("#FEFFDD")

View File

@ -57,7 +57,8 @@
// List participants
let linked = ()
for elmt in elmts {
let last-seq = none
for (i, elmt) in elmts.enumerate() {
if elmt.type == "par" {
participants.push(elmt)
} else if elmt.type == "seq" {
@ -73,15 +74,44 @@
participants.at(i).from-start = false
}
let p1 = elmt.p1
let p2 = elmt.p2
if elmt.p1 == "?" {
linked.push("?" + elmt.p2)
} else {
linked.push(elmt.p1)
p1 = "?" + elmt.p2
}
if elmt.p2 == "?" {
linked.push(elmt.p1 + "?")
} else {
linked.push(elmt.p2)
p2 = elmt.p1 + "?"
}
linked.push(p1)
linked.push(p2)
last-seq = (
elmt: elmt,
i: i,
p1: p1,
p2: p2
)
} else if elmt.type == "note" {
elmt.insert("linked", elmt.pos == none and elmt.side != "across")
if elmt.pos == none and elmt.side != "across" {
let names = participants.map(p => p.name)
let i1 = names.position(n => n == last-seq.p1)
let i2 = names.position(n => n == last-seq.p2)
let pars = ((i1, last-seq.p1), (i2, last-seq.p2)).sorted(key: p => p.first())
if elmt.side == "left" {
elmt.pos = pars.first().last()
} else if elmt.side == "right" {
elmt.pos = pars.last().last()
}
let seq = last-seq.elmt
seq.insert("linked-note", elmt)
elmts.at(last-seq.i) = seq
}
elmts.at(i) = elmt
if elmt.side == "left" {
linked.push("[")
} else if elmt.side == "right" {
linked.push("]")
}
}
}
@ -137,6 +167,7 @@
}
}
set text(font: "Source Sans 3")
render(participants, elmts)
}

View File

@ -3,4 +3,5 @@
#import "sequence.typ": _seq
#import "group.typ": _grp
#import "participant.typ": _par
#import "separator.typ": _sep
#import "separator.typ": _sep
#import "note.typ": _note

171
src/note.typ Normal file
View File

@ -0,0 +1,171 @@
#import "@preview/cetz:0.2.2": draw
#import "consts.typ": *
#let SIDES = (
"left",
"right",
"over",
"across"
)
#let SHAPES = (
"default",
"rect",
"hex"
)
#let _note(side, content, pos: none, color: COL-NOTE, shape: "default", aligned: false) = {
return ((
type: "note",
side: side,
content: content,
pos: pos,
color: color,
shape: shape,
aligned: aligned
),)
}
#let get-note-box(note) = {
let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD}
let inset = (
left: PAD.last() * 1pt,
right: PAD.last() * 1pt,
top: PAD.first() * 1pt,
bottom: PAD.first() * 1pt,
)
if note.shape == "default" {
inset.right += NOTE-CORNER-SIZE * 1pt
}
if note.side == "left" {
inset.right += NOTE-GAP * 1pt
} else if note.side == "right" {
inset.left += NOTE-GAP * 1pt
}
return box(note.content, inset: inset)
}
#let get-size(note) = {
let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD}
let m = measure(box(note.content))
let w = m.width / 1pt + PAD.last() * 2
let h = m.height / 1pt + PAD.first() * 2
if note.shape == "default" {
w += NOTE-CORNER-SIZE
}
return (
width: w,
height: h
)
}
#let _get-base-x(pars-i, x-pos, note) = {
if note.side == "across" {
return (x-pos.first() + x-pos.last()) / 2
}
if note.side == "over" {
if type(note.pos) == array {
let xs = note.pos.map(par => x-pos.at(pars-i.at(par)))
return xs.sum() / xs.len()
}
}
return x-pos.at(pars-i.at(note.pos))
}
#let render(pars-i, x-pos, note, y, lifelines) = {
let shapes = ()
let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD}
let m = measure(box(note.content))
let w = m.width / 1pt + PAD.last() * 2
let h = m.height / 1pt + PAD.first() * 2
let total-w = w
if note.shape == "default" {
total-w += NOTE-CORNER-SIZE
}
let base-x = _get-base-x(pars-i, x-pos, note)
let i = none
if note.pos != none and type(note.pos) == str {
i = pars-i.at(note.pos)
}
let x0 = base-x
if note.side == "left" {
x0 -= NOTE-GAP
x0 -= total-w
if lifelines.at(i).level != 0 {
x0 -= LIFELINE-W / 2
}
} else if note.side == "right" {
x0 += NOTE-GAP
x0 -= lifelines.at(i).level * LIFELINE-W / 2
} else if note.side == "over" or note.side == "across" {
x0 -= total-w / 2
}
let x1 = x0 + w
let x2 = x0 + total-w
let y0 = y
if note.linked {
y0 += h / 2
}
let y1 = y0 - h
if note.shape == "default" {
shapes += draw.merge-path(
stroke: black + .5pt,
fill: note.color,
close: true,
{
draw.line(
(x0, y0),
(x1, y0),
(x2, y0 - NOTE-CORNER-SIZE),
(x2, y1),
(x0, y1)
)
}
)
shapes += draw.line((x1, y0), (x1, y0 - NOTE-CORNER-SIZE), (x2, y0 - NOTE-CORNER-SIZE), stroke: black + .5pt)
} else if note.shape == "rect" {
shapes += draw.rect(
(x0, y0),
(x2, y1),
stroke: black + .5pt,
fill: note.color
)
} else if note.shape == "hex" {
let lx = x0 + PAD.last()
let rx = x2 - PAD.last()
let my = (y0 + y1) / 2
shapes += draw.merge-path(
stroke: black + .5pt,
fill: note.color,
close: true,
{
draw.line(
(lx, y0),
(rx, y0),
(x2, my),
(rx, y1),
(lx, y1),
(x0, my),
)
}
)
}
shapes += draw.content(
((x0 + x1)/2, (y0 + y1)/2),
note.content,
anchor: "center"
)
if note.pos != none or note.side == "across" {
y -= h
}
let r = (y, shapes)
return r
}

View File

@ -6,6 +6,7 @@
#import "sequence.typ"
#import "separator.typ"
#import "consts.typ": *
#import "note.typ" as note: get-note-box
#let DEBUG-INVISIBLE = false
@ -61,6 +62,29 @@
par.max-lifelines = calc.max(par.max-lifelines, par.lifeline-lvl)
}
participants.at(i) = par
} else if elmt.type == "note" {
let (p1, p2) = (none, none)
if elmt.side == "left" {
p1 = "["
p2 = elmt.pos
} else if elmt.side == "right" {
p1 = elmt.pos
p2 = "]"
}
if p1 != none and p2 != none {
let i1 = pars-i.at(p1)
let i2 = pars-i.at(p2)
cells.push(
(
elmt: elmt,
i1: i1,
i2: i2,
cell: get-note-box(elmt)
)
)
}
}
}
@ -143,6 +167,7 @@
let draw-group = group.render.with()
let draw-sep = separator.render.with(x-pos)
let draw-par = participant.render.with(x-pos)
let draw-note = note.render.with(pars-i, x-pos)
// Draw participants (start)
for p in participants {
@ -223,6 +248,15 @@
line.lines.push(("create", y))
}
lifelines.at(i) = line
// Note
} else if elmt.type == "note" {
if not elmt.linked {
y -= Y-SPACE
let shps
(y, shps) = draw-note(elmt, y, lifelines)
shapes += shps
}
}
}

View File

@ -1,6 +1,7 @@
#import "@preview/cetz:0.2.2": draw
#import "consts.typ": *
#import "participant.typ"
#import "note.typ"
#let get-arrow-marks(sym, color) = {
if type(sym) == array {
@ -61,10 +62,15 @@
y -= Y-SPACE
let h = 0
// Reserve space for comment
if elmt.comment != none {
y -= measure(box(elmt.comment)).height / 1pt + 6
h = calc.max(h, measure(box(elmt.comment)).height / 1pt + 6)
}
if "linked-note" in elmt {
h = calc.max(h, note.get-size(elmt.linked-note).height / 2)
}
y -= h
let i1 = pars-i.at(elmt.p1)
let i2 = pars-i.at(elmt.p2)
@ -148,6 +154,12 @@
)
)
let y0 = y
if "linked-note" in elmt {
let shps = note.render(pars-i, x-pos, elmt.linked-note, y, lifelines).last()
shapes += shps
}
if elmt.p1 == elmt.p2 {
if elmt.flip {
x1 = start-info.lx
@ -210,6 +222,11 @@
lifelines.at(i2) = dst-line
}
if "linked-note" in elmt {
let m = note.get-size(elmt.linked-note)
y = calc.min(y, y0 - m.height / 2)
}
let r = (y, lifelines, shapes)
return r
}