Compare commits

..

4 Commits

Author SHA1 Message Date
81871e2aca
updated examples 2024-06-21 02:56:49 +02:00
6500e5a4a3
added arrow tips (WIP) 2024-06-21 02:25:30 +02:00
6e7dc9913f
fixed some spacing issues 2024-06-21 02:24:35 +02:00
9c83f810bb
added events 2024-06-21 02:23:13 +02:00
12 changed files with 202 additions and 10 deletions

Binary file not shown.

Binary file not shown.

BIN
gallery/example3.pdf Normal file

Binary file not shown.

108
gallery/example3.typ Normal file
View File

@ -0,0 +1,108 @@
#import "/src/lib.typ" as chronos
#set page(width: auto, height: auto)
#let TYPST = image("typst.png", width: 1.5cm, height: 1.5cm, fit: "contain")
#let FERRIS = image("ferris.png", width: 1.5cm, height: 1.5cm, fit: "contain")
#let ME = image("me.jpg", width: 1.5cm, height: 1.5cm, fit: "contain")
#chronos.diagram({
import chronos: *
_par("Foo", display-name: "Participant", shape: "participant")
_par("Foo1", display-name: "Actor", shape: "actor")
_par("Foo2", display-name: "Boundary", shape: "boundary")
_par("Foo3", display-name: "Control", shape: "control")
_par("Foo4", display-name: "Entity", shape: "entity")
_par("Foo5", display-name: "Database", shape: "database")
_par("Foo6", display-name: "Collections", shape: "collections")
_par("Foo7", display-name: "Queue", shape: "queue")
_par("Foo8", display-name: "Typst", shape: "custom", custom-image: TYPST)
_par("Foo9", display-name: "Ferris", shape: "custom", custom-image: FERRIS)
_par("Foo10", display-name: "Baryhobal", shape: "custom", custom-image: ME)
_seq("Foo", "Foo1", comment: "To actor")
_seq("Foo", "Foo2", comment: "To boundary")
_seq("Foo", "Foo3", comment: "To control")
_seq("Foo", "Foo4", comment: "To entity")
_seq("Foo", "Foo5", comment: "To database")
_seq("Foo", "Foo6", comment: "To collections")
_seq("Foo", "Foo7", comment: "To queue")
_seq("Foo", "Foo8", comment: "To Typst")
_seq("Foo", "Foo9", comment: "To ferris")
_seq("Foo", "Foo10", comment: "To Baryhobal")
})
#pagebreak()
#chronos.diagram({
import chronos: *
_par("me", display-name: "Me", shape: "custom", custom-image: ME)
_par("typst", display-name: "Typst", shape: "custom", custom-image: TYPST)
_par("rust", display-name: "Rust", shape: "custom", custom-image: FERRIS)
_seq("me", "typst", comment: "opens document", enable-dst: true)
_seq("me", "typst", comment: "types document")
_seq("typst", "rust", comment: "compiles content", enable-dst: true)
_seq("rust", "typst", comment: "renders document", disable-src: true)
_seq("typst", "me", comment: "displays document")
_evt("typst", "disable")
})
#pagebreak()
#stack(dir: ltr, spacing: 1em,
chronos.diagram({
import chronos: *
_par("a", display-name: "Alice")
_par("b", display-name: "Bob")
_seq("a", "b", end-tip: ">", comment: `->`)
_seq("a", "b", end-tip: ">>", comment: `->>`)
_seq("a", "b", end-tip: "\\", comment: `-\`)
_seq("a", "b", end-tip: "\\\\", comment: `-\\`)
_seq("a", "b", end-tip: "/", comment: `-/`)
_seq("a", "b", end-tip: "//", comment: `-//`)
_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", 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", end-tip: ("o", ">>"), comment: `->>o`)
_seq("a", "b", end-tip: ("o", "\\"), comment: `-\o`)
_seq("a", "b", end-tip: ("o", "\\\\"), comment: `-\\o`)
_seq("a", "b", end-tip: ("o", "/"), comment: `-/o`)
_seq("a", "b", end-tip: ("o", "//"), comment: `-//o`)
_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("a", "a", end-tip: ">", comment: `->`)
_seq("a", "a", end-tip: ">>", comment: `->>`)
_seq("a", "a", end-tip: "\\", comment: `-\`)
_seq("a", "a", end-tip: "\\\\", comment: `-\\`)
_seq("a", "a", end-tip: "/", comment: `-/`)
_seq("a", "a", end-tip: "//", comment: `-//`)
_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", 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", end-tip: ("o", ">>"), comment: `->>o`)
_seq("a", "a", end-tip: ("o", "\\"), comment: `-\o`)
_seq("a", "a", end-tip: ("o", "\\\\"), comment: `-\\o`)
_seq("a", "a", end-tip: ("o", "/"), comment: `-/o`)
_seq("a", "a", end-tip: ("o", "//"), comment: `-//o`)
_seq("a", "a", start-tip: "x", end-tip: ("o", ">"), comment: `x->o`)
})
)

