d2/d2layouts/d2grid/grid_diagram.go

82 lines
2.7 KiB
Go
Raw Normal View History

2023-04-03 18:36:01 +00:00
package d2grid
import (
"strconv"
"oss.terrastruct.com/d2/d2graph"
)
2023-04-05 18:11:31 +00:00
type gridDiagram struct {
2023-04-03 18:36:01 +00:00
root *d2graph.Object
nodes []*d2graph.Object
rows int
columns int
rowDominant bool
2023-04-05 03:02:22 +00:00
width float64
height float64
2023-04-03 18:36:01 +00:00
}
2023-04-05 18:11:31 +00:00
func newGridDiagram(root *d2graph.Object) *gridDiagram {
gd := gridDiagram{root: root, nodes: root.ChildrenArray}
2023-04-03 18:36:01 +00:00
if root.Attributes.Rows != nil {
2023-04-05 18:11:31 +00:00
gd.rows, _ = strconv.Atoi(root.Attributes.Rows.Value)
2023-04-03 18:36:01 +00:00
}
if root.Attributes.Columns != nil {
2023-04-05 18:11:31 +00:00
gd.columns, _ = strconv.Atoi(root.Attributes.Columns.Value)
2023-04-03 18:36:01 +00:00
}
// compute exact row/column count based on values entered
2023-04-05 18:11:31 +00:00
if gd.columns == 0 {
gd.rowDominant = true
} else if gd.rows == 0 {
gd.rowDominant = false
2023-04-03 18:36:01 +00:00
} else {
// if keyword rows is first, rows are primary, columns secondary.
if root.Attributes.Rows.MapKey.Range.Before(root.Attributes.Columns.MapKey.Range) {
2023-04-05 18:11:31 +00:00
gd.rowDominant = true
}
// rows and columns specified, but we want to continue naturally if user enters more nodes
// e.g. 2 rows, 3 columns specified + g node added: │ with 3 columns, 2 rows:
// . original add row add column │ original add row add column
// . ┌───────┐ ┌───────┐ ┌─────────┐ │ ┌───────┐ ┌───────┐ ┌─────────┐
// . │ a b c │ │ a b c │ │ a b c d │ │ │ a c e │ │ a d g │ │ a c e g │
// . │ d e f │ │ d e f │ │ e f g │ │ │ b d f │ │ b e │ │ b d f │
// . └───────┘ │ g │ └─────────┘ │ └───────┘ │ c f │ └─────────┘
// . └───────┘ ▲ │ └───────┘ ▲
// . ▲ └─existing nodes modified │ ▲ └─existing nodes preserved
// . └─existing rows preserved │ └─existing rows modified
2023-04-05 18:11:31 +00:00
capacity := gd.rows * gd.columns
for capacity < len(gd.nodes) {
if gd.rowDominant {
gd.rows++
capacity += gd.columns
} else {
2023-04-05 18:11:31 +00:00
gd.columns++
capacity += gd.rows
}
2023-04-03 18:36:01 +00:00
}
}
2023-04-05 18:11:31 +00:00
return &gd
2023-04-03 18:36:01 +00:00
}
2023-04-05 18:11:31 +00:00
func (gd *gridDiagram) shift(dx, dy float64) {
for _, obj := range gd.nodes {
2023-04-03 18:36:01 +00:00
obj.TopLeft.X += dx
obj.TopLeft.Y += dy
}
}
2023-04-05 18:11:31 +00:00
func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) {
obj.Children = make(map[string]*d2graph.Object)
obj.ChildrenArray = make([]*d2graph.Object, 0)
2023-04-05 18:11:31 +00:00
for _, child := range gd.nodes {
obj.Children[child.ID] = child
obj.ChildrenArray = append(obj.ChildrenArray, child)
}
2023-04-05 18:11:31 +00:00
graph.Objects = append(graph.Objects, gd.nodes...)
}