more dynamic grid sizing according to node sizes
This commit is contained in:
parent
0ed4bfe244
commit
c958269b03
5 changed files with 315 additions and 111 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
package d2graph
|
package d2graph
|
||||||
|
|
||||||
func (obj *Object) IsGrid() bool {
|
func (obj *Object) IsGrid() bool {
|
||||||
return obj != nil && obj.Attributes != nil && len(obj.ChildrenArray) != 0 &&
|
return obj != nil && obj.Attributes != nil &&
|
||||||
(obj.Attributes.Rows != nil || obj.Attributes.Columns != nil)
|
(obj.Attributes.Rows != nil || obj.Attributes.Columns != nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package d2grid
|
package d2grid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"oss.terrastruct.com/d2/d2graph"
|
"oss.terrastruct.com/d2/d2graph"
|
||||||
|
|
@ -13,6 +12,8 @@ type grid struct {
|
||||||
rows int
|
rows int
|
||||||
columns int
|
columns int
|
||||||
|
|
||||||
|
rowDominant bool
|
||||||
|
|
||||||
cellWidth float64
|
cellWidth float64
|
||||||
cellHeight float64
|
cellHeight float64
|
||||||
width float64
|
width float64
|
||||||
|
|
@ -29,64 +30,38 @@ func newGrid(root *d2graph.Object) *grid {
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute exact row/column count based on values entered
|
// compute exact row/column count based on values entered
|
||||||
if g.rows == 0 {
|
if g.columns == 0 {
|
||||||
// set rows based on number of columns
|
g.rowDominant = true
|
||||||
g.rows = len(g.nodes) / g.columns
|
} else if g.rows == 0 {
|
||||||
if len(g.nodes)%g.columns != 0 {
|
g.rowDominant = false
|
||||||
g.rows++
|
|
||||||
}
|
|
||||||
} else if g.columns == 0 {
|
|
||||||
// set columns based on number of rows
|
|
||||||
g.columns = len(g.nodes) / g.rows
|
|
||||||
if len(g.nodes)%g.rows != 0 {
|
|
||||||
g.columns++
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// rows and columns specified (add more rows if needed)
|
// if keyword rows is first, rows are primary, columns secondary.
|
||||||
|
if root.Attributes.Rows.MapKey.Range.Before(root.Attributes.Columns.MapKey.Range) {
|
||||||
|
g.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
|
||||||
capacity := g.rows * g.columns
|
capacity := g.rows * g.columns
|
||||||
for capacity < len(g.nodes) {
|
for capacity < len(g.nodes) {
|
||||||
g.rows++
|
if g.rowDominant {
|
||||||
capacity += g.columns
|
g.rows++
|
||||||
|
capacity += g.columns
|
||||||
|
} else {
|
||||||
|
g.columns++
|
||||||
|
capacity += g.rows
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have the following nodes for a 2 row, 3 column grid
|
|
||||||
// . ┌A──────────────────┐ ┌B─────┐ ┌C────────────┐ ┌D───────────┐ ┌E───────────────────┐
|
|
||||||
// . │ │ │ │ │ │ │ │ │ │
|
|
||||||
// . │ │ │ │ │ │ │ │ │ │
|
|
||||||
// . └───────────────────┘ │ │ │ │ │ │ │ │
|
|
||||||
// . │ │ └─────────────┘ │ │ │ │
|
|
||||||
// . │ │ │ │ └────────────────────┘
|
|
||||||
// . └──────┘ │ │
|
|
||||||
// . └────────────┘
|
|
||||||
// Then we must get the max width and max height to determine the grid cell size
|
|
||||||
// . maxWidth├────────────────────┤
|
|
||||||
// . ┌A───────────────────┐ ┌B───────────────────┐ ┌C───────────────────┐ ┬maxHeight
|
|
||||||
// . │ │ │ │ │ │ │
|
|
||||||
// . │ │ │ │ │ │ │
|
|
||||||
// . │ │ │ │ │ │ │
|
|
||||||
// . │ │ │ │ │ │ │
|
|
||||||
// . │ │ │ │ │ │ │
|
|
||||||
// . │ │ │ │ │ │ │
|
|
||||||
// . └────────────────────┘ └────────────────────┘ └────────────────────┘ ┴
|
|
||||||
// . ┌D───────────────────┐ ┌E───────────────────┐
|
|
||||||
// . │ │ │ │
|
|
||||||
// . │ │ │ │
|
|
||||||
// . │ │ │ │
|
|
||||||
// . │ │ │ │
|
|
||||||
// . │ │ │ │
|
|
||||||
// . │ │ │ │
|
|
||||||
// . └────────────────────┘ └────────────────────┘
|
|
||||||
var maxWidth, maxHeight float64
|
|
||||||
for _, n := range g.nodes {
|
|
||||||
maxWidth = math.Max(maxWidth, n.Width)
|
|
||||||
maxHeight = math.Max(maxHeight, n.Height)
|
|
||||||
}
|
|
||||||
g.cellWidth = maxWidth
|
|
||||||
g.cellHeight = maxHeight
|
|
||||||
g.width = maxWidth + (float64(g.columns)-1)*(maxWidth+HORIZONTAL_PAD)
|
|
||||||
g.height = maxHeight + (float64(g.rows)-1)*(maxHeight+VERTICAL_PAD)
|
|
||||||
|
|
||||||
return &g
|
return &g
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,3 +71,13 @@ func (g *grid) shift(dx, dy float64) {
|
||||||
obj.TopLeft.Y += dy
|
obj.TopLeft.Y += dy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *grid) cleanup(obj *d2graph.Object, graph *d2graph.Graph) {
|
||||||
|
obj.Children = make(map[string]*d2graph.Object)
|
||||||
|
obj.ChildrenArray = make([]*d2graph.Object, 0)
|
||||||
|
for _, child := range g.nodes {
|
||||||
|
obj.Children[child.ID] = child
|
||||||
|
obj.ChildrenArray = append(obj.ChildrenArray, child)
|
||||||
|
}
|
||||||
|
graph.Objects = append(graph.Objects, g.nodes...)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package d2grid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"oss.terrastruct.com/d2/d2graph"
|
"oss.terrastruct.com/d2/d2graph"
|
||||||
|
|
@ -33,7 +34,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, layout d2graph.LayoutGraph) d
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.Root.IsGrid() {
|
if g.Root.IsGrid() && len(g.Root.ChildrenArray) != 0 {
|
||||||
g.Root.TopLeft = geo.NewPoint(0, 0)
|
g.Root.TopLeft = geo.NewPoint(0, 0)
|
||||||
} else if err := layout(ctx, g); err != nil {
|
} else if err := layout(ctx, g); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -93,20 +94,207 @@ func withoutGrids(ctx context.Context, g *d2graph.Graph) (idToGrid map[string]*g
|
||||||
|
|
||||||
func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) {
|
func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) {
|
||||||
grid := newGrid(obj)
|
grid := newGrid(obj)
|
||||||
|
// assume we have the following nodes to layout:
|
||||||
|
// . ┌A──────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐
|
||||||
|
// . └───────────────┘ │ │ │ │ │ │ │ │
|
||||||
|
// . │ │ └──────────┘ │ │ │ │
|
||||||
|
// . │ │ │ │ └─────────────────┘
|
||||||
|
// . └───┘ │ │
|
||||||
|
// . └─────────┘
|
||||||
|
// Note: if the grid is row dominant, all nodes should be the same height (same width if column dominant)
|
||||||
|
// . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┌D────────┐ ┌E────────────────┐
|
||||||
|
// . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │ │ │ │
|
||||||
|
// . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │ │ │ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤
|
||||||
|
// . │ │ ├ ─ ┤ │ │ │ │ │ │
|
||||||
|
// . └──────────────┘ └───┘ └──────────┘ └─────────┘ └─────────────────┘
|
||||||
|
|
||||||
// position nodes
|
// we want to split up the total width across the N rows or columns as evenly as possible
|
||||||
cursor := geo.NewPoint(0, 0)
|
var totalWidth, totalHeight float64
|
||||||
for i := 0; i < grid.rows; i++ {
|
for _, n := range grid.nodes {
|
||||||
for j := 0; j < grid.columns; j++ {
|
totalWidth += n.Width
|
||||||
n := grid.nodes[i*grid.columns+j]
|
totalHeight += n.Height
|
||||||
n.Width = grid.cellWidth
|
|
||||||
n.Height = grid.cellHeight
|
|
||||||
n.TopLeft = cursor.Copy()
|
|
||||||
cursor.X += grid.cellWidth + HORIZONTAL_PAD
|
|
||||||
}
|
|
||||||
cursor.X = 0
|
|
||||||
cursor.Y += float64(grid.cellHeight) + VERTICAL_PAD
|
|
||||||
}
|
}
|
||||||
|
totalWidth += HORIZONTAL_PAD * float64(len(grid.nodes)-1)
|
||||||
|
totalHeight += VERTICAL_PAD * float64(len(grid.nodes)-1)
|
||||||
|
|
||||||
|
layout := [][]int{{}}
|
||||||
|
if grid.rowDominant {
|
||||||
|
targetWidth := totalWidth / float64(grid.rows)
|
||||||
|
rowWidth := 0.
|
||||||
|
rowIndex := 0
|
||||||
|
for i, n := range grid.nodes {
|
||||||
|
layout[rowIndex] = append(layout[rowIndex], i)
|
||||||
|
rowWidth += n.Width + HORIZONTAL_PAD
|
||||||
|
// add a new row if we pass the target width and there are more nodes
|
||||||
|
if rowWidth > targetWidth && i < len(grid.nodes)-1 {
|
||||||
|
layout = append(layout, []int{})
|
||||||
|
rowIndex++
|
||||||
|
rowWidth = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
targetHeight := totalHeight / float64(grid.columns)
|
||||||
|
columnHeight := 0.
|
||||||
|
columnIndex := 0
|
||||||
|
for i, n := range grid.nodes {
|
||||||
|
layout[columnIndex] = append(layout[columnIndex], i)
|
||||||
|
columnHeight += n.Height + VERTICAL_PAD
|
||||||
|
if columnHeight > targetHeight && i < len(grid.nodes)-1 {
|
||||||
|
layout = append(layout, []int{})
|
||||||
|
columnIndex++
|
||||||
|
columnHeight = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor := geo.NewPoint(0, 0)
|
||||||
|
var maxY, maxX float64
|
||||||
|
if grid.rowDominant {
|
||||||
|
// if we have 2 rows, then each row's nodes should have the same height
|
||||||
|
// . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C)
|
||||||
|
// . ├ ─ ─ ─ ─ ─ ─ ─┤ │ │ │ │ │
|
||||||
|
// . │ │ │ │ ├ ─ ─ ─ ─ ─┤ │
|
||||||
|
// . │ │ │ │ │ │ │
|
||||||
|
// . └──────────────┘ └───┘ └──────────┘ ┴
|
||||||
|
// . ┌D────────┐ ┌E────────────────┐ ┬ maxHeight(D,E)
|
||||||
|
// . │ │ │ │ │
|
||||||
|
// . │ │ │ │ │
|
||||||
|
// . │ │ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤ │
|
||||||
|
// . │ │ │ │ │
|
||||||
|
// . └─────────┘ └─────────────────┘ ┴
|
||||||
|
rowWidths := []float64{}
|
||||||
|
for _, row := range layout {
|
||||||
|
rowHeight := 0.
|
||||||
|
for _, nodeIndex := range row {
|
||||||
|
n := grid.nodes[nodeIndex]
|
||||||
|
n.TopLeft = cursor.Copy()
|
||||||
|
cursor.X += n.Width + HORIZONTAL_PAD
|
||||||
|
rowHeight = math.Max(rowHeight, n.Height)
|
||||||
|
}
|
||||||
|
rowWidth := cursor.X - HORIZONTAL_PAD
|
||||||
|
rowWidths = append(rowWidths, rowWidth)
|
||||||
|
maxX = math.Max(maxX, rowWidth)
|
||||||
|
|
||||||
|
// set all nodes in row to the same height
|
||||||
|
for _, nodeIndex := range row {
|
||||||
|
n := grid.nodes[nodeIndex]
|
||||||
|
n.Height = rowHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
// new row
|
||||||
|
cursor.X = 0
|
||||||
|
cursor.Y += rowHeight + VERTICAL_PAD
|
||||||
|
}
|
||||||
|
maxY = cursor.Y - VERTICAL_PAD
|
||||||
|
|
||||||
|
// then expand thinnest nodes to make each row the same width
|
||||||
|
// . ┌A─────────────┐ ┌B──┐ ┌C─────────┐ ┬ maxHeight(A,B,C)
|
||||||
|
// . │ │ │ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │ │
|
||||||
|
// . └──────────────┘ └───┘ └──────────┘ ┴
|
||||||
|
// . ┌D────────┬────┐ ┌E────────────────┐ ┬ maxHeight(D,E)
|
||||||
|
// . │ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │
|
||||||
|
// . │ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │
|
||||||
|
// . └─────────┴────┘ └─────────────────┘ ┴
|
||||||
|
for i, row := range layout {
|
||||||
|
rowWidth := rowWidths[i]
|
||||||
|
if rowWidth == maxX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delta := maxX - rowWidth
|
||||||
|
nodes := []*d2graph.Object{}
|
||||||
|
var widest float64
|
||||||
|
for _, nodeIndex := range row {
|
||||||
|
n := grid.nodes[nodeIndex]
|
||||||
|
widest = math.Max(widest, n.Width)
|
||||||
|
nodes = append(nodes, n)
|
||||||
|
}
|
||||||
|
sort.Slice(nodes, func(i, j int) bool {
|
||||||
|
return nodes[i].Width < nodes[j].Width
|
||||||
|
})
|
||||||
|
// expand smaller nodes to fill remaining space
|
||||||
|
for _, n := range nodes {
|
||||||
|
if n.Width < widest {
|
||||||
|
var index int
|
||||||
|
for i, nodeIndex := range row {
|
||||||
|
if n == grid.nodes[nodeIndex] {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grow := math.Min(widest-n.Width, delta)
|
||||||
|
n.Width += grow
|
||||||
|
// shift following nodes
|
||||||
|
for i := index + 1; i < len(row); i++ {
|
||||||
|
grid.nodes[row[i]].TopLeft.X += grow
|
||||||
|
}
|
||||||
|
delta -= grow
|
||||||
|
if delta <= 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if delta > 0 {
|
||||||
|
grow := delta / float64(len(row))
|
||||||
|
for i := len(row) - 1; i >= 0; i-- {
|
||||||
|
n := grid.nodes[row[i]]
|
||||||
|
n.TopLeft.X += grow * float64(i)
|
||||||
|
n.Width += grow
|
||||||
|
delta -= grow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if we have 3 columns, then each column's nodes should have the same width
|
||||||
|
// . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤
|
||||||
|
// . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐
|
||||||
|
// . └──────────────┘ │ │ │ │
|
||||||
|
// . ┌B──┬──────────┐ └──────────┘ │ │
|
||||||
|
// . │ │ ┌D────────┬┐ └─────────────────┘
|
||||||
|
// . │ │ │ │ │
|
||||||
|
// . │ │ │ ││
|
||||||
|
// . └───┴──────────┘ │ │
|
||||||
|
// . │ ││
|
||||||
|
// . └─────────┴┘
|
||||||
|
for _, column := range layout {
|
||||||
|
columnWidth := 0.
|
||||||
|
for _, nodeIndex := range column {
|
||||||
|
n := grid.nodes[nodeIndex]
|
||||||
|
n.TopLeft = cursor.Copy()
|
||||||
|
cursor.Y += n.Height + VERTICAL_PAD
|
||||||
|
columnWidth = math.Max(columnWidth, n.Width)
|
||||||
|
}
|
||||||
|
maxY = math.Max(maxY, cursor.Y-VERTICAL_PAD)
|
||||||
|
// set all nodes in column to the same width
|
||||||
|
for _, nodeIndex := range column {
|
||||||
|
n := grid.nodes[nodeIndex]
|
||||||
|
n.Width = columnWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
// new column
|
||||||
|
cursor.Y = 0
|
||||||
|
cursor.X += columnWidth + HORIZONTAL_PAD
|
||||||
|
}
|
||||||
|
maxX = cursor.X - HORIZONTAL_PAD
|
||||||
|
// then expand shortest nodes to make each column the same height
|
||||||
|
// . ├maxWidth(A,B)─┤ ├maxW(C,D)─┤ ├maxWidth(E)──────┤
|
||||||
|
// . ┌A─────────────┐ ┌C─────────┐ ┌E────────────────┐
|
||||||
|
// . ├ ─ ─ ─ ─ ─ ─ ┤ │ │ │ │
|
||||||
|
// . │ │ └──────────┘ │ │
|
||||||
|
// . └──────────────┘ ┌D─────────┐ ├ ─ ─ ─ ─ ─ ─ ─ ─ ┤
|
||||||
|
// . ┌B─────────────┐ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │
|
||||||
|
// . │ │ │ │ │ │
|
||||||
|
// . └──────────────┘ └──────────┘ └─────────────────┘
|
||||||
|
// TODO see rows
|
||||||
|
}
|
||||||
|
grid.width = maxX
|
||||||
|
grid.height = maxY
|
||||||
|
|
||||||
// position labels and icons
|
// position labels and icons
|
||||||
for _, n := range grid.nodes {
|
for _, n := range grid.nodes {
|
||||||
|
|
@ -125,37 +313,32 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*grid, error) {
|
||||||
// - translating the grid to its position placed by the core layout engine
|
// - translating the grid to its position placed by the core layout engine
|
||||||
// - restore the children of the grid
|
// - restore the children of the grid
|
||||||
// - sorts objects to their original graph order
|
// - sorts objects to their original graph order
|
||||||
func cleanup(g *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]int) {
|
func cleanup(graph *d2graph.Graph, grids map[string]*grid, objectsOrder map[string]int) {
|
||||||
var objects []*d2graph.Object
|
defer func() {
|
||||||
if g.Root.IsGrid() {
|
sort.SliceStable(graph.Objects, func(i, j int) bool {
|
||||||
objects = []*d2graph.Object{g.Root}
|
return objectsOrder[graph.Objects[i].AbsID()] < objectsOrder[graph.Objects[j].AbsID()]
|
||||||
} else {
|
})
|
||||||
objects = g.Objects
|
}()
|
||||||
|
|
||||||
|
if graph.Root.IsGrid() {
|
||||||
|
grid, exists := grids[graph.Root.AbsID()]
|
||||||
|
if exists {
|
||||||
|
grid.cleanup(graph.Root, graph)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, obj := range objects {
|
|
||||||
|
for _, obj := range graph.Objects {
|
||||||
grid, exists := grids[obj.AbsID()]
|
grid, exists := grids[obj.AbsID()]
|
||||||
if !exists {
|
if !exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
|
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
|
||||||
|
|
||||||
// shift the grid from (0, 0)
|
// shift the grid from (0, 0)
|
||||||
grid.shift(
|
grid.shift(
|
||||||
obj.TopLeft.X+CONTAINER_PADDING,
|
obj.TopLeft.X+CONTAINER_PADDING,
|
||||||
obj.TopLeft.Y+CONTAINER_PADDING,
|
obj.TopLeft.Y+CONTAINER_PADDING,
|
||||||
)
|
)
|
||||||
|
grid.cleanup(obj, graph)
|
||||||
obj.Children = make(map[string]*d2graph.Object)
|
|
||||||
obj.ChildrenArray = make([]*d2graph.Object, 0)
|
|
||||||
for _, child := range grid.nodes {
|
|
||||||
obj.Children[child.ID] = child
|
|
||||||
obj.ChildrenArray = append(obj.ChildrenArray, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
g.Objects = append(g.Objects, grid.nodes...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.SliceStable(g.Objects, func(i, j int) bool {
|
|
||||||
return objectsOrder[g.Objects[i].AbsID()] < objectsOrder[g.Objects[j].AbsID()]
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
80
e2etests/testdata/files/dagger_grid.d2
vendored
80
e2etests/testdata/files/dagger_grid.d2
vendored
|
|
@ -1,25 +1,61 @@
|
||||||
todo root level grid: {
|
rows: 4
|
||||||
rows: 4
|
style.fill: black
|
||||||
|
|
||||||
flow: {
|
flow: "" {
|
||||||
width: 800
|
width: 800
|
||||||
height: 200
|
height: 200
|
||||||
|
style: {
|
||||||
|
fill: cornflowerblue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dagger engine: {
|
|
||||||
width: 800
|
DAGGER ENGINE: {
|
||||||
}
|
width: 800
|
||||||
|
style: {
|
||||||
any docker compatible runtime: {
|
fill: beige
|
||||||
width: 800
|
stroke: darkcyan
|
||||||
}
|
font-color: blue
|
||||||
|
stroke-width: 8
|
||||||
any ci: {
|
}
|
||||||
width: 800
|
}
|
||||||
}
|
|
||||||
|
ANY DOCKER COMPATIBLE RUNTIME: {
|
||||||
windows
|
width: 800
|
||||||
linux
|
style: {
|
||||||
macos
|
fill: lightcyan
|
||||||
kubernetes
|
stroke: darkcyan
|
||||||
|
font-color: black
|
||||||
|
stroke-width: 8
|
||||||
|
}
|
||||||
|
icon: https://icons.terrastruct.com/dev%2Fdocker.svg
|
||||||
|
}
|
||||||
|
|
||||||
|
ANY CI: {
|
||||||
|
style: {
|
||||||
|
fill: gold
|
||||||
|
stroke: maroon
|
||||||
|
font-color: maroon
|
||||||
|
stroke-width: 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WINDOWS.style: {
|
||||||
|
font-color: white
|
||||||
|
fill: darkcyan
|
||||||
|
stroke: black
|
||||||
|
}
|
||||||
|
LINUX.style: {
|
||||||
|
font-color: white
|
||||||
|
fill: darkcyan
|
||||||
|
stroke: black
|
||||||
|
}
|
||||||
|
MACOS.style: {
|
||||||
|
font-color: white
|
||||||
|
fill: darkcyan
|
||||||
|
stroke: black
|
||||||
|
}
|
||||||
|
KUBERNETES.style: {
|
||||||
|
font-color: white
|
||||||
|
fill: darkcyan
|
||||||
|
stroke: black
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
e2etests/testdata/files/teleport_grid.d2
vendored
2
e2etests/testdata/files/teleport_grid.d2
vendored
|
|
@ -9,7 +9,7 @@ teleport -> identity provider
|
||||||
teleport <- identity provider
|
teleport <- identity provider
|
||||||
|
|
||||||
users: "" {
|
users: "" {
|
||||||
rows: 2
|
columns: 1
|
||||||
|
|
||||||
Engineers: {
|
Engineers: {
|
||||||
shape: circle
|
shape: circle
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue