diff --git a/TODO.md b/TODO.md index 53c8180..781ff9c 100644 --- a/TODO.md +++ b/TODO.md @@ -12,7 +12,7 @@ - [x] Notes - [x] Synchronized arrows - [x] Slanted arrows -- [ ] Different types of arrow tips (WIP) +- [x] Different types of arrow tips - [ ] 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/example3.pdf b/gallery/example3.pdf index 1bb20e6..b20dd93 100644 Binary files a/gallery/example3.pdf and b/gallery/example3.pdf differ diff --git a/gallery/example3.typ b/gallery/example3.typ index 65014ff..3cdce3a 100644 --- a/gallery/example3.typ +++ b/gallery/example3.typ @@ -65,11 +65,11 @@ chronos.diagram({ _seq("a", "b", end-tip: "x", comment: `->x`) _seq("a", "b", start-tip: "x", comment: `x->`) _seq("a", "b", start-tip: "o", comment: `o->`) - _seq("a", "b", end-tip: "o", comment: `->o`) - _seq("a", "b", start-tip: "o", end-tip: "o", comment: `o->o`) + _seq("a", "b", end-tip: ("o", ">"), comment: `->o`) + _seq("a", "b", start-tip: "o", end-tip: ("o", ">"), comment: `o->o`) _seq("a", "b", start-tip: ">", end-tip: ">", comment: `<->`) _seq("a", "b", start-tip: ("o", ">"), end-tip: ("o", ">"), comment: `o<->o`) - _seq("a", "b", start-tip: ("x", ">"), end-tip: ("x", ">"), comment: `x<->x`) + _seq("a", "b", start-tip: "x", end-tip: "x", comment: `x<->x`) _seq("a", "b", end-tip: ("o", ">>"), comment: `->>o`) _seq("a", "b", end-tip: ("o", "\\"), comment: `-\o`) _seq("a", "b", end-tip: ("o", "\\\\"), comment: `-\\o`) @@ -78,6 +78,34 @@ chronos.diagram({ _seq("a", "b", start-tip: "x", end-tip: ("o", ">"), comment: `x->o`) }), +chronos.diagram({ + import chronos: * + + _par("a", display-name: "Alice") + _par("b", display-name: "Bob") + + _seq("b", "a", end-tip: ">", comment: `->`) + _seq("b", "a", end-tip: ">>", comment: `->>`) + _seq("b", "a", end-tip: "\\", comment: `-\`) + _seq("b", "a", end-tip: "\\\\", comment: `-\\`) + _seq("b", "a", end-tip: "/", comment: `-/`) + _seq("b", "a", end-tip: "//", comment: `-//`) + _seq("b", "a", end-tip: "x", comment: `->x`) + _seq("b", "a", start-tip: "x", comment: `x->`) + _seq("b", "a", start-tip: "o", comment: `o->`) + _seq("b", "a", end-tip: ("o", ">"), comment: `->o`) + _seq("b", "a", start-tip: "o", end-tip: ("o", ">"), comment: `o->o`) + _seq("b", "a", start-tip: ">", end-tip: ">", comment: `<->`) + _seq("b", "a", start-tip: ("o", ">"), end-tip: ("o", ">"), comment: `o<->o`) + _seq("b", "a", start-tip: "x", end-tip: "x", comment: `x<->x`) + _seq("b", "a", end-tip: ("o", ">>"), comment: `->>o`) + _seq("b", "a", end-tip: ("o", "\\"), comment: `-\o`) + _seq("b", "a", end-tip: ("o", "\\\\"), comment: `-\\o`) + _seq("b", "a", end-tip: ("o", "/"), comment: `-/o`) + _seq("b", "a", end-tip: ("o", "//"), comment: `-//o`) + _seq("b", "a", start-tip: "x", end-tip: ("o", ">"), comment: `x->o`) +}), + chronos.diagram({ import chronos: * @@ -93,11 +121,11 @@ chronos.diagram({ _seq("a", "a", end-tip: "x", comment: `->x`) _seq("a", "a", start-tip: "x", comment: `x->`) _seq("a", "a", start-tip: "o", comment: `o->`) - _seq("a", "a", end-tip: "o", comment: `->o`) - _seq("a", "a", start-tip: "o", end-tip: "o", comment: `o->o`) + _seq("a", "a", end-tip: ("o", ">"), comment: `->o`) + _seq("a", "a", start-tip: "o", end-tip: ("o", ">"), comment: `o->o`) _seq("a", "a", start-tip: ">", end-tip: ">", comment: `<->`) _seq("a", "a", start-tip: ("o", ">"), end-tip: ("o", ">"), comment: `o<->o`) - _seq("a", "a", start-tip: ("x", ">"), end-tip: ("x", ">"), comment: `x<->x`) + _seq("a", "a", start-tip: "x", end-tip: "x", comment: `x<->x`) _seq("a", "a", end-tip: ("o", ">>"), comment: `->>o`) _seq("a", "a", end-tip: ("o", "\\"), comment: `-\o`) _seq("a", "a", end-tip: ("o", "\\\\"), comment: `-\\o`) diff --git a/src/consts.typ b/src/consts.typ index 4857aa7..ba99801 100644 --- a/src/consts.typ +++ b/src/consts.typ @@ -4,6 +4,8 @@ #let LIFELINE-W = 10 #let CREATE-OFFSET = 15 #let DEFAULT-SLANT = 10 +#let CROSS-TIP-SIZE = 4 +#let CIRCLE-TIP-RADIUS = 3 #let SYM-GAP = 5 #let PAR-PAD = (5pt, 3pt) diff --git a/src/sequence.typ b/src/sequence.typ index 4866e41..0485d49 100644 --- a/src/sequence.typ +++ b/src/sequence.typ @@ -16,10 +16,34 @@ "/": (symbol: ">", fill: color, harpoon: true), "//": (symbol: "straight", harpoon: true), "x": none, - "o": (symbol: "o"), + "o": none, ).at(sym) } +#let reverse-arrow-mark(mark) = { + if type(mark) == array { + return mark.map(m => reverse-arrow-mark(m)) + } + let mark2 = mark + if type(mark) == dictionary and mark.at("harpoon", default: false) { + let flipped = mark.at("flip", default: false) + mark2.insert("flip", not flipped) + } + return mark2 +} + +#let is-tip-of-type(type_, tip) = { + if type(tip) == str and tip == type_ { + return true + } + if type(tip) == array and tip.contains(type_) { + return true + } + return false +} +#let is-circle-tip = is-tip-of-type.with("o") +#let is-cross-tip = is-tip-of-type.with("x") + #let _seq( p1, p2, @@ -175,6 +199,15 @@ shapes += shps } + let flip-mark = end-info.i <= start-info.i + if elmt.flip { + flip-mark = not flip-mark + } + if flip-mark { + style.mark.end = reverse-arrow-mark(style.mark.end) + } + + let pts if elmt.p1 == elmt.p2 { if elmt.flip { x1 = start-info.lx @@ -197,12 +230,11 @@ ) } - shapes += draw.line( + pts = ( (x1, start-info.y), (x-mid, start-info.y), (x-mid, end-info.y), - (x2, end-info.y), - ..style + (x2, end-info.y) ) } else { @@ -219,12 +251,58 @@ ) } - shapes += draw.line( + pts = ( (x1, start-info.y), - (x2, end-info.y), - ..style + (x2, end-info.y) ) } + + // Start circle tip + if is-circle-tip(elmt.start-tip) { + shapes += draw.circle(pts.first(), radius: CIRCLE-TIP-RADIUS, stroke: elmt.color, fill: none, name: "_circle-start-tip") + pts.at(0) = "_circle-start-tip" + + // Start cross tip + } else if is-cross-tip(elmt.start-tip) { + let size = CROSS-TIP-SIZE + let cross-pt = (pts.first(), size * 2, pts.at(1)) + shapes += draw.line( + (rel: (-size, -size), to: cross-pt), + (rel: (size, size), to: cross-pt), + stroke: elmt.color + 1.5pt + ) + shapes += draw.line( + (rel: (-size, size), to: cross-pt), + (rel: (size, -size), to: cross-pt), + stroke: elmt.color + 1.5pt + ) + pts.at(0) = cross-pt + } + + // End circle tip + if is-circle-tip(elmt.end-tip) { + shapes += draw.circle(pts.last(), radius: 3, stroke: elmt.color, fill: none, name: "_circle-end-tip") + pts.at(pts.len() - 1) = "_circle-end-tip" + + // End cross tip + } else if is-cross-tip(elmt.end-tip) { + let size = CROSS-TIP-SIZE + let cross-pt = (pts.last(), size * 2, pts.at(pts.len() - 2)) + shapes += draw.line( + (rel: (-size, -size), to: cross-pt), + (rel: (size, size), to: cross-pt), + stroke: elmt.color + 1.5pt + ) + shapes += draw.line( + (rel: (-size, size), to: cross-pt), + (rel: (size, -size), to: cross-pt), + stroke: elmt.color + 1.5pt + ) + pts.at(pts.len() - 1) = cross-pt + } + + shapes += draw.line(..pts, ..style) + if elmt.enable-dst { let dst-line = lifelines.at(i2) dst-line.lines.push(("enable", end-info.y, elmt.lifeline-style))