diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index 6ea80d7a..94fda006 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -311,7 +311,6 @@ func TestPointerEnterLeaveNested(t *testing.T) { func TestPointerActiveInputDisappears(t *testing.T) { handler1 := new(int) - // Save this logic so we can redo it later. var ops op.Ops var r Router @@ -386,9 +385,7 @@ func TestMultitouch(t *testing.T) { // addPointerHandler adds a pointer.InputOp for the tag in a // rectangular area. func addPointerHandler(ops *op.Ops, tag event.Tag, area image.Rectangle) { - var stack op.StackOp - stack.Push(ops) - defer stack.Pop() + defer op.Push(ops).Pop() pointer.Rect(area).Add(ops) pointer.InputOp{Tag: tag}.Add(ops) } diff --git a/layout/flex.go b/layout/flex.go index a31077e0..7037d923 100644 --- a/layout/flex.go +++ b/layout/flex.go @@ -89,15 +89,14 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions { } crossMin, crossMax := axisCrossConstraint(f.Axis, cs) cs = axisConstraints(f.Axis, 0, mainMax, crossMin, crossMax) - var m op.MacroOp - m.Record(gtx.Ops) + macro := op.Record(gtx.Ops) gtx := gtx gtx.Constraints = cs dims := child.widget(gtx) - m.Stop() + macro.Stop() sz := axisMain(f.Axis, dims.Size) size += sz - children[i].macro = m + children[i].macro = macro children[i].dims = dims } rigidSize := size @@ -124,15 +123,14 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions { } crossMin, crossMax := axisCrossConstraint(f.Axis, cs) cs = axisConstraints(f.Axis, flexSize, flexSize, crossMin, crossMax) - var m op.MacroOp - m.Record(gtx.Ops) + macro := op.Record(gtx.Ops) gtx := gtx gtx.Constraints = cs dims := child.widget(gtx) - m.Stop() + macro.Stop() sz := axisMain(f.Axis, dims.Size) size += sz - children[i].macro = m + children[i].macro = macro children[i].dims = dims } var maxCross int @@ -176,8 +174,7 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions { cross = maxBaseline - b } } - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) op.TransformOp{}.Offset(FPt(axisPoint(f.Axis, mainSize, cross))).Add(gtx.Ops) child.macro.Add() stack.Pop() diff --git a/layout/layout.go b/layout/layout.go index a92df55b..4930c168 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -135,8 +135,7 @@ func (in Inset) Layout(gtx Context, w Widget) Dimensions { if mcs.Min.Y > mcs.Max.Y { mcs.Min.Y = mcs.Max.Y } - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) op.TransformOp{}.Offset(FPt(image.Point{X: left, Y: top})).Add(gtx.Ops) gtx.Constraints = mcs dims := w(gtx) @@ -155,8 +154,7 @@ func UniformInset(v unit.Value) Inset { // Layout a widget according to the direction. func (a Direction) Layout(gtx Context, w Widget) Dimensions { - var macro op.MacroOp - macro.Record(gtx.Ops) + macro := op.Record(gtx.Ops) cs := gtx.Constraints gtx.Constraints.Min = image.Point{} dims := w(gtx) @@ -181,8 +179,7 @@ func (a Direction) Layout(gtx Context, w Widget) Dimensions { case SW, S, SE: p.Y = sz.Y - dims.Size.Y } - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) op.TransformOp{}.Offset(FPt(p)).Add(gtx.Ops) macro.Add() stack.Pop() diff --git a/layout/list.go b/layout/list.go index ecc908f8..64ae1c9d 100644 --- a/layout/list.go +++ b/layout/list.go @@ -95,7 +95,7 @@ func (l *List) init(gtx Context, len int) { l.Position.Offset = 0 l.Position.First = len } - l.macro.Record(gtx.Ops) + l.macro = op.Record(gtx.Ops) l.next() } @@ -137,7 +137,7 @@ func (l *List) next() { l.dir = l.nextDir() } if l.more() { - l.child.Record(l.ctx.Ops) + l.child = op.Record(l.ctx.Ops) } } @@ -257,8 +257,7 @@ func (l *List) layout() Dimensions { Min: axisPoint(l.Axis, min, -inf), Max: axisPoint(l.Axis, max, inf), } - var stack op.StackOp - stack.Push(ops) + stack := op.Push(ops) clip.Rect{Rect: FRect(r)}.Op(ops).Add(ops) op.TransformOp{}.Offset(FPt(axisPoint(l.Axis, pos, cross))).Add(ops) child.macro.Add() @@ -279,9 +278,7 @@ func (l *List) layout() Dimensions { } dims := axisPoint(l.Axis, pos, maxCross) l.macro.Stop() - var st op.StackOp - st.Push(l.ctx.Ops) - defer st.Pop() + defer op.Push(l.ctx.Ops).Pop() pointer.Rect(image.Rectangle{Max: dims}).Add(ops) l.scroll.Add(ops) l.macro.Add() diff --git a/layout/stack.go b/layout/stack.go index 447547b2..fd030e8d 100644 --- a/layout/stack.go +++ b/layout/stack.go @@ -54,19 +54,18 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions { if w.expanded { continue } - var m op.MacroOp - m.Record(gtx.Ops) + macro := op.Record(gtx.Ops) gtx := gtx gtx.Constraints.Min = image.Pt(0, 0) dims := w.widget(gtx) - m.Stop() + macro.Stop() if w := dims.Size.X; w > maxSZ.X { maxSZ.X = w } if h := dims.Size.Y; h > maxSZ.Y { maxSZ.Y = h } - children[i].macro = m + children[i].macro = macro children[i].dims = dims } // Then lay out Expanded children. @@ -74,21 +73,20 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions { if !w.expanded { continue } - var m op.MacroOp - m.Record(gtx.Ops) + macro := op.Record(gtx.Ops) gtx := gtx gtx.Constraints = Constraints{ Min: maxSZ, Max: gtx.Constraints.Max, } dims := w.widget(gtx) - m.Stop() + macro.Stop() if w := dims.Size.X; w > maxSZ.X { maxSZ.X = w } if h := dims.Size.Y; h > maxSZ.Y { maxSZ.Y = h } - children[i].macro = m + children[i].macro = macro children[i].dims = dims } @@ -109,8 +107,7 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions { case SW, S, SE: p.Y = maxSZ.Y - sz.Y } - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) op.TransformOp{}.Offset(FPt(p)).Add(gtx.Ops) ch.macro.Add() stack.Pop() diff --git a/op/clip/clip.go b/op/clip/clip.go index 6a1f47c2..c54bdcc8 100644 --- a/op/clip/clip.go +++ b/op/clip/clip.go @@ -53,7 +53,7 @@ func (p Op) Add(o *op.Ops) { // Begin the path, storing the path data and final Op into ops. func (p *Path) Begin(ops *op.Ops) { p.ops = ops - p.macro.Record(ops) + p.macro = op.Record(ops) // Write the TypeAux opcode and a byte for marking whether the // path has had its MaxY filled out. If not, the gpu will fill it // before using it. diff --git a/op/op.go b/op/op.go index 49a3dc02..6a230e3b 100644 --- a/op/op.go +++ b/op/op.go @@ -36,15 +36,19 @@ mutable state stack and execution flow can be controlled with macros. The StackOp saves the current state to the state stack and restores it later: ops := new(op.Ops) - var stack op.StackOp // Save the current state, in particular the transform. - stack.Push(ops) + stack := op.Push(ops) // Apply a transform to subsequent operations. op.TransformOp{}.Offset(...).Add(ops) ... // Restore the previous transform. stack.Pop() +You can also use this one-line to save the current state and restore it at the +end of a function : + + defer op.Push(ops).Pop() + The CallOp invokes another operation list: ops := new(op.Ops) @@ -54,8 +58,7 @@ The CallOp invokes another operation list: The MacroOp records a list of operations to be executed later: ops := new(op.Ops) - var macro op.MacroOp - macro.Record(ops) + macro := op.Record(ops) // Record operations by adding them. op.InvalidateOp{}.Add(ops) ... @@ -155,7 +158,13 @@ func (c CallOp) Add(o *Ops) { } // Push (save) the current operations state. -func (s *StackOp) Push(o *Ops) { +func Push(o *Ops) *StackOp { + var s StackOp + s.push(o) + return &s +} + +func (s *StackOp) push(o *Ops) { if s.active { panic("unbalanced push") } @@ -221,7 +230,13 @@ func (o *Ops) pc() pc { } // Record a macro of operations. -func (m *MacroOp) Record(o *Ops) { +func Record(o *Ops) MacroOp { + var m MacroOp + m.record(o) + return m +} + +func (m *MacroOp) record(o *Ops) { if m.recording { panic("already recording") } diff --git a/widget/bool.go b/widget/bool.go index 270e51fc..f2f0cc6d 100644 --- a/widget/bool.go +++ b/widget/bool.go @@ -39,9 +39,7 @@ func (b *Bool) Layout(gtx layout.Context) layout.Dimensions { b.changed = true } } - var st op.StackOp - st.Push(gtx.Ops) - defer st.Pop() + defer op.Push(gtx.Ops).Pop() pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) b.gesture.Add(gtx.Ops) return layout.Dimensions{Size: gtx.Constraints.Min} diff --git a/widget/button.go b/widget/button.go index 2b890603..6a1ddbed 100644 --- a/widget/button.go +++ b/widget/button.go @@ -67,11 +67,10 @@ func (b *Clickable) History() []Press { func (b *Clickable) Layout(gtx layout.Context) layout.Dimensions { b.update(gtx) - var st op.StackOp - st.Push(gtx.Ops) + stack := op.Push(gtx.Ops) pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) b.click.Add(gtx.Ops) - st.Pop() + stack.Pop() for len(b.history) > 0 { c := b.history[0] if gtx.Now().Sub(c.Time) < 1*time.Second { diff --git a/widget/editor.go b/widget/editor.go index b3fe246a..27c5d640 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -328,8 +328,7 @@ func (e *Editor) PaintText(gtx layout.Context) { clip := textPadding(e.lines) clip.Max = clip.Max.Add(e.viewSize) for _, shape := range e.shapes { - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) op.TransformOp{}.Offset(shape.offset).Add(gtx.Ops) shape.clip.Add(gtx.Ops) paint.PaintOp{Rect: layout.FRect(clip).Sub(shape.offset)}.Add(gtx.Ops) @@ -344,8 +343,7 @@ func (e *Editor) PaintCaret(gtx layout.Context) { carWidth := fixed.I(gtx.Px(unit.Dp(1))) carLine, _, carX, carY := e.layoutCaret() - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) carX -= carWidth / 2 carAsc, carDesc := -e.lines[carLine].Bounds.Min.Y, e.lines[carLine].Bounds.Max.Y carRect := image.Rectangle{ diff --git a/widget/enum.go b/widget/enum.go index 70dc90f5..79b681cc 100644 --- a/widget/enum.go +++ b/widget/enum.go @@ -37,9 +37,7 @@ func (e *Enum) Changed() bool { // Layout adds the event handler for key. func (e *Enum) Layout(gtx layout.Context, key string) layout.Dimensions { - var st op.StackOp - st.Push(gtx.Ops) - defer st.Pop() + defer op.Push(gtx.Ops).Pop() pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) if index(e.values, key) == -1 { diff --git a/widget/image.go b/widget/image.go index 15a3ca83..5ade15d5 100644 --- a/widget/image.go +++ b/widget/image.go @@ -33,11 +33,10 @@ func (im Image) Layout(gtx layout.Context) layout.Dimensions { w, h := gtx.Px(unit.Dp(wf*scale)), gtx.Px(unit.Dp(hf*scale)) cs := gtx.Constraints d := cs.Constrain(image.Pt(w, h)) - var s op.StackOp - s.Push(gtx.Ops) + stack := op.Push(gtx.Ops) clip.Rect{Rect: f32.Rectangle{Max: layout.FPt(d)}}.Op(gtx.Ops).Add(gtx.Ops) im.Src.Add(gtx.Ops) paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: float32(w), Y: float32(h)}}}.Add(gtx.Ops) - s.Pop() + stack.Pop() return layout.Dimensions{Size: d} } diff --git a/widget/label.go b/widget/label.go index cab5aeec..45c35875 100644 --- a/widget/label.go +++ b/widget/label.go @@ -107,8 +107,7 @@ func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size un break } lclip := layout.FRect(clip).Sub(off) - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) op.TransformOp{}.Offset(off).Add(gtx.Ops) str := txt[start:end] s.ShapeString(font, textSize, str, l).Add(gtx.Ops) diff --git a/widget/material/button.go b/widget/material/button.go index bb5f7f31..0d28e537 100644 --- a/widget/material/button.go +++ b/widget/material/button.go @@ -188,8 +188,7 @@ func drawInk(gtx layout.Context, c widget.Press) { return } t = t / duration - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) size := float32(gtx.Px(unit.Dp(700))) * t rr := size * .5 col := byte(0xaa * (1 - t*t)) diff --git a/widget/material/editor.go b/widget/material/editor.go index 1a4dd719..96739924 100644 --- a/widget/material/editor.go +++ b/widget/material/editor.go @@ -39,10 +39,8 @@ func Editor(th *Theme, editor *widget.Editor, hint string) EditorStyle { } func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions { - var stack op.StackOp - stack.Push(gtx.Ops) - var macro op.MacroOp - macro.Record(gtx.Ops) + defer op.Push(gtx.Ops).Pop() + macro := op.Record(gtx.Ops) paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops) tl := widget.Label{Alignment: e.Editor.Alignment} dims := tl.Layout(gtx, e.shaper, e.Font, e.TextSize, e.Hint) @@ -62,6 +60,5 @@ func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions { } paint.ColorOp{Color: e.Color}.Add(gtx.Ops) e.Editor.PaintCaret(gtx) - stack.Pop() return dims } diff --git a/widget/material/switch.go b/widget/material/switch.go index 401b1dcf..bc71e6a8 100644 --- a/widget/material/switch.go +++ b/widget/material/switch.go @@ -36,8 +36,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { trackOff := float32(thumbSize-trackHeight) * .5 // Draw track. - var stack op.StackOp - stack.Push(gtx.Ops) + stack := op.Push(gtx.Ops) trackCorner := float32(trackHeight) / 2 trackRect := f32.Rectangle{Max: f32.Point{ X: float32(trackWidth), @@ -53,7 +52,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { stack.Pop() // Compute thumb offset and color. - stack.Push(gtx.Ops) + stack = op.Push(gtx.Ops) col := rgb(0xffffff) if s.Switch.Value { off := trackWidth - thumbSize @@ -63,8 +62,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { // Draw thumb shadow, a translucent disc slightly larger than the // thumb itself. - var shadowStack op.StackOp - shadowStack.Push(gtx.Ops) + shadowStack := op.Push(gtx.Ops) shadowSize := float32(2) // Center shadow horizontally and slightly adjust its Y. op.TransformOp{}.Offset(f32.Point{X: -shadowSize / 2, Y: -.75}).Add(gtx.Ops) @@ -76,7 +74,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { stack.Pop() // Draw thumb ink. - stack.Push(gtx.Ops) + stack = op.Push(gtx.Ops) inkSize := float32(gtx.Px(unit.Dp(44))) rr := inkSize * .5 inkOff := f32.Point{ @@ -97,7 +95,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { stack.Pop() // Set up click area. - stack.Push(gtx.Ops) + stack = op.Push(gtx.Ops) clickSize := gtx.Px(unit.Dp(40)) clickOff := f32.Point{ X: (float32(trackWidth) - float32(clickSize)) * .5, @@ -114,8 +112,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { } func drawDisc(ops *op.Ops, sz float32, col color.RGBA) { - var stack op.StackOp - stack.Push(ops) + defer op.Push(ops).Pop() rr := sz / 2 r := f32.Rectangle{Max: f32.Point{X: sz, Y: sz}} clip.Rect{ @@ -124,5 +121,4 @@ func drawDisc(ops *op.Ops, sz float32, col color.RGBA) { }.Op(ops).Add(ops) paint.ColorOp{Color: col}.Add(ops) paint.PaintOp{Rect: r}.Add(ops) - stack.Pop() }