layout: added Axis methods

Signed-off-by: pierre <pierre.curto@gmail.com>
This commit is contained in:
pierre
2021-01-11 07:59:35 +01:00
committed by Elias Naur
parent f7f94c93fe
commit 0e3e446393
3 changed files with 78 additions and 77 deletions
+12 -62
View File
@@ -3,8 +3,6 @@
package layout package layout
import ( import (
"image"
"gioui.org/op" "gioui.org/op"
) )
@@ -83,8 +81,8 @@ func Flexed(weight float32, widget Widget) FlexChild {
func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions { func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
size := 0 size := 0
cs := gtx.Constraints cs := gtx.Constraints
mainMin, mainMax := axisMainConstraint(f.Axis, cs) mainMin, mainMax := f.Axis.mainConstraint(cs)
crossMin, crossMax := axisCrossConstraint(f.Axis, cs) crossMin, crossMax := f.Axis.crossConstraint(cs)
remaining := mainMax remaining := mainMax
var totalWeight float32 var totalWeight float32
cgtx := gtx cgtx := gtx
@@ -95,10 +93,10 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
continue continue
} }
macro := op.Record(gtx.Ops) macro := op.Record(gtx.Ops)
cgtx.Constraints = axisConstraints(f.Axis, 0, remaining, crossMin, crossMax) cgtx.Constraints = f.Axis.constraints(0, remaining, crossMin, crossMax)
dims := child.widget(cgtx) dims := child.widget(cgtx)
c := macro.Stop() c := macro.Stop()
sz := axisMain(f.Axis, dims.Size) sz := f.Axis.Main(dims.Size)
size += sz size += sz
remaining -= sz remaining -= sz
if remaining < 0 { if remaining < 0 {
@@ -130,10 +128,10 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
} }
} }
macro := op.Record(gtx.Ops) macro := op.Record(gtx.Ops)
cgtx.Constraints = axisConstraints(f.Axis, flexSize, flexSize, crossMin, crossMax) cgtx.Constraints = f.Axis.constraints(flexSize, flexSize, crossMin, crossMax)
dims := child.widget(cgtx) dims := child.widget(cgtx)
c := macro.Stop() c := macro.Stop()
sz := axisMain(f.Axis, dims.Size) sz := f.Axis.Main(dims.Size)
size += sz size += sz
remaining -= sz remaining -= sz
if remaining < 0 { if remaining < 0 {
@@ -145,7 +143,7 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
var maxCross int var maxCross int
var maxBaseline int var maxBaseline int
for _, child := range children { for _, child := range children {
if c := axisCross(f.Axis, child.dims.Size); c > maxCross { if c := f.Axis.Cross(child.dims.Size); c > maxCross {
maxCross = c maxCross = c
} }
if b := child.dims.Size.Y - child.dims.Baseline; b > maxBaseline { if b := child.dims.Size.Y - child.dims.Baseline; b > maxBaseline {
@@ -175,19 +173,19 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
var cross int var cross int
switch f.Alignment { switch f.Alignment {
case End: case End:
cross = maxCross - axisCross(f.Axis, dims.Size) cross = maxCross - f.Axis.Cross(dims.Size)
case Middle: case Middle:
cross = (maxCross - axisCross(f.Axis, dims.Size)) / 2 cross = (maxCross - f.Axis.Cross(dims.Size)) / 2
case Baseline: case Baseline:
if f.Axis == Horizontal { if f.Axis == Horizontal {
cross = maxBaseline - b cross = maxBaseline - b
} }
} }
stack := op.Push(gtx.Ops) stack := op.Push(gtx.Ops)
op.Offset(FPt(axisPoint(f.Axis, mainSize, cross))).Add(gtx.Ops) op.Offset(FPt(f.Axis.point(mainSize, cross))).Add(gtx.Ops)
child.call.Add(gtx.Ops) child.call.Add(gtx.Ops)
stack.Pop() stack.Pop()
mainSize += axisMain(f.Axis, dims.Size) mainSize += f.Axis.Main(dims.Size)
if i < len(children)-1 { if i < len(children)-1 {
switch f.Spacing { switch f.Spacing {
case SpaceEvenly: case SpaceEvenly:
@@ -215,58 +213,10 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
mainSize += space / (len(children) * 2) mainSize += space / (len(children) * 2)
} }
} }
sz := axisPoint(f.Axis, mainSize, maxCross) sz := f.Axis.point(mainSize, maxCross)
return Dimensions{Size: sz, Baseline: sz.Y - maxBaseline} return Dimensions{Size: sz, Baseline: sz.Y - maxBaseline}
} }
func axisPoint(a Axis, main, cross int) image.Point {
if a == Horizontal {
return image.Point{main, cross}
} else {
return image.Point{cross, main}
}
}
func axisMain(a Axis, sz image.Point) int {
if a == Horizontal {
return sz.X
} else {
return sz.Y
}
}
func axisCross(a Axis, sz image.Point) int {
if a == Horizontal {
return sz.Y
} else {
return sz.X
}
}
func axisMainConstraint(a Axis, cs Constraints) (int, int) {
if a == Horizontal {
return cs.Min.X, cs.Max.X
} else {
return cs.Min.Y, cs.Max.Y
}
}
func axisCrossConstraint(a Axis, cs Constraints) (int, int) {
if a == Horizontal {
return cs.Min.Y, cs.Max.Y
} else {
return cs.Min.X, cs.Max.X
}
}
func axisConstraints(a Axis, mainMin, mainMax, crossMin, crossMax int) Constraints {
if a == Horizontal {
return Constraints{Min: image.Pt(mainMin, crossMin), Max: image.Pt(mainMax, crossMax)}
} else {
return Constraints{Min: image.Pt(crossMin, mainMin), Max: image.Pt(crossMax, mainMax)}
}
}
func (s Spacing) String() string { func (s Spacing) String() string {
switch s { switch s {
case SpaceEnd: case SpaceEnd:
+51
View File
@@ -225,6 +225,57 @@ func (a Alignment) String() string {
} }
} }
// Main returns the main axis of p.
// I.e. if a is Horizontal, then the returned value is p.X.
func (a Axis) Main(p image.Point) int {
if a == Horizontal {
return p.X
}
return p.Y
}
// Cross returns the cross axis of p.
// I.e. if a is Horizontal, then the returned value is p.Y.
func (a Axis) Cross(p image.Point) int {
if a == Horizontal {
return p.Y
}
return p.X
}
// point returns the point having its values set based on the axis.
// I.e. if a is Horizontal, then the returned value is image.Point{X: main, Y: cross}.
func (a Axis) point(main, cross int) image.Point {
if a == Horizontal {
return image.Pt(main, cross)
}
return image.Pt(cross, main)
}
// mainConstraint returns the min and max main constraints for axis a.
func (a Axis) mainConstraint(cs Constraints) (int, int) {
if a == Horizontal {
return cs.Min.X, cs.Max.X
}
return cs.Min.Y, cs.Max.Y
}
// crossConstraint returns the min and max cross constraints for axis a.
func (a Axis) crossConstraint(cs Constraints) (int, int) {
if a == Horizontal {
return cs.Min.Y, cs.Max.Y
}
return cs.Min.X, cs.Max.X
}
// constraints returns the constraints for axis a.
func (a Axis) constraints(mainMin, mainMax, crossMin, crossMax int) Constraints {
if a == Horizontal {
return Constraints{Min: image.Pt(mainMin, crossMin), Max: image.Pt(mainMax, crossMax)}
}
return Constraints{Min: image.Pt(crossMin, mainMin), Max: image.Pt(crossMax, mainMax)}
}
func (a Axis) String() string { func (a Axis) String() string {
switch a { switch a {
case Horizontal: case Horizontal:
+15 -15
View File
@@ -98,8 +98,8 @@ func (l *List) init(gtx Context, len int) {
// Layout the List. // Layout the List.
func (l *List) Layout(gtx Context, len int, w ListElement) Dimensions { func (l *List) Layout(gtx Context, len int, w ListElement) Dimensions {
l.init(gtx, len) l.init(gtx, len)
crossMin, crossMax := axisCrossConstraint(l.Axis, gtx.Constraints) crossMin, crossMax := l.Axis.crossConstraint(gtx.Constraints)
gtx.Constraints = axisConstraints(l.Axis, 0, inf, crossMin, crossMax) gtx.Constraints = l.Axis.constraints(0, inf, crossMin, crossMax)
macro := op.Record(gtx.Ops) macro := op.Record(gtx.Ops)
for l.next(); l.more(); l.next() { for l.next(); l.more(); l.next() {
child := op.Record(gtx.Ops) child := op.Record(gtx.Ops)
@@ -155,7 +155,7 @@ func (l *List) more() bool {
} }
func (l *List) nextDir() iterationDir { func (l *List) nextDir() iterationDir {
_, vsize := axisMainConstraint(l.Axis, l.cs) _, vsize := l.Axis.mainConstraint(l.cs)
last := l.Position.First + len(l.children) last := l.Position.First + len(l.children)
// Clamp offset. // Clamp offset.
if l.maxSize-l.Position.Offset < vsize && last == l.len { if l.maxSize-l.Position.Offset < vsize && last == l.len {
@@ -178,7 +178,7 @@ func (l *List) nextDir() iterationDir {
// End the current child by specifying its dimensions. // End the current child by specifying its dimensions.
func (l *List) end(dims Dimensions, call op.CallOp) { func (l *List) end(dims Dimensions, call op.CallOp) {
child := scrollChild{dims.Size, call} child := scrollChild{dims.Size, call}
mainSize := axisMain(l.Axis, child.size) mainSize := l.Axis.Main(child.size)
l.maxSize += mainSize l.maxSize += mainSize
switch l.dir { switch l.dir {
case iterateForward: case iterateForward:
@@ -200,12 +200,12 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions {
if l.more() { if l.more() {
panic("unfinished child") panic("unfinished child")
} }
mainMin, mainMax := axisMainConstraint(l.Axis, l.cs) mainMin, mainMax := l.Axis.mainConstraint(l.cs)
children := l.children children := l.children
// Skip invisible children // Skip invisible children
for len(children) > 0 { for len(children) > 0 {
sz := children[0].size sz := children[0].size
mainSize := axisMain(l.Axis, sz) mainSize := l.Axis.Main(sz)
if l.Position.Offset <= mainSize { if l.Position.Offset <= mainSize {
break break
} }
@@ -217,10 +217,10 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions {
var maxCross int var maxCross int
for i, child := range children { for i, child := range children {
sz := child.size sz := child.size
if c := axisCross(l.Axis, sz); c > maxCross { if c := l.Axis.Cross(sz); c > maxCross {
maxCross = c maxCross = c
} }
size += axisMain(l.Axis, sz) size += l.Axis.Main(sz)
if size >= mainMax { if size >= mainMax {
children = children[:i+1] children = children[:i+1]
break break
@@ -236,11 +236,11 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions {
var cross int var cross int
switch l.Alignment { switch l.Alignment {
case End: case End:
cross = maxCross - axisCross(l.Axis, sz) cross = maxCross - l.Axis.Cross(sz)
case Middle: case Middle:
cross = (maxCross - axisCross(l.Axis, sz)) / 2 cross = (maxCross - l.Axis.Cross(sz)) / 2
} }
childSize := axisMain(l.Axis, sz) childSize := l.Axis.Main(sz)
max := childSize + pos max := childSize + pos
if max > mainMax { if max > mainMax {
max = mainMax max = mainMax
@@ -250,12 +250,12 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions {
min = 0 min = 0
} }
r := image.Rectangle{ r := image.Rectangle{
Min: axisPoint(l.Axis, min, -inf), Min: l.Axis.point(min, -inf),
Max: axisPoint(l.Axis, max, inf), Max: l.Axis.point(max, inf),
} }
stack := op.Push(ops) stack := op.Push(ops)
clip.Rect(r).Add(ops) clip.Rect(r).Add(ops)
op.Offset(FPt(axisPoint(l.Axis, pos, cross))).Add(ops) op.Offset(FPt(l.Axis.point(pos, cross))).Add(ops)
child.call.Add(ops) child.call.Add(ops)
stack.Pop() stack.Pop()
pos += childSize pos += childSize
@@ -272,7 +272,7 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions {
if pos > mainMax { if pos > mainMax {
pos = mainMax pos = mainMax
} }
dims := axisPoint(l.Axis, pos, maxCross) dims := l.Axis.point(pos, maxCross)
call := macro.Stop() call := macro.Stop()
defer op.Push(ops).Pop() defer op.Push(ops).Pop()
pointer.Rect(image.Rectangle{Max: dims}).Add(ops) pointer.Rect(image.Rectangle{Max: dims}).Add(ops)