diff --git a/internal/rendertest/bench_test.go b/internal/rendertest/bench_test.go index 498bed5c..d83578e4 100644 --- a/internal/rendertest/bench_test.go +++ b/internal/rendertest/bench_test.go @@ -82,13 +82,13 @@ func BenchmarkDrawUI(b *testing.B) { for i := 0; i < b.N; i++ { resetOps(gtx) - p := op.Push(gtx.Ops) + p := op.Save(gtx.Ops) off := float32(math.Mod(float64(i)/10, 10)) op.Offset(f32.Pt(off, off)).Add(gtx.Ops) drawCore(gtx, th) - p.Pop() + p.Load() w.Frame(gtx.Ops) } finishBenchmark(b, w) @@ -104,14 +104,14 @@ func BenchmarkDrawUITransformed(b *testing.B) { for i := 0; i < b.N; i++ { resetOps(gtx) - p := op.Push(gtx.Ops) + p := op.Save(gtx.Ops) angle := float32(math.Mod(float64(i)/1000, 0.05)) a := f32.Affine2D{}.Shear(f32.Point{}, angle, angle).Rotate(f32.Point{}, angle) op.Affine(a).Add(gtx.Ops) drawCore(gtx, th) - p.Pop() + p.Load() w.Frame(gtx.Ops) } finishBenchmark(b, w) @@ -153,7 +153,7 @@ func Benchmark1000CirclesInstanced(b *testing.B) { func draw1000Circles(gtx layout.Context) { ops := gtx.Ops for x := 0; x < 100; x++ { - p := op.Push(ops) + p := op.Save(ops) op.Offset(f32.Pt(float32(x*10), 0)).Add(ops) for y := 0; y < 10; y++ { paint.FillShape(ops, @@ -162,7 +162,7 @@ func draw1000Circles(gtx layout.Context) { ) op.Offset(f32.Pt(0, float32(100))).Add(ops) } - p.Pop() + p.Load() } } @@ -175,16 +175,16 @@ func draw1000CirclesInstanced(gtx layout.Context) { c := r.Stop() for x := 0; x < 100; x++ { - p := op.Push(ops) + p := op.Save(ops) op.Offset(f32.Pt(float32(x*10), 0)).Add(ops) for y := 0; y < 10; y++ { - pi := op.Push(ops) + pi := op.Save(ops) paint.ColorOp{Color: color.NRGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120}}.Add(ops) c.Add(ops) - pi.Pop() + pi.Load() op.Offset(f32.Pt(0, float32(100))).Add(ops) } - p.Pop() + p.Load() } } @@ -204,7 +204,7 @@ func drawIndividualShapes(gtx layout.Context, th *material.Theme) chan op.CallOp ops := &op1 c := op.Record(ops) for x := 0; x < 9; x++ { - p := op.Push(ops) + p := op.Save(ops) op.Offset(f32.Pt(float32(x*50), 0)).Add(ops) for y := 0; y < 9; y++ { paint.FillShape(ops, @@ -213,7 +213,7 @@ func drawIndividualShapes(gtx layout.Context, th *material.Theme) chan op.CallOp ) op.Offset(f32.Pt(0, float32(50))).Add(ops) } - p.Pop() + p.Load() } c1 <- c.Stop() }() @@ -235,10 +235,10 @@ func drawShapeInstances(gtx layout.Context, th *material.Theme) chan op.CallOp { rad := float32(0) for x := 0; x < 20; x++ { for y := 0; y < 20; y++ { - p := op.Push(ops) + p := op.Save(ops) op.Offset(f32.Pt(float32(x*50+25), float32(y*50+25))).Add(ops) c.Add(ops) - p.Pop() + p.Load() rad += math.Pi * 2 / 400 } } @@ -256,11 +256,11 @@ func drawText(gtx layout.Context, th *material.Theme) chan op.CallOp { txt := material.H6(th, "") for x := 0; x < 40; x++ { txt.Text = textRows[x] - p := op.Push(ops) + p := op.Save(ops) op.Offset(f32.Pt(float32(0), float32(24*x))).Add(ops) gtx.Ops = ops txt.Layout(gtx) - p.Pop() + p.Load() } c3 <- c.Stop() }() diff --git a/internal/rendertest/clip_test.go b/internal/rendertest/clip_test.go index 9c339aa8..20696726 100644 --- a/internal/rendertest/clip_test.go +++ b/internal/rendertest/clip_test.go @@ -229,7 +229,7 @@ func TestStrokedPathRoundRound(t *testing.T) { func TestStrokedPathFlatMiter(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) clip.Stroke{ Path: p, @@ -241,10 +241,10 @@ func TestStrokedPathFlatMiter(t *testing.T) { }, }.Op().Add(o) paint.Fill(o, red) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) clip.Stroke{ Path: p, @@ -253,7 +253,7 @@ func TestStrokedPathFlatMiter(t *testing.T) { }, }.Op().Add(o) paint.Fill(o, black) - stk.Pop() + stk.Load() } }, func(r result) { @@ -266,7 +266,7 @@ func TestStrokedPathFlatMiter(t *testing.T) { func TestStrokedPathFlatMiterInf(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) clip.Stroke{ Path: p, @@ -278,10 +278,10 @@ func TestStrokedPathFlatMiterInf(t *testing.T) { }, }.Op().Add(o) paint.Fill(o, red) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) clip.Stroke{ Path: p, @@ -290,7 +290,7 @@ func TestStrokedPathFlatMiterInf(t *testing.T) { }, }.Op().Add(o) paint.Fill(o, black) - stk.Pop() + stk.Load() } }, func(r result) { @@ -303,7 +303,7 @@ func TestStrokedPathFlatMiterInf(t *testing.T) { func TestStrokedPathZeroWidth(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) p := new(clip.Path) p.Begin(o) p.Move(f32.Pt(10, 50)) @@ -316,11 +316,11 @@ func TestStrokedPathZeroWidth(t *testing.T) { }.Op().Add(o) paint.Fill(o, black) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) p := new(clip.Path) p.Begin(o) p.Move(f32.Pt(10, 50)) @@ -330,7 +330,7 @@ func TestStrokedPathZeroWidth(t *testing.T) { }.Op().Add(o) // width=0, disable stroke paint.Fill(o, red) - stk.Pop() + stk.Load() } }, func(r result) { @@ -344,7 +344,7 @@ func TestStrokedPathZeroWidth(t *testing.T) { func TestDashedPathFlatCapEllipse(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) p := newEllipsePath(o) var dash clip.Dash @@ -367,10 +367,10 @@ func TestDashedPathFlatCapEllipse(t *testing.T) { o, red, ) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) p := newEllipsePath(o) clip.Stroke{ Path: p, @@ -383,7 +383,7 @@ func TestDashedPathFlatCapEllipse(t *testing.T) { o, black, ) - stk.Pop() + stk.Load() } }, func(r result) { @@ -396,7 +396,7 @@ func TestDashedPathFlatCapEllipse(t *testing.T) { func TestDashedPathFlatCapZ(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) var dash clip.Dash dash.Begin(o) @@ -414,18 +414,18 @@ func TestDashedPathFlatCapZ(t *testing.T) { Dashes: dash.End(), }.Op().Add(o) paint.Fill(o, red) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) clip.Stroke{ Path: p, Style: clip.StrokeStyle{Width: 2}, }.Op().Add(o) paint.Fill(o, black) - stk.Pop() + stk.Load() } }, func(r result) { r.expect(0, 0, colornames.White) @@ -438,7 +438,7 @@ func TestDashedPathFlatCapZ(t *testing.T) { func TestDashedPathFlatCapZNoDash(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) var dash clip.Dash dash.Begin(o) @@ -455,16 +455,16 @@ func TestDashedPathFlatCapZNoDash(t *testing.T) { Dashes: dash.End(), }.Op().Add(o) paint.Fill(o, red) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) clip.Stroke{ Path: newZigZagPath(o), Style: clip.StrokeStyle{Width: 2}, }.Op().Add(o) paint.Fill(o, black) - stk.Pop() + stk.Load() } }, func(r result) { r.expect(0, 0, colornames.White) @@ -477,7 +477,7 @@ func TestDashedPathFlatCapZNoDash(t *testing.T) { func TestDashedPathFlatCapZNoPath(t *testing.T) { run(t, func(o *op.Ops) { { - stk := op.Push(o) + stk := op.Save(o) var dash clip.Dash dash.Begin(o) dash.Dash(0) @@ -492,17 +492,17 @@ func TestDashedPathFlatCapZNoPath(t *testing.T) { Dashes: dash.End(), }.Op().Add(o) paint.Fill(o, red) - stk.Pop() + stk.Load() } { - stk := op.Push(o) + stk := op.Save(o) p := newZigZagPath(o) clip.Stroke{ Path: p, Style: clip.StrokeStyle{Width: 2}, }.Op().Add(o) paint.Fill(o, black) - stk.Pop() + stk.Load() } }, func(r result) { r.expect(0, 0, colornames.White) diff --git a/internal/rendertest/render_test.go b/internal/rendertest/render_test.go index 87678a20..75b3fb99 100644 --- a/internal/rendertest/render_test.go +++ b/internal/rendertest/render_test.go @@ -33,26 +33,26 @@ func TestTransformMacro(t *testing.T) { m2 := op.Record(o) paint.ColorOp{Color: red}.Add(o) // Simulate a draw text call - stack := op.Push(o) + stack := op.Save(o) op.Offset(f32.Pt(0, 10)).Add(o) // Apply the clip-path. c.Add(o) paint.PaintOp{}.Add(o) - stack.Pop() + stack.Load() c2 := m2.Stop() // Call each of them in a transform - s1 := op.Push(o) + s1 := op.Save(o) op.Offset(f32.Pt(0, 0)).Add(o) c1.Add(o) - s1.Pop() - s2 := op.Push(o) + s1.Load() + s2 := op.Save(o) op.Offset(f32.Pt(0, 0)).Add(o) c2.Add(o) - s2.Pop() + s2.Load() }, func(r result) { r.expect(5, 15, colornames.Red) r.expect(15, 15, colornames.Black) @@ -140,14 +140,14 @@ func TestReuseStencil(t *testing.T) { c2 := drawChild(ops, txt) // lay out the children - stack1 := op.Push(ops) + stack1 := op.Save(ops) c1.Add(ops) - stack1.Pop() + stack1.Load() - stack2 := op.Push(ops) + stack2 := op.Save(ops) op.Offset(f32.Pt(0, 50)).Add(ops) c2.Add(ops) - stack2.Pop() + stack2.Load() }, func(r result) { r.expect(5, 5, colornames.Black) r.expect(5, 55, colornames.Black) @@ -161,11 +161,11 @@ func TestBuildOffscreen(t *testing.T) { txt := constSqCirc() draw := func(off float32, o *op.Ops) { - s := op.Push(o) + s := op.Save(o) op.Offset(f32.Pt(0, off)).Add(o) txt.Add(o) paint.PaintOp{}.Add(o) - s.Pop() + s.Load() } multiRun(t, @@ -230,12 +230,12 @@ func TestLinearGradient(t *testing.T) { Stop2: f32.Pt(gr.Max.X, gr.Min.Y), Color2: g.To, }.Add(ops) - st := op.Push(ops) + st := op.Save(ops) clip.RRect{Rect: gr}.Add(ops) op.Affine(f32.Affine2D{}.Offset(pixelAligned.Min)).Add(ops) scale(pixelAligned.Dx()/128, 1).Add(ops) paint.PaintOp{}.Add(ops) - st.Pop() + st.Load() gr = gr.Add(f32.Pt(0, gradienth)) } }, func(r result) { @@ -260,10 +260,10 @@ func TestLinearGradientAngled(t *testing.T) { Stop2: f32.Pt(0, 0), Color2: red, }.Add(ops) - st := op.Push(ops) + st := op.Save(ops) clip.Rect(image.Rect(0, 0, 64, 64)).Add(ops) paint.PaintOp{}.Add(ops) - st.Pop() + st.Load() paint.LinearGradientOp{ Stop1: f32.Pt(64, 64), @@ -271,10 +271,10 @@ func TestLinearGradientAngled(t *testing.T) { Stop2: f32.Pt(128, 0), Color2: green, }.Add(ops) - st = op.Push(ops) + st = op.Save(ops) clip.Rect(image.Rect(64, 0, 128, 64)).Add(ops) paint.PaintOp{}.Add(ops) - st.Pop() + st.Load() paint.LinearGradientOp{ Stop1: f32.Pt(64, 64), @@ -282,10 +282,10 @@ func TestLinearGradientAngled(t *testing.T) { Stop2: f32.Pt(128, 128), Color2: blue, }.Add(ops) - st = op.Push(ops) + st = op.Save(ops) clip.Rect(image.Rect(64, 64, 128, 128)).Add(ops) paint.PaintOp{}.Add(ops) - st.Pop() + st.Load() paint.LinearGradientOp{ Stop1: f32.Pt(64, 64), @@ -293,10 +293,10 @@ func TestLinearGradientAngled(t *testing.T) { Stop2: f32.Pt(0, 128), Color2: magenta, }.Add(ops) - st = op.Push(ops) + st = op.Save(ops) clip.Rect(image.Rect(0, 64, 64, 128)).Add(ops) paint.PaintOp{}.Add(ops) - st.Pop() + st.Load() }, func(r result) {}) } diff --git a/internal/rendertest/transform_test.go b/internal/rendertest/transform_test.go index 86c54548..286ab677 100644 --- a/internal/rendertest/transform_test.go +++ b/internal/rendertest/transform_test.go @@ -130,7 +130,7 @@ func TestOffsetScaleTexture(t *testing.T) { func TestRotateTexture(t *testing.T) { run(t, func(o *op.Ops) { - defer op.Push(o).Pop() + defer op.Save(o).Load() squares.Add(o) a := f32.Affine2D{}.Offset(f32.Pt(30, 30)).Rotate(f32.Pt(40, 40), math.Pi/4) op.Affine(a).Add(o) diff --git a/io/pointer/doc.go b/io/pointer/doc.go index b99d97d0..7243b945 100644 --- a/io/pointer/doc.go +++ b/io/pointer/doc.go @@ -51,13 +51,13 @@ For example: var stack op.StackOp var h1, h2 *Handler - stack := op.Push(ops) + state := op.Save(ops) pointer.InputOp{Tag: h1}.Add(Ops) - stack.Pop() + state.Load() - stack = op.Push(ops) + state = op.Save(ops) pointer.InputOp{Tag: h2}.Add(ops) - stack.Pop() + state.Load() implies a tree of two inner nodes, each with one pointer handler. diff --git a/io/router/key_test.go b/io/router/key_test.go index b147ec9f..0e975edb 100644 --- a/io/router/key_test.go +++ b/io/router/key_test.go @@ -38,30 +38,30 @@ func TestKeyStacked(t *testing.T) { ops := new(op.Ops) r := new(Router) - s := op.Push(ops) + s := op.Save(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) // FocusOp must not overwrite the // FocusOp{Focus: true}. key.FocusOp{Focus: false}.Add(ops) - s.Pop() - s = op.Push(ops) + s.Load() + s = op.Save(ops) key.SoftKeyboardOp{Show: false}.Add(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) key.FocusOp{Focus: true}.Add(ops) - s.Pop() - s = op.Push(ops) + s.Load() + s = op.Save(ops) key.InputOp{Tag: &handlers[2]}.Add(ops) // SoftwareKeyboardOp will open the keyboard, // overwriting `SoftKeyboardOp{Show: false}`. key.SoftKeyboardOp{Show: true}.Add(ops) - s.Pop() - s = op.Push(ops) + s.Load() + s = op.Save(ops) key.SoftKeyboardOp{Show: false}.Add(ops) key.InputOp{Tag: &handlers[3]}.Add(ops) // FocusOp must not overwrite the // FocusOp{Focus: true}. key.FocusOp{Focus: false}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -93,16 +93,16 @@ func TestKeyRemoveFocus(t *testing.T) { r := new(Router) // New InputOp with Focus and Keyboard: - s := op.Push(ops) + s := op.Save(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) key.FocusOp{Focus: true}.Add(ops) key.SoftKeyboardOp{Show: true}.Add(ops) - s.Pop() + s.Load() // New InputOp without any focus: - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -118,19 +118,19 @@ func TestKeyRemoveFocus(t *testing.T) { ops.Reset() // Will get the focus removed: - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) - s.Pop() + s.Load() // Unchanged: - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) - s.Pop() + s.Load() // Removing any Focus: - s = op.Push(ops) + s = op.Save(ops) key.FocusOp{Focus: false}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -141,18 +141,18 @@ func TestKeyRemoveFocus(t *testing.T) { ops.Reset() - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) - s.Pop() + s.Load() // Setting Focus without InputOp: - s = op.Push(ops) + s = op.Save(ops) key.FocusOp{Focus: true}.Add(ops) - s.Pop() + s.Load() - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -165,18 +165,18 @@ func TestKeyRemoveFocus(t *testing.T) { // Set focus to InputOp which already // exists in the previous frame: - s = op.Push(ops) + s = op.Save(ops) key.FocusOp{Focus: true}.Add(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) key.SoftKeyboardOp{Show: true}.Add(ops) - s.Pop() + s.Load() // Tries to remove focus: // It must not overwrite the previous `FocusOp`. - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) key.FocusOp{Focus: false}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -192,16 +192,16 @@ func TestKeyFocusedInvisible(t *testing.T) { r := new(Router) // Set new InputOp with focus: - s := op.Push(ops) + s := op.Save(ops) key.FocusOp{Focus: true}.Add(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) key.SoftKeyboardOp{Show: true}.Add(ops) - s.Pop() + s.Load() // Set new InputOp without focus: - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -217,9 +217,9 @@ func TestKeyFocusedInvisible(t *testing.T) { // // Unchanged: - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) @@ -232,14 +232,14 @@ func TestKeyFocusedInvisible(t *testing.T) { // Respawn the first element: // It must receive one `Event{Focus: false}`. - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[0]}.Add(ops) - s.Pop() + s.Load() // Unchanged - s = op.Push(ops) + s = op.Save(ops) key.InputOp{Tag: &handlers[1]}.Add(ops) - s.Pop() + s.Load() r.Frame(ops) diff --git a/io/router/pointer_test.go b/io/router/pointer_test.go index e8638578..5acc5c2e 100644 --- a/io/router/pointer_test.go +++ b/io/router/pointer_test.go @@ -243,12 +243,12 @@ func TestMultipleAreas(t *testing.T) { var ops op.Ops addPointerHandler(&ops, handler, image.Rect(0, 0, 100, 100)) - st := op.Push(&ops) + st := op.Save(&ops) pointer.Rect(image.Rect(50, 50, 200, 200)).Add(&ops) // Second area has no Types set, yet should receive events because // Types for the same handles are or-ed together. pointer.InputOp{Tag: handler}.Add(&ops) - st.Pop() + st.Load() var r Router r.Frame(&ops) @@ -468,7 +468,7 @@ func TestCursorNameOp(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) { - defer op.Push(ops).Pop() + defer op.Save(ops).Load() pointer.Rect(area).Add(ops) pointer.InputOp{ Tag: tag, diff --git a/layout/flex.go b/layout/flex.go index 9fe997a0..d197d755 100644 --- a/layout/flex.go +++ b/layout/flex.go @@ -181,10 +181,10 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions { cross = maxBaseline - b } } - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) op.Offset(FPt(f.Axis.point(mainSize, cross))).Add(gtx.Ops) child.call.Add(gtx.Ops) - stack.Pop() + stack.Load() mainSize += f.Axis.Main(dims.Size) if i < len(children)-1 { switch f.Spacing { diff --git a/layout/layout.go b/layout/layout.go index 396e4fef..dc3074f5 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -141,11 +141,11 @@ func (in Inset) Layout(gtx Context, w Widget) Dimensions { if mcs.Min.Y > mcs.Max.Y { mcs.Min.Y = mcs.Max.Y } - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) op.Offset(FPt(image.Point{X: left, Y: top})).Add(gtx.Ops) gtx.Constraints = mcs dims := w(gtx) - stack.Pop() + stack.Load() return Dimensions{ Size: dims.Size.Add(image.Point{X: right + left, Y: top + bottom}), Baseline: dims.Baseline + bottom, @@ -186,10 +186,10 @@ func (d Direction) Layout(gtx Context, w Widget) Dimensions { case SW, S, SE: p.Y = sz.Y - dims.Size.Y } - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) op.Offset(FPt(p)).Add(gtx.Ops) call.Add(gtx.Ops) - stack.Pop() + stack.Load() return Dimensions{ Size: sz, Baseline: dims.Baseline + sz.Y - dims.Size.Y - p.Y, diff --git a/layout/list.go b/layout/list.go index aa6da691..201a3d0a 100644 --- a/layout/list.go +++ b/layout/list.go @@ -253,11 +253,11 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions { Min: l.Axis.point(min, -inf), Max: l.Axis.point(max, inf), } - stack := op.Push(ops) + stack := op.Save(ops) clip.Rect(r).Add(ops) op.Offset(FPt(l.Axis.point(pos, cross))).Add(ops) child.call.Add(ops) - stack.Pop() + stack.Load() pos += childSize } atStart := l.Position.First == 0 && l.Position.Offset <= 0 @@ -274,7 +274,7 @@ func (l *List) layout(ops *op.Ops, macro op.MacroOp) Dimensions { } dims := l.Axis.point(pos, maxCross) call := macro.Stop() - defer op.Push(ops).Pop() + defer op.Save(ops).Load() pointer.Rect(image.Rectangle{Max: dims}).Add(ops) l.scroll.Add(ops) call.Add(ops) diff --git a/layout/stack.go b/layout/stack.go index d17129d6..5e25ca46 100644 --- a/layout/stack.go +++ b/layout/stack.go @@ -104,10 +104,10 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions { case SW, S, SE: p.Y = maxSZ.Y - sz.Y } - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) op.Offset(FPt(p)).Add(gtx.Ops) ch.call.Add(gtx.Ops) - stack.Pop() + stack.Load() if baseline == 0 { if b := ch.dims.Baseline; b != 0 { baseline = b + maxSZ.Y - sz.Y - p.Y diff --git a/op/op.go b/op/op.go index 0b9aeca5..3ba3746b 100644 --- a/op/op.go +++ b/op/op.go @@ -33,21 +33,21 @@ State An Ops list can be viewed as a very simple virtual machine: it has an implicit 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: +The Save function saves the current state for later restoring: ops := new(op.Ops) // Save the current state, in particular the transform. - stack := op.Push(ops) + state := op.Save(ops) // Apply a transform to subsequent operations. op.Offset(...).Add(ops) ... // Restore the previous transform. - stack.Pop() + state.Load() 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() + defer op.Save(ops).Load() The MacroOp records a list of operations to be executed later: @@ -85,15 +85,15 @@ type Ops struct { // refs hold external references for operations. refs []interface{} // nextStateID is the id allocated for the next - // StackOp. + // StateOp. nextStateID int macroStack stack } -// StackOp saves and restores the operation state -// in a stack-like manner. -type StackOp struct { +// StateOp represents a saved operation snapshop to be restored +// later. +type StateOp struct { id int macroID int ops *Ops @@ -125,8 +125,8 @@ type TransformOp struct { t f32.Affine2D } -// stack tracks the integer identities of StackOp and MacroOp -// operations to ensure correct pairing of Push/Pop and Record/End. +// stack tracks the integer identities of MacroOp +// operations to ensure correct pairing of Record/End. type stack struct { currentID int nextID int @@ -142,10 +142,10 @@ type pc struct { refs int } -// Push (save) the current operations state. -func Push(o *Ops) StackOp { +// Save the current operations state. +func Save(o *Ops) StateOp { o.nextStateID++ - s := StackOp{ + s := StateOp{ ops: o, id: o.nextStateID, macroID: o.macroStack.currentID, @@ -157,8 +157,8 @@ func Push(o *Ops) StackOp { return s } -// Pop (restore) a previously Pushed operations state. -func (s StackOp) Pop() { +// Load a previously saved operations state. +func (s StateOp) Load() { if s.id == 0 { panic("zero-value op") } diff --git a/op/paint/paint.go b/op/paint/paint.go index dbff7be0..e36eca3e 100644 --- a/op/paint/paint.go +++ b/op/paint/paint.go @@ -139,7 +139,7 @@ func (d PaintOp) Add(o *op.Ops) { // FillShape fills the clip shape with a color. func FillShape(ops *op.Ops, c color.NRGBA, shape clip.Op) { - defer op.Push(ops).Pop() + defer op.Save(ops).Load() shape.Add(ops) Fill(ops, c) } @@ -149,7 +149,7 @@ func FillShape(ops *op.Ops, c color.NRGBA, shape clip.Op) { // the painted area. Use FillShape unless you need to paint several // times within the same clip.Op. func Fill(ops *op.Ops, c color.NRGBA) { - defer op.Push(ops).Pop() + defer op.Save(ops).Load() ColorOp{Color: c}.Add(ops) PaintOp{}.Add(ops) } diff --git a/widget/border.go b/widget/border.go index da201447..86e356da 100644 --- a/widget/border.go +++ b/widget/border.go @@ -24,7 +24,7 @@ func (b Border) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { dims := w(gtx) sz := dims.Size rr := float32(gtx.Px(b.CornerRadius)) - st := op.Push(gtx.Ops) + st := op.Save(gtx.Ops) width := gtx.Px(b.Width) clip.Border{ Rect: f32.Rectangle{ @@ -35,6 +35,6 @@ func (b Border) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { }.Add(gtx.Ops) paint.ColorOp{Color: b.Color}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - st.Pop() + st.Load() return dims } diff --git a/widget/button.go b/widget/button.go index f5349204..db3e34c9 100644 --- a/widget/button.go +++ b/widget/button.go @@ -74,10 +74,10 @@ func (b *Clickable) History() []Press { func (b *Clickable) Layout(gtx layout.Context) layout.Dimensions { b.update(gtx) - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) b.click.Add(gtx.Ops) - stack.Pop() + stack.Load() for len(b.history) > 0 { c := b.history[0] if c.End.IsZero() || gtx.Now.Sub(c.End) < 1*time.Second { diff --git a/widget/editor.go b/widget/editor.go index f7bbe9a3..a1673b42 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -451,12 +451,12 @@ func (e *Editor) PaintText(gtx layout.Context) { cl := textPadding(e.lines) cl.Max = cl.Max.Add(e.viewSize) for _, shape := range e.shapes { - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) op.Offset(layout.FPt(shape.offset)).Add(gtx.Ops) shape.clip.Add(gtx.Ops) clip.Rect(cl.Sub(shape.offset)).Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - stack.Pop() + stack.Load() } } @@ -469,7 +469,7 @@ func (e *Editor) PaintCaret(gtx layout.Context) { carX := e.caret.x carY := e.caret.y - defer op.Push(gtx.Ops).Pop() + defer op.Save(gtx.Ops).Load() carX -= carWidth / 2 carAsc, carDesc := -e.lines[e.caret.line].Bounds.Min.Y, e.lines[e.caret.line].Bounds.Max.Y carRect := image.Rectangle{ @@ -492,10 +492,10 @@ func (e *Editor) PaintCaret(gtx layout.Context) { cl.Max = cl.Max.Add(e.viewSize) carRect = cl.Intersect(carRect) if !carRect.Empty() { - st := op.Push(gtx.Ops) + st := op.Save(gtx.Ops) clip.Rect(carRect).Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - st.Pop() + st.Load() } } diff --git a/widget/enum.go b/widget/enum.go index 442000e9..39d1eb3c 100644 --- a/widget/enum.go +++ b/widget/enum.go @@ -37,7 +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 { - defer op.Push(gtx.Ops).Pop() + defer op.Save(gtx.Ops).Load() pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) if index(e.values, key) == -1 { diff --git a/widget/float.go b/widget/float.go index 8d21c681..3c59a26a 100644 --- a/widget/float.go +++ b/widget/float.go @@ -52,7 +52,7 @@ func (f *Float) Layout(gtx layout.Context, pointerMargin int, min, max float32) f.pos = 1 } - defer op.Push(gtx.Ops).Pop() + defer op.Save(gtx.Ops).Load() rect := image.Rectangle{Max: size} rect.Min.X -= pointerMargin rect.Max.X += pointerMargin diff --git a/widget/image.go b/widget/image.go index e8d1ab25..77062651 100644 --- a/widget/image.go +++ b/widget/image.go @@ -32,10 +32,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)) - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) clip.Rect(image.Rectangle{Max: d}).Add(gtx.Ops) im.Src.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - stack.Pop() + stack.Load() return layout.Dimensions{Size: d} } diff --git a/widget/label.go b/widget/label.go index 629731d9..bf01137b 100644 --- a/widget/label.go +++ b/widget/label.go @@ -110,12 +110,12 @@ func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size un if !ok { break } - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) op.Offset(layout.FPt(off)).Add(gtx.Ops) s.Shape(font, textSize, l).Add(gtx.Ops) clip.Rect(cl.Sub(off)).Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - stack.Pop() + stack.Load() } return dims } diff --git a/widget/material/button.go b/widget/material/button.go index 03b88c3d..29b07982 100644 --- a/widget/material/button.go +++ b/widget/material/button.go @@ -271,7 +271,7 @@ func drawInk(gtx layout.Context, c widget.Press) { alpha := 0.7 * alphaBezier const col = 0.8 ba, bc := byte(alpha*0xff), byte(col*0xff) - defer op.Push(gtx.Ops).Pop() + defer op.Save(gtx.Ops).Load() rgba := f32color.MulAlpha(color.NRGBA{A: 0xff, R: bc, G: bc, B: bc}, ba) ink := paint.ColorOp{Color: rgba} ink.Add(gtx.Ops) diff --git a/widget/material/editor.go b/widget/material/editor.go index 7b01dbe4..0cf93882 100644 --- a/widget/material/editor.go +++ b/widget/material/editor.go @@ -40,7 +40,7 @@ func Editor(th *Theme, editor *widget.Editor, hint string) EditorStyle { } func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions { - defer op.Push(gtx.Ops).Pop() + defer op.Save(gtx.Ops).Load() macro := op.Record(gtx.Ops) paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops) var maxlines int diff --git a/widget/material/loader.go b/widget/material/loader.go index c34d2d37..892bc862 100644 --- a/widget/material/loader.go +++ b/widget/material/loader.go @@ -36,7 +36,7 @@ func (l LoaderStyle) Layout(gtx layout.Context) layout.Dimensions { } sz := gtx.Constraints.Constrain(image.Pt(diam, diam)) radius := float64(sz.X) * .5 - defer op.Push(gtx.Ops).Pop() + defer op.Save(gtx.Ops).Load() op.Offset(f32.Pt(float32(radius), float32(radius))).Add(gtx.Ops) dt := (time.Duration(gtx.Now.UnixNano()) % (time.Second)).Seconds() diff --git a/widget/material/slider.go b/widget/material/slider.go index 2a99ebc9..1ce95ffa 100644 --- a/widget/material/slider.go +++ b/widget/material/slider.go @@ -58,13 +58,13 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { size.Y = 2 * (touchSizePx / 2) } - st := op.Push(gtx.Ops) + st := op.Save(gtx.Ops) op.Offset(f32.Pt(thumbRadius, 0)).Add(gtx.Ops) gtx.Constraints.Min = image.Pt(size.X-2*thumbRadiusInt, size.Y) s.Float.Layout(gtx, thumbRadiusInt, s.Min, s.Max) gtx.Constraints.Min.Y = size.Y thumbPos := thumbRadius + s.Float.Pos() - st.Pop() + st.Load() color := s.Color if gtx.Queue == nil { @@ -72,7 +72,7 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { } // Draw track before thumb. - st = op.Push(gtx.Ops) + st = op.Save(gtx.Ops) track := f32.Rectangle{ Min: f32.Point{ X: thumbRadius, @@ -86,19 +86,19 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { clip.RRect{Rect: track}.Add(gtx.Ops) paint.ColorOp{Color: color}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - st.Pop() + st.Load() // Draw track after thumb. - st = op.Push(gtx.Ops) + st = op.Save(gtx.Ops) track.Min.X = thumbPos track.Max.X = float32(size.X) - thumbRadius clip.RRect{Rect: track}.Add(gtx.Ops) paint.ColorOp{Color: f32color.MulAlpha(color, 96)}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - st.Pop() + st.Load() // Draw thumb. - st = op.Push(gtx.Ops) + st = op.Save(gtx.Ops) thumb := f32.Rectangle{ Min: f32.Point{ X: thumbPos - thumbRadius, @@ -116,7 +116,7 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { }.Add(gtx.Ops) paint.ColorOp{Color: color}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - st.Pop() + st.Load() return layout.Dimensions{Size: size} } diff --git a/widget/material/switch.go b/widget/material/switch.go index bf1d8eaa..50158c43 100644 --- a/widget/material/switch.go +++ b/widget/material/switch.go @@ -45,7 +45,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { trackOff := float32(thumbSize-trackHeight) * .5 // Draw track. - stack := op.Push(gtx.Ops) + stack := op.Save(gtx.Ops) trackCorner := float32(trackHeight) / 2 trackRect := f32.Rectangle{Max: f32.Point{ X: float32(trackWidth), @@ -66,10 +66,10 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { }.Add(gtx.Ops) paint.ColorOp{Color: trackColor}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) - stack.Pop() + stack.Load() // Draw thumb ink. - stack = op.Push(gtx.Ops) + stack = op.Save(gtx.Ops) inkSize := gtx.Px(unit.Dp(44)) rr := float32(inkSize) * .5 inkOff := f32.Point{ @@ -87,10 +87,10 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { for _, p := range s.Switch.History() { drawInk(gtx, p) } - stack.Pop() + stack.Load() // Compute thumb offset and color. - stack = op.Push(gtx.Ops) + stack = op.Save(gtx.Ops) if s.Switch.Value { off := trackWidth - thumbSize op.Offset(f32.Point{X: float32(off)}).Add(gtx.Ops) @@ -98,19 +98,19 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { // Draw thumb shadow, a translucent disc slightly larger than the // thumb itself. - shadowStack := op.Push(gtx.Ops) + shadowStack := op.Save(gtx.Ops) shadowSize := float32(2) // Center shadow horizontally and slightly adjust its Y. op.Offset(f32.Point{X: -shadowSize / 2, Y: -.75}).Add(gtx.Ops) drawDisc(gtx.Ops, float32(thumbSize)+shadowSize, argb(0x55000000)) - shadowStack.Pop() + shadowStack.Load() // Draw thumb. drawDisc(gtx.Ops, float32(thumbSize), col) - stack.Pop() + stack.Load() // Set up click area. - stack = op.Push(gtx.Ops) + stack = op.Save(gtx.Ops) clickSize := gtx.Px(unit.Dp(40)) clickOff := f32.Point{ X: (float32(trackWidth) - float32(clickSize)) * .5, @@ -121,14 +121,14 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { pointer.Ellipse(image.Rectangle{Max: sz}).Add(gtx.Ops) gtx.Constraints.Min = sz s.Switch.Layout(gtx) - stack.Pop() + stack.Load() dims := image.Point{X: trackWidth, Y: thumbSize} return layout.Dimensions{Size: dims} } func drawDisc(ops *op.Ops, sz float32, col color.NRGBA) { - defer op.Push(ops).Pop() + defer op.Save(ops).Load() rr := sz / 2 r := f32.Rectangle{Max: f32.Point{X: sz, Y: sz}} clip.RRect{