Compare commits
	
		
			12 Commits
		
	
	
		
			8ee14167de
			...
			dev
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1000a3a19a | |||
| f3763cb1f7 | |||
| c19d507486 | |||
| fe01e63dd0 | |||
| d6c390f3c5 | |||
| bbc8bb0339 | |||
| f39e14654a | |||
| aca2d858fe | |||
| 6c97bb807f | |||
| f812ac93c2 | |||
| caad9ed823 | |||
| 0b401df67d | 
| @@ -1,7 +1,10 @@ | |||||||
| #import "/src/cetz.typ": draw | #import "/src/cetz.typ": draw | ||||||
|  |  | ||||||
| #import "/src/consts.typ": * | #import "/src/consts.typ": * | ||||||
| #import "/src/core/utils.typ": get-ctx, set-ctx | #import "/src/core/utils.typ": get-ctx, set-ctx, expand-parent-group | ||||||
|  |  | ||||||
|  | #let display-name(name) = text(name, weight: "bold") | ||||||
|  | #let display-desc(desc) = text([\[#desc\]], weight: "bold", size: .8em) | ||||||
|  |  | ||||||
| #let render-start(grp) = get-ctx(ctx => { | #let render-start(grp) = get-ctx(ctx => { | ||||||
|   let grp = grp |   let grp = grp | ||||||
| @@ -18,14 +21,21 @@ | |||||||
|     ) |     ) | ||||||
|   ) |   ) | ||||||
|   ctx.groups = ctx.groups.map(g => { |   ctx.groups = ctx.groups.map(g => { | ||||||
|     if g.at(1).min-i == grp.min-i { g.at(2) += 1 } |     if g.group.min-i == grp.min-i { g.start-lvl += 1 } | ||||||
|     if g.at(1).max-i == grp.max-i { g.at(3) += 1 } |     if g.group.max-i == grp.max-i { g.end-lvl += 1 } | ||||||
|     g |     g | ||||||
|   }) |   }) | ||||||
|   if grp.grp-type == "alt" { |   if grp.grp-type == "alt" { | ||||||
|     grp.insert("elses", ()) |     grp.insert("elses", ()) | ||||||
|   } |   } | ||||||
|   ctx.groups.push((ctx.y, grp, 0, 0)) |   ctx.groups.push(( | ||||||
|  |     start-y: ctx.y, | ||||||
|  |     group: grp, | ||||||
|  |     start-lvl: 0, | ||||||
|  |     end-lvl: 0, | ||||||
|  |     min-x: ctx.x-pos.at(grp.min-i) - 10, | ||||||
|  |     max-x: ctx.x-pos.at(grp.max-i) + 10 | ||||||
|  |   )) | ||||||
|   ctx.y -= m.height / 1pt |   ctx.y -= m.height / 1pt | ||||||
|  |  | ||||||
|   set-ctx(c => { |   set-ctx(c => { | ||||||
| @@ -37,8 +47,8 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| #let draw-group(x0, x1, y0, y1, group) = { | #let draw-group(x0, x1, y0, y1, group) = { | ||||||
|   let name = text(group.name, weight: "bold") |   let name = display-name(group.name) | ||||||
|   let m = measure(box(name)) |   let m = measure(name) | ||||||
|   let w = m.width / 1pt + 15 |   let w = m.width / 1pt + 15 | ||||||
|   let h = m.height / 1pt + 6 |   let h = m.height / 1pt + 6 | ||||||
|   draw.rect( |   draw.rect( | ||||||
| @@ -64,7 +74,7 @@ | |||||||
|   if group.desc != none { |   if group.desc != none { | ||||||
|     draw.content( |     draw.content( | ||||||
|       (x0 + w, y0), |       (x0 + w, y0), | ||||||
|       text([\[#group.desc\]], weight: "bold", size: .8em), |       display-desc(group.desc), | ||||||
|       anchor: "north-west", |       anchor: "north-west", | ||||||
|       padding: 3pt |       padding: 3pt | ||||||
|     ) |     ) | ||||||
| @@ -79,7 +89,7 @@ | |||||||
|   ) |   ) | ||||||
|   draw.content( |   draw.content( | ||||||
|     (x0, y), |     (x0, y), | ||||||
|     text([\[#elmt.desc\]], weight: "bold", size: .8em), |     display-desc(elmt.desc), | ||||||
|     anchor: "north-west", |     anchor: "north-west", | ||||||
|     padding: 3pt |     padding: 3pt | ||||||
|   ) |   ) | ||||||
| @@ -87,9 +97,32 @@ | |||||||
|  |  | ||||||
| #let render-end(group) = get-ctx(ctx => { | #let render-end(group) = get-ctx(ctx => { | ||||||
|   ctx.y -= Y-SPACE |   ctx.y -= Y-SPACE | ||||||
|   let (start-y, group, start-lvl, end-lvl) = ctx.groups.pop() |   let ( | ||||||
|   let x0 = ctx.x-pos.at(group.min-i) - start-lvl * 10 - 20 |     start-y, | ||||||
|   let x1 = ctx.x-pos.at(group.max-i) + end-lvl * 10 + 20 |     group, | ||||||
|  |     start-lvl, | ||||||
|  |     end-lvl, | ||||||
|  |     min-x, | ||||||
|  |     max-x | ||||||
|  |   ) = ctx.groups.pop() | ||||||
|  |   let x0 = min-x - 10 | ||||||
|  |   let x1 = max-x + 10 | ||||||
|  |    | ||||||
|  |   // Fit name and descriptions | ||||||
|  |   let name-m = measure(display-name(group.name)) | ||||||
|  |   let width = name-m.width / 1pt + 15 | ||||||
|  |   if group.desc != none { | ||||||
|  |     let desc-m = measure(display-desc(group.desc)) | ||||||
|  |     width += desc-m.width / 1pt + 6 | ||||||
|  |   } | ||||||
|  |   if group.grp-type == "alt" { | ||||||
|  |     width = calc.max(width, ..group.elses.map(e => { | ||||||
|  |       let elmt = e.at(1) | ||||||
|  |       let desc-m = measure(display-desc(elmt.desc)) | ||||||
|  |       return desc-m.width / 1pt + 6 | ||||||
|  |     })) | ||||||
|  |   } | ||||||
|  |   x1 = calc.max(x1, x0 + width + 3) | ||||||
|    |    | ||||||
|   draw-group(x0, x1, start-y, ctx.y, group) |   draw-group(x0, x1, start-y, ctx.y, group) | ||||||
|  |  | ||||||
| @@ -104,12 +137,14 @@ | |||||||
|     c.groups = ctx.groups |     c.groups = ctx.groups | ||||||
|     return c |     return c | ||||||
|   }) |   }) | ||||||
|  |  | ||||||
|  |   expand-parent-group(x0, x1) | ||||||
| }) | }) | ||||||
|  |  | ||||||
| #let render-else(else_) = set-ctx(ctx => { | #let render-else(else_) = set-ctx(ctx => { | ||||||
|   ctx.y -= Y-SPACE |   ctx.y -= Y-SPACE | ||||||
|   let m = measure(text([\[#else_.desc\]], weight: "bold", size: .8em)) |   let m = measure(text([\[#else_.desc\]], weight: "bold", size: .8em)) | ||||||
|   ctx.groups.last().at(1).elses.push(( |   ctx.groups.last().group.elses.push(( | ||||||
|     ctx.y, else_ |     ctx.y, else_ | ||||||
|   )) |   )) | ||||||
|   ctx.y -= m.height / 1pt |   ctx.y -= m.height / 1pt | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| #import "/src/cetz.typ": draw | #import "/src/cetz.typ": draw | ||||||
|  |  | ||||||
| #import "/src/consts.typ": * | #import "/src/consts.typ": * | ||||||
| #import "/src/core/utils.typ": get-ctx, set-ctx | #import "/src/core/utils.typ": get-ctx, set-ctx, expand-parent-group | ||||||
|  |  | ||||||
| #let get-size(note) = { | #let get-size(note) = { | ||||||
|   let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} |   let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} | ||||||
| @@ -159,5 +159,7 @@ | |||||||
|         return c |         return c | ||||||
|       }) |       }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     expand-parent-group(x0, x2) | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
| @@ -81,7 +81,7 @@ | |||||||
|   draw.content( |   draw.content( | ||||||
|     (x, y), |     (x, y), | ||||||
|     p.display-name, |     p.display-name, | ||||||
|     anchor: if bottom {"north"} else {"south"} |     anchor: if bottom {"north"} else {"base"} | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -109,7 +109,7 @@ | |||||||
|   draw.content( |   draw.content( | ||||||
|     (x, y), |     (x, y), | ||||||
|     p.display-name, |     p.display-name, | ||||||
|     anchor: if bottom {"north"} else {"south"} |     anchor: if bottom {"north"} else {"base"} | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -127,7 +127,7 @@ | |||||||
|   draw.content( |   draw.content( | ||||||
|     (x, y), |     (x, y), | ||||||
|     p.display-name, |     p.display-name, | ||||||
|     anchor: if bottom {"north"} else {"south"} |     anchor: if bottom {"north"} else {"base"} | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -150,7 +150,7 @@ | |||||||
|   draw.content( |   draw.content( | ||||||
|     (x, y), |     (x, y), | ||||||
|     p.display-name, |     p.display-name, | ||||||
|     anchor: if bottom {"north"} else {"south"} |     anchor: if bottom {"north"} else {"base"} | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -183,7 +183,7 @@ | |||||||
|   draw.content( |   draw.content( | ||||||
|     (x, y), |     (x, y), | ||||||
|     p.display-name, |     p.display-name, | ||||||
|     anchor: if bottom {"north"} else {"south"} |     anchor: if bottom {"north"} else {"base"} | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -287,7 +287,7 @@ | |||||||
|   draw.content( |   draw.content( | ||||||
|     (x, y), |     (x, y), | ||||||
|     p.display-name, |     p.display-name, | ||||||
|     anchor: if bottom {"north"} else {"south"} |     anchor: if bottom {"north"} else {"base"} | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| #import "/src/cetz.typ": draw, vector | #import "/src/cetz.typ": draw, vector, coordinate | ||||||
|  |  | ||||||
| #import "note.typ" | #import "note.typ" | ||||||
| #import "/src/consts.typ": * | #import "/src/consts.typ": * | ||||||
| #import "/src/core/utils.typ": get-ctx, set-ctx | #import "/src/core/utils.typ": get-ctx, set-ctx, expand-parent-group | ||||||
|  |  | ||||||
| #let get-arrow-marks(sym, color) = { | #let get-arrow-marks(sym, color) = { | ||||||
|   if sym == none { |   if sym == none { | ||||||
| @@ -223,6 +223,11 @@ | |||||||
|       ).at(seq.comment-align) |       ).at(seq.comment-align) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     expand-parent-group( | ||||||
|  |       calc.min(x1, x2, x-mid), | ||||||
|  |       calc.max(x1, x2, x-mid) | ||||||
|  |     ) | ||||||
|  |  | ||||||
|   } else { |   } else { | ||||||
|     pts = ( |     pts = ( | ||||||
|       (x1, start-info.y), |       (x1, start-info.y), | ||||||
| @@ -261,6 +266,11 @@ | |||||||
|       (p1, p2) = (p2, p1) |       (p1, p2) = (p2, p1) | ||||||
|     } |     } | ||||||
|     comment-angle = vector.angle2(p1, p2) |     comment-angle = vector.angle2(p1, p2) | ||||||
|  |  | ||||||
|  |     expand-parent-group( | ||||||
|  |       calc.min(x1, x2), | ||||||
|  |       calc.max(x1, x2) | ||||||
|  |     ) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Start circle tip |   // Start circle tip | ||||||
| @@ -335,8 +345,23 @@ | |||||||
|       comment, |       comment, | ||||||
|       anchor: comment-anchor, |       anchor: comment-anchor, | ||||||
|       angle: comment-angle, |       angle: comment-angle, | ||||||
|       padding: 3pt |       padding: 3pt, | ||||||
|  |       name: "comment" | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |     // TODO: Improve this | ||||||
|  |     draw.get-ctx(c => { | ||||||
|  |       let (_, left, right) = coordinate.resolve( | ||||||
|  |         c, | ||||||
|  |         "comment.west", | ||||||
|  |         "comment.east" | ||||||
|  |       ) | ||||||
|  |       expand-parent-group( | ||||||
|  |         left.at(0), | ||||||
|  |         right.at(0) | ||||||
|  |       ) | ||||||
|  |     }) | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if seq.create-dst { |   if seq.create-dst { | ||||||
|   | |||||||
| @@ -220,7 +220,7 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| /// Compute remaining widths for longer sequences (spanning multiple columns) | /// Compute remaining widths for longer sequences (spanning multiple columns) | ||||||
| #let long-seq-min-col-widths(cells, widths) = { | #let long-seq-min-col-widths(participants, cells, widths) = { | ||||||
|   let widths = widths |   let widths = widths | ||||||
|   let multicol-cells = cells.filter(c => c.i2 - c.i1 > 1) |   let multicol-cells = cells.filter(c => c.i2 - c.i1 > 1) | ||||||
|   multicol-cells = multicol-cells.sorted(key: c => { |   multicol-cells = multicol-cells.sorted(key: c => { | ||||||
| @@ -228,13 +228,23 @@ | |||||||
|   }) |   }) | ||||||
|   for cell in multicol-cells { |   for cell in multicol-cells { | ||||||
|     let m = measure(cell.cell) |     let m = measure(cell.cell) | ||||||
|  |  | ||||||
|  |     let i1 = cell.i1 | ||||||
|  |     let i2 = cell.i2 - 1 | ||||||
|  |     let i = i2 | ||||||
|  |     if cell.i1 == 0 and participants.at(0).name == "[" { | ||||||
|  |       i = 0 | ||||||
|  |       i1 += 1 | ||||||
|  |       i2 += 1 | ||||||
|  |     } | ||||||
|     let width = ( |     let width = ( | ||||||
|       m.width / 1pt + |       m.width / 1pt + | ||||||
|       COMMENT-PAD - |       COMMENT-PAD - | ||||||
|       widths.slice(cell.i1, cell.i2 - 1).sum() |       widths.slice(i1, i2).sum() | ||||||
|     ) |     ) | ||||||
|     widths.at(cell.i2 - 1) = calc.max( |      | ||||||
|       widths.at(cell.i2 - 1), width |     widths.at(i) = calc.max( | ||||||
|  |       widths.at(i), width | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
|   return widths |   return widths | ||||||
| @@ -307,7 +317,7 @@ | |||||||
|   widths = notes-min-col-widths(elements, widths, pars-i) |   widths = notes-min-col-widths(elements, widths, pars-i) | ||||||
|   widths = simple-seq-min-col-widths(cells, widths) |   widths = simple-seq-min-col-widths(cells, widths) | ||||||
|   widths = self-seq-min-col-widths(cells, widths) |   widths = self-seq-min-col-widths(cells, widths) | ||||||
|   widths = long-seq-min-col-widths(cells, widths) |   widths = long-seq-min-col-widths(participants, cells, widths) | ||||||
|   widths = col-widths-add-lifelines(participants, widths) |   widths = col-widths-add-lifelines(participants, widths) | ||||||
|   widths = process-col-elements(elements, widths, pars-i) |   widths = process-col-elements(elements, widths, pars-i) | ||||||
|   return widths |   return widths | ||||||
|   | |||||||
| @@ -105,3 +105,13 @@ | |||||||
|   let ctx = c.shared-state.chronos |   let ctx = c.shared-state.chronos | ||||||
|   func(ctx) |   func(ctx) | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | #let expand-parent-group(x0, x1) = set-ctx(ctx => { | ||||||
|  |   if ctx.groups.len() != 0 { | ||||||
|  |     let group = ctx.groups.last() | ||||||
|  |     group.min-x = calc.min(group.min-x, x0) | ||||||
|  |     group.max-x = calc.max(group.max-x, x1) | ||||||
|  |     ctx.groups.last() = group | ||||||
|  |   } | ||||||
|  |   return ctx | ||||||
|  | }) | ||||||
| @@ -39,5 +39,5 @@ | |||||||
|   } |   } | ||||||
|   _grp(name, desc: desc, type: "loop", elmts) |   _grp(name, desc: desc, type: "loop", elmts) | ||||||
| } | } | ||||||
| #let _opt(desc, elmts) = grp("opt", desc: desc, type: "opt", elmts) | #let _opt(desc, elmts) = _grp("opt", desc: desc, type: "opt", elmts) | ||||||
| #let _break(desc, elmts) = grp("break", desc: desc, type: "break", elmts) | #let _break(desc, elmts) = _grp("break", desc: desc, type: "break", elmts) | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| #import "core/draw/delay.typ" | #import "core/draw/delay.typ" | ||||||
|  | #import "core/draw/event.typ": render as evt-render | ||||||
| #import "core/draw/separator.typ" | #import "core/draw/separator.typ" | ||||||
| #import "core/draw/sync.typ" | #import "core/draw/sync.typ" | ||||||
| #import "core/utils.typ": set-ctx | #import "core/utils.typ": set-ctx | ||||||
|   | |||||||
| Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB | 
| Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										4
									
								
								tests/special-group/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,4 @@ | |||||||
|  | # generated by tytanic, do not edit | ||||||
|  |  | ||||||
|  | diff/** | ||||||
|  | out/** | ||||||
							
								
								
									
										
											BIN
										
									
								
								tests/special-group/ref/1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								tests/special-group/ref/2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								tests/special-group/ref/3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 17 KiB | 
							
								
								
									
										
											BIN
										
									
								
								tests/special-group/ref/4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 8.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								tests/special-group/ref/5.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 8.3 KiB | 
							
								
								
									
										71
									
								
								tests/special-group/test.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,71 @@ | |||||||
|  | #set page(width: auto, height: auto) | ||||||
|  | #import "/src/lib.typ": * | ||||||
|  |  | ||||||
|  | #let preamble = { | ||||||
|  |   _par("a", display-name: [Alice]) | ||||||
|  |   _par("b", display-name: [Bob]) | ||||||
|  |   _col("a", "b", width: 2cm) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #diagram({ | ||||||
|  |   preamble | ||||||
|  |   _grp("Group 1", { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  |   _grp("Group 2", desc: [Description], { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | #pagebreak() | ||||||
|  |  | ||||||
|  | #diagram({ | ||||||
|  |   preamble | ||||||
|  |   _alt( | ||||||
|  |     "case 1", { | ||||||
|  |       _seq("a", "b") | ||||||
|  |     }, | ||||||
|  |     "case 2", { | ||||||
|  |       _seq("a", "b") | ||||||
|  |     }, | ||||||
|  |     "case 3", { | ||||||
|  |       _seq("a", "b") | ||||||
|  |     } | ||||||
|  |   ) | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | #pagebreak() | ||||||
|  |  | ||||||
|  | #diagram({ | ||||||
|  |   preamble | ||||||
|  |   _loop("loop 1", { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  |   _loop("loop 2", min: 1, { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  |   _loop("loop 3", max: 10, { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  |   _loop("loop 3", min: 1, max: 10, { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | #pagebreak() | ||||||
|  |  | ||||||
|  | #diagram({ | ||||||
|  |   preamble | ||||||
|  |   _opt("Optional", { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | #pagebreak() | ||||||
|  |  | ||||||
|  | #diagram({ | ||||||
|  |   preamble | ||||||
|  |   _break("Break", { | ||||||
|  |     _seq("a", "b") | ||||||
|  |   }) | ||||||
|  | }) | ||||||