refactored groups, separators and delays
This commit is contained in:
		
							
								
								
									
										27
									
								
								src/core/draw/delay.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/core/draw/delay.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| #import "../utils.typ": get-ctx, set-ctx | ||||
| #import "../../cetz.typ": draw | ||||
|  | ||||
| #let render(delay) = get-ctx(ctx => { | ||||
|   let y0 = ctx.y | ||||
|   let y1 = ctx.y - delay.size | ||||
|   for (i, line) in ctx.lifelines.enumerate() { | ||||
|     line.lines.push(("delay-start", y0)) | ||||
|     line.lines.push(("delay-end", y1)) | ||||
|     ctx.lifelines.at(i) = line | ||||
|   } | ||||
|   if delay.name != none { | ||||
|     let x0 = ctx.x-pos.first() | ||||
|     let x1 = ctx.x-pos.last() | ||||
|     draw.content( | ||||
|       ((x0 + x1) / 2, (y0 + y1) / 2), | ||||
|       anchor: "center", | ||||
|       delay.name | ||||
|     ) | ||||
|   } | ||||
|   ctx.y = y1 | ||||
|   set-ctx(c => { | ||||
|     c.y = ctx.y | ||||
|     c.lifelines = ctx.lifelines | ||||
|     return c | ||||
|   }) | ||||
| }) | ||||
							
								
								
									
										120
									
								
								src/core/draw/group.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/core/draw/group.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| #import "../utils.typ": get-ctx, set-ctx | ||||
