op: add op.Push and op.Record funcs

The funcs replace stack.Push and macro.Record, which become private.
This makes stack and macro faster to write, in particular for stacks
where you can just write the following line to save and restore the
state :

  defer op.Push(ops).Pop()

This usage requires Push to return a pointer (since Pop has a pointer
receiver), or else the code doesn't compile.

For consistancy, I tried to do the same for op.Record, but this implied
to turn all the MacroOp fields into pointers, and this caused some
panics. As a result, op.Record doesn't return a pointer.

An other side effect pointed by Larry Clapp: StackOp and MacroOp are not
re-usable any more, you have to allocate a new one for each usage, using
the described funcs above.

Signed-off-by: Thomas Bruyelle <thomas.bruyelle@gmail.com>
This commit is contained in:
Thomas Bruyelle
2020-05-28 10:50:48 +02:00
committed by Elias Naur
parent bade277876
commit ae8a377cda
16 changed files with 62 additions and 79 deletions
+1 -4
View File
@@ -311,7 +311,6 @@ func TestPointerEnterLeaveNested(t *testing.T) {
func TestPointerActiveInputDisappears(t *testing.T) { func TestPointerActiveInputDisappears(t *testing.T) {
handler1 := new(int) handler1 := new(int)
// Save this logic so we can redo it later.
var ops op.Ops var ops op.Ops
var r Router var r Router
@@ -386,9 +385,7 @@ func TestMultitouch(t *testing.T) {
// addPointerHandler adds a pointer.InputOp for the tag in a // addPointerHandler adds a pointer.InputOp for the tag in a
// rectangular area. // rectangular area.
func addPointerHandler(ops *op.Ops, tag event.Tag, area image.Rectangle) { func addPointerHandler(ops *op.Ops, tag event.Tag, area image.Rectangle) {
var stack op.StackOp defer op.Push(ops).Pop()
stack.Push(ops)
defer stack.Pop()
pointer.Rect(area).Add(ops) pointer.Rect(area).Add(ops)
pointer.InputOp{Tag: tag}.Add(ops) pointer.InputOp{Tag: tag}.Add(ops)
} }
+7 -10
View File
@@ -89,15 +89,14 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
} }
crossMin, crossMax := axisCrossConstraint(f.Axis, cs) crossMin, crossMax := axisCrossConstraint(f.Axis, cs)
cs = axisConstraints(f.Axis, 0, mainMax, crossMin, crossMax) cs = axisConstraints(f.Axis, 0, mainMax, crossMin, crossMax)
var m op.MacroOp macro := op.Record(gtx.Ops)
m.Record(gtx.Ops)
gtx := gtx gtx := gtx
gtx.Constraints = cs gtx.Constraints = cs
dims := child.widget(gtx) dims := child.widget(gtx)
m.Stop() macro.Stop()
sz := axisMain(f.Axis, dims.Size) sz := axisMain(f.Axis, dims.Size)
size += sz size += sz
children[i].macro = m children[i].macro = macro
children[i].dims = dims children[i].dims = dims
} }
rigidSize := size rigidSize := size
@@ -124,15 +123,14 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
} }
crossMin, crossMax := axisCrossConstraint(f.Axis, cs) crossMin, crossMax := axisCrossConstraint(f.Axis, cs)
cs = axisConstraints(f.Axis, flexSize, flexSize, crossMin, crossMax) cs = axisConstraints(f.Axis, flexSize, flexSize, crossMin, crossMax)
var m op.MacroOp macro := op.Record(gtx.Ops)
m.Record(gtx.Ops)
gtx := gtx gtx := gtx
gtx.Constraints = cs gtx.Constraints = cs
dims := child.widget(gtx) dims := child.widget(gtx)
m.Stop() macro.Stop()
sz := axisMain(f.Axis, dims.Size) sz := axisMain(f.Axis, dims.Size)
size += sz size += sz
children[i].macro = m children[i].macro = macro
children[i].dims = dims children[i].dims = dims
} }
var maxCross int var maxCross int
@@ -176,8 +174,7 @@ func (f Flex) Layout(gtx Context, children ...FlexChild) Dimensions {
cross = maxBaseline - b cross = maxBaseline - b
} }
} }
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
op.TransformOp{}.Offset(FPt(axisPoint(f.Axis, mainSize, cross))).Add(gtx.Ops) op.TransformOp{}.Offset(FPt(axisPoint(f.Axis, mainSize, cross))).Add(gtx.Ops)
child.macro.Add() child.macro.Add()
stack.Pop() stack.Pop()
+3 -6
View File
@@ -135,8 +135,7 @@ func (in Inset) Layout(gtx Context, w Widget) Dimensions {
if mcs.Min.Y > mcs.Max.Y { if mcs.Min.Y > mcs.Max.Y {
mcs.Min.Y = mcs.Max.Y mcs.Min.Y = mcs.Max.Y
} }
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
op.TransformOp{}.Offset(FPt(image.Point{X: left, Y: top})).Add(gtx.Ops) op.TransformOp{}.Offset(FPt(image.Point{X: left, Y: top})).Add(gtx.Ops)
gtx.Constraints = mcs gtx.Constraints = mcs
dims := w(gtx) dims := w(gtx)
@@ -155,8 +154,7 @@ func UniformInset(v unit.Value) Inset {
// Layout a widget according to the direction. // Layout a widget according to the direction.
func (a Direction) Layout(gtx Context, w Widget) Dimensions { func (a Direction) Layout(gtx Context, w Widget) Dimensions {
var macro op.MacroOp macro := op.Record(gtx.Ops)
macro.Record(gtx.Ops)
cs := gtx.Constraints cs := gtx.Constraints
gtx.Constraints.Min = image.Point{} gtx.Constraints.Min = image.Point{}
dims := w(gtx) dims := w(gtx)
@@ -181,8 +179,7 @@ func (a Direction) Layout(gtx Context, w Widget) Dimensions {
case SW, S, SE: case SW, S, SE:
p.Y = sz.Y - dims.Size.Y p.Y = sz.Y - dims.Size.Y
} }
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
op.TransformOp{}.Offset(FPt(p)).Add(gtx.Ops) op.TransformOp{}.Offset(FPt(p)).Add(gtx.Ops)
macro.Add() macro.Add()
stack.Pop() stack.Pop()
+4 -7
View File
@@ -95,7 +95,7 @@ func (l *List) init(gtx Context, len int) {
l.Position.Offset = 0 l.Position.Offset = 0
l.Position.First = len l.Position.First = len
} }
l.macro.Record(gtx.Ops) l.macro = op.Record(gtx.Ops)
l.next() l.next()
} }
@@ -137,7 +137,7 @@ func (l *List) next() {
l.dir = l.nextDir() l.dir = l.nextDir()
} }
if l.more() { 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), Min: axisPoint(l.Axis, min, -inf),
Max: axisPoint(l.Axis, max, inf), Max: axisPoint(l.Axis, max, inf),
} }
var stack op.StackOp stack := op.Push(ops)
stack.Push(ops)
clip.Rect{Rect: FRect(r)}.Op(ops).Add(ops) clip.Rect{Rect: FRect(r)}.Op(ops).Add(ops)
op.TransformOp{}.Offset(FPt(axisPoint(l.Axis, pos, cross))).Add(ops) op.TransformOp{}.Offset(FPt(axisPoint(l.Axis, pos, cross))).Add(ops)
child.macro.Add() child.macro.Add()
@@ -279,9 +278,7 @@ func (l *List) layout() Dimensions {
} }
dims := axisPoint(l.Axis, pos, maxCross) dims := axisPoint(l.Axis, pos, maxCross)
l.macro.Stop() l.macro.Stop()
var st op.StackOp defer op.Push(l.ctx.Ops).Pop()
st.Push(l.ctx.Ops)
defer st.Pop()
pointer.Rect(image.Rectangle{Max: dims}).Add(ops) pointer.Rect(image.Rectangle{Max: dims}).Add(ops)
l.scroll.Add(ops) l.scroll.Add(ops)
l.macro.Add() l.macro.Add()
+7 -10
View File
@@ -54,19 +54,18 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions {
if w.expanded { if w.expanded {
continue continue
} }
var m op.MacroOp macro := op.Record(gtx.Ops)
m.Record(gtx.Ops)
gtx := gtx gtx := gtx
gtx.Constraints.Min = image.Pt(0, 0) gtx.Constraints.Min = image.Pt(0, 0)
dims := w.widget(gtx) dims := w.widget(gtx)
m.Stop() macro.Stop()
if w := dims.Size.X; w > maxSZ.X { if w := dims.Size.X; w > maxSZ.X {
maxSZ.X = w maxSZ.X = w
} }
if h := dims.Size.Y; h > maxSZ.Y { if h := dims.Size.Y; h > maxSZ.Y {
maxSZ.Y = h maxSZ.Y = h
} }
children[i].macro = m children[i].macro = macro
children[i].dims = dims children[i].dims = dims
} }
// Then lay out Expanded children. // Then lay out Expanded children.
@@ -74,21 +73,20 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions {
if !w.expanded { if !w.expanded {
continue continue
} }
var m op.MacroOp macro := op.Record(gtx.Ops)
m.Record(gtx.Ops)
gtx := gtx gtx := gtx
gtx.Constraints = Constraints{ gtx.Constraints = Constraints{
Min: maxSZ, Max: gtx.Constraints.Max, Min: maxSZ, Max: gtx.Constraints.Max,
} }
dims := w.widget(gtx) dims := w.widget(gtx)
m.Stop() macro.Stop()
if w := dims.Size.X; w > maxSZ.X { if w := dims.Size.X; w > maxSZ.X {
maxSZ.X = w maxSZ.X = w
} }
if h := dims.Size.Y; h > maxSZ.Y { if h := dims.Size.Y; h > maxSZ.Y {
maxSZ.Y = h maxSZ.Y = h
} }
children[i].macro = m children[i].macro = macro
children[i].dims = dims children[i].dims = dims
} }
@@ -109,8 +107,7 @@ func (s Stack) Layout(gtx Context, children ...StackChild) Dimensions {
case SW, S, SE: case SW, S, SE:
p.Y = maxSZ.Y - sz.Y p.Y = maxSZ.Y - sz.Y
} }
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
op.TransformOp{}.Offset(FPt(p)).Add(gtx.Ops) op.TransformOp{}.Offset(FPt(p)).Add(gtx.Ops)
ch.macro.Add() ch.macro.Add()
stack.Pop() stack.Pop()
+1 -1
View File
@@ -53,7 +53,7 @@ func (p Op) Add(o *op.Ops) {
// Begin the path, storing the path data and final Op into ops. // Begin the path, storing the path data and final Op into ops.
func (p *Path) Begin(ops *op.Ops) { func (p *Path) Begin(ops *op.Ops) {
p.ops = ops p.ops = ops
p.macro.Record(ops) p.macro = op.Record(ops)
// Write the TypeAux opcode and a byte for marking whether the // 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 // path has had its MaxY filled out. If not, the gpu will fill it
// before using it. // before using it.
+21 -6
View File
@@ -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: The StackOp saves the current state to the state stack and restores it later:
ops := new(op.Ops) ops := new(op.Ops)
var stack op.StackOp
// Save the current state, in particular the transform. // Save the current state, in particular the transform.
stack.Push(ops) stack := op.Push(ops)
// Apply a transform to subsequent operations. // Apply a transform to subsequent operations.
op.TransformOp{}.Offset(...).Add(ops) op.TransformOp{}.Offset(...).Add(ops)
... ...
// Restore the previous transform. // Restore the previous transform.
stack.Pop() 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: The CallOp invokes another operation list:
ops := new(op.Ops) 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: The MacroOp records a list of operations to be executed later:
ops := new(op.Ops) ops := new(op.Ops)
var macro op.MacroOp macro := op.Record(ops)
macro.Record(ops)
// Record operations by adding them. // Record operations by adding them.
op.InvalidateOp{}.Add(ops) op.InvalidateOp{}.Add(ops)
... ...
@@ -155,7 +158,13 @@ func (c CallOp) Add(o *Ops) {
} }
// Push (save) the current operations state. // 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 { if s.active {
panic("unbalanced push") panic("unbalanced push")
} }
@@ -221,7 +230,13 @@ func (o *Ops) pc() pc {
} }
// Record a macro of operations. // 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 { if m.recording {
panic("already recording") panic("already recording")
} }
+1 -3
View File
@@ -39,9 +39,7 @@ func (b *Bool) Layout(gtx layout.Context) layout.Dimensions {
b.changed = true b.changed = true
} }
} }
var st op.StackOp defer op.Push(gtx.Ops).Pop()
st.Push(gtx.Ops)
defer st.Pop()
pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops)
b.gesture.Add(gtx.Ops) b.gesture.Add(gtx.Ops)
return layout.Dimensions{Size: gtx.Constraints.Min} return layout.Dimensions{Size: gtx.Constraints.Min}
+2 -3
View File
@@ -67,11 +67,10 @@ func (b *Clickable) History() []Press {
func (b *Clickable) Layout(gtx layout.Context) layout.Dimensions { func (b *Clickable) Layout(gtx layout.Context) layout.Dimensions {
b.update(gtx) b.update(gtx)
var st op.StackOp stack := op.Push(gtx.Ops)
st.Push(gtx.Ops)
pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops)
b.click.Add(gtx.Ops) b.click.Add(gtx.Ops)
st.Pop() stack.Pop()
for len(b.history) > 0 { for len(b.history) > 0 {
c := b.history[0] c := b.history[0]
if gtx.Now().Sub(c.Time) < 1*time.Second { if gtx.Now().Sub(c.Time) < 1*time.Second {
+2 -4
View File
@@ -328,8 +328,7 @@ func (e *Editor) PaintText(gtx layout.Context) {
clip := textPadding(e.lines) clip := textPadding(e.lines)
clip.Max = clip.Max.Add(e.viewSize) clip.Max = clip.Max.Add(e.viewSize)
for _, shape := range e.shapes { for _, shape := range e.shapes {
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
op.TransformOp{}.Offset(shape.offset).Add(gtx.Ops) op.TransformOp{}.Offset(shape.offset).Add(gtx.Ops)
shape.clip.Add(gtx.Ops) shape.clip.Add(gtx.Ops)
paint.PaintOp{Rect: layout.FRect(clip).Sub(shape.offset)}.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))) carWidth := fixed.I(gtx.Px(unit.Dp(1)))
carLine, _, carX, carY := e.layoutCaret() carLine, _, carX, carY := e.layoutCaret()
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
carX -= carWidth / 2 carX -= carWidth / 2
carAsc, carDesc := -e.lines[carLine].Bounds.Min.Y, e.lines[carLine].Bounds.Max.Y carAsc, carDesc := -e.lines[carLine].Bounds.Min.Y, e.lines[carLine].Bounds.Max.Y
carRect := image.Rectangle{ carRect := image.Rectangle{
+1 -3
View File
@@ -37,9 +37,7 @@ func (e *Enum) Changed() bool {
// Layout adds the event handler for key. // Layout adds the event handler for key.
func (e *Enum) Layout(gtx layout.Context, key string) layout.Dimensions { func (e *Enum) Layout(gtx layout.Context, key string) layout.Dimensions {
var st op.StackOp defer op.Push(gtx.Ops).Pop()
st.Push(gtx.Ops)
defer st.Pop()
pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops) pointer.Rect(image.Rectangle{Max: gtx.Constraints.Min}).Add(gtx.Ops)
if index(e.values, key) == -1 { if index(e.values, key) == -1 {
+2 -3
View File
@@ -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)) w, h := gtx.Px(unit.Dp(wf*scale)), gtx.Px(unit.Dp(hf*scale))
cs := gtx.Constraints cs := gtx.Constraints
d := cs.Constrain(image.Pt(w, h)) d := cs.Constrain(image.Pt(w, h))
var s op.StackOp stack := op.Push(gtx.Ops)
s.Push(gtx.Ops)
clip.Rect{Rect: f32.Rectangle{Max: layout.FPt(d)}}.Op(gtx.Ops).Add(gtx.Ops) clip.Rect{Rect: f32.Rectangle{Max: layout.FPt(d)}}.Op(gtx.Ops).Add(gtx.Ops)
im.Src.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) 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} return layout.Dimensions{Size: d}
} }
+1 -2
View File
@@ -107,8 +107,7 @@ func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size un
break break
} }
lclip := layout.FRect(clip).Sub(off) lclip := layout.FRect(clip).Sub(off)
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
op.TransformOp{}.Offset(off).Add(gtx.Ops) op.TransformOp{}.Offset(off).Add(gtx.Ops)
str := txt[start:end] str := txt[start:end]
s.ShapeString(font, textSize, str, l).Add(gtx.Ops) s.ShapeString(font, textSize, str, l).Add(gtx.Ops)
+1 -2
View File
@@ -188,8 +188,7 @@ func drawInk(gtx layout.Context, c widget.Press) {
return return
} }
t = t / duration t = t / duration
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
size := float32(gtx.Px(unit.Dp(700))) * t size := float32(gtx.Px(unit.Dp(700))) * t
rr := size * .5 rr := size * .5
col := byte(0xaa * (1 - t*t)) col := byte(0xaa * (1 - t*t))
+2 -5
View File
@@ -39,10 +39,8 @@ func Editor(th *Theme, editor *widget.Editor, hint string) EditorStyle {
} }
func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions { func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions {
var stack op.StackOp defer op.Push(gtx.Ops).Pop()
stack.Push(gtx.Ops) macro := op.Record(gtx.Ops)
var macro op.MacroOp
macro.Record(gtx.Ops)
paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops) paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops)
tl := widget.Label{Alignment: e.Editor.Alignment} tl := widget.Label{Alignment: e.Editor.Alignment}
dims := tl.Layout(gtx, e.shaper, e.Font, e.TextSize, e.Hint) 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) paint.ColorOp{Color: e.Color}.Add(gtx.Ops)
e.Editor.PaintCaret(gtx) e.Editor.PaintCaret(gtx)
stack.Pop()
return dims return dims
} }
+6 -10
View File
@@ -36,8 +36,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
trackOff := float32(thumbSize-trackHeight) * .5 trackOff := float32(thumbSize-trackHeight) * .5
// Draw track. // Draw track.
var stack op.StackOp stack := op.Push(gtx.Ops)
stack.Push(gtx.Ops)
trackCorner := float32(trackHeight) / 2 trackCorner := float32(trackHeight) / 2
trackRect := f32.Rectangle{Max: f32.Point{ trackRect := f32.Rectangle{Max: f32.Point{
X: float32(trackWidth), X: float32(trackWidth),
@@ -53,7 +52,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
stack.Pop() stack.Pop()
// Compute thumb offset and color. // Compute thumb offset and color.
stack.Push(gtx.Ops) stack = op.Push(gtx.Ops)
col := rgb(0xffffff) col := rgb(0xffffff)
if s.Switch.Value { if s.Switch.Value {
off := trackWidth - thumbSize 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 // Draw thumb shadow, a translucent disc slightly larger than the
// thumb itself. // thumb itself.
var shadowStack op.StackOp shadowStack := op.Push(gtx.Ops)
shadowStack.Push(gtx.Ops)
shadowSize := float32(2) shadowSize := float32(2)
// Center shadow horizontally and slightly adjust its Y. // Center shadow horizontally and slightly adjust its Y.
op.TransformOp{}.Offset(f32.Point{X: -shadowSize / 2, Y: -.75}).Add(gtx.Ops) 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() stack.Pop()
// Draw thumb ink. // Draw thumb ink.
stack.Push(gtx.Ops) stack = op.Push(gtx.Ops)
inkSize := float32(gtx.Px(unit.Dp(44))) inkSize := float32(gtx.Px(unit.Dp(44)))
rr := inkSize * .5 rr := inkSize * .5
inkOff := f32.Point{ inkOff := f32.Point{
@@ -97,7 +95,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
stack.Pop() stack.Pop()
// Set up click area. // Set up click area.
stack.Push(gtx.Ops) stack = op.Push(gtx.Ops)
clickSize := gtx.Px(unit.Dp(40)) clickSize := gtx.Px(unit.Dp(40))
clickOff := f32.Point{ clickOff := f32.Point{
X: (float32(trackWidth) - float32(clickSize)) * .5, 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) { func drawDisc(ops *op.Ops, sz float32, col color.RGBA) {
var stack op.StackOp defer op.Push(ops).Pop()
stack.Push(ops)
rr := sz / 2 rr := sz / 2
r := f32.Rectangle{Max: f32.Point{X: sz, Y: sz}} r := f32.Rectangle{Max: f32.Point{X: sz, Y: sz}}
clip.Rect{ clip.Rect{
@@ -124,5 +121,4 @@ func drawDisc(ops *op.Ops, sz float32, col color.RGBA) {
}.Op(ops).Add(ops) }.Op(ops).Add(ops)
paint.ColorOp{Color: col}.Add(ops) paint.ColorOp{Color: col}.Add(ops)
paint.PaintOp{Rect: r}.Add(ops) paint.PaintOp{Rect: r}.Add(ops)
stack.Pop()
} }