diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index 606ab8302..10b61586b 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -14,43 +14,43 @@ import ( func Layout(ctx context.Context, g *d2graph.Graph) (err error) { pad := 50. // 2 * 25 edgeYStep := 100. - objectXStep := 200. - maxObjectHeight := 0. + actorXStep := 200. + maxActorHeight := 0. - var objectsInOrder []*d2graph.Object + var actorsInOrder []*d2graph.Object seen := make(map[*d2graph.Object]struct{}) for _, edge := range g.Edges { if _, exists := seen[edge.Src]; !exists { seen[edge.Src] = struct{}{} - objectsInOrder = append(objectsInOrder, edge.Src) + actorsInOrder = append(actorsInOrder, edge.Src) } if _, exists := seen[edge.Dst]; !exists { seen[edge.Dst] = struct{}{} - objectsInOrder = append(objectsInOrder, edge.Dst) + actorsInOrder = append(actorsInOrder, edge.Dst) } edgeYStep = math.Max(edgeYStep, float64(edge.LabelDimensions.Height)+pad) - objectXStep = math.Max(objectXStep, float64(edge.LabelDimensions.Width)+pad) - maxObjectHeight = math.Max(maxObjectHeight, edge.Src.Height+pad) - maxObjectHeight = math.Max(maxObjectHeight, edge.Dst.Height+pad) + actorXStep = math.Max(actorXStep, float64(edge.LabelDimensions.Width)+pad) + maxActorHeight = math.Max(maxActorHeight, edge.Src.Height+pad) + maxActorHeight = math.Max(maxActorHeight, edge.Dst.Height+pad) } - placeObjects(objectsInOrder, maxObjectHeight, objectXStep) + placeActors(actorsInOrder, maxActorHeight, actorXStep) // edges are placed in the order users define them - routeEdges(g.Edges, maxObjectHeight, edgeYStep) - addLifelineEdges(g, objectsInOrder, edgeYStep) + routeEdges(g.Edges, maxActorHeight, edgeYStep) + addLifelineEdges(g, actorsInOrder, edgeYStep) return nil } -// placeObjects places objects side by side -func placeObjects(objectsInOrder []*d2graph.Object, maxHeight, xStep float64) { +// placeActors places actors bottom aligned, side by side +func placeActors(actorsInOrder []*d2graph.Object, maxHeight, xStep float64) { x := 0. - for _, obj := range objectsInOrder { - yDiff := maxHeight - obj.Height - obj.TopLeft = geo.NewPoint(x, yDiff/2.) - x += obj.Width + xStep - obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + for _, actors := range actorsInOrder { + yOffset := maxHeight - actors.Height + actors.TopLeft = geo.NewPoint(x, yOffset) + x += actors.Width + xStep + actors.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } } @@ -72,39 +72,39 @@ func routeEdges(edgesInOrder []*d2graph.Edge, startY, yStep float64) { } } -// addLifelineEdges adds a new edge for each object in the graph that represents the -// edge below he object showing its lifespan +// addLifelineEdges adds a new edge for each actor in the graph that represents the +// edge below the actor showing its lifespan // ┌──────────────┐ -// │ object │ +// │ actor │ // └──────┬───────┘ // │ // │ lifeline // │ // │ -func addLifelineEdges(g *d2graph.Graph, objectsInOrder []*d2graph.Object, yStep float64) { +func addLifelineEdges(g *d2graph.Graph, actorsInOrder []*d2graph.Object, yStep float64) { endY := g.Edges[len(g.Edges)-1].Route[0].Y + yStep - for _, obj := range objectsInOrder { - objBottom := obj.Center() - objBottom.Y = obj.TopLeft.Y + obj.Height - objLifelineEnd := obj.Center() - objLifelineEnd.Y = endY + for _, actor := range actorsInOrder { + actorBottom := actor.Center() + actorBottom.Y = actor.TopLeft.Y + actor.Height + actorLifelineEnd := actor.Center() + actorLifelineEnd.Y = endY g.Edges = append(g.Edges, &d2graph.Edge{ Attributes: d2graph.Attributes{ Style: d2graph.Style{ StrokeDash: &d2graph.Scalar{ Value: "10", }, - Stroke: obj.Attributes.Style.Stroke, - StrokeWidth: obj.Attributes.Style.StrokeWidth, + Stroke: actor.Attributes.Style.Stroke, + StrokeWidth: actor.Attributes.Style.StrokeWidth, }, }, - Src: obj, + Src: actor, SrcArrow: false, Dst: &d2graph.Object{ - ID: obj.ID + fmt.Sprintf("-lifeline-end-%d", go2.StringToIntHash(obj.ID+"-lifeline-end")), + ID: actor.ID + fmt.Sprintf("-lifeline-end-%d", go2.StringToIntHash(actor.ID+"-lifeline-end")), }, DstArrow: false, - Route: []*geo.Point{objBottom, objLifelineEnd}, + Route: []*geo.Point{actorBottom, actorLifelineEnd}, }) } } diff --git a/d2layouts/d2sequence/layout_test.go b/d2layouts/d2sequence/layout_test.go index 4ffb0237f..f01575292 100644 --- a/d2layouts/d2sequence/layout_test.go +++ b/d2layouts/d2sequence/layout_test.go @@ -45,27 +45,29 @@ func TestLayout(t *testing.T) { ctx := log.WithTB(context.Background(), t, nil) Layout(ctx, g) - // asserts that objects were placed in the expected x order and at y=0 - objectsOrder := []*d2graph.Object{ + // asserts that actors were placed in the expected x order and at y=0 + actors := []*d2graph.Object{ g.Objects[0], g.Objects[1], } - for i := 1; i < len(objectsOrder); i++ { - if objectsOrder[i].TopLeft.X < objectsOrder[i-1].TopLeft.X { - t.Fatalf("expected object[%d].TopLeft.X > object[%d].TopLeft.X", i, i-1) + for i := 1; i < len(actors); i++ { + if actors[i].TopLeft.X < actors[i-1].TopLeft.X { + t.Fatalf("expected actor[%d].TopLeft.X > actor[%d].TopLeft.X", i, i-1) } - if objectsOrder[i].Center().Y != objectsOrder[i-1].Center().Y { - t.Fatalf("expected object[%d] and object[%d] to be at the same center y", i, i-1) + actorBottom := actors[i].TopLeft.Y + actors[i].Height + prevActorBottom := actors[i-1].TopLeft.Y + actors[i-1].Height + if actorBottom != prevActorBottom { + t.Fatalf("expected actor[%d] and actor[%d] to be at the same bottom y", i, i-1) } } - nExpectedEdges := nEdges + len(objectsOrder) + nExpectedEdges := nEdges + len(actors) if len(g.Edges) != nExpectedEdges { t.Fatalf("expected %d edges, got %d", nExpectedEdges, len(g.Edges)) } - // assert that edges were placed in y order and have the endpoints at their objects - // uses `nEdges` because Layout creates some vertical edges to represent the object lifeline + // assert that edges were placed in y order and have the endpoints at their actors + // uses `nEdges` because Layout creates some vertical edges to represent the actor lifeline for i := 0; i < nEdges; i++ { edge := g.Edges[i] if len(edge.Route) != 2 { @@ -75,10 +77,10 @@ func TestLayout(t *testing.T) { t.Fatalf("expected edge[%d] to be a horizontal line", i) } if edge.Route[0].X != edge.Src.Center().X { - t.Fatalf("expected edge[%d] source endpoint to be at the middle of the source object", i) + t.Fatalf("expected edge[%d] source endpoint to be at the middle of the source actor", i) } if edge.Route[1].X != edge.Dst.Center().X { - t.Fatalf("expected edge[%d] target endpoint to be at the middle of the target object", i) + t.Fatalf("expected edge[%d] target endpoint to be at the middle of the target actor", i) } if i > 0 { prevEdge := g.Edges[i-1] @@ -98,10 +100,10 @@ func TestLayout(t *testing.T) { t.Fatalf("expected edge[%d] to be a vertical line", i) } if edge.Route[0].X != edge.Src.Center().X { - t.Fatalf("expected edge[%d] x to be at the object center", i) + t.Fatalf("expected edge[%d] x to be at the actor center", i) } if edge.Route[0].Y != edge.Src.Height+edge.Src.TopLeft.Y { - t.Fatalf("expected edge[%d] to start at the bottom of the source object", i) + t.Fatalf("expected edge[%d] to start at the bottom of the source actor", i) } if edge.Route[1].Y < lastSequenceEdge.Route[0].Y { t.Fatalf("expected edge[%d] to end after the last sequence edge", i)