adjust grid for outside top labels

This commit is contained in:
Gavin Nishizawa 2023-05-26 17:47:31 -07:00
parent 297819dc35
commit 6d8dde153e
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
4 changed files with 70 additions and 14 deletions

View file

@ -26,6 +26,7 @@ import (
"oss.terrastruct.com/d2/d2themes/d2themescatalog" "oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/d2/lib/color" "oss.terrastruct.com/d2/lib/color"
"oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label"
"oss.terrastruct.com/d2/lib/shape" "oss.terrastruct.com/d2/lib/shape"
"oss.terrastruct.com/d2/lib/textmeasure" "oss.terrastruct.com/d2/lib/textmeasure"
) )
@ -1989,3 +1990,36 @@ func (obj *Object) GetModifierElementAdjustments() (dx, dy float64) {
} }
return dx, dy return dx, dy
} }
func (obj *Object) ToShape() shape.Shape {
tl := obj.TopLeft
if tl == nil {
tl = geo.NewPoint(0, 0)
}
dslShape := strings.ToLower(obj.Shape.Value)
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[dslShape]
contentBox := geo.NewBox(tl, obj.Width, obj.Height)
return shape.NewShape(shapeType, contentBox)
}
func (obj *Object) GetLabelTopLeft() *geo.Point {
if obj.LabelPosition == nil {
return nil
}
s := obj.ToShape()
labelPosition := label.Position(*obj.LabelPosition)
var box *geo.Box
if labelPosition.IsOutside() {
box = s.GetBox()
} else {
box = s.GetInnerBox()
}
labelTL := labelPosition.GetPointOnBox(box, label.PADDING,
float64(obj.LabelDimensions.Width),
float64(obj.LabelDimensions.Height),
)
return labelTL
}

View file

@ -119,9 +119,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
} }
if obj.Icon != nil && obj.Shape.Value != d2target.ShapeImage { if obj.Icon != nil && obj.Shape.Value != d2target.ShapeImage {
contentBox := geo.NewBox(geo.NewPoint(0, 0), float64(obj.Width), float64(obj.Height)) s := obj.ToShape()
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[obj.Shape.Value]
s := shape.NewShape(shapeType, contentBox)
iconSize := d2target.GetIconSize(s.GetInnerBox(), string(label.InsideTopLeft)) iconSize := d2target.GetIconSize(s.GetInnerBox(), string(label.InsideTopLeft))
// Since dagre container labels are pushed up, we don't want a child container to collide // Since dagre container labels are pushed up, we don't want a child container to collide
maxContainerLabelHeight = go2.Max(maxContainerLabelHeight, (iconSize+label.PADDING*2)*2) maxContainerLabelHeight = go2.Max(maxContainerLabelHeight, (iconSize+label.PADDING*2)*2)
@ -491,8 +489,8 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
} }
} }
srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Shape.Value)], edge.Src.Box) srcShape := edge.Src.ToShape()
dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Shape.Value)], edge.Dst.Box) dstShape := edge.Dst.ToShape()
// trace the edge to the specific shape's border // trace the edge to the specific shape's border
points[startIndex] = shape.TraceToShapeBorder(srcShape, start, points[startIndex+1]) points[startIndex] = shape.TraceToShapeBorder(srcShape, start, points[startIndex+1])

View file

@ -501,8 +501,8 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
} }
} }
srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Shape.Value)], edge.Src.Box) srcShape := edge.Src.ToShape()
dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Shape.Value)], edge.Dst.Box) dstShape := edge.Dst.ToShape()
// trace the edge to the specific shape's border // trace the edge to the specific shape's border
points[startIndex] = shape.TraceToShapeBorder(srcShape, points[startIndex], points[startIndex+1]) points[startIndex] = shape.TraceToShapeBorder(srcShape, points[startIndex], points[startIndex+1])

View file

@ -6,13 +6,10 @@ import (
"fmt" "fmt"
"math" "math"
"sort" "sort"
"strings"
"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/d2/lib/shape"
"oss.terrastruct.com/util-go/go2" "oss.terrastruct.com/util-go/go2"
) )
@ -104,13 +101,12 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L
if obj.GridGap != nil || obj.VerticalGap != nil { if obj.GridGap != nil || obj.VerticalGap != nil {
verticalPadding = gd.verticalGap verticalPadding = gd.verticalGap
} }
// size shape according to grid // size shape according to grid
obj.SizeToContent(float64(gd.width), float64(gd.height), float64(2*horizontalPadding), float64(2*verticalPadding)) obj.SizeToContent(gd.width, gd.height, float64(2*horizontalPadding), float64(2*verticalPadding))
// compute where the grid should be placed inside shape // compute where the grid should be placed inside shape
dslShape := strings.ToLower(obj.Shape.Value) s := obj.ToShape()
shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[dslShape]
s := shape.NewShape(shapeType, geo.NewBox(geo.NewPoint(0, 0), obj.Width, obj.Height))
innerBox := s.GetInnerBox() innerBox := s.GetInnerBox()
if innerBox.TopLeft.X != 0 || innerBox.TopLeft.Y != 0 { if innerBox.TopLeft.X != 0 || innerBox.TopLeft.Y != 0 {
gd.shift(innerBox.TopLeft.X, innerBox.TopLeft.Y) gd.shift(innerBox.TopLeft.X, innerBox.TopLeft.Y)
@ -126,6 +122,34 @@ func withoutGridDiagrams(ctx context.Context, g *d2graph.Graph, layout d2graph.L
} }
if obj.LabelDimensions.Height != 0 { if obj.LabelDimensions.Height != 0 {
labelHeight := float64(obj.LabelDimensions.Height) + 2*label.PADDING labelHeight := float64(obj.LabelDimensions.Height) + 2*label.PADDING
{
// also check for grid cells with outside top labels
topY := gd.objects[0].TopLeft.Y
highestLabel := topY
for _, o := range gd.objects {
if o.TopLeft.Y > topY {
if gd.rowDirected {
break
} else {
continue
}
}
if o.LabelPosition != nil {
labelPosition := label.Position(*o.LabelPosition)
if labelPosition.IsOutside() {
labelTL := o.GetLabelTopLeft()
if labelTL.Y < highestLabel {
highestLabel = labelTL.Y
}
}
}
}
if highestLabel < topY {
labelHeight += topY - highestLabel + 2*label.PADDING
}
}
if labelHeight > float64(verticalPadding) { if labelHeight > float64(verticalPadding) {
// if the label doesn't fit within the padding, we need to add more // if the label doesn't fit within the padding, we need to add more
grow := labelHeight - float64(verticalPadding) grow := labelHeight - float64(verticalPadding)