diff --git a/TODO.md b/TODO.md index 781ff9c..2df6e84 100644 --- a/TODO.md +++ b/TODO.md @@ -13,6 +13,7 @@ - [x] Synchronized arrows - [x] Slanted arrows - [x] Different types of arrow tips +- [x] Sequence comment alignment - [ ] Fix column spacing with notes over multiple columns - [ ] Fix notes with arrows from start / to end / small arrows - [ ] Fix group size with self arrows + notes diff --git a/gallery/example1.pdf b/gallery/example1.pdf index 1b07978..df9f41a 100644 Binary files a/gallery/example1.pdf and b/gallery/example1.pdf differ diff --git a/gallery/example2.pdf b/gallery/example2.pdf index 00341c9..d1d5ae5 100644 Binary files a/gallery/example2.pdf and b/gallery/example2.pdf differ diff --git a/gallery/example2.typ b/gallery/example2.typ index 4993132..c078461 100644 --- a/gallery/example2.typ +++ b/gallery/example2.typ @@ -107,4 +107,63 @@ _gap() _evt("bob", "disable") -}) \ No newline at end of file +}) + +#grid(columns: 2, column-gutter: 2em, + chronos.diagram({ + import chronos: * + + _par("alice", display-name: "Alice") + _par("bob", display-name: "Bob") + _seq("alice", "bob", comment: "This is a very long comment") + + // Left to right + _seq("alice", "bob", comment: "Start aligned", comment-align: "start") + _seq("alice", "bob", comment: "End aligned", comment-align: "end") + _seq("alice", "bob", comment: "Left aligned", comment-align: "left") + _seq("alice", "bob", comment: "Right aligned", comment-align: "right") + _seq("alice", "bob", comment: "Centered", comment-align: "center") + _gap() + + // Right to left + _seq("bob", "alice", comment: "Start aligned", comment-align: "start") + _seq("bob", "alice", comment: "End aligned", comment-align: "end") + _seq("bob", "alice", comment: "Left aligned", comment-align: "left") + _seq("bob", "alice", comment: "Right aligned", comment-align: "right") + _seq("bob", "alice", comment: "Centered", comment-align: "center") + _gap() + + // Slant left to right + _seq("alice", "bob", comment: "Start aligned", comment-align: "start", slant: 10) + _seq("alice", "bob", comment: "End aligned", comment-align: "end", slant: 10) + _seq("alice", "bob", comment: "Left aligned", comment-align: "left", slant: 10) + _seq("alice", "bob", comment: "Right aligned", comment-align: "right", slant: 10) + _seq("alice", "bob", comment: "Centered", comment-align: "center", slant: 10) + _gap() + + // Slant right to left + _seq("bob", "alice", comment: "Start aligned", comment-align: "start", slant: 10) + _seq("bob", "alice", comment: "End aligned", comment-align: "end", slant: 10) + _seq("bob", "alice", comment: "Left aligned", comment-align: "left", slant: 10) + _seq("bob", "alice", comment: "Right aligned", comment-align: "right", slant: 10) + _seq("bob", "alice", comment: "Centered", comment-align: "center", slant: 10) + }), + + chronos.diagram({ + import chronos: * + + _par("alice", display-name: "Alice") + + _seq("alice", "alice", comment: "Start aligned", comment-align: "start") + _seq("alice", "alice", comment: "End aligned", comment-align: "end") + _seq("alice", "alice", comment: "Left aligned", comment-align: "left") + _seq("alice", "alice", comment: "Right aligned", comment-align: "right") + _seq("alice", "alice", comment: "Centered", comment-align: "center") + + _seq("alice", "alice", comment: "Start aligned", comment-align: "start", flip: true) + _seq("alice", "alice", comment: "End aligned", comment-align: "end", flip: true) + _seq("alice", "alice", comment: "Left aligned", comment-align: "left", flip: true) + _seq("alice", "alice", comment: "Right aligned", comment-align: "right", flip: true) + _seq("alice", "alice", comment: "Centered", comment-align: "center", flip: true) + }) +) \ No newline at end of file diff --git a/gallery/example3.pdf b/gallery/example3.pdf index b20dd93..60c3e2b 100644 Binary files a/gallery/example3.pdf and b/gallery/example3.pdf differ diff --git a/gallery/notes.pdf b/gallery/notes.pdf index 9a0d034..f90fe88 100644 Binary files a/gallery/notes.pdf and b/gallery/notes.pdf differ diff --git a/src/note.typ b/src/note.typ index 4c12eb3..454d20b 100644 --- a/src/note.typ +++ b/src/note.typ @@ -109,7 +109,7 @@ } } else if note.side == "right" { x0 += NOTE-GAP - x0 -= lifelines.at(i).level * LIFELINE-W / 2 + x0 += lifelines.at(i).level * LIFELINE-W / 2 } else if note.side == "over" or note.side == "across" { x0 -= total-w / 2 } diff --git a/src/sequence.typ b/src/sequence.typ index 0485d49..4d2f735 100644 --- a/src/sequence.typ +++ b/src/sequence.typ @@ -1,4 +1,4 @@ -#import "@preview/cetz:0.2.2": draw +#import "@preview/cetz:0.2.2": draw, vector #import "consts.typ": * #import "participant.typ" #import "note.typ" @@ -48,6 +48,7 @@ p1, p2, comment: none, + comment-align: "left", dashed: false, start-tip: "", end-tip: ">", @@ -67,6 +68,7 @@ p1: p1, p2: p2, comment: comment, + comment-align: comment-align, dashed: dashed, start-tip: start-tip, end-tip: end-tip, @@ -208,6 +210,10 @@ } let pts + let comment-pt + let comment-anchor + let comment-angle = 0deg + if elmt.p1 == elmt.p2 { if elmt.flip { x1 = start-info.lx @@ -221,15 +227,6 @@ calc.max(x1, x2) + 20 } - if elmt.comment != none { - shapes += draw.content( - (x1, start-info.y), - elmt.comment, - anchor: if elmt.flip {"south-east"} else {"south-west"}, - padding: 3pt - ) - } - pts = ( (x1, start-info.y), (x-mid, start-info.y), @@ -237,24 +234,62 @@ (x2, end-info.y) ) - } else { if elmt.comment != none { - let x = calc.min(x1, x2) - if x2 < x1 { - x += COMMENT-PAD - } - shapes += draw.content( - (x, start-info.y), - elmt.comment, - anchor: "south-west", - padding: 3pt - ) + comment-anchor = ( + start: if x-mid < x1 {"south-east"} else {"south-west"}, + end: if x-mid < x1 {"south-west"} else {"south-east"}, + left: "south-west", + right: "south-east", + center: "south", + ).at(elmt.comment-align) + + comment-pt = ( + start: pts.first(), + end: pts.at(1), + left: if x-mid < x1 {pts.at(1)} else {pts.first()}, + right: if x-mid < x1 {pts.first()} else {pts.at(1)}, + center: (pts.first(), 50%, pts.at(1)) + ).at(elmt.comment-align) } + } else { pts = ( (x1, start-info.y), (x2, end-info.y) ) + + if elmt.comment != none { + let start-pt = pts.first() + let end-pt = pts.last() + if elmt.start-tip != "" { + start-pt = (pts.first(), COMMENT-PAD, pts.last()) + } + if elmt.end-tip != "" { + end-pt = (pts.last(), COMMENT-PAD, pts.first()) + } + + comment-pt = ( + start: start-pt, + end: end-pt, + left: if x2 < x1 {end-pt} else {start-pt}, + right: if x2 < x1 {start-pt} else {end-pt}, + center: (start-pt, 50%, end-pt) + ).at(elmt.comment-align) + + comment-anchor = ( + start: if x2 < x1 {"south-east"} else {"south-west"}, + end: if x2 < x1 {"south-west"} else {"south-east"}, + left: "south-west", + right: "south-east", + center: "south", + ).at(elmt.comment-align) + } + + let (p1, p2) = pts + if x2 < x1 { + (p1, p2) = (p2, p1) + } + comment-angle = vector.angle2(p1, p2) } // Start circle tip @@ -303,6 +338,16 @@ shapes += draw.line(..pts, ..style) + if elmt.comment != none { + shapes += draw.content( + comment-pt, + elmt.comment, + anchor: comment-anchor, + angle: comment-angle, + padding: 3pt + ) + } + if elmt.enable-dst { let dst-line = lifelines.at(i2) dst-line.lines.push(("enable", end-info.y, elmt.lifeline-style))