Combine Row/Column layouts into Contract layout

This commit is contained in:
Sasha Koshka 2024-05-17 03:56:49 -04:00
parent 68d49e1b02
commit 1cb9e8091e
2 changed files with 86 additions and 83 deletions

View File

@ -119,9 +119,5 @@ func (flow Flow) deltaMinor (rectangle image.Rectangle) int {
} }
} }
func (flow Flow) fallback () tomo.Layout { func (flow Flow) fallback () tomo.Layout {
if flow.v() { return Contract(flow)
return Column { }
} else {
return Row { }
}
} }

View File

@ -3,86 +3,93 @@ package layouts
import "image" import "image"
import "git.tebibyte.media/tomo/tomo" import "git.tebibyte.media/tomo/tomo"
type Row struct { } // Contract is a layout that arranges boxes in a simple row or column according
// to their minimum sizes.
type Contract bool
func (Row) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point { // ContractVertical is a vertical contracted layout.
dot := image.Point { } const ContractVertical Contract = true
for _, box := range boxes {
minimum := box.MinimumSize() // ContractHorizontal is a horizontal contracted layout.
dot.X += minimum.X const ContractHorizontal Contract = false
if dot.Y < minimum.Y {
dot.Y = minimum.Y func (contract Contract) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
if contract.v() {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.Y += minimum.Y
if dot.X < minimum.X {
dot.X = minimum.X
}
}
dot.Y += hints.Gap.Y * (len(boxes) - 1)
return dot
} else {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.X += minimum.X
if dot.Y < minimum.Y {
dot.Y = minimum.Y
}
}
dot.X += hints.Gap.X * (len(boxes) - 1)
return dot
}
}
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
if contract.v() {
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.Y += hints.Gap.Y }
minimum := box.MinimumSize()
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(hints.Bounds.Dx(), minimum.Y)),
})
dot.Y += minimum.Y
}
height := dot.Y - hints.Bounds.Min.Y
offset := 0
switch hints.AlignY {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dy() - height) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dy() - height
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(0, offset)))
}
} else {
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.X += hints.Gap.X }
minimum := box.MinimumSize()
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(minimum.X, hints.Bounds.Dy())),
})
dot.X += minimum.X
}
width := dot.X - hints.Bounds.Min.X
offset := 0
switch hints.AlignX {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dx() - width) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dx() - width
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(offset, 0)))
} }
} }
dot.X += hints.Gap.X * (len(boxes) - 1)
return dot
} }
func (Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) { func (contract Contract) v () bool { return contract == ContractVertical }
// TODO respect alignment value func (contract Contract) h () bool { return contract == ContractHorizontal }
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.X += hints.Gap.X }
minimum := box.MinimumSize()
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(minimum.X, hints.Bounds.Dy())),
})
dot.X += minimum.X
}
width := dot.X - hints.Bounds.Min.X
offset := 0
switch hints.AlignX {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dx() - width) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dx() - width
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(offset, 0)))
}
}
type Column struct { }
func (Column) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.Y += minimum.Y
if dot.X < minimum.X {
dot.X = minimum.X
}
}
dot.Y += hints.Gap.Y * (len(boxes) - 1)
return dot
}
func (Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
// TODO respect alignment value
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.Y += hints.Gap.Y }
minimum := box.MinimumSize()
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(hints.Bounds.Dx(), minimum.Y)),
})
dot.Y += minimum.Y
}
height := dot.Y - hints.Bounds.Min.Y
offset := 0
switch hints.AlignY {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dy() - height) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dy() - height
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(0, offset)))
}
}