layout grid including outside label sizes
This commit is contained in:
parent
c7ec370a54
commit
b9c139de59
2 changed files with 67 additions and 54 deletions
|
|
@ -2,7 +2,6 @@ package d2grid
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"oss.terrastruct.com/d2/d2graph"
|
||||
"oss.terrastruct.com/d2/lib/geo"
|
||||
|
|
@ -112,19 +111,3 @@ func (gd *gridDiagram) shift(dx, dy float64) {
|
|||
e.Move(dx, dy)
|
||||
}
|
||||
}
|
||||
|
||||
func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) {
|
||||
obj.Children = make(map[string]*d2graph.Object)
|
||||
obj.ChildrenArray = make([]*d2graph.Object, 0)
|
||||
|
||||
restore := func(parent, child *d2graph.Object) {
|
||||
parent.Children[strings.ToLower(child.ID)] = child
|
||||
parent.ChildrenArray = append(parent.ChildrenArray, child)
|
||||
graph.Objects = append(graph.Objects, child)
|
||||
}
|
||||
for _, child := range gd.objects {
|
||||
restore(obj, child)
|
||||
child.IterDescendants(restore)
|
||||
}
|
||||
graph.Edges = append(graph.Edges, gd.edges...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,43 +77,6 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
|
|||
}
|
||||
}
|
||||
|
||||
// also check for grid cells with outside top labels or icons
|
||||
// the first grid object is at the top (and always exists)
|
||||
topY := gd.objects[0].TopLeft.Y
|
||||
highestOutside := topY
|
||||
for _, o := range gd.objects {
|
||||
// we only want to compute label positions for objects at the top of the grid
|
||||
if o.TopLeft.Y > topY {
|
||||
if gd.rowDirected {
|
||||
// if the grid is rowDirected (row1, row2, etc) we can stop after finishing the first row
|
||||
break
|
||||
} else {
|
||||
// otherwise we continue until the next column
|
||||
continue
|
||||
}
|
||||
}
|
||||
if o.LabelPosition != nil {
|
||||
labelPosition := label.Position(*o.LabelPosition)
|
||||
if labelPosition.IsOutside() {
|
||||
labelTL := o.GetLabelTopLeft()
|
||||
if labelTL.Y < highestOutside {
|
||||
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 highestOutside < topY {
|
||||
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)
|
||||
|
|
@ -179,12 +142,19 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
|
|||
func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) {
|
||||
gd := newGridDiagram(obj)
|
||||
|
||||
// to handle objects with outside labels, we adjust their dimensions before layout and
|
||||
// after layout, we remove the label adjustment and reposition TopLeft if needed
|
||||
// TODO
|
||||
revertAdjustments := gd.sizeForOutsideLabels()
|
||||
|
||||
if gd.rows != 0 && gd.columns != 0 {
|
||||
gd.layoutEvenly(g, obj)
|
||||
} else {
|
||||
gd.layoutDynamic(g, obj)
|
||||
}
|
||||
|
||||
revertAdjustments()
|
||||
|
||||
// position labels and icons
|
||||
for _, o := range gd.objects {
|
||||
if o.Icon != nil {
|
||||
|
|
@ -871,3 +841,63 @@ func getDistToTarget(layout [][]*d2graph.Object, targetSize float64, horizontalG
|
|||
}
|
||||
return totalDelta
|
||||
}
|
||||
|
||||
func (gd *gridDiagram) sizeForOutsideLabels() (revert func()) {
|
||||
widthAdjustments := make(map[*d2graph.Object]float64)
|
||||
heightAdjustments := make(map[*d2graph.Object]float64)
|
||||
|
||||
// TODO icons!
|
||||
for _, o := range gd.objects {
|
||||
if !o.HasLabel() || o.LabelPosition == nil {
|
||||
continue
|
||||
}
|
||||
position := label.Position(*o.LabelPosition)
|
||||
|
||||
width := float64(o.LabelDimensions.Width + 2*label.PADDING)
|
||||
height := float64(o.LabelDimensions.Height + 2*label.PADDING)
|
||||
|
||||
switch position {
|
||||
case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight,
|
||||
label.OutsideBottomLeft, label.OutsideBottomCenter, label.OutsideBottomRight:
|
||||
heightAdjustments[o] = height
|
||||
if width > o.Width {
|
||||
widthAdjustments[o] = width - o.Width
|
||||
}
|
||||
case label.OutsideLeftTop, label.OutsideLeftMiddle, label.OutsideLeftBottom,
|
||||
label.OutsideRightTop, label.OutsideRightMiddle, label.OutsideRightBottom:
|
||||
widthAdjustments[o] = width
|
||||
if height > o.Height {
|
||||
heightAdjustments[o] = height - o.Height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return func() {
|
||||
for _, o := range gd.objects {
|
||||
if !o.HasLabel() || o.LabelPosition == nil {
|
||||
continue
|
||||
}
|
||||
widthAdjustment, hasW := widthAdjustments[o]
|
||||
heightAdjustment, hasH := heightAdjustments[o]
|
||||
if !hasW && !hasH {
|
||||
continue
|
||||
}
|
||||
|
||||
position := label.Position(*o.LabelPosition)
|
||||
|
||||
o.Height -= heightAdjustment
|
||||
o.Width -= widthAdjustment
|
||||
|
||||
switch position {
|
||||
case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight:
|
||||
if hasH {
|
||||
o.TopLeft.Y += heightAdjustment
|
||||
}
|
||||
case label.OutsideLeftTop, label.OutsideLeftMiddle, label.OutsideLeftBottom:
|
||||
if hasW {
|
||||
o.TopLeft.X += widthAdjustment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue