refactored setup-ctx to use CeTZ context
This commit is contained in:
		| @@ -54,8 +54,10 @@ | ||||
|   return style | ||||
| } | ||||
|  | ||||
| #let pre-resolve-styles(ctx, elements, participants) = { | ||||
| #let pre-resolve-styles() = get-ctx(ctx => { | ||||
|   let idx = (:) | ||||
|   let elements = ctx.setup.elements | ||||
|   let participants = ctx.setup.participants | ||||
|   for (i, par) in participants.enumerate() { | ||||
|     par.insert("resolved-style", resolve-style(ctx, par)) | ||||
|     participants.at(i) = par | ||||
| @@ -65,7 +67,7 @@ | ||||
|     if type(elmt) == function { | ||||
|       ctx = elmt(ctx).ctx | ||||
|     } else if is-elmt(elmt) { | ||||
|       if elmt.type == par { | ||||
|       if elmt.type == "par" { | ||||
|         let style = resolve-style(ctx, elmt) | ||||
|         elements.at(i).insert("resolved-style", style) | ||||
|         let i = idx.at(elmt.name) | ||||
| @@ -73,12 +75,17 @@ | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return (elements, participants) | ||||
| } | ||||
|    | ||||
|   set-ctx(c => { | ||||
|     c.setup.elements = elements | ||||
|     c.setup.participants = participants | ||||
|     return c | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| #let get-size(par) = { | ||||
|   if par.invisible { | ||||
|     return (width: 0pt, height: 0pt) | ||||
|     return (width: 0, height: 0) | ||||
|   } | ||||
|   let style = par.resolved-style | ||||
|   let func = shapes.at(style.shape).get-size | ||||
|   | ||||
| @@ -1,19 +1,28 @@ | ||||
| #import "/src/cetz.typ": canvas, draw | ||||
|  | ||||
| #import "draw/note.typ": get-box as get-note-box, get-size as get-note-size | ||||
| #import "draw/note.typ" | ||||
| #import "draw/participant.typ" | ||||
| #import "utils.typ": * | ||||
| #import "/src/consts.typ": * | ||||
|  | ||||
| #let DEBUG-INVISIBLE = false | ||||
|  | ||||
| #let init-lifelines(participants) = { | ||||
|   return participants.map(p => { | ||||
| #let init-lifelines() = set-ctx(ctx => { | ||||
|   ctx.setup.participants = ctx.setup.participants.map(p => { | ||||
|     p.insert("lifeline-lvl", 0) | ||||
|     p.insert("max-lifelines", 0) | ||||
|     p | ||||
|   }) | ||||
| } | ||||
|   return ctx | ||||
| }) | ||||
|  | ||||
| #let set-participants-i() = set-ctx(ctx => { | ||||
|   ctx.setup.insert( | ||||
|     "pars-i", | ||||
|     get-participants-i(ctx.setup.participants) | ||||
|   ) | ||||
|   return ctx | ||||
| }) | ||||
|  | ||||
| #let unwrap-syncs(elements) = { | ||||
|   let i = 0 | ||||
| @@ -78,28 +87,28 @@ | ||||
|   return participants | ||||
| } | ||||
|  | ||||
| #let note-get-cell(pars-i, note) = { | ||||
| #let note-get-cell(pars-i, n) = { | ||||
|   let (p1, p2) = (none, none) | ||||
|   let cell = none | ||||
|   if note.side == "left" { | ||||
|     p1 = note.pos2 | ||||
|     p2 = note.pos | ||||
|     cell = get-note-box(note) | ||||
|   } else if note.side == "right" { | ||||
|     p1 = note.pos | ||||
|     p2 = note.pos2 | ||||
|     cell = get-note-box(note) | ||||
|   } else if note.side == "over" and note.aligned-with != none { | ||||
|     let box1 = get-note-box(note) | ||||
|     let box2 = get-note-box(note.aligned-with) | ||||
|   if n.side == "left" { | ||||
|     p1 = n.pos2 | ||||
|     p2 = n.pos | ||||
|     cell = note.get-box(n) | ||||
|   } else if n.side == "right" { | ||||
|     p1 = n.pos | ||||
|     p2 = n.pos2 | ||||
|     cell = note.get-box(n) | ||||
|   } else if n.side == "over" and n.aligned-with != none { | ||||
|     let box1 = note.get-box(n) | ||||
|     let box2 = note.get-box(n.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 = note.pos | ||||
|     p2 = note.aligned-with.pos | ||||
|     p1 = n.pos | ||||
|     p2 = n.aligned-with.pos | ||||
|   } else { | ||||
|     return none | ||||
|   } | ||||
| @@ -107,7 +116,7 @@ | ||||
|   let i1 = pars-i.at(p1) | ||||
|   let i2 = pars-i.at(p2) | ||||
|   cell = ( | ||||
|     elmt: note, | ||||
|     elmt: n, | ||||
|     i1: calc.min(i1, i2), | ||||
|     i2: calc.max(i1, i2), | ||||
|     cell: cell | ||||
| @@ -116,7 +125,7 @@ | ||||
|   return cell | ||||
| } | ||||
|  | ||||
| #let compute-max-lifeline-levels(participants, elements, pars-i) = { | ||||
| #let compute-max-lifeline-levels(participants, elements, notes, pars-i) = { | ||||
|   let cells = () | ||||
|   for elmt in elements { | ||||
|     if elmt.type == "seq" { | ||||
| @@ -135,14 +144,14 @@ | ||||
|       ) | ||||
|      | ||||
|     } else if elmt.type == "note" { | ||||
|       let cell = note-get-cell(pars-i, elmt) | ||||
|       let cell = note-get-cell(pars-i, notes.at(elmt.id)) | ||||
|       if cell != none { | ||||
|         cells.push(cell) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return (participants, elements, cells) | ||||
|   return (participants, cells) | ||||
| } | ||||
|  | ||||
| /// Compute minimum widths for participant names and shapes | ||||
| @@ -161,13 +170,12 @@ | ||||
| } | ||||
|  | ||||
| /// Compute minimum width for over notes | ||||
| #let notes-min-col-widths(elements, widths, pars-i) = { | ||||
| #let notes-min-col-widths(notes, widths, pars-i) = { | ||||
|   let widths = widths | ||||
|   let notes = elements.filter(e => e.type == "note") | ||||
|   for n in notes.filter(e => (e.side == "over" and  | ||||
|                               type(e.pos) == str)) { | ||||
|      | ||||
|     let m = get-note-size(n) | ||||
|     let m = note.get-size(n) | ||||
|     let i = pars-i.at(n.pos) | ||||
|  | ||||
|     if i < widths.len() { | ||||
| @@ -306,62 +314,71 @@ | ||||
|   return widths | ||||
| } | ||||
|  | ||||
| #let compute-columns-width(participants, elements, pars-i) = { | ||||
|   elements = elements.filter(is-elmt) | ||||
| #let compute-columns-width() = set-ctx(ctx => { | ||||
|   let elements = ctx.setup.elements.filter(is-elmt) | ||||
|   let participants = ctx.setup.participants | ||||
|   let notes = ctx.setup.notes | ||||
|   let pars-i = ctx.setup.pars-i | ||||
|   elements = unwrap-syncs(elements) | ||||
|  | ||||
|   let cells | ||||
|   (participants, elements, cells) = compute-max-lifeline-levels(participants, elements, pars-i) | ||||
|   (participants, cells) = compute-max-lifeline-levels(participants, elements, notes, pars-i) | ||||
|  | ||||
|   let widths = participants-min-col-widths(participants) | ||||
|   widths = notes-min-col-widths(elements, widths, pars-i) | ||||
|   widths = notes-min-col-widths(notes, widths, pars-i) | ||||
|   widths = simple-seq-min-col-widths(cells, widths) | ||||
|   widths = self-seq-min-col-widths(cells, widths) | ||||
|   widths = long-seq-min-col-widths(participants, cells, widths) | ||||
|   widths = col-widths-add-lifelines(participants, widths) | ||||
|   widths = process-col-elements(elements, widths, pars-i) | ||||
|   return widths | ||||
| } | ||||
|  | ||||
| #let setup-ctx(participants, elements) = (ctx => { | ||||
|   let state = ctx.at("shared-state", default: (:)) | ||||
|   let ctx = ctx | ||||
|   ctx.insert("widths", widths) | ||||
|  | ||||
|   let (elements, participants) = participant.pre-resolve-styles( | ||||
|     extract-ctx(ctx, with-style: true), | ||||
|     elements, | ||||
|     participants | ||||
|   ) | ||||
|  | ||||
|   let chronos-ctx = ( | ||||
|     participants: init-lifelines(participants), | ||||
|     pars-i: get-participants-i(participants), | ||||
|     y: 0, | ||||
|     groups: (), | ||||
|     lifelines: participants.map(_ => ( | ||||
|       level: 0, | ||||
|       events: () | ||||
|     )) | ||||
|   ) | ||||
|   chronos-ctx.insert( | ||||
|     "widths", | ||||
|     compute-columns-width( | ||||
|       chronos-ctx.participants, | ||||
|       elements, | ||||
|       chronos-ctx.pars-i | ||||
|     ) | ||||
|   ) | ||||
|  | ||||
|   // Compute each column's X position | ||||
|   let x-pos = (0,) | ||||
|   for width in chronos-ctx.widths { | ||||
|   for width in widths { | ||||
|     x-pos.push(x-pos.last() + width) | ||||
|   } | ||||
|   chronos-ctx.insert("x-pos", x-pos) | ||||
|   state.insert("chronos", chronos-ctx) | ||||
|   ctx.shared-state = state | ||||
|   return ( | ||||
|     ctx: ctx | ||||
|   ) | ||||
|   ctx.insert("x-pos", x-pos) | ||||
|  | ||||
|   return ctx | ||||
| }) | ||||
|  | ||||
| #let setup-ctx(participants, elements, notes) = draw.get-ctx(_ => { | ||||
|   set-ctx(c => { | ||||
|     c.insert("participants", participants) | ||||
|     c.insert("setup", ( | ||||
|       elements: elements, | ||||
|       participants: participants, | ||||
|       notes: notes | ||||
|     )) | ||||
|     return c | ||||
|   }) | ||||
|  | ||||
|   participant.pre-resolve-styles() | ||||
|  | ||||
|   init-lifelines() | ||||
|   set-participants-i() | ||||
|  | ||||
|    | ||||
|   compute-columns-width() | ||||
|  | ||||
|   set-ctx(c => { | ||||
|     let setup = c.setup | ||||
|     c += ( | ||||
|       participants: setup.participants, | ||||
|       pars-i: setup.pars-i, | ||||
|       y: 0, | ||||
|       groups: (), | ||||
|       lifelines: setup.participants.map(_ => ( | ||||
|         level: 0, | ||||
|         events: () | ||||
|       )), | ||||
|       notes: setup.notes | ||||
|     ) | ||||
|     c.remove("setup") | ||||
|     return c | ||||
|   }) | ||||
| },) | ||||
|  | ||||
| #let render-debug() = get-ctx(ctx => { | ||||
| @@ -383,7 +400,7 @@ | ||||
| }) | ||||
|  | ||||
| #let render(participants, elements, notes) = context canvas(length: 1pt, { | ||||
|   setup-ctx(participants, elements) | ||||
|   setup-ctx(participants, elements, notes) | ||||
|    | ||||
|   // Draw participants (start) | ||||
|   get-ctx(ctx => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user