BIN
gallery/ferris.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
gallery/me.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

BIN
gallery/typst.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -9,6 +9,15 @@
),) ),)
} }
#let _evt(participant, event) = {
return ((
type: "evt",
participant: participant,
event: event,
lifeline-style: auto
),)
}
#let diagram(elements) = { #let diagram(elements) = {
if elements == none { if elements == none {
return return

View File

@ -1,4 +1,4 @@
#import "diagram.typ": diagram, from-plantuml, _gap #import "diagram.typ": diagram, from-plantuml, _gap, _evt
#import "sequence.typ": _seq #import "sequence.typ": _seq
#import "group.typ": _grp #import "group.typ": _grp

View File

@ -49,6 +49,18 @@
p.max-lifelines = calc.max(p.max-lifelines, p.lifeline-lvl) p.max-lifelines = calc.max(p.max-lifelines, p.lifeline-lvl)
participants.at(i2) = p participants.at(i2) = p
} }
} else if elmt.type == "evt" {
let par-name = elmt.participant
let i = pars-i.at(par-name)
let par = participants.at(i)
if elmt.event == "disable" or elmt.event == "destroy" {
par.lifeline-lvl -= 1
} else if elmt.event == "enable" {
par.lifeline-lvl += 1
par.max-lifelines = calc.max(par.max-lifelines, par.lifeline-lvl)
}
participants.at(i) = par
} }
} }
@ -74,6 +86,21 @@
) )
} }
// Compute minimum width for self sequences
for cell in cells.filter(c => c.i1 == c.i2) {
let m = measure(cell.cell)
let i = cell.i1
if cell.elmt.flip {
i -= 1
}
if 0 <= i and i < widths.len() {
widths.at(i) = calc.max(
widths.at(i),
m.width / 1pt + COMMENT-PAD
)
}
}
// Compute remaining widths for longer sequences (spanning multiple columns) // Compute remaining widths for longer sequences (spanning multiple columns)
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 => {
@ -124,7 +151,7 @@
} }
} }
let y = -Y-SPACE let y = 0
let groups = () let groups = ()
let lifelines = participants.map(_ => ( let lifelines = participants.map(_ => (
level: 0, level: 0,
@ -141,6 +168,7 @@
// Groups (start) -> reserve space for labels + store position // Groups (start) -> reserve space for labels + store position
} else if elmt.type == "grp" { } else if elmt.type == "grp" {
y -= Y-SPACE
let m = measure( let m = measure(
box( box(
elmt.name, elmt.name,
@ -153,17 +181,16 @@
g g
}) })
groups.push((y, elmt, 0, 0)) groups.push((y, elmt, 0, 0))
y -= m.height / 1pt + Y-SPACE y -= m.height / 1pt
// Groups (end) -> actual drawing // Groups (end) -> actual drawing
} else if elmt.type == "grp-end" { } else if elmt.type == "grp-end" {
y -= Y-SPACE
let (start-y, group, start-lvl, end-lvl) = groups.pop() let (start-y, group, start-lvl, end-lvl) = groups.pop()
let x0 = x-pos.at(group.min-i) - start-lvl * 10 - 20 let x0 = x-pos.at(group.min-i) - start-lvl * 10 - 20
let x1 = x-pos.at(group.max-i) + end-lvl * 10 + 20 let x1 = x-pos.at(group.max-i) + end-lvl * 10 + 20
shapes += draw-group(x0, x1, start-y, y, group) shapes += draw-group(x0, x1, start-y, y, group)
y -= Y-SPACE
// Separator // Separator
} else if elmt.type == "sep" { } else if elmt.type == "sep" {
let shps let shps
@ -173,9 +200,34 @@
// Gap // Gap
} else if elmt.type == "gap" { } else if elmt.type == "gap" {
y -= elmt.size y -= elmt.size
// Event
} else if elmt.type == "evt" {
let par-name = elmt.participant
let i = pars-i.at(par-name)
let par = participants.at(i)
let line = lifelines.at(i)
if elmt.event == "disable" {
line.level -= 1
line.lines.push(("disable", y))
} else if elmt.event == "destroy" {
line.lines.push(("destroy", y))
} else if elmt.event == "enable" {
line.level += 1
line.lines.push(("enable", y, elmt.lifeline-style))
} else if elmt.event == "create" {
shapes += participant.render(x-pos, par, y: y)
line.lines.push(("create", y))
}
lifelines.at(i) = line
} }
} }
y -= Y-SPACE
// Draw vertical lines + lifelines + end participants // Draw vertical lines + lifelines + end participants
shapes += draw.on-layer(-1, { shapes += draw.on-layer(-1, {
if DEBUG-INVISIBLE { if DEBUG-INVISIBLE {

View File

@ -10,6 +10,7 @@
#let render(x-pos, elmt, y) = { #let render(x-pos, elmt, y) = {
let shapes = () let shapes = ()
y -= Y-SPACE
let x0 = x-pos.first() - 20 let x0 = x-pos.first() - 20
let x1 = x-pos.last() + 20 let x1 = x-pos.last() + 20
@ -48,7 +49,6 @@
fill: COL-SEP-NAME fill: COL-SEP-NAME
) )
y -= h / 2 y -= h / 2
y -= Y-SPACE
let r = (y, shapes) let r = (y, shapes)
return r return r

View File

@ -2,12 +2,30 @@
#import "consts.typ": * #import "consts.typ": *
#import "participant.typ" #import "participant.typ"
#let get-arrow-marks(sym, color) = {
if type(sym) == array {
return sym.map(s => get-arrow-marks(s, color))
}
(
"": none,
">": (symbol: ">", fill: color),
">>": (symbol: "straight"),
"\\": (symbol: ">", fill: color, harpoon: true, flip: true),
"\\\\": (symbol: "straight", harpoon: true, flip: true),
"/": (symbol: ">", fill: color, harpoon: true),
"//": (symbol: "straight", harpoon: true),
"x": none,
"o": (symbol: "o"),
).at(sym)
}
#let _seq( #let _seq(
p1, p1,
p2, p2,
comment: none, comment: none,
dashed: false, dashed: false,
tip: "default", start-tip: "",
end-tip: ">",
color: black, color: black,
flip: false, flip: false,
enable-dst: false, enable-dst: false,
@ -24,7 +42,8 @@
p2: p2, p2: p2,
comment: comment, comment: comment,
dashed: dashed, dashed: dashed,
tip: tip, start-tip: start-tip,
end-tip: end-tip,
color: color, color: color,
flip: flip, flip: flip,
enable-dst: enable-dst, enable-dst: enable-dst,
@ -40,6 +59,8 @@
#let render(pars-i, x-pos, participants, elmt, y, lifelines) = { #let render(pars-i, x-pos, participants, elmt, y, lifelines) = {
let shapes = () let shapes = ()
y -= Y-SPACE
// Reserve space for comment // Reserve space for comment
if elmt.comment != none { if elmt.comment != none {
y -= measure(box(elmt.comment)).height / 1pt + 6 y -= measure(box(elmt.comment)).height / 1pt + 6
@ -117,7 +138,10 @@
} }
let style = ( let style = (
mark: (end: ">", fill: elmt.color), mark: (
start: get-arrow-marks(elmt.start-tip, elmt.color),
end: get-arrow-marks(elmt.end-tip, elmt.color)
),
stroke: ( stroke: (
dash: if elmt.dashed {"dashed"} else {"solid"}, dash: if elmt.dashed {"dashed"} else {"solid"},
paint: elmt.color paint: elmt.color
@ -185,7 +209,6 @@
dst-line.lines.push(("create", y)) dst-line.lines.push(("create", y))
lifelines.at(i2) = dst-line lifelines.at(i2) = dst-line
} }
y -= Y-SPACE
let r = (y, lifelines, shapes) let r = (y, lifelines, shapes)
return r return r