diff --git a/layout/flex.go b/layout/flex.go index 9957103c..1dbf03b6 100644 --- a/layout/flex.go +++ b/layout/flex.go @@ -20,9 +20,6 @@ type Flex struct { // Alignment is the alignment in the cross axis. Alignment Alignment - ctx *Context - macro op.MacroOp - mode flexMode size int rigidSize int // fraction is the rounding error from a Flexible weighting. @@ -60,58 +57,29 @@ const ( SpaceEvenly ) -const ( - modeNone flexMode = iota - modeBegun - modeRigid - modeFlex -) - -// Init must be called before Rigid or Flexible. -func (f *Flex) Init(gtx *Context) *Flex { - if f.mode > modeBegun { - panic("must End the current child before calling Init again") - } - f.mode = modeBegun - f.ctx = gtx - f.size = 0 - f.rigidSize = 0 - f.maxCross = 0 - f.maxBaseline = 0 - return f -} - -func (f *Flex) begin(mode flexMode) { - switch { - case f.mode == modeNone: - panic("must Init before adding a child") - case f.mode > modeBegun: - panic("must End before adding a child") - } - f.mode = mode - f.macro.Record(f.ctx.Ops) -} - // Rigid lays out a widget with the main axis constrained to the range // from 0 to the remaining space. -func (f *Flex) Rigid(w Widget) FlexChild { - f.begin(modeRigid) - cs := f.ctx.Constraints +func (f *Flex) Rigid(gtx *Context, w Widget) FlexChild { + cs := gtx.Constraints mainc := axisMainConstraint(f.Axis, cs) mainMax := mainc.Max - f.size if mainMax < 0 { mainMax = 0 } cs = axisConstraints(f.Axis, Constraint{Max: mainMax}, axisCrossConstraint(f.Axis, cs)) - dims := f.ctx.Layout(cs, w) - return f.end(dims) + var m op.MacroOp + m.Record(gtx.Ops) + dims := gtx.Layout(cs, w) + m.Stop() + f.rigidSize += axisMain(f.Axis, dims.Size) + f.expand(dims) + return FlexChild{m, dims} } // Flexible is like Rigid, where the main axis size is also constrained to a // fraction of the space not taken up by Rigid children. -func (f *Flex) Flexible(weight float32, w Widget) FlexChild { - f.begin(modeFlex) - cs := f.ctx.Constraints +func (f *Flex) Flexible(gtx *Context, weight float32, w Widget) FlexChild { + cs := gtx.Constraints mainc := axisMainConstraint(f.Axis, cs) var flexSize int if mainc.Max > f.size { @@ -127,36 +95,31 @@ func (f *Flex) Flexible(weight float32, w Widget) FlexChild { } submainc := Constraint{Max: flexSize} cs = axisConstraints(f.Axis, submainc, axisCrossConstraint(f.Axis, cs)) - dims := f.ctx.Layout(cs, w) - return f.end(dims) + var m op.MacroOp + m.Record(gtx.Ops) + dims := gtx.Layout(cs, w) + m.Stop() + f.expand(dims) + return FlexChild{m, dims} } // End a child by specifying its dimensions. Pass the returned layout result // to Layout. -func (f *Flex) end(dims Dimensions) FlexChild { - if f.mode <= modeBegun { - panic("End called without an active child") - } - f.macro.Stop() +func (f *Flex) expand(dims Dimensions) { sz := axisMain(f.Axis, dims.Size) f.size += sz - if f.mode == modeRigid { - f.rigidSize += sz - } - f.mode = modeBegun if c := axisCross(f.Axis, dims.Size); c > f.maxCross { f.maxCross = c } if b := dims.Baseline; b > f.maxBaseline { f.maxBaseline = b } - return FlexChild{f.macro, dims} } // Layout a list of children. The order of the children determines their laid // out order. -func (f *Flex) Layout(children ...FlexChild) { - cs := f.ctx.Constraints +func (f *Flex) Layout(gtx *Context, children ...FlexChild) { + cs := gtx.Constraints mainc := axisMainConstraint(f.Axis, cs) crossSize := axisCrossConstraint(f.Axis, cs).Constrain(f.maxCross) var space int @@ -190,9 +153,9 @@ func (f *Flex) Layout(children ...FlexChild) { } } var stack op.StackOp - stack.Push(f.ctx.Ops) - op.TransformOp{}.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))).Add(f.ctx.Ops) - child.macro.Add(f.ctx.Ops) + stack.Push(gtx.Ops) + op.TransformOp{}.Offset(toPointF(axisPoint(f.Axis, mainSize, cross))).Add(gtx.Ops) + child.macro.Add(gtx.Ops) stack.Pop() mainSize += axisMain(f.Axis, dims.Size) if i < len(children)-1 { @@ -223,7 +186,11 @@ func (f *Flex) Layout(children ...FlexChild) { if baseline == 0 { baseline = sz.Y } - f.ctx.Dimensions = Dimensions{Size: sz, Baseline: baseline} + gtx.Dimensions = Dimensions{Size: sz, Baseline: baseline} + f.size = 0 + f.rigidSize = 0 + f.maxCross = 0 + f.maxBaseline = 0 } func axisPoint(a Axis, main, cross int) image.Point { diff --git a/layout/layout_test.go b/layout/layout_test.go index cc78c9bd..a55b568f 100644 --- a/layout/layout_test.go +++ b/layout/layout_test.go @@ -63,21 +63,20 @@ func ExampleFlex() { gtx.Reset(cfg, image.Point{X: 100, Y: 100}) flex := layout.Flex{} - flex.Init(gtx) // Rigid 10x10 widget. - child1 := flex.Rigid(func() { + child1 := flex.Rigid(gtx, func() { fmt.Printf("Rigid: %v\n", gtx.Constraints.Width) layoutWidget(gtx, 10, 10) }) // Child with 50% space allowance. - child2 := flex.Flexible(0.5, func() { + child2 := flex.Flexible(gtx, 0.5, func() { fmt.Printf("50%%: %v\n", gtx.Constraints.Width) layoutWidget(gtx, 10, 10) }) - flex.Layout(child1, child2) + flex.Layout(gtx, child1, child2) // Output: // Rigid: {0 100} @@ -89,20 +88,19 @@ func ExampleStack() { gtx.Reset(cfg, image.Point{X: 100, Y: 100}) stack := layout.Stack{} - stack.Init(gtx) // Rigid 50x50 widget. - child1 := stack.Rigid(func() { + child1 := stack.Rigid(gtx, func() { layoutWidget(gtx, 50, 50) }) // Force widget to the same size as the first. - child2 := stack.Expand(func() { + child2 := stack.Expand(gtx, func() { fmt.Printf("Expand: %v\n", gtx.Constraints) layoutWidget(gtx, 10, 10) }) - stack.Layout(child1, child2) + stack.Layout(gtx, child1, child2) // Output: // Expand: {{50 50} {50 50}} diff --git a/layout/stack.go b/layout/stack.go index c98ace4c..694c07b3 100644 --- a/layout/stack.go +++ b/layout/stack.go @@ -15,11 +15,8 @@ type Stack struct { // smaller than the available space. Alignment Direction - macro op.MacroOp - constrained bool - ctx *Context - maxSZ image.Point - baseline int + maxSZ image.Point + baseline int } // StackChild is the layout result of a call to End. @@ -28,45 +25,33 @@ type StackChild struct { dims Dimensions } -// Init a stack before calling Rigid or Expand. -func (s *Stack) Init(gtx *Context) *Stack { - s.ctx = gtx - s.constrained = true - s.maxSZ = image.Point{} - s.baseline = 0 - return s -} - -func (s *Stack) begin() { - if !s.constrained { - panic("must Init before adding a child") - } - s.macro.Record(s.ctx.Ops) -} - // Rigid lays out a widget with the same constraints that were // passed to Init. -func (s *Stack) Rigid(w Widget) StackChild { - s.begin() - dims := s.ctx.Layout(s.ctx.Constraints, w) - return s.end(dims) +func (s *Stack) Rigid(gtx *Context, w Widget) StackChild { + var m op.MacroOp + m.Record(gtx.Ops) + dims := gtx.Layout(gtx.Constraints, w) + m.Stop() + s.expand(dims) + return StackChild{m, dims} } // Expand lays out a widget with constraints that exactly match // the biggest child previously added. -func (s *Stack) Expand(w Widget) StackChild { - s.begin() +func (s *Stack) Expand(gtx *Context, w Widget) StackChild { + var m op.MacroOp + m.Record(gtx.Ops) cs := Constraints{ Width: Constraint{Min: s.maxSZ.X, Max: s.maxSZ.X}, Height: Constraint{Min: s.maxSZ.Y, Max: s.maxSZ.Y}, } - dims := s.ctx.Layout(cs, w) - return s.end(dims) + dims := gtx.Layout(cs, w) + m.Stop() + s.expand(dims) + return StackChild{m, dims} } -// End a child by specifying its dimensions. -func (s *Stack) end(dims Dimensions) StackChild { - s.macro.Stop() +func (s *Stack) expand(dims Dimensions) { if w := dims.Size.X; w > s.maxSZ.X { s.maxSZ.X = w } @@ -78,12 +63,11 @@ func (s *Stack) end(dims Dimensions) StackChild { s.baseline = b } } - return StackChild{s.macro, dims} } // Layout a list of children. The order of the children determines their laid // out order. -func (s *Stack) Layout(children ...StackChild) { +func (s *Stack) Layout(gtx *Context, children ...StackChild) { for _, ch := range children { sz := ch.dims.Size var p image.Point @@ -100,17 +84,19 @@ func (s *Stack) Layout(children ...StackChild) { p.Y = s.maxSZ.Y - sz.Y } var stack op.StackOp - stack.Push(s.ctx.Ops) - op.TransformOp{}.Offset(toPointF(p)).Add(s.ctx.Ops) - ch.macro.Add(s.ctx.Ops) + stack.Push(gtx.Ops) + op.TransformOp{}.Offset(toPointF(p)).Add(gtx.Ops) + ch.macro.Add(gtx.Ops) stack.Pop() } b := s.baseline if b == 0 { b = s.maxSZ.Y } - s.ctx.Dimensions = Dimensions{ + gtx.Dimensions = Dimensions{ Size: s.maxSZ, Baseline: b, } + s.maxSZ = image.Point{} + s.baseline = 0 }