handle merging multiple different child margins and container padding in rank direction

This commit is contained in:
Gavin Nishizawa 2023-07-12 14:21:51 -07:00
parent b6795e65e1
commit 2c5c395315
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD

View file

@ -754,6 +754,42 @@ func shiftDown(g *d2graph.Graph, start, distance float64, isHorizontal bool) {
} }
} }
func shiftUp(g *d2graph.Graph, start, distance float64, isHorizontal bool) {
if isHorizontal {
for _, obj := range g.Objects {
if start < obj.TopLeft.X {
continue
}
obj.TopLeft.X -= distance
}
for _, edge := range g.Edges {
for _, p := range edge.Route {
// Note: == so incoming edge shifts down with object at startY
if start <= p.X {
continue
}
p.X -= distance
}
}
} else {
for _, obj := range g.Objects {
if start < obj.TopLeft.Y {
continue
}
obj.TopLeft.Y -= distance
}
for _, edge := range g.Edges {
for _, p := range edge.Route {
// Note: == so incoming edge shifts down with object at startY
if start <= p.Y {
continue
}
p.Y -= distance
}
}
}
}
// shift down everything that is below start // shift down everything that is below start
// shift all nodes that are reachable via an edge or being directly below a shifting node or expanding container // shift all nodes that are reachable via an edge or being directly below a shifting node or expanding container
// expand containers to wrap shifted nodes // expand containers to wrap shifted nodes
@ -1040,11 +1076,15 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
if _, has := startingAncestorPositions[parent]; !has { if _, has := startingAncestorPositions[parent]; !has {
startingAncestorPositions[parent] = math.Inf(1) startingAncestorPositions[parent] = math.Inf(1)
} }
var startPosition float64
if isHorizontal { if isHorizontal {
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], parent.TopLeft.X+rankSep/2.-MIN_MARGIN-padding.left) paddingIncrease := math.Max(0, padding.left-rankSep/2)
startPosition = parent.TopLeft.X - paddingIncrease
} else { } else {
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], parent.TopLeft.Y+rankSep/2.-MIN_MARGIN-padding.top) paddingIncrease := math.Max(0, padding.top-rankSep/2)
startPosition = parent.TopLeft.Y - paddingIncrease
} }
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], startPosition)
for _, child := range parent.ChildrenArray { for _, child := range parent.ChildrenArray {
if r, has := objectRanks[child]; has { if r, has := objectRanks[child]; has {
if r != rank { if r != rank {
@ -1059,10 +1099,11 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
} }
margin, _ := getSpacing(child) margin, _ := getSpacing(child)
if isHorizontal { if isHorizontal {
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], child.TopLeft.X-margin.left-MIN_MARGIN) startPosition = child.TopLeft.X - margin.left
} else { } else {
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], child.TopLeft.Y-margin.top-MIN_MARGIN) startPosition = child.TopLeft.Y - margin.top
} }
startingAncestorPositions[parent] = math.Min(startingAncestorPositions[parent], startPosition)
} }
if parent.Parent != g.Root { if parent.Parent != g.Root {
ancestors = append(ancestors, parent.Parent) ancestors = append(ancestors, parent.Parent)
@ -1073,20 +1114,19 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
endingAncestorPositions := make(map[*d2graph.Object]float64) endingAncestorPositions := make(map[*d2graph.Object]float64)
for len(endingParents) > 0 { for len(endingParents) > 0 {
delta := 0.
var ancestors []*d2graph.Object var ancestors []*d2graph.Object
for _, parent := range endingParents { for _, parent := range endingParents {
_, padding := getSpacing(parent) _, padding := getSpacing(parent)
if _, has := endingAncestorPositions[parent]; !has { if _, has := endingAncestorPositions[parent]; !has {
endingAncestorPositions[parent] = math.Inf(-1) endingAncestorPositions[parent] = math.Inf(-1)
} }
var endPosition float64
if isHorizontal { if isHorizontal {
delta = math.Max(delta, padding.right) endPosition = parent.TopLeft.X + parent.Width + padding.right - rankSep/2.
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], parent.TopLeft.X+parent.Width-rankSep/2+MIN_MARGIN+padding.right)
} else { } else {
delta = math.Max(delta, padding.bottom) endPosition = parent.TopLeft.Y + parent.Height + padding.bottom - rankSep/2.
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], parent.TopLeft.Y+parent.Height-rankSep/2+MIN_MARGIN+padding.bottom)
} }
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], endPosition)
for _, child := range parent.ChildrenArray { for _, child := range parent.ChildrenArray {
if r, has := objectRanks[child]; has { if r, has := objectRanks[child]; has {
if r != rank { if r != rank {
@ -1100,13 +1140,13 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
} }
} }
margin, _ := getSpacing(child) margin, _ := getSpacing(child)
if isHorizontal { if isHorizontal {
delta = math.Max(delta, margin.right) endPosition = child.TopLeft.X + child.Width + margin.right
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], child.TopLeft.X+child.Width+margin.right+MIN_MARGIN)
} else { } else {
delta = math.Max(delta, margin.bottom) endPosition = child.TopLeft.Y + child.Height + margin.bottom
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], child.TopLeft.Y+child.Height+margin.bottom+MIN_MARGIN)
} }
endingAncestorPositions[parent] = math.Max(endingAncestorPositions[parent], endPosition)
} }
if parent.Parent != g.Root { if parent.Parent != g.Root {
ancestors = append(ancestors, parent.Parent) ancestors = append(ancestors, parent.Parent)
@ -1115,70 +1155,38 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
endingParents = ancestors endingParents = ancestors
} }
endingAncestorPositionOrder := make([]*d2graph.Object, 0, len(endingAncestorPositions)) startingAdjustmentOrder := make([]*d2graph.Object, 0, len(startingAncestorPositions))
for ancestor := range endingAncestorPositions {
endingAncestorPositionOrder = append(endingAncestorPositionOrder, ancestor)
}
// adjust rank ancestors bottom-up
sort.Slice(endingAncestorPositionOrder, func(i, j int) bool {
return endingAncestorPositions[endingAncestorPositionOrder[i]] > endingAncestorPositions[endingAncestorPositionOrder[j]]
})
for _, ancestor := range endingAncestorPositionOrder {
var endDelta float64
if isHorizontal {
endDelta = endingAncestorPositions[ancestor] - (ancestor.TopLeft.X + ancestor.Width)
} else {
endDelta = endingAncestorPositions[ancestor] - (ancestor.TopLeft.Y + ancestor.Height)
}
if endDelta > 0 {
var position float64
if isHorizontal {
position = ancestor.TopLeft.X + ancestor.Width - 1
} else {
position = ancestor.TopLeft.Y + ancestor.Height - 1
}
for _, obj := range g.Objects {
if !obj.IsContainer() {
continue
}
start := startingParentRanks[obj]
end := endingParentRanks[obj]
if start <= rank && rank <= end {
if isHorizontal && obj.TopLeft.X+obj.Width > position {
obj.Width += endDelta
} else if !isHorizontal && obj.TopLeft.Y+obj.Height > position {
obj.Height += endDelta
}
}
}
shiftDown(g, position, endDelta, isHorizontal)
}
}
startingAncestorPositionOrder := make([]*d2graph.Object, 0, len(startingAncestorPositions))
for ancestor := range startingAncestorPositions { for ancestor := range startingAncestorPositions {
startingAncestorPositionOrder = append(startingAncestorPositionOrder, ancestor) startingAdjustmentOrder = append(startingAdjustmentOrder, ancestor)
} }
// adjust rank ancestors bottom-up // adjust starting ancestors top-down
sort.Slice(startingAncestorPositionOrder, func(i, j int) bool { sort.Slice(startingAdjustmentOrder, func(i, j int) bool {
return startingAncestorPositions[startingAncestorPositionOrder[i]] > startingAncestorPositions[startingAncestorPositionOrder[j]] iPos := startingAncestorPositions[startingAdjustmentOrder[i]]
jPos := startingAncestorPositions[startingAdjustmentOrder[j]]
return iPos < jPos
}) })
for _, ancestor := range startingAncestorPositionOrder { endingAdjustmentOrder := make([]*d2graph.Object, 0, len(endingAncestorPositions))
var endDelta float64 for ancestor := range endingAncestorPositions {
if isHorizontal { endingAdjustmentOrder = append(endingAdjustmentOrder, ancestor)
endDelta = ancestor.TopLeft.X - startingAncestorPositions[ancestor]
} else {
endDelta = ancestor.TopLeft.Y - startingAncestorPositions[ancestor]
} }
if endDelta > 0 {
// adjust ending ancestors bottom-up
sort.Slice(endingAdjustmentOrder, func(i, j int) bool {
iPos := endingAncestorPositions[endingAdjustmentOrder[i]]
jPos := endingAncestorPositions[endingAdjustmentOrder[j]]
return jPos < iPos
})
for _, ancestor := range endingAdjustmentOrder {
var position float64 var position float64
if isHorizontal { if isHorizontal {
position = ancestor.TopLeft.X + 1 position = ancestor.TopLeft.X + ancestor.Width
} else { } else {
position = ancestor.TopLeft.Y + 1 position = ancestor.TopLeft.Y + ancestor.Height
} }
endDelta := endingAncestorPositions[ancestor] - position
if endDelta > 0 {
for _, obj := range g.Objects { for _, obj := range g.Objects {
if !obj.IsContainer() { if !obj.IsContainer() {
continue continue
@ -1186,9 +1194,10 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
start := startingParentRanks[obj] start := startingParentRanks[obj]
end := endingParentRanks[obj] end := endingParentRanks[obj]
if start <= rank && rank <= end { if start <= rank && rank <= end {
if isHorizontal && obj.TopLeft.X+obj.Width > position { if isHorizontal && position <= obj.TopLeft.X+obj.Width {
obj.Width += endDelta obj.Width += endDelta
} else if !isHorizontal && obj.TopLeft.Y+obj.Height > position { } else if !isHorizontal &&
position <= obj.TopLeft.Y+obj.Height {
obj.Height += endDelta obj.Height += endDelta
} }
} }
@ -1196,6 +1205,33 @@ func adjustRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
shiftDown(g, position, endDelta, isHorizontal) shiftDown(g, position, endDelta, isHorizontal)
} }
} }
for _, ancestor := range startingAdjustmentOrder {
var position float64
if isHorizontal {
position = ancestor.TopLeft.X
} else {
position = ancestor.TopLeft.Y
}
startDelta := position - startingAncestorPositions[ancestor]
if startDelta > 0 {
for _, obj := range g.Objects {
if !obj.IsContainer() {
continue
}
start := startingParentRanks[obj]
end := endingParentRanks[obj]
if start <= rank && rank <= end {
if isHorizontal && obj.TopLeft.X <= position {
obj.Width += startDelta
} else if !isHorizontal && obj.TopLeft.Y <= position {
obj.Height += startDelta
}
}
}
shiftUp(g, position, startDelta, isHorizontal)
}
}
} }
} }