fix grid icon positioning

This commit is contained in:
Gavin Nishizawa 2023-05-30 11:59:39 -07:00
parent f64c0f1c77
commit 176df52cec
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
3 changed files with 75 additions and 48 deletions

View file

@ -238,7 +238,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
obj.Width = math.Ceil(dn.Width) obj.Width = math.Ceil(dn.Width)
obj.Height = math.Ceil(dn.Height) obj.Height = math.Ceil(dn.Height)
if obj.HasLabel() { if obj.HasLabel() && obj.LabelPosition == nil {
if len(obj.ChildrenArray) > 0 { if len(obj.ChildrenArray) > 0 {
obj.LabelPosition = go2.Pointer(string(label.OutsideTopCenter)) obj.LabelPosition = go2.Pointer(string(label.OutsideTopCenter))
} else if obj.HasOutsideBottomLabel() { } else if obj.HasOutsideBottomLabel() {
@ -251,7 +251,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
} }
} }
if obj.Icon != nil { if obj.Icon != nil && obj.IconPosition == nil {
if len(obj.ChildrenArray) > 0 { if len(obj.ChildrenArray) > 0 {
obj.IconPosition = go2.Pointer(string(label.OutsideTopLeft)) obj.IconPosition = go2.Pointer(string(label.OutsideTopLeft))
obj.LabelPosition = go2.Pointer(string(label.OutsideTopRight)) obj.LabelPosition = go2.Pointer(string(label.OutsideTopRight))

View file

@ -407,7 +407,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
obj.Width = math.Ceil(n.Width) obj.Width = math.Ceil(n.Width)
obj.Height = math.Ceil(n.Height) obj.Height = math.Ceil(n.Height)
if obj.HasLabel() { if obj.HasLabel() && obj.LabelPosition == nil {
if len(obj.ChildrenArray) > 0 { if len(obj.ChildrenArray) > 0 {
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
} else if obj.HasOutsideBottomLabel() { } else if obj.HasOutsideBottomLabel() {
@ -419,7 +419,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
} }
} }
if obj.Icon != nil { if obj.Icon != nil && obj.IconPosition == nil {
if len(obj.ChildrenArray) > 0 { if len(obj.ChildrenArray) > 0 {
obj.IconPosition = go2.Pointer(string(label.InsideTopLeft)) obj.IconPosition = go2.Pointer(string(label.InsideTopLeft))
obj.LabelPosition = go2.Pointer(string(label.InsideTopRight)) obj.LabelPosition = go2.Pointer(string(label.InsideTopRight))

View file

@ -8,6 +8,7 @@ import (
"sort" "sort"
"oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2target"
"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/util-go/go2" "oss.terrastruct.com/util-go/go2"
@ -112,21 +113,37 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L
gd.shift(innerBox.TopLeft.X, innerBox.TopLeft.Y) gd.shift(innerBox.TopLeft.X, innerBox.TopLeft.Y)
} }
var dx, dy float64 // compute how much space the label and icon occupy
if obj.LabelDimensions.Width != 0 { var occupiedWidth, occupiedHeight float64
labelWidth := float64(obj.LabelDimensions.Width) + 2*label.PADDING if obj.Icon != nil {
if labelWidth > obj.Width { iconSpace := float64(d2target.MAX_ICON_SIZE + 2*label.PADDING)
dx = (labelWidth - obj.Width) / 2 occupiedWidth = iconSpace
obj.Width = labelWidth occupiedHeight = iconSpace
} }
}
if obj.LabelDimensions.Height != 0 {
labelHeight := float64(obj.LabelDimensions.Height) + 2*label.PADDING
// also check for grid cells with outside top labels var dx, dy float64
if obj.LabelDimensions.Height != 0 {
occupiedHeight = math.Max(
occupiedHeight,
float64(obj.LabelDimensions.Height)+2*label.PADDING,
)
}
if obj.LabelDimensions.Width != 0 {
// . ├────┤───────├────┤
// . icon label icon
// with an icon in top left we need 2x the space to fit the label in the center
occupiedWidth *= 2
occupiedWidth += float64(obj.LabelDimensions.Width) + 2*label.PADDING
if occupiedWidth > obj.Width {
dx = (occupiedWidth - obj.Width) / 2
obj.Width = occupiedWidth
}
}
// also check for grid cells with outside top labels or icons
// the first grid object is at the top (and always exists) // the first grid object is at the top (and always exists)
topY := gd.objects[0].TopLeft.Y topY := gd.objects[0].TopLeft.Y
highestLabel := topY highestOutside := topY
for _, o := range gd.objects { for _, o := range gd.objects {
// we only want to compute label positions for objects at the top of the grid // we only want to compute label positions for objects at the top of the grid
if o.TopLeft.Y > topY { if o.TopLeft.Y > topY {
@ -142,32 +159,42 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L
labelPosition := label.Position(*o.LabelPosition) labelPosition := label.Position(*o.LabelPosition)
if labelPosition.IsOutside() { if labelPosition.IsOutside() {
labelTL := o.GetLabelTopLeft() labelTL := o.GetLabelTopLeft()
if labelTL.Y < highestLabel { if labelTL.Y < highestOutside {
highestLabel = labelTL.Y highestOutside = labelTL.Y
}
}
}
if o.IconPosition != nil {
switch label.Position(*o.IconPosition) {
case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight:
iconSpace := float64(d2target.MAX_ICON_SIZE + label.PADDING)
if topY-iconSpace < highestOutside {
highestOutside = topY - iconSpace
} }
} }
} }
} }
if highestLabel < topY { if highestOutside < topY {
labelHeight += topY - highestLabel + 2*label.PADDING occupiedHeight += topY - highestOutside + 2*label.PADDING
}
if occupiedHeight > float64(verticalPadding) {
// if the label doesn't fit within the padding, we need to add more
dy = occupiedHeight - float64(verticalPadding)
obj.Height += dy
} }
if labelHeight > float64(verticalPadding) {
// if the label doesn't fit within the padding, we need to add more
grow := labelHeight - float64(verticalPadding)
dy = grow
obj.Height += grow
}
}
// we need to center children if we have to expand to fit the container label // we need to center children if we have to expand to fit the container label
if dx != 0 || dy != 0 { if dx != 0 || dy != 0 {
gd.shift(dx, dy) gd.shift(dx, dy)
} }
} }
if obj.LabelPosition == nil { if obj.HasLabel() {
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
} }
if obj.Icon != nil {
obj.IconPosition = go2.Pointer(string(label.InsideTopLeft))
}
gridDiagrams[obj.AbsID()] = gd gridDiagrams[obj.AbsID()] = gd
for _, o := range gd.objects { for _, o := range gd.objects {