This commit is contained in:
Gavin Nishizawa 2023-04-03 11:45:45 -07:00
parent f8617d1560
commit abe27cdc26
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD

View file

@ -13,6 +13,33 @@ import (
"oss.terrastruct.com/d2/lib/label"
)
// Layout runs the sequence diagram layout engine on objects of shape sequence_diagram
//
// 1. Traverse graph from root, skip objects with shape not `sequence_diagram`
// 2. Construct a sequence diagram from all descendant objects and edges
// 3. Remove those objects and edges from the main graph
// 4. Run layout on sequence diagrams
// 5. Set the resulting dimensions to the main graph shape
// 6. Run core layouts (still without sequence diagram innards)
// 7. Put back sequence diagram innards in correct location
func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error {
sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g)
if err != nil {
return err
}
if g.Root.IsSequenceDiagram() {
// the sequence diagram is the only layout engine if the whole diagram is
// shape: sequence_diagram
g.Root.TopLeft = geo.NewPoint(0, 0)
} else if err := layout(ctx, g); err != nil {
return err
}
cleanup(g, sequenceDiagrams, objectOrder, edgeOrder)
return nil
}
func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]*sequenceDiagram, map[string]int, map[string]int, error) {
objectsToRemove := make(map[*d2graph.Object]struct{})
edgesToRemove := make(map[*d2graph.Edge]struct{})
@ -69,33 +96,6 @@ func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]
return sequenceDiagrams, objectOrder, edgeOrder, nil
}
// Layout runs the sequence diagram layout engine on objects of shape sequence_diagram
//
// 1. Traverse graph from root, skip objects with shape not `sequence_diagram`
// 2. Construct a sequence diagram from all descendant objects and edges
// 3. Remove those objects and edges from the main graph
// 4. Run layout on sequence diagrams
// 5. Set the resulting dimensions to the main graph shape
// 6. Run core layouts (still without sequence diagram innards)
// 7. Put back sequence diagram innards in correct location
func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error {
sequenceDiagrams, objectOrder, edgeOrder, err := WithoutSequenceDiagrams(ctx, g)
if err != nil {
return err
}
if g.Root.IsSequenceDiagram() {
// the sequence diagram is the only layout engine if the whole diagram is
// shape: sequence_diagram
g.Root.TopLeft = geo.NewPoint(0, 0)
} else if err := layout(ctx, g); err != nil {
return err
}
cleanup(g, sequenceDiagrams, objectOrder, edgeOrder)
return nil
}
// layoutSequenceDiagram finds the edges inside the sequence diagram and performs the layout on the object descendants
func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiagram, error) {
var edges []*d2graph.Edge
@ -154,11 +154,11 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj
objects = g.Objects
}
for _, obj := range objects {
if _, exists := sequenceDiagrams[obj.AbsID()]; !exists {
sd, exists := sequenceDiagrams[obj.AbsID()]
if !exists {
continue
}
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
sd := sequenceDiagrams[obj.AbsID()]
// shift the sequence diagrams as they are always placed at (0, 0) with some padding
sd.shift(
@ -181,12 +181,12 @@ func cleanup(g *d2graph.Graph, sequenceDiagrams map[string]*sequenceDiagram, obj
}
}
g.Edges = append(g.Edges, sequenceDiagrams[obj.AbsID()].messages...)
g.Edges = append(g.Edges, sequenceDiagrams[obj.AbsID()].lifelines...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].actors...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].notes...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].groups...)
g.Objects = append(g.Objects, sequenceDiagrams[obj.AbsID()].spans...)
g.Edges = append(g.Edges, sd.messages...)
g.Edges = append(g.Edges, sd.lifelines...)
g.Objects = append(g.Objects, sd.actors...)
g.Objects = append(g.Objects, sd.notes...)
g.Objects = append(g.Objects, sd.groups...)
g.Objects = append(g.Objects, sd.spans...)
}
// no new objects, so just keep the same position