fit container padding
This commit is contained in:
parent
180a444ca0
commit
f99405eaa3
1 changed files with 133 additions and 3 deletions
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"oss.terrastruct.com/d2/lib/geo"
|
"oss.terrastruct.com/d2/lib/geo"
|
||||||
"oss.terrastruct.com/d2/lib/label"
|
"oss.terrastruct.com/d2/lib/label"
|
||||||
"oss.terrastruct.com/d2/lib/log"
|
"oss.terrastruct.com/d2/lib/log"
|
||||||
|
"oss.terrastruct.com/d2/lib/shape"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed setup.js
|
//go:embed setup.js
|
||||||
|
|
@ -31,9 +32,9 @@ var setupJS string
|
||||||
var dagreJS string
|
var dagreJS string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MIN_RANK_SEP = 60
|
MIN_RANK_SEP = 60
|
||||||
EDGE_LABEL_GAP = 20
|
EDGE_LABEL_GAP = 20
|
||||||
MIN_MARGIN = 10.
|
DEFAULT_PADDING = 30.
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigurableOpts struct {
|
type ConfigurableOpts struct {
|
||||||
|
|
@ -266,6 +267,8 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
|
||||||
adjustRankSpacing(g, float64(rootAttrs.ranksep), isHorizontal)
|
adjustRankSpacing(g, float64(rootAttrs.ranksep), isHorizontal)
|
||||||
adjustCrossRankSpacing(g, float64(rootAttrs.ranksep), !isHorizontal)
|
adjustCrossRankSpacing(g, float64(rootAttrs.ranksep), !isHorizontal)
|
||||||
|
|
||||||
|
fitContainerPadding(g, float64(rootAttrs.ranksep), isHorizontal)
|
||||||
|
|
||||||
for _, edge := range g.Edges {
|
for _, edge := range g.Edges {
|
||||||
points := edge.Route
|
points := edge.Route
|
||||||
startIndex, endIndex := 0, len(points)-1
|
startIndex, endIndex := 0, len(points)-1
|
||||||
|
|
@ -1306,3 +1309,130 @@ func adjustCrossRankSpacing(g *d2graph.Graph, rankSep float64, isHorizontal bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fitContainerPadding(g *d2graph.Graph, rankSep float64, isHorizontal bool) {
|
||||||
|
for _, obj := range g.Root.ChildrenArray {
|
||||||
|
fitPadding(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fitPadding(obj *d2graph.Object) {
|
||||||
|
dslShape := strings.ToLower(obj.Shape.Value)
|
||||||
|
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[dslShape]
|
||||||
|
// Note: there's no shape-specific padding/placement in dagre yet
|
||||||
|
if !obj.IsContainer() || shapeType != shape.SQUARE_TYPE {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, child := range obj.ChildrenArray {
|
||||||
|
fitPadding(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, padding := getSpacing(obj)
|
||||||
|
padding.top = math.Max(padding.top, DEFAULT_PADDING)
|
||||||
|
padding.bottom = math.Max(padding.bottom, DEFAULT_PADDING)
|
||||||
|
padding.left = math.Max(padding.left, DEFAULT_PADDING)
|
||||||
|
padding.right = math.Max(padding.right, DEFAULT_PADDING)
|
||||||
|
|
||||||
|
innerTop := math.Inf(1)
|
||||||
|
innerBottom := math.Inf(-1)
|
||||||
|
innerLeft := math.Inf(1)
|
||||||
|
innerRight := math.Inf(-1)
|
||||||
|
|
||||||
|
for _, child := range obj.ChildrenArray {
|
||||||
|
margin, _ := getSpacing(child)
|
||||||
|
|
||||||
|
innerTop = math.Min(innerTop, child.TopLeft.Y-math.Max(margin.top, padding.top))
|
||||||
|
innerBottom = math.Max(innerBottom, child.TopLeft.Y+child.Height+math.Max(margin.bottom, padding.bottom))
|
||||||
|
innerLeft = math.Min(innerLeft, child.TopLeft.X-math.Max(margin.left, padding.left))
|
||||||
|
innerRight = math.Max(innerRight, child.TopLeft.X+child.Width+math.Max(margin.right, padding.right))
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTop := obj.TopLeft.Y
|
||||||
|
currentBottom := obj.TopLeft.Y + obj.Height
|
||||||
|
currentLeft := obj.TopLeft.X
|
||||||
|
currentRight := obj.TopLeft.X + obj.Width
|
||||||
|
|
||||||
|
topDelta := innerTop - currentTop
|
||||||
|
bottomDelta := currentBottom - innerBottom
|
||||||
|
leftDelta := innerLeft - currentLeft
|
||||||
|
rightDelta := currentRight - innerRight
|
||||||
|
|
||||||
|
if 0 < topDelta {
|
||||||
|
obj.TopLeft.Y += topDelta
|
||||||
|
obj.Height -= topDelta
|
||||||
|
adjustEdges(obj, currentTop, topDelta, false)
|
||||||
|
}
|
||||||
|
if 0 < bottomDelta {
|
||||||
|
obj.Height -= bottomDelta
|
||||||
|
adjustEdges(obj, currentBottom, -bottomDelta, false)
|
||||||
|
}
|
||||||
|
if 0 < leftDelta {
|
||||||
|
obj.TopLeft.X += leftDelta
|
||||||
|
obj.Width -= leftDelta
|
||||||
|
adjustEdges(obj, currentLeft, leftDelta, true)
|
||||||
|
}
|
||||||
|
if 0 < rightDelta {
|
||||||
|
obj.Width -= rightDelta
|
||||||
|
adjustEdges(obj, currentRight, -rightDelta, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func adjustEdges(obj *d2graph.Object, objPosition, delta float64, isHorizontal bool) {
|
||||||
|
adjust := func(p *geo.Point) {
|
||||||
|
var position float64
|
||||||
|
if isHorizontal {
|
||||||
|
position = p.X
|
||||||
|
} else {
|
||||||
|
position = p.Y
|
||||||
|
}
|
||||||
|
if geo.PrecisionCompare(position, objPosition, 1) == 0 {
|
||||||
|
if isHorizontal {
|
||||||
|
p.X += delta
|
||||||
|
} else {
|
||||||
|
p.Y += delta
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// check side corners
|
||||||
|
var isOnSide bool
|
||||||
|
if isHorizontal {
|
||||||
|
if geo.PrecisionCompare(p.Y, obj.TopLeft.Y, 1) == 0 ||
|
||||||
|
geo.PrecisionCompare(p.Y, obj.TopLeft.Y+obj.Height, 1) == 0 {
|
||||||
|
isOnSide = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if geo.PrecisionCompare(p.X, obj.TopLeft.X, 1) == 0 ||
|
||||||
|
geo.PrecisionCompare(p.X, obj.TopLeft.X+obj.Width, 1) == 0 {
|
||||||
|
isOnSide = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isOnSide {
|
||||||
|
var isInRange bool
|
||||||
|
if delta > 0 {
|
||||||
|
if objPosition < position && position < objPosition+delta {
|
||||||
|
isInRange = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if objPosition+delta < position && position < objPosition {
|
||||||
|
isInRange = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isInRange {
|
||||||
|
if isHorizontal {
|
||||||
|
p.X = objPosition + delta
|
||||||
|
} else {
|
||||||
|
p.Y = objPosition + delta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, edge := range obj.Graph.Edges {
|
||||||
|
if edge.Src == obj {
|
||||||
|
adjust(edge.Route[0])
|
||||||
|
}
|
||||||
|
if edge.Dst == obj {
|
||||||
|
adjust(edge.Route[len(edge.Route)-1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue