diff --git a/d2layouts/d2grid/grid_diagram.go b/d2layouts/d2grid/grid_diagram.go index bb02ca94b..f9a69b92d 100644 --- a/d2layouts/d2grid/grid_diagram.go +++ b/d2layouts/d2grid/grid_diagram.go @@ -11,6 +11,7 @@ import ( type gridDiagram struct { root *d2graph.Object objects []*d2graph.Object + edges []*d2graph.Edge rows int columns int @@ -122,4 +123,7 @@ func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) { restore(obj, child) child.IterDescendants(restore) } + for _, e := range gd.edges { + graph.Edges = append(graph.Edges, e) + } } diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 3e5e1d104..2d473e23d 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -31,7 +31,7 @@ const ( // 7. Put grid children back in correct location func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d2graph.LayoutGraph { return func(ctx context.Context, g *d2graph.Graph) error { - gridDiagrams, objectOrder, err := withoutGridDiagrams(ctx, g, layout) + gridDiagrams, objectOrder, edgeOrder, err := withoutGridDiagrams(ctx, g, layout) if err != nil { return err } @@ -42,19 +42,24 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d return err } - cleanup(g, gridDiagrams, objectOrder) + cleanup(g, gridDiagrams, objectOrder, edgeOrder) return nil } } -func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) (gridDiagrams map[string]*gridDiagram, objectOrder map[string]int, err error) { +func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) (gridDiagrams map[string]*gridDiagram, objectOrder, edgeOrder map[string]int, err error) { toRemove := make(map[*d2graph.Object]struct{}) + edgeToRemove := make(map[*d2graph.Edge]struct{}) gridDiagrams = make(map[string]*gridDiagram) objectOrder = make(map[string]int) for i, obj := range g.Objects { objectOrder[obj.AbsID()] = i } + edgeOrder = make(map[string]int) + for i, edge := range g.Edges { + edgeOrder[edge.AbsID()] = i + } var processGrid func(obj *d2graph.Object) error processGrid = func(obj *d2graph.Object) error { @@ -200,6 +205,22 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L for _, o := range gd.objects { toRemove[o] = struct{}{} } + + // simple straight line edge routing between grid objects + for i, e := range g.Edges { + edgeOrder[e.AbsID()] = i + if e.Dst.ClosestGridDiagram() != obj { + continue + } + e.Route = []*geo.Point{e.Src.Center(), e.Dst.Center()} + e.TraceToShape(e.Route, 0, 1) + if e.Label.Value != "" { + e.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) + } + gd.edges = append(gd.edges, e) + edgeToRemove[e] = struct{}{} + } + return nil } @@ -218,7 +239,7 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L } if err := processGrid(obj); err != nil { - return nil, nil, err + return nil, nil, nil, err } } } @@ -230,8 +251,15 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L } } g.Objects = layoutObjects + layoutEdges := make([]*d2graph.Edge, 0, len(edgeToRemove)) + for _, e := range g.Edges { + if _, exists := edgeToRemove[e]; !exists { + layoutEdges = append(layoutEdges, e) + } + } + g.Edges = layoutEdges - return gridDiagrams, objectOrder, nil + return gridDiagrams, objectOrder, edgeOrder, nil } func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) { @@ -940,11 +968,14 @@ func getDistToTarget(layout [][]*d2graph.Object, targetSize float64, horizontalG // - translating the grid to its position placed by the core layout engine // - restore the children of the grid // - sorts objects to their original graph order -func cleanup(graph *d2graph.Graph, gridDiagrams map[string]*gridDiagram, objectsOrder map[string]int) { +func cleanup(graph *d2graph.Graph, gridDiagrams map[string]*gridDiagram, objectsOrder, edgeOrder map[string]int) { defer func() { sort.SliceStable(graph.Objects, func(i, j int) bool { return objectsOrder[graph.Objects[i].AbsID()] < objectsOrder[graph.Objects[j].AbsID()] }) + sort.SliceStable(graph.Edges, func(i, j int) bool { + return edgeOrder[graph.Edges[i].AbsID()] < edgeOrder[graph.Edges[j].AbsID()] + }) }() var restore func(obj *d2graph.Object)