refactored notes rendering

This commit is contained in:
2025-07-28 21:07:57 +02:00
parent e8666d466b
commit 6385762696
7 changed files with 82 additions and 42 deletions

View File

@@ -21,10 +21,10 @@
_par("a", display-name: "Alice") _par("a", display-name: "Alice")
_par("b", display-name: "Bob") _par("b", display-name: "Bob")
_note("left", [This is displayed\ left of Alice.], pos: "a", color: rgb("#00FFFF")) _note("left", [This is displayed\ left of Alice.], pos: "a", fill: rgb("#00FFFF"))
_note("right", [This is displayed right of Alice.], pos: "a") _note("right", [This is displayed right of Alice.], pos: "a")
_note("over", [This is displayed over Alice.], pos: "a") _note("over", [This is displayed over Alice.], pos: "a")
_note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), color: rgb("#FFAAAA")) _note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), fill: rgb("#FFAAAA"))
_note("over", [This is yet another\ example of\ a long note.], pos: ("a", "b")) _note("over", [This is yet another\ example of\ a long note.], pos: ("a", "b"))
}) })

View File

@@ -1,14 +1,51 @@
#import "/src/cetz.typ": draw #import "/src/cetz.typ": draw, styles
#import "/src/consts.typ": * #import "/src/consts.typ": *
#import "/src/core/utils.typ": get-ctx, set-ctx, expand-parent-group #import "/src/core/utils.typ": get-ctx, is-elmt, set-ctx, expand-parent-group, normalize-measure
#let note-default-style = (
shape: "default",
fill: rgb("#FEFFDD"),
stroke: black + .5pt
)
#let resolve-style(ctx, note) = {
return styles.resolve(
ctx.style,
merge: note.style,
root: "note",
base: note-default-style
)
}
#let pre-resolve-styles() = get-ctx(ctx => {
let ctx = ctx
let notes = ctx.setup.notes
for (i, elmt) in ctx.setup.elements.enumerate() {
if type(elmt) == function {
ctx = elmt(ctx).ctx
} else if is-elmt(elmt) {
if elmt.type == "note" {
let style = resolve-style(ctx, elmt)
notes.at(elmt.id).insert("resolved-style", style)
}
}
}
set-ctx(c => {
c.setup.notes = notes
return c
})
})
#let get-size(note) = { #let get-size(note) = {
let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} let style = note.resolved-style
let PAD = if style.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD}
let m = measure(box(note.content)) let m = measure(box(note.content))
let w = m.width / 1pt + PAD.last() * 2 let w = m.width / 1pt + PAD.last() * 2
let h = m.height / 1pt + PAD.first() * 2 let h = m.height / 1pt + PAD.first() * 2
if note.shape == "default" { if style.shape == "default" {
w += NOTE-CORNER-SIZE w += NOTE-CORNER-SIZE
} }
return ( return (
@@ -31,14 +68,15 @@
} }
#let get-box(note) = { #let get-box(note) = {
let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} let style = note.resolved-style
let PAD = if style.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD}
let inset = ( let inset = (
left: PAD.last() * 1pt, left: PAD.last() * 1pt,
right: PAD.last() * 1pt, right: PAD.last() * 1pt,
top: PAD.first() * 1pt, top: PAD.first() * 1pt,
bottom: PAD.first() * 1pt, bottom: PAD.first() * 1pt,
) )
if note.shape == "default" { if style.shape == "default" {
inset.right += NOTE-CORNER-SIZE * 1pt inset.right += NOTE-CORNER-SIZE * 1pt
} }
if note.side == "left" { if note.side == "left" {
@@ -62,18 +100,21 @@
} }
get-ctx(ctx => { get-ctx(ctx => {
let note = ctx.notes.at(note.id)
let y = y let y = y
if y == auto { if y == auto {
y = ctx.y y = ctx.y
} }
let style = note.resolved-style
let shape = style.shape
let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} let PAD = if shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD}
let m = measure(box(note.content)) let m = normalize-measure(box(note.content))
let w = m.width / 1pt + PAD.last() * 2 let w = m.width + PAD.last() * 2
let h = m.height / 1pt + PAD.first() * 2 let h = m.height + PAD.first() * 2
let total-w = w let total-w = w
if note.shape == "default" { if shape == "default" {
total-w += NOTE-CORNER-SIZE total-w += NOTE-CORNER-SIZE
} }
@@ -106,31 +147,31 @@
} }
let y1 = y0 - h let y1 = y0 - h
if note.shape == "default" { if shape == "default" {
draw.line( draw.line(
(x0, y0), (x0, y0),
(x1, y0), (x1, y0),
(x2, y0 - NOTE-CORNER-SIZE), (x2, y0 - NOTE-CORNER-SIZE),
(x2, y1), (x2, y1),
(x0, y1), (x0, y1),
stroke: black + .5pt, stroke: style.stroke,
fill: note.color, fill: style.fill,
close: true close: true
) )
draw.line( draw.line(
(x1, y0), (x1, y0),
(x1, y0 - NOTE-CORNER-SIZE), (x1, y0 - NOTE-CORNER-SIZE),
(x2, y0 - NOTE-CORNER-SIZE), (x2, y0 - NOTE-CORNER-SIZE),
stroke: black + .5pt stroke: style.stroke
) )
} else if note.shape == "rect" { } else if shape == "rect" {
draw.rect( draw.rect(
(x0, y0), (x0, y0),
(x2, y1), (x2, y1),
stroke: black + .5pt, stroke: style.stroke,
fill: note.color fill: style.fill
) )
} else if note.shape == "hex" { } else if shape == "hex" {
let lx = x0 + PAD.last() let lx = x0 + PAD.last()
let rx = x2 - PAD.last() let rx = x2 - PAD.last()
let my = (y0 + y1) / 2 let my = (y0 + y1) / 2
@@ -141,8 +182,8 @@
(rx, y1), (rx, y1),
(lx, y1), (lx, y1),
(x0, my), (x0, my),
stroke: black + .5pt, stroke: style.stroke,
fill: note.color, fill: style.fill,
close: true close: true
) )
} }

