forked from HEL/chronos
		
	added groups
This commit is contained in:
		| @@ -1,3 +1,4 @@ | ||||
| #import "utils.typ": get-group-span | ||||
| #import "renderer.typ": render | ||||
|  | ||||
| #let _seq( | ||||
| @@ -37,9 +38,40 @@ | ||||
|   return false | ||||
| } | ||||
|  | ||||
| #let _grp(name, desc: none, type: "default", elmts) = { | ||||
|   return (( | ||||
|     type: "grp", | ||||
|     name: name, | ||||
|     desc: desc, | ||||
|     grp-type: type, | ||||
|     elmts: elmts | ||||
|   ),) | ||||
| } | ||||
|  | ||||
| #let diagram(elements) = { | ||||
|   let participants = () | ||||
|   for elmt in elements { | ||||
|   let elmts = elements | ||||
|   let i = 0 | ||||
|   let a = elmts.len() | ||||
|   while i < elmts.len() { | ||||
|     let elmt = elmts.at(i) | ||||
|     if elmt.type == "grp" { | ||||
|       elmts = ( | ||||
|         elmts.slice(0, i + 1) + | ||||
|         elmt.elmts + | ||||
|         (( | ||||
|           type: "grp-end" | ||||
|         ),) + | ||||
|         elmts.slice(i+1) | ||||
|       ) | ||||
|     } | ||||
|     i += 1 | ||||
|   } | ||||
|   let b = elmts.len() | ||||
|   [#a / #b] | ||||
|   [#elmts.map(e => e.type)] | ||||
|  | ||||
|   for elmt in elmts { | ||||
|     if elmt.type == "par" { | ||||
|       participants.push(elmt) | ||||
|     } else if elmt.type == "seq" { | ||||
| @@ -52,7 +84,15 @@ | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   render(participants, elements) | ||||
|   for (i, elmt) in elmts.enumerate() { | ||||
|     if elmt.type == "grp" { | ||||
|       let (min-i, max-i) = get-group-span(participants, elmt) | ||||
|       elmts.at(i).insert("min-i", min-i) | ||||
|       elmts.at(i).insert("max-i", max-i) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   render(participants, elmts) | ||||
| } | ||||
|  | ||||
| #let from-plantuml(code) = { | ||||
|   | ||||
| @@ -1,16 +1,10 @@ | ||||
| #import "@preview/cetz:0.2.2": canvas, draw | ||||
| #import "utils.typ": get-participants-i | ||||
|  | ||||
| #let Y-SPACE = 20 | ||||
| #let Y-SPACE = 10 | ||||
| #let PAR-PAD = (5pt, 3pt) | ||||
| #let PAR-SPACE = 10 | ||||
|  | ||||
| #let get-participants-i(participants) = { | ||||
|   let pars-i = (:) | ||||
|   for (i, p) in participants.enumerate() { | ||||
|     pars-i.insert(p.name, i) | ||||
|   } | ||||
|   return pars-i | ||||
| } | ||||
|  | ||||
| #let get-columns-width(participants, elements) = { | ||||
|   let pars-i = get-participants-i(participants) | ||||
| @@ -62,6 +56,44 @@ | ||||
|   return widths | ||||
| } | ||||
|  | ||||
| #let draw-group(x0, x1, y0, y1, group) = { | ||||
|   let m = measure(box(group.name)) | ||||
|   let w = m.width / 1pt + 15 | ||||
|   let h = m.height / 1pt + 6 | ||||
|   draw.rect( | ||||
|     (x0, y0), | ||||
|     (x1, y1) | ||||
|   ) | ||||
|   draw.merge-path( | ||||
|     fill: gray.lighten(20%), | ||||
|     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), | ||||
|     group.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"), | ||||
|       anchor: "north-west", | ||||
|       padding: 3pt | ||||
|     ) | ||||
|   } | ||||
| } | ||||
|  | ||||
| #let render(participants, elements) = context canvas(length: 1pt, { | ||||
|   let pars-i = get-participants-i(participants) | ||||
|  | ||||
| @@ -85,6 +117,8 @@ | ||||
|   } | ||||
|  | ||||
|   let y = -Y-SPACE | ||||
|   let groups = () | ||||
|  | ||||
|   // Draw sequences | ||||
|   for elmt in elements { | ||||
|     if elmt.type == "seq" { | ||||
| @@ -98,12 +132,8 @@ | ||||
|         ) | ||||
|       ) | ||||
|  | ||||
|       draw.line( | ||||
|         (x1, y), | ||||
|         (x2, y), | ||||
|         ..style | ||||
|       ) | ||||
|       if elmt.comment != none { | ||||
|         y -= measure(box(elmt.comment)).height / 1pt + 6 | ||||
|         draw.content( | ||||
|           (calc.min(x1, x2), y), | ||||
|           elmt.comment, | ||||
| @@ -111,6 +141,33 @@ | ||||
|           padding: 3pt | ||||
|         ) | ||||
|       } | ||||
|  | ||||
|       draw.line( | ||||
|         (x1, y), | ||||
|         (x2, y), | ||||
|         ..style | ||||
|       ) | ||||
|       y -= Y-SPACE | ||||
|     } else if elmt.type == "grp" { | ||||
|       let m = measure( | ||||
|         box( | ||||
|           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 | ||||
|       }) | ||||
|       groups.push((y, elmt, 0, 0)) | ||||
|       y -= m.height / 1pt + Y-SPACE | ||||
|      | ||||
|     } else if elmt.type == "grp-end" { | ||||
|       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 | ||||
|       draw-group(x0, x1, start-y, y, group) | ||||
|  | ||||
|       y -= Y-SPACE | ||||
|     } | ||||
|   } | ||||
|   | ||||
							
								
								
									
										27
									
								
								src/utils.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/utils.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| #let get-participants-i(participants) = { | ||||
|   let pars-i = (:) | ||||
|   for (i, p) in participants.enumerate() { | ||||
|     pars-i.insert(p.name, i) | ||||
|   } | ||||
|   return pars-i | ||||
| } | ||||
|  | ||||
| #let get-group-span(participants, group) = { | ||||
|   let min-i = participants.len() - 1 | ||||
|   let max-i = 0 | ||||
|   let pars-i = get-participants-i(participants) | ||||
|  | ||||
|   for elmt in group.elmts { | ||||
|     if elmt.type == "seq" { | ||||
|       let i1 = pars-i.at(elmt.p1) | ||||
|       let i2 = pars-i.at(elmt.p2) | ||||
|       min-i = calc.min(min-i, i1, i2) | ||||
|       max-i = calc.max(max-i, i1, i2) | ||||
|     } else if elmt.type == "grp" { | ||||
|       let (i0, i1) = get-group-span(participants, elmt) | ||||
|       min-i = calc.min(min-i, i0) | ||||
|       max-i = calc.max(max-i, i1) | ||||
|     } | ||||
|   } | ||||
|   return (min-i, max-i) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user