inject nested graph, fit, spacing
This commit is contained in:
parent
dc6e0644b9
commit
477015d408
2 changed files with 80 additions and 20 deletions
|
|
@ -1,9 +1,11 @@
|
|||
package d2layouts
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"oss.terrastruct.com/d2/d2graph"
|
||||
"oss.terrastruct.com/d2/lib/geo"
|
||||
)
|
||||
|
||||
type GraphType string
|
||||
|
|
@ -15,7 +17,7 @@ const (
|
|||
SequenceDiagram GraphType = "sequence-diagram"
|
||||
)
|
||||
|
||||
func LayoutNested(g *d2graph.Graph, graphType GraphType, coreLayout d2graph.LayoutGraph) {
|
||||
func LayoutNested(g *d2graph.Graph, graphType GraphType, coreLayout d2graph.LayoutGraph) geo.Spacing {
|
||||
// Before we can layout these nodes, we need to handle all nested diagrams first.
|
||||
extracted := make(map[*d2graph.Object]*d2graph.Graph)
|
||||
|
||||
|
|
@ -29,10 +31,10 @@ func LayoutNested(g *d2graph.Graph, graphType GraphType, coreLayout d2graph.Layo
|
|||
nestedGraph := ExtractNested(child)
|
||||
|
||||
// Layout of nestedGraph is completed
|
||||
LayoutNested(nestedGraph, graphType, coreLayout)
|
||||
spacing := LayoutNested(nestedGraph, graphType, coreLayout)
|
||||
|
||||
// Fit child to size of nested layout
|
||||
FitToGraph(child, nestedGraph)
|
||||
FitToGraph(child, nestedGraph, spacing)
|
||||
|
||||
// We will restore the contents after running layout with child as the placeholder
|
||||
extracted[child] = nestedGraph
|
||||
|
|
@ -43,12 +45,14 @@ func LayoutNested(g *d2graph.Graph, graphType GraphType, coreLayout d2graph.Layo
|
|||
|
||||
// We can now run layout with accurate sizes of nested layout containers
|
||||
// Layout according to the type of diagram
|
||||
LayoutDiagram(g, graphType, coreLayout)
|
||||
spacing := LayoutDiagram(g, graphType, coreLayout)
|
||||
|
||||
// With the layout set, inject all the extracted graphs
|
||||
for n, nestedGraph := range extracted {
|
||||
InjectNested(n, nestedGraph)
|
||||
}
|
||||
|
||||
return spacing
|
||||
}
|
||||
|
||||
func NestedGraphType(obj *d2graph.Object) GraphType {
|
||||
|
|
@ -65,15 +69,15 @@ func NestedGraphType(obj *d2graph.Object) GraphType {
|
|||
}
|
||||
|
||||
func ExtractNested(container *d2graph.Object) *d2graph.Graph {
|
||||
tempGraph := d2graph.NewGraph()
|
||||
tempGraph.RootLevel = int(container.Level())
|
||||
nestedGraph := d2graph.NewGraph()
|
||||
nestedGraph.RootLevel = int(container.Level())
|
||||
|
||||
// separate out nested edges
|
||||
g := container.Graph
|
||||
remainingEdges := make([]*d2graph.Edge, 0, len(g.Edges))
|
||||
for _, edge := range g.Edges {
|
||||
if edge.Src.Parent.IsDescendantOf(container) && edge.Dst.Parent.IsDescendantOf(container) {
|
||||
tempGraph.Edges = append(tempGraph.Edges, edge)
|
||||
nestedGraph.Edges = append(nestedGraph.Edges, edge)
|
||||
} else {
|
||||
remainingEdges = append(remainingEdges, edge)
|
||||
}
|
||||
|
|
@ -84,7 +88,7 @@ func ExtractNested(container *d2graph.Object) *d2graph.Graph {
|
|||
remainingObjects := make([]*d2graph.Object, 0, len(g.Objects))
|
||||
for _, obj := range g.Objects {
|
||||
if obj.IsDescendantOf(container) {
|
||||
tempGraph.Objects = append(tempGraph.Objects, obj)
|
||||
nestedGraph.Objects = append(nestedGraph.Objects, obj)
|
||||
} else {
|
||||
remainingObjects = append(remainingObjects, obj)
|
||||
}
|
||||
|
|
@ -92,14 +96,14 @@ func ExtractNested(container *d2graph.Object) *d2graph.Graph {
|
|||
g.Objects = remainingObjects
|
||||
|
||||
// update object and new root references
|
||||
for _, o := range tempGraph.Objects {
|
||||
o.Graph = tempGraph
|
||||
for _, o := range nestedGraph.Objects {
|
||||
o.Graph = nestedGraph
|
||||
}
|
||||
// set root references
|
||||
tempGraph.Root.ChildrenArray = append(tempGraph.Root.ChildrenArray, container.ChildrenArray...)
|
||||
nestedGraph.Root.ChildrenArray = append(nestedGraph.Root.ChildrenArray, container.ChildrenArray...)
|
||||
for _, child := range container.ChildrenArray {
|
||||
child.Parent = tempGraph.Root
|
||||
tempGraph.Root.Children[strings.ToLower(child.ID)] = child
|
||||
child.Parent = nestedGraph.Root
|
||||
nestedGraph.Root.Children[strings.ToLower(child.ID)] = child
|
||||
}
|
||||
|
||||
// remove container's references
|
||||
|
|
@ -108,17 +112,68 @@ func ExtractNested(container *d2graph.Object) *d2graph.Graph {
|
|||
}
|
||||
container.ChildrenArray = nil
|
||||
|
||||
return tempGraph
|
||||
// position contents relative to 0,0
|
||||
dx := -container.TopLeft.X
|
||||
dy := -container.TopLeft.Y
|
||||
for _, o := range nestedGraph.Objects {
|
||||
o.TopLeft.X += dx
|
||||
o.TopLeft.Y += dy
|
||||
}
|
||||
for _, e := range nestedGraph.Edges {
|
||||
e.Move(dx, dy)
|
||||
}
|
||||
return nestedGraph
|
||||
}
|
||||
|
||||
func InjectNested(container *d2graph.Object, graph *d2graph.Graph) {
|
||||
// TODO
|
||||
func InjectNested(container *d2graph.Object, nestedGraph *d2graph.Graph) {
|
||||
g := container.Graph
|
||||
for _, obj := range nestedGraph.Root.ChildrenArray {
|
||||
obj.Parent = container
|
||||
container.Children[strings.ToLower(obj.ID)] = obj
|
||||
container.ChildrenArray = append(container.ChildrenArray, obj)
|
||||
}
|
||||
for _, obj := range nestedGraph.Objects {
|
||||
obj.Graph = g
|
||||
}
|
||||
g.Objects = append(g.Objects, nestedGraph.Objects...)
|
||||
g.Edges = append(g.Edges, nestedGraph.Edges...)
|
||||
|
||||
// Note: assumes nestedGraph's layout has contents positioned relative to 0,0
|
||||
dx := container.TopLeft.X
|
||||
dy := container.TopLeft.Y
|
||||
for _, o := range nestedGraph.Objects {
|
||||
o.TopLeft.X += dx
|
||||
o.TopLeft.Y += dy
|
||||
}
|
||||
for _, e := range nestedGraph.Edges {
|
||||
e.Move(dx, dy)
|
||||
}
|
||||
}
|
||||
|
||||
func FitToGraph(container *d2graph.Object, graph *d2graph.Graph) {
|
||||
// TODO
|
||||
func boundingBox(g *d2graph.Graph) (tl, br *geo.Point) {
|
||||
if len(g.Objects) == 0 {
|
||||
return geo.NewPoint(0, 0), geo.NewPoint(0, 0)
|
||||
}
|
||||
tl = geo.NewPoint(math.Inf(1), math.Inf(1))
|
||||
br = geo.NewPoint(math.Inf(-1), math.Inf(-1))
|
||||
|
||||
for _, obj := range g.Objects {
|
||||
tl.X = math.Min(tl.X, obj.TopLeft.X)
|
||||
tl.Y = math.Min(tl.Y, obj.TopLeft.Y)
|
||||
br.X = math.Max(br.X, obj.TopLeft.X+obj.Width)
|
||||
br.Y = math.Max(br.Y, obj.TopLeft.Y+obj.Height)
|
||||
}
|
||||
|
||||
return tl, br
|
||||
}
|
||||
|
||||
func LayoutDiagram(graph *d2graph.Graph, graphType GraphType, coreLayout d2graph.LayoutGraph) {
|
||||
// TODO
|
||||
func FitToGraph(container *d2graph.Object, nestedGraph *d2graph.Graph, padding geo.Spacing) {
|
||||
tl, br := boundingBox(nestedGraph)
|
||||
container.Width = padding.Left + br.X - tl.X + padding.Right
|
||||
container.Height = padding.Top + br.Y - tl.Y + padding.Bottom
|
||||
}
|
||||
|
||||
func LayoutDiagram(graph *d2graph.Graph, graphType GraphType, coreLayout d2graph.LayoutGraph) geo.Spacing {
|
||||
// TODO
|
||||
return geo.Spacing{}
|
||||
}
|
||||
|
|
|
|||
5
lib/geo/spacing.go
Normal file
5
lib/geo/spacing.go
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
package geo
|
||||
|
||||
type Spacing struct {
|
||||
Top, Bottom, Left, Right float64
|
||||
}
|
||||
Loading…
Reference in a new issue