Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sequence diagrams: Render more compacted #796

Merged
merged 3 commits into from
Feb 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/release/changelogs/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- Ensures labels fit inside shapes with shape-specific inner bounding boxes. [#702](https://github.com/terrastruct/d2/pull/702)
- dagre container labels changed positions to outside the shape. Many previously obscured container labels are now legible. [#788](https://github.com/terrastruct/d2/pull/788)
- Improves package shape dimensions with short height. [#702](https://github.com/terrastruct/d2/pull/702)
- Sequence diagrams are rendered more compacted, both vertically and horizontally. [#796](https://github.com/terrastruct/d2/pull/796)
- Keeps person shape from becoming too distorted. [#702](https://github.com/terrastruct/d2/pull/702)
- Ensures shapes with icons have enough padding for their labels. [#702](https://github.com/terrastruct/d2/pull/702)
- `--force-appendix` flag adds an appendix to SVG outputs with tooltips or links. [#761](https://github.com/terrastruct/d2/pull/761)
Expand All @@ -37,5 +38,6 @@
- Fixes groups overlapping in sequence diagrams when they end in a self loop. [#728](https://github.com/terrastruct/d2/pull/728)
- Fixes dimensions of unlabeled squares or circles with only a set width or height. [#702](https://github.com/terrastruct/d2/pull/702)
- Fixes scaling of actor shapes in sequence diagrams. [#702](https://github.com/terrastruct/d2/pull/702)
- Sequence diagram note ordering was sometimes wrong. [#796](https://github.com/terrastruct/d2/pull/796)
- Images can now be set to sizes smaller than 128x128. [#702](https://github.com/terrastruct/d2/pull/702)
- Fixes class height when there are no rows. [#756](https://github.com/terrastruct/d2/pull/756)
25 changes: 14 additions & 11 deletions d2layouts/d2sequence/constants.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package d2sequence

// leaves at least 25 units of space on the left/right when computing the space required between actors
const HORIZONTAL_PAD = 50.
// units of space on the left/right when computing the space required between actors
const HORIZONTAL_PAD = 40.

// leaves at least 25 units of space on the top/bottom when computing the space required between messages
const VERTICAL_PAD = 50.
// units of space on the top/bottom when computing the space required between messages
// TODO lower
const VERTICAL_PAD = 40.

const MIN_ACTOR_DISTANCE = 250.
const MIN_ACTOR_DISTANCE = 150.

const MIN_ACTOR_WIDTH = 150.
const MIN_ACTOR_WIDTH = 100.

const SELF_MESSAGE_HORIZONTAL_TRAVEL = 100.
const SELF_MESSAGE_HORIZONTAL_TRAVEL = 80.

const GROUP_CONTAINER_PADDING = 24.
const GROUP_CONTAINER_PADDING = 12.

const EDGE_GROUP_LABEL_PADDING = 20.

// min vertical distance between messages
const MIN_MESSAGE_DISTANCE = 80.
const MIN_MESSAGE_DISTANCE = 30.

// default size
const SPAN_BASE_WIDTH = 12.
Expand All @@ -24,9 +27,9 @@ const SPAN_BASE_WIDTH = 12.
const SPAN_DEPTH_GROWTH_FACTOR = 8.

// when a span has a single messages
const MIN_SPAN_HEIGHT = 80.
const MIN_SPAN_HEIGHT = 30.

const SPAN_MESSAGE_PAD = 16.
const SPAN_MESSAGE_PAD = 10.

const LIFELINE_STROKE_WIDTH int = 2

Expand Down
4 changes: 2 additions & 2 deletions d2layouts/d2sequence/layout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ func TestSelfEdges(t *testing.T) {
t.Fatalf("route does not end at the same actor, start at %.5f, end at %.5f", route[0].X, route[3].X)
}

if route[3].Y-route[0].Y != d2sequence.MIN_MESSAGE_DISTANCE {
t.Fatalf("expected route height to be %.f5, got %.5f", d2sequence.MIN_MESSAGE_DISTANCE, route[3].Y-route[0].Y)
if route[3].Y-route[0].Y != d2sequence.MIN_MESSAGE_DISTANCE*1.5 {
t.Fatalf("expected route height to be %.5f, got %.5f", d2sequence.MIN_MESSAGE_DISTANCE*1.5, route[3].Y-route[0].Y)
}
}

Expand Down
65 changes: 60 additions & 5 deletions d2layouts/d2sequence/sequence_diagram.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ func newSequenceDiagram(objects []*d2graph.Object, messages []*d2graph.Edge) *se

for _, message := range sd.messages {
sd.verticalIndices[message.AbsID()] = getEdgeEarliestLineNum(message)
// TODO this should not be global yStep, only affect the neighbors
sd.yStep = math.Max(sd.yStep, float64(message.LabelDimensions.Height))

// ensures that long labels, spanning over multiple actors, don't make for large gaps between actors
Expand All @@ -176,7 +177,6 @@ func newSequenceDiagram(objects []*d2graph.Object, messages []*d2graph.Edge) *se
if _, exists := sd.firstMessage[message.Dst]; !exists {
sd.firstMessage[message.Dst] = message
}

}

sd.yStep += VERTICAL_PAD
Expand Down Expand Up @@ -209,6 +209,9 @@ func (sd *sequenceDiagram) placeGroups() {
group.ZIndex = GROUP_Z_INDEX
sd.placeGroup(group)
}
for _, group := range sd.groups {
sd.adjustGroupLabel(group)
}
}

func (sd *sequenceDiagram) placeGroup(group *d2graph.Object) {
Expand Down Expand Up @@ -273,6 +276,56 @@ func (sd *sequenceDiagram) placeGroup(group *d2graph.Object) {
)
}

func (sd *sequenceDiagram) adjustGroupLabel(group *d2graph.Object) {
if group.LabelHeight == nil {
return
}

heightAdd := (*group.LabelHeight + EDGE_GROUP_LABEL_PADDING) - GROUP_CONTAINER_PADDING
if heightAdd < 0 {
return
}

group.Height += float64(heightAdd)

// Extend stuff within this group
for _, g := range sd.groups {
if g.TopLeft.Y < group.TopLeft.Y && g.TopLeft.Y+g.Height > group.TopLeft.Y {
g.Height += float64(heightAdd)
}
}
for _, s := range sd.spans {
if s.TopLeft.Y < group.TopLeft.Y && s.TopLeft.Y+s.Height > group.TopLeft.Y {
s.Height += float64(heightAdd)
}
}

// Move stuff down
for _, m := range sd.messages {
if go2.Min(m.Route[0].Y, m.Route[len(m.Route)-1].Y) > group.TopLeft.Y {
for _, p := range m.Route {
p.Y += float64(heightAdd)
}
}
}
for _, s := range sd.spans {
if s.TopLeft.Y > group.TopLeft.Y {
s.TopLeft.Y += float64(heightAdd)
}
}
for _, g := range sd.groups {
if g.TopLeft.Y > group.TopLeft.Y {
g.TopLeft.Y += float64(heightAdd)
}
}
for _, n := range sd.notes {
if n.TopLeft.Y > group.TopLeft.Y {
n.TopLeft.Y += float64(heightAdd)
}
}

}

// placeActors places actors bottom aligned, side by side with centers spaced by sd.actorXStep
func (sd *sequenceDiagram) placeActors() {
centerX := sd.actors[0].Width / 2.
Expand Down Expand Up @@ -354,7 +407,7 @@ func (sd *sequenceDiagram) placeNotes() {
rankToX[sd.objectRank[actor]] = actor.Center().X
}

for i, note := range sd.notes {
for _, note := range sd.notes {
verticalIndex := sd.verticalIndices[note.AbsID()]
y := sd.maxActorHeight + sd.yStep

Expand All @@ -363,8 +416,10 @@ func (sd *sequenceDiagram) placeNotes() {
y += sd.yStep
}
}
for _, otherNote := range sd.notes[:i] {
y += otherNote.Height + sd.yStep
for _, otherNote := range sd.notes {
if sd.verticalIndices[otherNote.AbsID()] < verticalIndex {
y += otherNote.Height + sd.yStep
}
}

x := rankToX[sd.objectRank[note]] - (note.Width / 2.)
Expand Down Expand Up @@ -499,7 +554,7 @@ func (sd *sequenceDiagram) routeMessages() error {

if isSelfMessage || isToDescendant || isFromDescendant || isToSibling {
midX := startX + SELF_MESSAGE_HORIZONTAL_TRAVEL
endY := startY + MIN_MESSAGE_DISTANCE
endY := startY + MIN_MESSAGE_DISTANCE*1.5
message.Route = []*geo.Point{
geo.NewPoint(startX, startY),
geo.NewPoint(midX, startY),
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading