Update code for layouts, objects
This commit is contained in:
@@ -15,19 +15,19 @@ const ContractVertical Contract = true
|
||||
// ContractHorizontal is a horizontal contracted layout.
|
||||
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.BoxQuerier) image.Point {
|
||||
return contract.fallback().MinimumSize(hints, boxes)
|
||||
}
|
||||
|
||||
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes tomo.BoxArranger) {
|
||||
contract.fallback().Arrange(hints, boxes)
|
||||
}
|
||||
|
||||
func (contract Contract) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||
func (contract Contract) RecommendedHeight (hints tomo.LayoutHints, boxes tomo.BoxQuerier, width int) int {
|
||||
return contract.fallback().RecommendedHeight(hints, boxes, width)
|
||||
}
|
||||
|
||||
func (contract Contract) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||
func (contract Contract) RecommendedWidth (hints tomo.LayoutHints, boxes tomo.BoxQuerier, height int) int {
|
||||
return contract.fallback().RecommendedWidth(hints, boxes, height)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,21 +17,21 @@ const FlowVertical Flow = true
|
||||
// FlowHorizontal is a horizontal flow layout.
|
||||
const FlowHorizontal Flow = false
|
||||
|
||||
func (flow Flow) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||
func (flow Flow) MinimumSize (hints tomo.LayoutHints, boxes tomo.BoxQuerier) image.Point {
|
||||
// TODO: write down somewhere that layout minimums aren't taken into
|
||||
// account when the respective direction is overflowed
|
||||
return flow.fallback().MinimumSize(hints, boxes)
|
||||
}
|
||||
|
||||
func (flow Flow) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
func (flow Flow) Arrange (hints tomo.LayoutHints, boxes tomo.BoxArranger) {
|
||||
if flow.v() && !hints.OverflowY || flow.h() && !hints.OverflowX {
|
||||
flow.fallback().Arrange(hints, boxes)
|
||||
}
|
||||
|
||||
// find a minor size value that will fit all boxes
|
||||
minorSize := 0
|
||||
for _, box := range boxes {
|
||||
boxSize := flow.minor(box.MinimumSize())
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
boxSize := flow.minor(boxes.MinimumSize(index))
|
||||
if boxSize > minorSize { minorSize = boxSize }
|
||||
}
|
||||
if minorSize == 0 { return }
|
||||
@@ -43,17 +43,16 @@ func (flow Flow) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
// arrange
|
||||
point := hints.Bounds.Min
|
||||
index := 0
|
||||
for index < len(boxes) {
|
||||
for index < boxes.Len() {
|
||||
// get a slice of boxes for this major step
|
||||
stepIndexEnd := index + minorSteps
|
||||
if stepIndexEnd > len(boxes) { stepIndexEnd = len(boxes) }
|
||||
step := boxes[index:stepIndexEnd]
|
||||
if stepIndexEnd > boxes.Len() { stepIndexEnd = boxes.Len() }
|
||||
index += minorSteps
|
||||
|
||||
// find a major size that will fit all boxes on this major step
|
||||
majorSize := 0
|
||||
for _, box := range step {
|
||||
boxSize := flow.major(box.MinimumSize())
|
||||
for index := index; index < stepIndexEnd; index ++ {
|
||||
boxSize := flow.major(boxes.MinimumSize(index))
|
||||
if boxSize > majorSize { majorSize = boxSize }
|
||||
}
|
||||
if majorSize == 0 { continue }
|
||||
@@ -62,9 +61,9 @@ func (flow Flow) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
var size image.Point
|
||||
size = flow.incrMajor(size, majorSize)
|
||||
size = flow.incrMinor(size, minorSize)
|
||||
for _, box := range step {
|
||||
for index := index; index < stepIndexEnd; index ++ {
|
||||
bounds := image.Rectangle { Min: point, Max: point.Add(size) }
|
||||
box.SetBounds(bounds)
|
||||
boxes.SetBounds(index, bounds)
|
||||
|
||||
point = flow.incrMinor(point, minorSize + flow.minor(hints.Gap))
|
||||
}
|
||||
@@ -125,12 +124,12 @@ func (flow Flow) fallback () tomo.Layout {
|
||||
return Contract(flow)
|
||||
}
|
||||
|
||||
func (flow Flow) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||
func (flow Flow) RecommendedHeight (hints tomo.LayoutHints, boxes tomo.BoxQuerier, width int) int {
|
||||
// TODO
|
||||
return 0
|
||||
}
|
||||
|
||||
func (flow Flow) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||
func (flow Flow) RecommendedWidth (hints tomo.LayoutHints, boxes tomo.BoxQuerier, height int) int {
|
||||
// TODO
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func NewGrid (columns ...bool) func (rows ...bool) *Grid {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Grid) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||
func (this *Grid) MinimumSize (hints tomo.LayoutHints, boxes tomo.BoxQuerier) image.Point {
|
||||
cols, rows := this.minimums(boxes)
|
||||
size := image.Pt (
|
||||
(len(cols) - 1) * hints.Gap.X,
|
||||
@@ -42,7 +42,7 @@ func (this *Grid) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.P
|
||||
return size
|
||||
}
|
||||
|
||||
func (this *Grid) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
func (this *Grid) Arrange (hints tomo.LayoutHints, boxes tomo.BoxArranger) {
|
||||
xExpand := func (index int) bool {
|
||||
return this.xExpand[index]
|
||||
}
|
||||
@@ -56,9 +56,9 @@ func (this *Grid) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
expand(hints, rows, hints.Bounds.Dy(), yExpand)
|
||||
|
||||
position := hints.Bounds.Min
|
||||
for index, box := range boxes {
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
col, row := index % len(cols), index / len(cols)
|
||||
box.SetBounds(image.Rectangle {
|
||||
boxes.SetBounds(index, image.Rectangle {
|
||||
Min: position,
|
||||
Max: position.Add(image.Pt(cols[col], rows[row])),
|
||||
})
|
||||
@@ -71,13 +71,13 @@ func (this *Grid) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Grid) minimums (boxes []tomo.Box) ([]int, []int) {
|
||||
func (this *Grid) minimums (boxes tomo.BoxQuerier) ([]int, []int) {
|
||||
nCols, nRows := this.dimensions(boxes)
|
||||
cols, rows := make([]int, nCols), make([]int, nRows)
|
||||
|
||||
for index, box := range boxes {
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
col, row := index % len(cols), index / len(cols)
|
||||
minimum := box.MinimumSize()
|
||||
minimum := boxes.MinimumSize(index)
|
||||
if cols[col] < minimum.X {
|
||||
cols[col] = minimum.X
|
||||
}
|
||||
@@ -89,8 +89,8 @@ func (this *Grid) minimums (boxes []tomo.Box) ([]int, []int) {
|
||||
return cols, rows
|
||||
}
|
||||
|
||||
func (this *Grid) dimensions (boxes []tomo.Box) (int, int) {
|
||||
return len(this.xExpand), ceilDiv(len(boxes), len(this.xExpand))
|
||||
func (this *Grid) dimensions (boxes tomo.BoxQuerier) (int, int) {
|
||||
return len(this.xExpand), ceilDiv(boxes.Len(), len(this.xExpand))
|
||||
}
|
||||
|
||||
func expand (hints tomo.LayoutHints, sizes []int, space int, expands func (int) bool) {
|
||||
@@ -116,10 +116,10 @@ func ceilDiv (x, y int) int {
|
||||
return int(math.Ceil(float64(x) / float64(y)))
|
||||
}
|
||||
|
||||
func (this *Grid) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||
func (this *Grid) RecommendedHeight (hints tomo.LayoutHints, boxes tomo.BoxQuerier, width int) int {
|
||||
return this.MinimumSize(hints, boxes).Y
|
||||
}
|
||||
|
||||
func (this *Grid) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||
func (this *Grid) RecommendedWidth (hints tomo.LayoutHints, boxes tomo.BoxQuerier, height int) int {
|
||||
return this.MinimumSize(hints, boxes).X
|
||||
}
|
||||
|
||||
@@ -13,33 +13,33 @@ type Row []bool
|
||||
// value will expand, and others will contract.
|
||||
type Column []bool
|
||||
|
||||
func (column Column) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||
func (column Column) MinimumSize (hints tomo.LayoutHints, boxes tomo.BoxQuerier) image.Point {
|
||||
dot := image.Point { }
|
||||
for _, box := range boxes {
|
||||
minimum := box.MinimumSize()
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
minimum := boxes.MinimumSize(index)
|
||||
dot.Y += minimum.Y
|
||||
if dot.X < minimum.X {
|
||||
dot.X = minimum.X
|
||||
}
|
||||
}
|
||||
dot.Y += hints.Gap.Y * (len(boxes) - 1)
|
||||
dot.Y += hints.Gap.Y * (boxes.Len() - 1)
|
||||
return dot
|
||||
}
|
||||
|
||||
func (row Row) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||
func (row Row) MinimumSize (hints tomo.LayoutHints, boxes tomo.BoxQuerier) image.Point {
|
||||
dot := image.Point { }
|
||||
for _, box := range boxes {
|
||||
minimum := box.MinimumSize()
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
minimum := boxes.MinimumSize(index)
|
||||
dot.X += minimum.X
|
||||
if dot.Y < minimum.Y {
|
||||
dot.Y = minimum.Y
|
||||
}
|
||||
}
|
||||
dot.X += hints.Gap.X * (len(boxes) - 1)
|
||||
dot.X += hints.Gap.X * (boxes.Len() - 1)
|
||||
return dot
|
||||
}
|
||||
|
||||
func (column Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
func (column Column) Arrange (hints tomo.LayoutHints, boxes tomo.BoxArranger) {
|
||||
expands := func (index int) bool {
|
||||
if index >= len(column) { return false }
|
||||
return column[index]
|
||||
@@ -48,13 +48,14 @@ func (column Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
// determine expanding box size
|
||||
expandingSize := 0.0
|
||||
if !hints.OverflowY {
|
||||
gaps := len(boxes) - 1
|
||||
gaps := boxes.Len() - 1
|
||||
freeSpace := float64(hints.Bounds.Dy() - hints.Gap.Y * gaps)
|
||||
nExpanding := 0; for index, box := range boxes {
|
||||
nExpanding := 0;
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
if expands(index) {
|
||||
nExpanding ++
|
||||
} else {
|
||||
freeSpace -= float64(box.MinimumSize().Y)
|
||||
freeSpace -= float64(boxes.MinimumSize(index).Y)
|
||||
}
|
||||
}
|
||||
expandingSize = freeSpace / float64(nExpanding)
|
||||
@@ -63,8 +64,8 @@ func (column Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
// determine width
|
||||
width := 0
|
||||
if hints.OverflowX {
|
||||
for _, box := range boxes {
|
||||
minimum := box.MinimumSize()
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
minimum := boxes.MinimumSize(index)
|
||||
if width < minimum.X { width = minimum.X }
|
||||
}
|
||||
} else {
|
||||
@@ -73,44 +74,43 @@ func (column Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
|
||||
// arrange
|
||||
dot := hints.Bounds.Min
|
||||
for index, box := range boxes {
|
||||
bounds := make([]image.Rectangle, boxes.Len())
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
if index > 0 { dot.Y += hints.Gap.Y }
|
||||
|
||||
// determine height
|
||||
height := box.MinimumSize().Y
|
||||
height := boxes.MinimumSize(index).Y
|
||||
if hints.OverflowY {
|
||||
if box, ok := box.(tomo.ContentBox); ok {
|
||||
height = box.RecommendedHeight(width)
|
||||
}
|
||||
height = boxes.RecommendedHeight(index, width)
|
||||
} else {
|
||||
if expands(index) {
|
||||
height = int(expandingSize)
|
||||
}
|
||||
}
|
||||
|
||||
// set bounds
|
||||
box.SetBounds(image.Rectangle {
|
||||
// store bounds of this box
|
||||
bounds[index] = image.Rectangle {
|
||||
Min: dot,
|
||||
Max: dot.Add(image.Pt(width, height)),
|
||||
})
|
||||
}
|
||||
dot.Y += height
|
||||
}
|
||||
|
||||
|
||||
// align
|
||||
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)))
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
boxes.SetBounds(index, bounds[index].Add(image.Pt(0, offset)))
|
||||
}
|
||||
}
|
||||
|
||||
func (row Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
func (row Row) Arrange (hints tomo.LayoutHints, boxes tomo.BoxArranger) {
|
||||
expands := func (index int) bool {
|
||||
if index >= len(row) { return false }
|
||||
return row[index]
|
||||
@@ -119,13 +119,14 @@ func (row Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
// determine expanding box size
|
||||
expandingSize := 0.0
|
||||
if !hints.OverflowY {
|
||||
gaps := len(boxes) - 1
|
||||
gaps := boxes.Len() - 1
|
||||
freeSpace := float64(hints.Bounds.Dx() - hints.Gap.X * gaps)
|
||||
nExpanding := 0; for index, box := range boxes {
|
||||
nExpanding := 0;
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
if expands(index) {
|
||||
nExpanding ++
|
||||
} else {
|
||||
freeSpace -= float64(box.MinimumSize().X)
|
||||
freeSpace -= float64(boxes.MinimumSize(index).X)
|
||||
}
|
||||
}
|
||||
expandingSize = freeSpace / float64(nExpanding)
|
||||
@@ -134,8 +135,8 @@ func (row Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
// determine height
|
||||
height := 0
|
||||
if hints.OverflowY {
|
||||
for _, box := range boxes {
|
||||
minimum := box.MinimumSize()
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
minimum := boxes.MinimumSize(index)
|
||||
if height < minimum.Y { height = minimum.Y }
|
||||
}
|
||||
} else {
|
||||
@@ -144,95 +145,76 @@ func (row Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
|
||||
// arrange
|
||||
dot := hints.Bounds.Min
|
||||
for index, box := range boxes {
|
||||
bounds := make([]image.Rectangle, boxes.Len())
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
if index > 0 { dot.X += hints.Gap.X }
|
||||
|
||||
// determine width
|
||||
width := box.MinimumSize().X
|
||||
width := boxes.MinimumSize(index).X
|
||||
if hints.OverflowY {
|
||||
if box, ok := box.(tomo.ContentBox); ok {
|
||||
width = box.RecommendedHeight(height)
|
||||
}
|
||||
width = boxes.RecommendedHeight(index, height)
|
||||
} else {
|
||||
if expands(index) {
|
||||
width = int(expandingSize)
|
||||
}
|
||||
}
|
||||
|
||||
// set bounds
|
||||
box.SetBounds(image.Rectangle {
|
||||
// store bounds
|
||||
bounds[index] = image.Rectangle {
|
||||
Min: dot,
|
||||
Max: dot.Add(image.Pt(width, height)),
|
||||
})
|
||||
}
|
||||
dot.X += width
|
||||
}
|
||||
|
||||
// align
|
||||
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)))
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
boxes.SetBounds(index, bounds[index].Add(image.Pt(offset, 0)))
|
||||
}
|
||||
}
|
||||
|
||||
func (column Column) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||
func (column Column) RecommendedHeight (hints tomo.LayoutHints, boxes tomo.BoxQuerier, width int) int {
|
||||
height := 0
|
||||
for _, box := range boxes {
|
||||
if box, ok := box.(tomo.ContentBox); ok {
|
||||
height += box.RecommendedHeight(width)
|
||||
} else {
|
||||
height += box.MinimumSize().Y
|
||||
}
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
height += boxes.RecommendedHeight(index, width)
|
||||
}
|
||||
height += hints.Gap.Y * (len(boxes) - 1)
|
||||
height += hints.Gap.Y * (boxes.Len() - 1)
|
||||
return height
|
||||
}
|
||||
|
||||
func (row Row) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||
func (row Row) RecommendedHeight (hints tomo.LayoutHints, boxes tomo.BoxQuerier, width int) int {
|
||||
height := 0
|
||||
for _, box := range boxes {
|
||||
minimum := box.MinimumSize()
|
||||
boxHeight := 0
|
||||
if box, ok := box.(tomo.ContentBox); ok {
|
||||
boxHeight = box.RecommendedHeight(minimum.X)
|
||||
} else {
|
||||
boxHeight = minimum.Y
|
||||
}
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
minimum := boxes.MinimumSize(index)
|
||||
boxHeight := boxes.RecommendedHeight(index, minimum.X)
|
||||
if boxHeight > height { height = boxHeight }
|
||||
}
|
||||
return height
|
||||
}
|
||||
|
||||
func (column Column) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||
func (column Column) RecommendedWidth (hints tomo.LayoutHints, boxes tomo.BoxQuerier, height int) int {
|
||||
width := 0
|
||||
for _, box := range boxes {
|
||||
minimum := box.MinimumSize()
|
||||
boxWidth := 0
|
||||
if box, ok := box.(tomo.ContentBox); ok {
|
||||
boxWidth = box.RecommendedHeight(minimum.Y)
|
||||
} else {
|
||||
boxWidth = minimum.X
|
||||
}
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
minimum := boxes.MinimumSize(index)
|
||||
boxWidth := boxes.RecommendedWidth(index, minimum.Y)
|
||||
if boxWidth > width { width = boxWidth }
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
func (row Row) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||
func (row Row) RecommendedWidth (hints tomo.LayoutHints, boxes tomo.BoxQuerier, height int) int {
|
||||
width := 0
|
||||
for _, box := range boxes {
|
||||
if box, ok := box.(tomo.ContentBox); ok {
|
||||
width += box.RecommendedWidth(height)
|
||||
} else {
|
||||
width += box.MinimumSize().X
|
||||
}
|
||||
for index := 0; index < boxes.Len(); index ++ {
|
||||
width += boxes.RecommendedWidth(index, height)
|
||||
}
|
||||
width += hints.Gap.X * (len(boxes) - 1)
|
||||
width += hints.Gap.X * (boxes.Len() - 1)
|
||||
return width
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user