...

Source file src/oss.terrastruct.com/d2/d2layouts/d2sequence/layout.go

Documentation: oss.terrastruct.com/d2/d2layouts/d2sequence

     1  package d2sequence
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"oss.terrastruct.com/util-go/go2"
     8  
     9  	"oss.terrastruct.com/d2/d2graph"
    10  	"oss.terrastruct.com/d2/d2target"
    11  	"oss.terrastruct.com/d2/lib/geo"
    12  	"oss.terrastruct.com/d2/lib/label"
    13  )
    14  
    15  // Layout runs the sequence diagram layout engine on objects of shape sequence_diagram
    16  //
    17  // 1. Run layout on sequence diagrams
    18  // 2. Set the resulting dimensions to the main graph shape
    19  func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) error {
    20  	// used in layout code
    21  	g.Root.Shape.Value = d2target.ShapeSequenceDiagram
    22  
    23  	sd, err := layoutSequenceDiagram(g, g.Root)
    24  	if err != nil {
    25  		return err
    26  	}
    27  	g.Root.Box = geo.NewBox(nil, sd.getWidth()+GROUP_CONTAINER_PADDING*2, sd.getHeight()+GROUP_CONTAINER_PADDING*2)
    28  
    29  	// the sequence diagram is the only layout engine if the whole diagram is
    30  	// shape: sequence_diagram
    31  	g.Root.TopLeft = geo.NewPoint(0, 0)
    32  
    33  	obj := g.Root
    34  
    35  	obj.LabelPosition = go2.Pointer(label.InsideTopCenter.String())
    36  
    37  	// shift the sequence diagrams as they are always placed at (0, 0) with some padding
    38  	sd.shift(
    39  		geo.NewPoint(
    40  			obj.TopLeft.X+GROUP_CONTAINER_PADDING,
    41  			obj.TopLeft.Y+GROUP_CONTAINER_PADDING,
    42  		),
    43  	)
    44  
    45  	obj.Children = make(map[string]*d2graph.Object)
    46  	obj.ChildrenArray = make([]*d2graph.Object, 0)
    47  	for _, child := range sd.actors {
    48  		obj.Children[strings.ToLower(child.ID)] = child
    49  		obj.ChildrenArray = append(obj.ChildrenArray, child)
    50  	}
    51  	for _, child := range sd.groups {
    52  		if child.Parent.AbsID() == obj.AbsID() {
    53  			obj.Children[strings.ToLower(child.ID)] = child
    54  			obj.ChildrenArray = append(obj.ChildrenArray, child)
    55  		}
    56  	}
    57  
    58  	g.Edges = append(g.Edges, sd.lifelines...)
    59  
    60  	return nil
    61  }
    62  
    63  // layoutSequenceDiagram finds the edges inside the sequence diagram and performs the layout on the object descendants
    64  func layoutSequenceDiagram(g *d2graph.Graph, obj *d2graph.Object) (*sequenceDiagram, error) {
    65  	var edges []*d2graph.Edge
    66  	for _, edge := range g.Edges {
    67  		// both Src and Dst must be inside the sequence diagram
    68  		if obj == g.Root || (strings.HasPrefix(edge.Src.AbsID(), obj.AbsID()+".") && strings.HasPrefix(edge.Dst.AbsID(), obj.AbsID()+".")) {
    69  			edges = append(edges, edge)
    70  		}
    71  	}
    72  
    73  	sd, err := newSequenceDiagram(obj.ChildrenArray, edges)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	err = sd.layout()
    78  	return sd, err
    79  }
    80  

View as plain text