refactored notes rendering
This commit is contained in:
		| @@ -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")) | ||||||
| }) | }) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|       ) |       ) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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 | ||||||
|       })) |       })) | ||||||
|     ) |     ) | ||||||
|   | |||||||
| @@ -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 => { | ||||||
|   | |||||||
| @@ -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") { | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/note.typ
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/note.typ
									
									
									
									
									
								
							| @@ -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() | ||||||
|   ),) |   ),) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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")) | ||||||
| }) | }) | ||||||
		Reference in New Issue
	
	Block a user