Contract layouts are now based on new Row and Column layouts
This commit is contained in:
parent
1596d54834
commit
9ce7f8b8f3
@ -5,9 +5,9 @@ import "git.tebibyte.media/tomo/tomo/input"
|
|||||||
import "git.tebibyte.media/tomo/tomo/event"
|
import "git.tebibyte.media/tomo/tomo/event"
|
||||||
import "git.tebibyte.media/tomo/objects/layouts"
|
import "git.tebibyte.media/tomo/objects/layouts"
|
||||||
|
|
||||||
var buttonLayout = layouts.NewGrid([]bool { true }, []bool { true })
|
var buttonLayout = layouts.Row { true }
|
||||||
var iconButtonLayout = layouts.NewGrid([]bool { true }, []bool { true })
|
var iconButtonLayout = layouts.Row { true }
|
||||||
var bothButtonLayout = layouts.NewGrid([]bool { false, true }, []bool { true })
|
var bothButtonLayout = layouts.Row { false, true }
|
||||||
|
|
||||||
// Button is a clickable button.
|
// Button is a clickable button.
|
||||||
type Button struct {
|
type Button struct {
|
||||||
|
@ -16,93 +16,25 @@ const ContractVertical Contract = true
|
|||||||
const ContractHorizontal Contract = false
|
const ContractHorizontal Contract = false
|
||||||
|
|
||||||
func (contract Contract) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
func (contract Contract) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||||
if contract.v() {
|
return contract.fallback().MinimumSize(hints, boxes)
|
||||||
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) {
|
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||||
// TODO if we overflow in a direction, respect the reccomended size
|
contract.fallback().Arrange(hints, boxes)
|
||||||
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)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (contract Contract) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
func (contract Contract) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||||
// TODO
|
return contract.fallback().RecommendedHeight(hints, boxes, width)
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (contract Contract) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
func (contract Contract) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||||
// TODO
|
return contract.fallback().RecommendedWidth(hints, boxes, height)
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (contract Contract) v () bool { return contract == ContractVertical }
|
func (contract Contract) fallback () tomo.Layout {
|
||||||
func (contract Contract) h () bool { return contract == ContractHorizontal }
|
if contract == ContractVertical {
|
||||||
|
return Column { }
|
||||||
|
} else {
|
||||||
|
return Row { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
200
layouts/rowcol.go
Normal file
200
layouts/rowcol.go
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
package layouts
|
||||||
|
|
||||||
|
import "image"
|
||||||
|
import "git.tebibyte.media/tomo/tomo"
|
||||||
|
|
||||||
|
var _ tomo.Layout = ContractVertical
|
||||||
|
|
||||||
|
// Row arranges boxes in a row. Boxes that share an index with a true value will
|
||||||
|
// expand, and others will contract.
|
||||||
|
type Row []bool
|
||||||
|
|
||||||
|
// Column arranges boxes in a column. Boxes that share an index with a true
|
||||||
|
// value will expand, and others will contract.
|
||||||
|
type Column []bool
|
||||||
|
|
||||||
|
func (column 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 (row Row) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||||
|
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 (column Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||||
|
expands := func (index int) bool {
|
||||||
|
if index < len(boxes) { return false }
|
||||||
|
return column[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine expanding box size
|
||||||
|
expandingSize := 0
|
||||||
|
if !hints.OverflowY {
|
||||||
|
gaps := len(boxes) - 1
|
||||||
|
freeSpace := float64(hints.Bounds.Dy() - hints.Gap.Y * gaps)
|
||||||
|
nExpanding := 0; for index, box := range boxes {
|
||||||
|
if expands(index) {
|
||||||
|
nExpanding ++
|
||||||
|
} else {
|
||||||
|
freeSpace -= float64(box.MinimumSize().X)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine width
|
||||||
|
width := 0
|
||||||
|
if hints.OverflowX {
|
||||||
|
for _, box := range boxes {
|
||||||
|
minimum := box.MinimumSize()
|
||||||
|
if width < minimum.X { width = minimum.X }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
width = hints.Bounds.Dx()
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrange
|
||||||
|
dot := hints.Bounds.Min
|
||||||
|
for index, box := range boxes {
|
||||||
|
if index > 0 { dot.Y += hints.Gap.Y }
|
||||||
|
|
||||||
|
// determine height
|
||||||
|
height := box.MinimumSize().Y
|
||||||
|
if hints.OverflowY {
|
||||||
|
if box, ok := box.(tomo.ContentBox); ok {
|
||||||
|
height = box.RecommendedHeight(width)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if expands(index) {
|
||||||
|
height = expandingSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set bounds
|
||||||
|
box.SetBounds(image.Rectangle {
|
||||||
|
Min: dot,
|
||||||
|
Max: dot.Add(image.Pt(width, height)),
|
||||||
|
})
|
||||||
|
dot.Y += height
|
||||||
|
}
|
||||||
|
|
||||||
|
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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (row Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||||
|
expands := func (index int) bool {
|
||||||
|
if index < len(boxes) { return false }
|
||||||
|
return row[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine expanding box size
|
||||||
|
expandingSize := 0
|
||||||
|
if !hints.OverflowY {
|
||||||
|
gaps := len(boxes) - 1
|
||||||
|
freeSpace := float64(hints.Bounds.Dx() - hints.Gap.X * gaps)
|
||||||
|
nExpanding := 0; for index, box := range boxes {
|
||||||
|
if expands(index) {
|
||||||
|
nExpanding ++
|
||||||
|
} else {
|
||||||
|
freeSpace -= float64(box.MinimumSize().Y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine height
|
||||||
|
height := 0
|
||||||
|
if hints.OverflowY {
|
||||||
|
for _, box := range boxes {
|
||||||
|
minimum := box.MinimumSize()
|
||||||
|
if height < minimum.Y { height = minimum.Y }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = hints.Bounds.Dy()
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrange
|
||||||
|
dot := hints.Bounds.Min
|
||||||
|
for index, box := range boxes {
|
||||||
|
if index > 0 { dot.X += hints.Gap.X }
|
||||||
|
|
||||||
|
// determine width
|
||||||
|
width := box.MinimumSize().X
|
||||||
|
if hints.OverflowY {
|
||||||
|
if box, ok := box.(tomo.ContentBox); ok {
|
||||||
|
width = box.RecommendedHeight(height)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if expands(index) {
|
||||||
|
width = expandingSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set bounds
|
||||||
|
box.SetBounds(image.Rectangle {
|
||||||
|
Min: dot,
|
||||||
|
Max: dot.Add(image.Pt(width, height)),
|
||||||
|
})
|
||||||
|
dot.X += width
|
||||||
|
}
|
||||||
|
|
||||||
|
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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (column Column) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||||
|
// TODO
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (row Row) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||||
|
// TODO
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (column Column) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||||
|
// TODO
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (row Row) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||||
|
// TODO
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user