View File

@@ -70,7 +70,8 @@
h = calc.max( h = calc.max(
h, h,
..seq.linked-notes.map(n => { ..seq.linked-notes.map(n => {
note.get-size(n).height / 2 let nt = ctx.notes.at(n.id)
note.get-size(nt).height / 2
}) })
) )
ctx.y -= h ctx.y -= h
@@ -354,7 +355,8 @@
end-info.y = calc.min( end-info.y = calc.min(
end-info.y, end-info.y,
y0 - calc.max(..seq.linked-notes.map(n => { y0 - calc.max(..seq.linked-notes.map(n => {
let m = note.get-size(n) let nt = ctx.notes.at(n.id)
let m = note.get-size(nt)
return m.height / 2 return m.height / 2
})) }))
) )

View File

@@ -87,7 +87,7 @@
return participants return participants
} }
#let note-get-cell(pars-i, n) = { #let note-get-cell(notes, pars-i, n) = {
let (p1, p2) = (none, none) let (p1, p2) = (none, none)
let cell = none let cell = none
if n.side == "left" { if n.side == "left" {
@@ -99,8 +99,9 @@
p2 = n.pos2 p2 = n.pos2
cell = note.get-box(n) cell = note.get-box(n)
} else if n.side == "over" and n.aligned-with != none { } else if n.side == "over" and n.aligned-with != none {
let aligned-with = notes.at(n.aligned-with.id)
let box1 = note.get-box(n) let box1 = note.get-box(n)
let box2 = note.get-box(n.aligned-with) let box2 = note.get-box(aligned-with)
let m1 = measure(box1) let m1 = measure(box1)
let m2 = measure(box2) let m2 = measure(box2)
cell = box( cell = box(
@@ -144,7 +145,7 @@
) )
} else if elmt.type == "note" { } else if elmt.type == "note" {
let cell = note-get-cell(pars-i, notes.at(elmt.id)) let cell = note-get-cell(notes, pars-i, notes.at(elmt.id))
if cell != none { if cell != none {
cells.push(cell) cells.push(cell)
} }
@@ -360,7 +361,7 @@
init-lifelines() init-lifelines()
set-participants-i() set-participants-i()
note.pre-resolve-styles()
compute-columns-width() compute-columns-width()
set-ctx(c => { set-ctx(c => {

View File

@@ -150,6 +150,7 @@
let n = ctx.last-note.note let n = ctx.last-note.note
n.aligned-with = note n.aligned-with = note
ctx.elmts.at(ctx.last-note.i) = n ctx.elmts.at(ctx.last-note.i) = n
ctx.notes.at(ctx.last-note.note.id) = n
} }
if note.side in ("left", "right") { if note.side in ("left", "right") {

View File

@@ -18,10 +18,9 @@
side, side,
content, content,
pos: none, pos: none,
color: COL-NOTE,
shape: "default",
aligned: false, aligned: false,
allow-overlap: true allow-overlap: true,
..style
) = { ) = {
if side == "over" { if side == "over" {
if pos == none { if pos == none {
@@ -33,19 +32,15 @@
panic("Aligned notes can only be over a participant (got side '" + side + "')") panic("Aligned notes can only be over a participant (got side '" + side + "')")
} }
} }
if color == auto {
color = COL-NOTE
}
return (( return ((
type: "note", type: "note",
draw: note.render, draw: note.render,
side: side, side: side,
content: content, content: content,
pos: pos, pos: pos,
color: color,
shape: shape,
aligned: aligned, aligned: aligned,
aligned-with: none, aligned-with: none,
allow-overlap: allow-overlap allow-overlap: allow-overlap,
style: style.named()
),) ),)
} }

View File

@@ -5,9 +5,9 @@
_par("a", display-name: "Alice") _par("a", display-name: "Alice")
_par("b", display-name: "Bob") _par("b", display-name: "Bob")
_note("left", [This is displayed\ left of Alice.], pos: "a", color: rgb("#00FFFF")) _note("left", [This is displayed\ left of Alice.], pos: "a", fill: rgb("#00FFFF"))
_note("right", [This is displayed right of Alice.], pos: "a") _note("right", [This is displayed right of Alice.], pos: "a")
_note("over", [This is displayed over Alice.], pos: "a") _note("over", [This is displayed over Alice.], pos: "a")
_note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), color: rgb("#FFAAAA")) _note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), fill: rgb("#FFAAAA"))
_note("over", [This is yet another\ example of\ a long note.], pos: ("a", "b")) _note("over", [This is yet another\ example of\ a long note.], pos: ("a", "b"))
}) })