implemented aligned notes

This commit is contained in:
Louis Heredero 2024-06-21 17:26:50 +02:00
parent f08f30b9e2
commit 0cff9d6799
Signed by: HEL
GPG Key ID: 8D83DE470F8544E7
5 changed files with 94 additions and 12 deletions

Binary file not shown.

View File

@ -74,10 +74,19 @@
#chronos.diagram({
_par("a", display-name: "Alice")
_par("b", display-name: "Bob")
_par("c", display-name: "Charlie")
_par("d", display-name: "Donald")
_par("e", display-name: "Eddie")
_note("over", [initial state of Alice], pos: "a")
_note("over", [initial state of Bob], pos: "b", aligned: true)
_seq("b", "a", comment: [hello])
_note("over", [initial state of Bob the builder], pos: "b", aligned: true)
_note("over", [Note 1], pos: "a")
_note("over", [Note 2], pos: "b", aligned: true)
_note("over", [Note 3], pos: "c", aligned: true)
_seq("a", "d")
_note("over", [this is an extremely long note], pos: ("d", "e"))
})
#pagebreak()
@ -111,4 +120,19 @@
_note("over", [
#underline([This is hosted], stroke: rgb("#FF33FF")) by #box(baseline: 50%, image("gitea.png", width: 1cm, height: 1cm, fit: "contain"))
], pos: ("a", "b"))
})
})
// TODO
/*
#pagebreak()
#chronos.diagram({
_par("a", display-name: [Alice])
_par("b", display-name: [Bob])
_seq("a", "b", comment: [Hello])
_note("left", [This is a note])
_seq("[", "a", comment: [Test])
_note("left", [This is also a note])
})*/

View File

@ -58,6 +58,7 @@
// List participants
let linked = ()
let last-seq = none
let last-note = none
for (i, elmt) in elmts.enumerate() {
if elmt.type == "par" {
participants.push(elmt)
@ -107,12 +108,21 @@
seq.insert("linked-note", elmt)
elmts.at(last-seq.i) = seq
}
if elmt.aligned {
let n = last-note.elmt
n.aligned-with = elmt
elmts.at(last-note.i) = n
}
elmts.at(i) = elmt
if elmt.side == "left" {
linked.push("[")
} else if elmt.side == "right" {
linked.push("]")
}
last-note = (
elmt: elmt,
i: i
)
}
}
linked = linked.dedup()

View File

@ -15,6 +15,16 @@
)
#let _note(side, content, pos: none, color: COL-NOTE, shape: "default", aligned: false) = {
if side == "over" {
if pos == none {
panic("Pos cannot be none with side 'over'")
}
}
if aligned {
if side != "over" {
panic("Aligned notes can only be over a participant (got side '" + side + "')")
}
}
return ((
type: "note",
side: side,
@ -22,7 +32,8 @@
pos: pos,
color: color,
shape: shape,
aligned: aligned
aligned: aligned,
aligned-with: none
),)
}
@ -66,7 +77,7 @@
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 (calc.min(..xs) + calc.max(..xs)) / 2
}
}
return x-pos.at(pars-i.at(note.pos))
@ -162,7 +173,7 @@
anchor: "center"
)
if note.pos != none or note.side == "across" {
if note.aligned-with == none and (note.pos != none or note.side == "across") {
y -= h
}

View File

@ -65,23 +65,36 @@
} else if elmt.type == "note" {
let (p1, p2) = (none, none)
let cell = none
if elmt.side == "left" {
p1 = "["
p2 = elmt.pos
cell = get-note-box(elmt)
} else if elmt.side == "right" {
p1 = elmt.pos
p2 = "]"
cell = get-note-box(elmt)
} else if elmt.side == "over" {
if elmt.aligned-with != none {
let box1 = get-note-box(elmt)
let box2 = get-note-box(elmt.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 = elmt.pos
p2 = elmt.aligned-with.pos
}
}
if p1 != none and p2 != none {
if p1 != none and p2 != none and cell != 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)
i1: calc.min(i1, i2),
i2: calc.max(i1, i2),
cell: cell
)
)
}
@ -101,6 +114,28 @@
widths.push(w1 / 2pt + w2 / 2pt + PAR-SPACE)
}
// Compute minimum width for over notes
for n in elements.filter(e => (e.type == "note" and
e.side == "over" and
type(e.pos) == str)) {
let m = note.get-size(n)
let i = pars-i.at(n.pos)
if i < widths.len() {
widths.at(i) = calc.max(
widths.at(i),
m.width / 2 + NOTE-GAP
)
}
if i > 0 {
widths.at(i - 1) = calc.max(
widths.at(i - 1),
m.width / 2 + NOTE-GAP
)
}
}
// Compute minimum width for simple sequences (spanning 1 column)
for cell in cells.filter(c => c.i2 - c.i1 == 1) {
let m = measure(cell.cell)
@ -111,7 +146,7 @@
}
// Compute minimum width for self sequences
for cell in cells.filter(c => c.i1 == c.i2) {
for cell in cells.filter(c => c.elmt.type == "seq" and c.i1 == c.i2) {
let m = measure(cell.cell)
let i = cell.i1
if cell.elmt.flip {
@ -252,7 +287,9 @@
// Note
} else if elmt.type == "note" {
if not elmt.linked {
y -= Y-SPACE
if not elmt.aligned {
y -= Y-SPACE
}
let shps
(y, shps) = draw-note(elmt, y, lifelines)
shapes += shps