ui/layout: make List more friendly to for loops

With this change, a List l can be iterated with

    for l.Init(...); l.More(); l.Next() {
        l.Elem(..., l.Constraints(), l.Index())
    }

instead of

   l.Init(...)
   for {
       i, cs, ok := l.Next()
       if !ok {
               break
       }
       l.End(..., cs, i))
    }

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-07-11 18:07:16 +02:00
parent 431fa218b2
commit fe4a61ec89
+41 -12
View File
@@ -40,6 +40,10 @@ type List struct {
maxSize int
children []scrollChild
dir iterationDir
// Iterator state.
index int
more bool
}
type iterationDir uint8
@@ -50,7 +54,11 @@ const (
iterateBackward
)
// Init prepares the list for iterating through its elements with Next.
func (l *List) Init(ops *ui.Ops, cs Constraints, len int) {
if l.more {
panic("unfinished element")
}
l.update()
l.ops = ops
l.dir = iterateNone
@@ -58,10 +66,12 @@ func (l *List) Init(ops *ui.Ops, cs Constraints, len int) {
l.children = l.children[:0]
l.cs = cs
l.len = len
l.more = true
if l.first > len {
l.first = len
}
ops.Begin()
l.Next()
}
func (l *List) Dragging() bool {
@@ -79,20 +89,35 @@ func (l *List) update() {
l.offset += d
}
func (l *List) Next() (int, Constraints, bool) {
if l.dir != iterateNone {
panic("a previous Next was not finished with Elem")
// Next advances the list to the next element.
func (l *List) Next() {
if !l.more {
panic("end of list reached")
}
i, more := l.next()
l.more = more
if !more {
return
}
i, ok := l.next()
if l.Invert {
i = l.len - 1 - i
}
var cs Constraints
if ok {
cs = axisConstraints(l.Axis, Constraint{Max: ui.Inf}, l.crossConstraintChild(l.cs))
l.ops.Begin()
}
return i, cs, ok
l.index = i
l.ops.Begin()
}
// Index is the current element index.
func (l *List) Index() int {
return l.index
}
// Constraints is the constraints for the current element.
func (l *List) Constraints() Constraints {
return axisConstraints(l.Axis, Constraint{Max: ui.Inf}, l.crossConstraintChild(l.cs))
}
func (l *List) More() bool {
return l.more
}
func (l *List) next() (int, bool) {
@@ -119,7 +144,8 @@ func (l *List) next() (int, bool) {
return 0, false
}
func (l *List) End(dims Dimens) {
// Elem completes an element.
func (l *List) Elem(dims Dimens) {
block := l.ops.End()
child := scrollChild{dims.Size, block}
switch l.dir {
@@ -134,12 +160,15 @@ func (l *List) End(dims Dimens) {
l.maxSize += mainSize
l.children = append([]scrollChild{child}, l.children...)
default:
panic("call Next before End")
panic("call Next before Elem")
}
l.dir = iterateNone
}
func (l *List) Layout() Dimens {
if l.more {
panic("unfinished element")
}
mainc := axisMainConstraint(l.Axis, l.cs)
for len(l.children) > 0 {
sz := l.children[0].size