| #import "../../consts.typ": * | ||||
| #import "../../cetz.typ": draw | ||||
|  | ||||
| #let render-start(grp) = get-ctx(ctx => { | ||||
|   let grp = grp | ||||
|   ctx.y -= Y-SPACE | ||||
|   let m = measure( | ||||
|     box( | ||||
|       grp.name, | ||||
|       inset: ( | ||||
|         left: 5pt, | ||||
|         right: 5pt, | ||||
|         top: 3pt, | ||||
|         bottom: 3pt | ||||
|       ), | ||||
|     ) | ||||
|   ) | ||||
|   ctx.groups = ctx.groups.map(g => { | ||||
|     if g.at(1).min-i == grp.min-i { g.at(2) += 1 } | ||||
|     if g.at(1).max-i == grp.max-i { g.at(3) += 1 } | ||||
|     g | ||||
|   }) | ||||
|   if grp.grp-type == "alt" { | ||||
|     grp.insert("elses", ()) | ||||
|   } | ||||
|   ctx.groups.push((ctx.y, grp, 0, 0)) | ||||
|   ctx.y -= m.height / 1pt | ||||
|  | ||||
|   set-ctx(c => { | ||||
|     c.y = ctx.y | ||||
|     c.groups = ctx.groups | ||||
|     return c | ||||
|   }) | ||||
| }) | ||||
|  | ||||
|  | ||||
| #let draw-group(x0, x1, y0, y1, group) = { | ||||
|   let name = text(group.name, weight: "bold") | ||||
|   let m = measure(box(name)) | ||||
|   let w = m.width / 1pt + 15 | ||||
|   let h = m.height / 1pt + 6 | ||||
|   draw.rect( | ||||
|     (x0, y0), | ||||
|     (x1, y1) | ||||
|   ) | ||||
|   draw.merge-path( | ||||
|     fill: COL-GRP-NAME, | ||||
|     close: true, | ||||
|     { | ||||
|       draw.line( | ||||
|         (x0, y0), | ||||
|         (x0 + w, y0), | ||||
|         (x0 + w, y0 - h / 2), | ||||
|         (x0 + w - 5, y0 - h), | ||||
|         (x0, y0 - h) | ||||
|       ) | ||||
|     } | ||||
|   ) | ||||
|   draw.content( | ||||
|     (x0, y0), | ||||
|     name, | ||||
|     anchor: "north-west", | ||||
|     padding: (left: 5pt, right: 10pt, top: 3pt, bottom: 3pt) | ||||
|   ) | ||||
|  | ||||
|   if group.desc != none { | ||||
|     draw.content( | ||||
|       (x0 + w, y0), | ||||
|       text([\[#group.desc\]], weight: "bold", size: .8em), | ||||
|       anchor: "north-west", | ||||
|       padding: 3pt | ||||
|     ) | ||||
|   } | ||||
| } | ||||
|  | ||||
| #let draw-else(x0, x1, y, elmt) = { | ||||
|   draw.line( | ||||
|     (x0, y), | ||||
|     (x1, y), | ||||
|     stroke: (dash: (2pt, 1pt), thickness: .5pt) | ||||
|   ) | ||||
|   draw.content( | ||||
|     (x0, y), | ||||
|     text([\[#elmt.desc\]], weight: "bold", size: .8em), | ||||
|     anchor: "north-west", | ||||
|     padding: 3pt | ||||
|   ) | ||||
| } | ||||
|  | ||||
| #let render-end(group) = get-ctx(ctx => { | ||||
|   ctx.y -= Y-SPACE | ||||
|   let (start-y, group, start-lvl, end-lvl) = ctx.groups.pop() | ||||
|   let x0 = ctx.x-pos.at(group.min-i) - start-lvl * 10 - 20 | ||||
|   let x1 = ctx.x-pos.at(group.max-i) + end-lvl * 10 + 20 | ||||
|    | ||||
|   draw-group(x0, x1, start-y, ctx.y, group) | ||||
|  | ||||
|   if group.grp-type == "alt" { | ||||
|     for (else-y, else-elmt) in group.elses { | ||||
|       draw-else(x0, x1, else-y, else-elmt) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   set-ctx(c => { | ||||
|     c.y = ctx.y | ||||
|     c.groups = ctx.groups | ||||
|     return c | ||||
|   }) | ||||
| }) | ||||
|  | ||||
| #let render-else(else_) = set-ctx(ctx => { | ||||
|   ctx.y -= Y-SPACE | ||||
|   let m = measure(text([\[#else_.desc\]], weight: "bold", size: .8em)) | ||||
|   ctx.groups.last().at(1).elses.push(( | ||||
|     ctx.y, else_ | ||||
|   )) | ||||
|   ctx.y -= m.height / 1pt | ||||
|   return ctx | ||||
| }) | ||||
							
								
								
									
										46
									
								
								src/core/draw/separator.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/core/draw/separator.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| #import "../utils.typ": get-ctx, set-ctx | ||||
| #import "../../consts.typ": * | ||||
| #import "../../cetz.typ": draw | ||||
|  | ||||
| #let render(sep) = get-ctx(ctx => { | ||||
|   ctx.y -= Y-SPACE | ||||
|  | ||||
|   let x0 = ctx.x-pos.first() - 20 | ||||
|   let x1 = ctx.x-pos.last() + 20 | ||||
|   let m = measure( | ||||
|     box( | ||||
|       sep.name, | ||||
|       inset: (left: 3pt, right: 3pt, top: 5pt, bottom: 5pt) | ||||
|     ) | ||||
|   ) | ||||
|   let w = m.width / 1pt | ||||
|   let h = m.height / 1pt | ||||
|   let cx = (x0 + x1) / 2 | ||||
|   let xl = cx - w / 2 | ||||
|   let xr = cx + w / 2 | ||||
|  | ||||
|   ctx.y -= h / 2 | ||||
|   draw.rect( | ||||
|     (x0, ctx.y), | ||||
|     (x1, ctx.y - 3), | ||||
|     stroke: none, | ||||
|     fill: white | ||||
|   ) | ||||
|   draw.line((x0, ctx.y), (x1, ctx.y)) | ||||
|   ctx.y -= 3 | ||||
|   draw.line((x0, ctx.y), (x1, ctx.y)) | ||||
|   draw.content( | ||||
|     ((x0 + x1) / 2, ctx.y + 1.5), | ||||
|     sep.name, | ||||
|     anchor: "center", | ||||
|     padding: (5pt, 3pt), | ||||
|     frame: "rect", | ||||
|     fill: COL-SEP-NAME | ||||
|   ) | ||||
|   ctx.y -= h / 2 | ||||
|  | ||||
|   set-ctx(c => { | ||||
|     c.y = ctx.y | ||||
|     return c | ||||
|   }) | ||||
| }) | ||||
| @@ -354,7 +354,6 @@ | ||||
| },) | ||||
|  | ||||
| #let render(participants, elements) = context canvas(length: 1pt, { | ||||
|   let shapes = () | ||||
|   setup-ctx(participants, elements) | ||||
|    | ||||
|   // Draw participants (start) | ||||
| @@ -372,80 +371,6 @@ | ||||
|       (elmt,) | ||||
|     } else if "draw" in elmt and elmt.type != "par" { | ||||
|       (elmt.draw)(elmt) | ||||
|  | ||||
|     // Groups (start) -> reserve space for labels + store position | ||||
|     } else if elmt.type == "grp" { | ||||
|       y -= Y-SPACE | ||||
|       let m = measure( | ||||
|         box( | ||||
|           elmt.name, | ||||
|           inset: ( | ||||
|             left: 5pt, | ||||
|             right: 5pt, | ||||
|             top: 3pt, | ||||
|             bottom: 3pt | ||||
|           ), | ||||
|         ) | ||||
|       ) | ||||
|       groups = groups.map(g => { | ||||
|         if g.at(1).min-i == elmt.min-i { g.at(2) += 1 } | ||||
|         if g.at(1).max-i == elmt.max-i { g.at(3) += 1 } | ||||
|         g | ||||
|       }) | ||||
|       if elmt.grp-type == "alt" { | ||||
|         elmt.insert("elses", ()) | ||||
|       } | ||||
|       groups.push((y, elmt, 0, 0)) | ||||
|       y -= m.height / 1pt | ||||
|      | ||||
|     // Groups (end) -> actual drawing | ||||
|     } else if elmt.type == "grp-end" { | ||||
|       y -= Y-SPACE | ||||
|       let (start-y, group, start-lvl, end-lvl) = groups.pop() | ||||
|       let x0 = x-pos.at(group.min-i) - start-lvl * 10 - 20 | ||||
|       let x1 = x-pos.at(group.max-i) + end-lvl * 10 + 20 | ||||
|       shapes += draw-group(x0, x1, start-y, y, group) | ||||
|  | ||||
|       if group.grp-type == "alt" { | ||||
|         for (else-y, else-elmt) in group.elses { | ||||
|           shapes += draw-else(x0, x1, else-y, else-elmt) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|     // Alt's elses -> reserve space for label + store position | ||||
|     } else if elmt.type == "else" { | ||||
|       y -= Y-SPACE | ||||
|       let m = measure(text([\[#elmt.desc\]], weight: "bold", size: .8em)) | ||||
|       groups.last().at(1).elses.push(( | ||||
|         y, elmt | ||||
|       )) | ||||
|       y -= m.height / 1pt | ||||
|  | ||||
|     // Separator | ||||
|     } else if elmt.type == "sep" { | ||||
|       let shps | ||||
|       (y, shps) = draw-sep(elmt, y) | ||||
|       shapes += shps | ||||
|  | ||||
|     // Delay | ||||
|     } else if elmt.type == "delay" { | ||||
|       let y0 = y | ||||
|       let y1 = y - elmt.size | ||||
|       for (i, line) in lifelines.enumerate() { | ||||
|         line.lines.push(("delay-start", y0)) | ||||
|         line.lines.push(("delay-end", y1)) | ||||
|         lifelines.at(i) = line | ||||
|       } | ||||
|       if elmt.name != none { | ||||
|         let x0 = x-pos.first() | ||||
|         let x1 = x-pos.last() | ||||
|         shapes += draw.content( | ||||
|           ((x0 + x1) / 2, (y0 + y1) / 2), | ||||
|           anchor: "center", | ||||
|           elmt.name | ||||
|         ) | ||||
|       } | ||||
|       y = y1 | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -476,6 +401,4 @@ | ||||
|      | ||||
|     participant.render-lifelines() | ||||
|   }) | ||||
|  | ||||
|   shapes | ||||
| }) | ||||
| @@ -1,5 +1,6 @@ | ||||
| #import "utils.typ": is-elmt, get-group-span | ||||
| #import "../participant.typ": _exists as par-exists, _par | ||||
| #import "draw/group.typ": render-end as grp-render-end | ||||
|  | ||||
| #let flatten-group(elmts, i) = { | ||||
|   let group = elmts.at(i) | ||||
| @@ -9,6 +10,7 @@ | ||||
|     group.elmts + | ||||
|     (( | ||||
|       type: "grp-end", | ||||
|       draw: grp-render-end, | ||||
|       start-i: i | ||||
|     ),) + | ||||
|     elmts.slice(i+1) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user