~eliasnaur/gio

a89c6d1c33a345747faa7bfc5a9747f481efba2c — Elias Naur 4 years ago 4d84f46
all: rename `c` to `gtx` for *layout.Context parameters

Short like `ctx` but not as easily confused with context.Context
values.

Suggested by Larry Clapp.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
M apps/gophers/ui.go => apps/gophers/ui.go +96 -96
@@ 171,44 171,44 @@ func (u *UI) face(f *sfnt.Font, size float32) text.Face {
	return u.faces.For(f, ui.Sp(size))
}

func (u *UI) layoutTimings(c *layout.Context) {
func (u *UI) layoutTimings(gtx *layout.Context) {
	if !u.profiling {
		return
	}
	for e, ok := c.Next(u); ok; e, ok = c.Next(u) {
	for e, ok := gtx.Next(u); ok; e, ok = gtx.Next(u) {
		if e, ok := e.(system.ProfileEvent); ok {
			u.profile = e
		}
	}
	system.ProfileOp{Key: u}.Add(c.Ops)
	system.ProfileOp{Key: u}.Add(gtx.Ops)
	var mstats runtime.MemStats
	runtime.ReadMemStats(&mstats)
	mallocs := mstats.Mallocs - u.lastMallocs
	u.lastMallocs = mstats.Mallocs
	layout.Align(layout.NE).Layout(c, func() {
		layout.Inset{Top: ui.Dp(16)}.Layout(c, func() {
	layout.Align(layout.NE).Layout(gtx, func() {
		layout.Inset{Top: ui.Dp(16)}.Layout(gtx, func() {
			txt := fmt.Sprintf("m: %d %s", mallocs, u.profile.Timings)
			text.Label{Material: theme.text, Face: u.face(fonts.mono, 10), Text: txt}.Layout(c)
			text.Label{Material: theme.text, Face: u.face(fonts.mono, 10), Text: txt}.Layout(gtx)
		})
	})
}

func (u *UI) Layout(c *layout.Context) {
	u.faces.Reset(c)
func (u *UI) Layout(gtx *layout.Context) {
	u.faces.Reset(gtx)
	for i := range u.userClicks {
		click := &u.userClicks[i]
		for e, ok := click.Next(c); ok; e, ok = click.Next(c) {
		for e, ok := click.Next(gtx); ok; e, ok = click.Next(gtx) {
			if e.Type == gesture.TypeClick {
				u.selectedUser = u.newUserPage(u.users[i])
			}
		}
	}
	if u.selectedUser == nil {
		u.layoutUsers(c)
		u.layoutUsers(gtx)
	} else {
		u.selectedUser.Layout(c)
		u.selectedUser.Layout(gtx)
	}
	u.layoutTimings(c)
	u.layoutTimings(gtx)
}

func (u *UI) newUserPage(user *user) *userPage {


@@ 221,156 221,156 @@ func (u *UI) newUserPage(user *user) *userPage {
	return up
}

func (up *userPage) Layout(c *layout.Context) {
func (up *userPage) Layout(gtx *layout.Context) {
	l := up.commitsList
	if l.Dragging() {
		key.HideInputOp{}.Add(c.Ops)
		key.HideInputOp{}.Add(gtx.Ops)
	}
	l.Layout(c, len(up.commits), func(i int) {
		up.commit(c, i)
	l.Layout(gtx, len(up.commits), func(i int) {
		up.commit(gtx, i)
	})
}

func (up *userPage) commit(c *layout.Context, index int) {
func (up *userPage) commit(gtx *layout.Context, index int) {
	u := up.user
	msg := up.commits[index].GetMessage()
	label := text.Label{Material: theme.text, Face: up.faces.For(fonts.regular, ui.Sp(12)), Text: msg}
	in := layout.Inset{Top: ui.Dp(16), Right: ui.Dp(8), Left: ui.Dp(8)}
	in.Layout(c, func() {
		f := (&layout.Flex{Axis: layout.Horizontal}).Init(c)
	in.Layout(gtx, func() {
		f := (&layout.Flex{Axis: layout.Horizontal}).Init(gtx)
		c1 := f.Rigid(func() {
			sz := c.Px(ui.Dp(48))
			sz := gtx.Px(ui.Dp(48))
			cc := clipCircle{}
			cc.Layout(c, func() {
				c.Constraints = layout.RigidConstraints(c.Constraints.Constrain(image.Point{X: sz, Y: sz}))
				widget.Image{Src: u.avatar, Rect: u.avatar.Bounds()}.Layout(c)
			cc.Layout(gtx, func() {
				gtx.Constraints = layout.RigidConstraints(gtx.Constraints.Constrain(image.Point{X: sz, Y: sz}))
				widget.Image{Src: u.avatar, Rect: u.avatar.Bounds()}.Layout(gtx)
			})
		})
		c2 := f.Flexible(1, func() {
			c.Constraints.Width.Min = c.Constraints.Width.Max
			layout.Inset{Left: ui.Dp(8)}.Layout(c, func() {
				label.Layout(c)
			gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
			layout.Inset{Left: ui.Dp(8)}.Layout(gtx, func() {
				label.Layout(gtx)
			})
		})
		f.Layout(c1, c2)
	})
}

func (u *UI) layoutUsers(c *layout.Context) {
	st := (&layout.Stack{}).Init(c)
func (u *UI) layoutUsers(gtx *layout.Context) {
	st := (&layout.Stack{}).Init(gtx)
	c2 := st.Rigid(func() {
		layout.Align(layout.SE).Layout(c, func() {
		layout.Align(layout.SE).Layout(gtx, func() {
			in := layout.UniformInset(ui.Dp(16))
			in.Layout(c, func() {
				u.fab.Layout(c)
			in.Layout(gtx, func() {
				u.fab.Layout(gtx)
			})
		})
	})

	c1 := st.Expand(func() {
		f := (&layout.Flex{Axis: layout.Vertical}).Init(c)
		f := (&layout.Flex{Axis: layout.Vertical}).Init(gtx)

		c1 := f.Rigid(func() {
			c.Constraints.Width.Min = c.Constraints.Width.Max
			layout.UniformInset(ui.Dp(16)).Layout(c, func() {
				sz := c.Px(ui.Dp(200))
				cs := c.Constraints
				c.Constraints = layout.RigidConstraints(cs.Constrain(image.Point{X: sz, Y: sz}))
				u.edit.Layout(c)
			gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
			layout.UniformInset(ui.Dp(16)).Layout(gtx, func() {
				sz := gtx.Px(ui.Dp(200))
				cs := gtx.Constraints
				gtx.Constraints = layout.RigidConstraints(cs.Constrain(image.Point{X: sz, Y: sz}))
				u.edit.Layout(gtx)
			})
		})

		c2 := f.Rigid(func() {
			c.Constraints.Width.Min = c.Constraints.Width.Max
			gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
			in := layout.Inset{Bottom: ui.Dp(16), Left: ui.Dp(16), Right: ui.Dp(16)}
			in.Layout(c, func() {
				u.edit2.Layout(c)
			in.Layout(gtx, func() {
				u.edit2.Layout(gtx)
			})
		})

		c3 := f.Rigid(func() {
			c.Constraints.Width.Min = c.Constraints.Width.Max
			gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
			s := layout.Stack{Alignment: layout.Center}
			s.Init(c)
			s.Init(gtx)
			c2 := s.Rigid(func() {
				grey := colorMaterial(c.Ops, rgb(0x888888))
				grey := colorMaterial(gtx.Ops, rgb(0x888888))
				in := layout.Inset{Top: ui.Dp(16), Right: ui.Dp(8), Bottom: ui.Dp(8), Left: ui.Dp(8)}
				in.Layout(c, func() {
				in.Layout(gtx, func() {
					lbl := text.Label{Material: grey, Face: u.face(fonts.regular, 11), Text: "GOPHERS"}
					lbl.Layout(c)
					lbl.Layout(gtx)
				})
			})
			c1 := s.Expand(func() {
				fill{colorMaterial(c.Ops, rgb(0xf2f2f2))}.Layout(c)
				fill{colorMaterial(gtx.Ops, rgb(0xf2f2f2))}.Layout(gtx)
			})
			s.Layout(c1, c2)
		})

		c4 := f.Flexible(1, func() {
			c.Constraints.Width.Min = c.Constraints.Width.Max
			u.layoutContributors(c)
			gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
			u.layoutContributors(gtx)
		})
		f.Layout(c1, c2, c3, c4)
	})
	st.Layout(c1, c2)
}

func (a *ActionButton) Layout(c *layout.Context) {
func (a *ActionButton) Layout(gtx *layout.Context) {
	f := layout.Flex{Axis: layout.Vertical, Alignment: layout.End}
	f.Init(c)
	f.Init(gtx)
	f.Layout(f.Rigid(func() {
		layout.Inset{Top: ui.Dp(4)}.Layout(c, func() {
			fab(c, a.sendIco.image(c), theme.brand, c.Px(ui.Dp(56)))
			pointer.EllipseAreaOp{Rect: image.Rectangle{Max: c.Dimensions.Size}}.Add(c.Ops)
		layout.Inset{Top: ui.Dp(4)}.Layout(gtx, func() {
			fab(gtx, a.sendIco.image(gtx), theme.brand, gtx.Px(ui.Dp(56)))
			pointer.EllipseAreaOp{Rect: image.Rectangle{Max: gtx.Dimensions.Size}}.Add(gtx.Ops)
		})
	}))
}

func (u *UI) layoutContributors(c *layout.Context) {
func (u *UI) layoutContributors(gtx *layout.Context) {
	l := u.usersList
	if l.Dragging() {
		key.HideInputOp{}.Add(c.Ops)
		key.HideInputOp{}.Add(gtx.Ops)
	}
	l.Layout(c, len(u.users), func(i int) {
		u.user(c, i)
	l.Layout(gtx, len(u.users), func(i int) {
		u.user(gtx, i)
	})
}

func (u *UI) user(c *layout.Context, index int) {
func (u *UI) user(gtx *layout.Context, index int) {
	user := u.users[index]
	elem := layout.Flex{Axis: layout.Vertical}
	elem.Init(c)
	elem.Init(gtx)
	c1 := elem.Rigid(func() {
		in := layout.UniformInset(ui.Dp(8))
		in.Layout(c, func() {
		in.Layout(gtx, func() {
			f := centerRowOpts()
			f.Init(c)
			f.Init(gtx)
			c1 := f.Rigid(func() {
				in := layout.Inset{Right: ui.Dp(8)}
				cc := clipCircle{}
				in.Layout(c, func() {
					cc.Layout(c, func() {
						sz := image.Point{X: c.Px(ui.Dp(48)), Y: c.Px(ui.Dp(48))}
						c.Constraints = layout.RigidConstraints(c.Constraints.Constrain(sz))
						widget.Image{Src: user.avatar, Rect: user.avatar.Bounds()}.Layout(c)
				in.Layout(gtx, func() {
					cc.Layout(gtx, func() {
						sz := image.Point{X: gtx.Px(ui.Dp(48)), Y: gtx.Px(ui.Dp(48))}
						gtx.Constraints = layout.RigidConstraints(gtx.Constraints.Constrain(sz))
						widget.Image{Src: user.avatar, Rect: user.avatar.Bounds()}.Layout(gtx)
					})
				})
			})
			c2 := f.Rigid(func() {
				f := column()
				f.Init(c)
				f.Init(gtx)
				c1 := f.Rigid(func() {
					f := baseline()
					f.Init(c)
					f.Init(gtx)
					c1 := f.Rigid(func() {
						text.Label{Material: theme.text, Face: u.face(fonts.regular, 13), Text: user.name}.Layout(c)
						text.Label{Material: theme.text, Face: u.face(fonts.regular, 13), Text: user.name}.Layout(gtx)
					})
					c2 := f.Flexible(1, func() {
						c.Constraints.Width.Min = c.Constraints.Width.Max
						layout.Align(layout.E).Layout(c, func() {
							layout.Inset{Left: ui.Dp(2)}.Layout(c, func() {
						gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
						layout.Align(layout.E).Layout(gtx, func() {
							layout.Inset{Left: ui.Dp(2)}.Layout(gtx, func() {
								lbl := text.Label{Material: theme.text, Face: u.face(fonts.regular, 10), Text: "3 hours ago"}
								lbl.Layout(c)
								lbl.Layout(gtx)
							})
						})
					})


@@ 378,17 378,17 @@ func (u *UI) user(c *layout.Context, index int) {
				})
				c2 := f.Rigid(func() {
					in := layout.Inset{Top: ui.Dp(4)}
					in.Layout(c, func() {
						text.Label{Material: theme.tertText, Face: u.face(fonts.regular, 12), Text: user.company}.Layout(c)
					in.Layout(gtx, func() {
						text.Label{Material: theme.tertText, Face: u.face(fonts.regular, 12), Text: user.company}.Layout(gtx)
					})
				})
				f.Layout(c1, c2)
			})
			f.Layout(c1, c2)
		})
		pointer.RectAreaOp{Rect: image.Rectangle{Max: c.Dimensions.Size}}.Add(c.Ops)
		pointer.RectAreaOp{Rect: image.Rectangle{Max: gtx.Dimensions.Size}}.Add(gtx.Ops)
		click := &u.userClicks[index]
		click.Add(c.Ops)
		click.Add(gtx.Ops)
	})
	elem.Layout(c1)
}


@@ 397,15 397,15 @@ type fill struct {
	material ui.MacroOp
}

func (f fill) Layout(c *layout.Context) {
	cs := c.Constraints
func (f fill) Layout(gtx *layout.Context) {
	cs := gtx.Constraints
	d := image.Point{X: cs.Width.Max, Y: cs.Height.Max}
	dr := f32.Rectangle{
		Max: f32.Point{X: float32(d.X), Y: float32(d.Y)},
	}
	f.material.Add(c.Ops)
	paint.PaintOp{Rect: dr}.Add(c.Ops)
	c.Dimensions = layout.Dimensions{Size: d, Baseline: d.Y}
	f.material.Add(gtx.Ops)
	paint.PaintOp{Rect: dr}.Add(gtx.Ops)
	gtx.Dimensions = layout.Dimensions{Size: d, Baseline: d.Y}
}

func column() layout.Flex {


@@ 423,12 423,12 @@ func baseline() layout.Flex {
type clipCircle struct {
}

func (cc *clipCircle) Layout(c *layout.Context, w layout.Widget) {
func (c *clipCircle) Layout(gtx *layout.Context, w layout.Widget) {
	var m ui.MacroOp
	m.Record(c.Ops)
	m.Record(gtx.Ops)
	w()
	m.Stop()
	dims := c.Dimensions
	dims := gtx.Dimensions
	max := dims.Size.X
	if dy := dims.Size.Y; dy > max {
		max = dy


@@ 436,24 436,24 @@ func (cc *clipCircle) Layout(c *layout.Context, w layout.Widget) {
	szf := float32(max)
	rr := szf * .5
	var stack ui.StackOp
	stack.Push(c.Ops)
	rrect(c.Ops, szf, szf, rr, rr, rr, rr)
	m.Add(c.Ops)
	stack.Push(gtx.Ops)
	rrect(gtx.Ops, szf, szf, rr, rr, rr, rr)
	m.Add(gtx.Ops)
	stack.Pop()
}

func fab(c *layout.Context, ico image.Image, mat ui.MacroOp, size int) {
func fab(gtx *layout.Context, ico image.Image, mat ui.MacroOp, size int) {
	dp := image.Point{X: (size - ico.Bounds().Dx()) / 2, Y: (size - ico.Bounds().Dy()) / 2}
	dims := image.Point{X: size, Y: size}
	rr := float32(size) * .5
	rrect(c.Ops, float32(size), float32(size), rr, rr, rr, rr)
	mat.Add(c.Ops)
	paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: float32(size), Y: float32(size)}}}.Add(c.Ops)
	paint.ImageOp{Src: ico, Rect: ico.Bounds()}.Add(c.Ops)
	rrect(gtx.Ops, float32(size), float32(size), rr, rr, rr, rr)
	mat.Add(gtx.Ops)
	paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: float32(size), Y: float32(size)}}}.Add(gtx.Ops)
	paint.ImageOp{Src: ico, Rect: ico.Bounds()}.Add(gtx.Ops)
	paint.PaintOp{
		Rect: toRectF(ico.Bounds().Add(dp)),
	}.Add(c.Ops)
	c.Dimensions = layout.Dimensions{Size: dims}
	}.Add(gtx.Ops)
	gtx.Dimensions = layout.Dimensions{Size: dims}
}

func toRectF(r image.Rectangle) f32.Rectangle {

M ui/layout/flex.go => ui/layout/flex.go +2 -2
@@ 68,12 68,12 @@ const (
)

// Init must be called before Rigid or Flexible.
func (f *Flex) Init(c *Context) *Flex {
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 = c
	f.ctx = gtx
	f.size = 0
	f.rigidSize = 0
	f.maxCross = 0

M ui/layout/layout.go => ui/layout/layout.go +19 -19
@@ 133,12 133,12 @@ type Inset struct {
type Align Direction

// Layout a widget.
func (in Inset) Layout(c *Context, w Widget) {
	top := c.Px(in.Top)
	right := c.Px(in.Right)
	bottom := c.Px(in.Bottom)
	left := c.Px(in.Left)
	mcs := c.Constraints
func (in Inset) Layout(gtx *Context, w Widget) {
	top := gtx.Px(in.Top)
	right := gtx.Px(in.Right)
	bottom := gtx.Px(in.Bottom)
	left := gtx.Px(in.Left)
	mcs := gtx.Constraints
	mcs.Width.Min -= left + right
	mcs.Width.Max -= left + right
	if mcs.Width.Min < 0 {


@@ 156,12 156,12 @@ func (in Inset) Layout(c *Context, w Widget) {
		mcs.Height.Max = mcs.Height.Min
	}
	var stack ui.StackOp
	stack.Push(c.Ops)
	ui.TransformOp{}.Offset(toPointF(image.Point{X: left, Y: top})).Add(c.Ops)
	dims := c.Layout(mcs, w)
	stack.Push(gtx.Ops)
	ui.TransformOp{}.Offset(toPointF(image.Point{X: left, Y: top})).Add(gtx.Ops)
	dims := gtx.Layout(mcs, w)
	stack.Pop()
	c.Dimensions = Dimensions{
		Size:     c.Constraints.Constrain(dims.Size.Add(image.Point{X: right + left, Y: top + bottom})),
	gtx.Dimensions = Dimensions{
		Size:     gtx.Constraints.Constrain(dims.Size.Add(image.Point{X: right + left, Y: top + bottom})),
		Baseline: dims.Baseline + top,
	}
}


@@ 173,14 173,14 @@ func UniformInset(v ui.Value) Inset {
}

// Layout a widget.
func (a Align) Layout(c *Context, w Widget) {
func (a Align) Layout(gtx *Context, w Widget) {
	var macro ui.MacroOp
	macro.Record(c.Ops)
	cs := c.Constraints
	macro.Record(gtx.Ops)
	cs := gtx.Constraints
	mcs := cs
	mcs.Width.Min = 0
	mcs.Height.Min = 0
	dims := c.Layout(mcs, w)
	dims := gtx.Layout(mcs, w)
	macro.Stop()
	sz := dims.Size
	if sz.X < cs.Width.Min {


@@ 203,11 203,11 @@ func (a Align) Layout(c *Context, w Widget) {
		p.Y = sz.Y - dims.Size.Y
	}
	var stack ui.StackOp
	stack.Push(c.Ops)
	ui.TransformOp{}.Offset(toPointF(p)).Add(c.Ops)
	macro.Add(c.Ops)
	stack.Push(gtx.Ops)
	ui.TransformOp{}.Offset(toPointF(p)).Add(gtx.Ops)
	macro.Add(gtx.Ops)
	stack.Pop()
	c.Dimensions = Dimensions{
	gtx.Dimensions = Dimensions{
		Size:     sz,
		Baseline: dims.Baseline,
	}

M ui/layout/list.go => ui/layout/list.go +7 -7
@@ 67,11 67,11 @@ const (
const inf = 1e6

// Init prepares the list for iterating through its children with Next.
func (l *List) init(c *Context, len int) {
func (l *List) init(gtx *Context, len int) {
	if l.more() {
		panic("unfinished child")
	}
	l.ctx = c
	l.ctx = gtx
	l.maxSize = 0
	l.children = l.children[:0]
	l.len = len


@@ 84,20 84,20 @@ func (l *List) init(c *Context, len int) {
		l.offset = 0
		l.first = len
	}
	l.macro.Record(c.Ops)
	l.macro.Record(gtx.Ops)
	l.next()
}

// Layout the List and return its dimensions.
func (l *List) Layout(c *Context, len int, w ListElement) {
	for l.init(c, len); l.more(); l.next() {
func (l *List) Layout(gtx *Context, len int, w ListElement) {
	for l.init(gtx, len); l.more(); l.next() {
		cs := axisConstraints(l.Axis, Constraint{Max: inf}, axisCrossConstraint(l.Axis, l.ctx.Constraints))
		i := l.index()
		l.end(c.Layout(cs, func() {
		l.end(gtx.Layout(cs, func() {
			w(i)
		}))
	}
	c.Dimensions = l.layout()
	gtx.Dimensions = l.layout()
}

func (l *List) scrollToEnd() bool {

M ui/layout/stack.go => ui/layout/stack.go +2 -2
@@ 29,8 29,8 @@ type StackChild struct {
}

// Init a stack before calling Rigid or Expand.
func (s *Stack) Init(c *Context) *Stack {
	s.ctx = c
func (s *Stack) Init(gtx *Context) *Stack {
	s.ctx = gtx
	s.constrained = true
	s.maxSZ = image.Point{}
	s.baseline = 0

M ui/text/editor.go => ui/text/editor.go +35 -35
@@ 81,9 81,9 @@ const (
)

// Next returns the next available editor event, or false if none are available.
func (e *Editor) Next(c *layout.Context) (EditorEvent, bool) {
func (e *Editor) Next(gtx *layout.Context) (EditorEvent, bool) {
	// Crude configuration change detection.
	if scale := c.Px(ui.Sp(100)); scale != e.oldScale {
	if scale := gtx.Px(ui.Sp(100)); scale != e.oldScale {
		e.invalidate()
		e.oldScale = scale
	}


@@ 97,7 97,7 @@ func (e *Editor) Next(c *layout.Context) (EditorEvent, bool) {
		axis = gesture.Vertical
		smin, smax = sbounds.Min.Y, sbounds.Max.Y
	}
	sdist := e.scroller.Scroll(c.Config, c.Queue, axis)
	sdist := e.scroller.Scroll(gtx.Config, gtx.Queue, axis)
	var soff int
	if e.SingleLine {
		e.scrollOff.X += sdist


@@ 106,26 106,26 @@ func (e *Editor) Next(c *layout.Context) (EditorEvent, bool) {
		e.scrollOff.Y += sdist
		soff = e.scrollOff.Y
	}
	for evt, ok := e.clicker.Next(c.Queue); ok; evt, ok = e.clicker.Next(c.Queue) {
	for evt, ok := e.clicker.Next(gtx.Queue); ok; evt, ok = e.clicker.Next(gtx.Queue) {
		switch {
		case evt.Type == gesture.TypePress && evt.Source == pointer.Mouse,
			evt.Type == gesture.TypeClick && evt.Source == pointer.Touch:
			e.blinkStart = c.Now()
			e.blinkStart = gtx.Now()
			e.moveCoord(image.Point{
				X: int(math.Round(float64(evt.Position.X))),
				Y: int(math.Round(float64(evt.Position.Y))),
			})
			e.requestFocus = true
			if e.scroller.State() != gesture.StateFlinging {
				e.scrollToCaret(c)
				e.scrollToCaret(gtx)
			}
		}
	}
	if (sdist > 0 && soff >= smax) || (sdist < 0 && soff <= smin) {
		e.scroller.Stop()
	}
	for ke, ok := c.Queue.Next(e); ok; ke, ok = c.Queue.Next(e) {
		e.blinkStart = c.Now()
	for ke, ok := gtx.Queue.Next(e); ok; ke, ok = gtx.Queue.Next(e) {
		e.blinkStart = gtx.Now()
		switch ke := ke.(type) {
		case key.FocusEvent:
			e.focused = ke.Focus


@@ 139,11 139,11 @@ func (e *Editor) Next(c *layout.Context) (EditorEvent, bool) {
				}
			}
			if e.command(ke) {
				e.scrollToCaret(c.Config)
				e.scrollToCaret(gtx.Config)
				e.scroller.Stop()
			}
		case key.EditEvent:
			e.scrollToCaret(c)
			e.scrollToCaret(gtx)
			e.scroller.Stop()
			e.append(ke.Text)
		}


@@ 164,11 164,11 @@ func (e *Editor) Focus() {
	e.requestFocus = true
}

func (e *Editor) Layout(c *layout.Context) {
	cs := c.Constraints
	for _, ok := e.Next(c); ok; _, ok = e.Next(c) {
func (e *Editor) Layout(gtx *layout.Context) {
	cs := gtx.Constraints
	for _, ok := e.Next(gtx); ok; _, ok = e.Next(gtx) {
	}
	twoDp := c.Px(ui.Dp(2))
	twoDp := gtx.Px(ui.Dp(2))
	e.padLeft, e.padRight = twoDp, twoDp
	maxWidth := cs.Width.Max
	if e.SingleLine {


@@ 196,7 196,7 @@ func (e *Editor) Layout(c *layout.Context) {
		Min: image.Point{X: 0, Y: 0},
		Max: image.Point{X: e.viewSize.X, Y: e.viewSize.Y},
	}
	key.InputOp{Key: e, Focus: e.requestFocus}.Add(c.Ops)
	key.InputOp{Key: e, Focus: e.requestFocus}.Add(gtx.Ops)
	e.requestFocus = false
	e.it = lineIterator{
		Lines:     lines,


@@ 206,14 206,14 @@ func (e *Editor) Layout(c *layout.Context) {
		Offset:    off,
	}
	var stack ui.StackOp
	stack.Push(c.Ops)
	stack.Push(gtx.Ops)
	// Apply material. Set a default color in case the material is empty.
	if e.rr.len() > 0 {
		paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(c.Ops)
		e.Material.Add(c.Ops)
		paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
		e.Material.Add(gtx.Ops)
	} else {
		paint.ColorOp{Color: color.RGBA{A: 0xaa}}.Add(c.Ops)
		e.HintMaterial.Add(c.Ops)
		paint.ColorOp{Color: color.RGBA{A: 0xaa}}.Add(gtx.Ops)
		e.HintMaterial.Add(gtx.Ops)
	}
	for {
		str, lineOff, ok := e.it.Next()


@@ 221,21 221,21 @@ func (e *Editor) Layout(c *layout.Context) {
			break
		}
		var stack ui.StackOp
		stack.Push(c.Ops)
		ui.TransformOp{}.Offset(lineOff).Add(c.Ops)
		e.Face.Path(str).Add(c.Ops)
		paint.PaintOp{Rect: toRectF(clip).Sub(lineOff)}.Add(c.Ops)
		stack.Push(gtx.Ops)
		ui.TransformOp{}.Offset(lineOff).Add(gtx.Ops)
		e.Face.Path(str).Add(gtx.Ops)
		paint.PaintOp{Rect: toRectF(clip).Sub(lineOff)}.Add(gtx.Ops)
		stack.Pop()
	}
	if e.focused {
		now := c.Now()
		now := gtx.Now()
		dt := now.Sub(e.blinkStart)
		blinking := dt < maxBlinkDuration
		const timePerBlink = time.Second / blinksPerSecond
		nextBlink := now.Add(timePerBlink/2 - dt%(timePerBlink/2))
		on := !blinking || dt%timePerBlink < timePerBlink/2
		if on {
			carWidth := e.caretWidth(c)
			carWidth := e.caretWidth(gtx)
			carX -= carWidth / 2
			carAsc, carDesc := -lines[carLine].Bounds.Min.Y, lines[carLine].Bounds.Max.Y
			carRect := image.Rectangle{


@@ 248,29 248,29 @@ func (e *Editor) Layout(c *layout.Context) {
			})
			carRect = clip.Intersect(carRect)
			if !carRect.Empty() {
				paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(c.Ops)
				e.Material.Add(c.Ops)
				paint.PaintOp{Rect: toRectF(carRect)}.Add(c.Ops)
				paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
				e.Material.Add(gtx.Ops)
				paint.PaintOp{Rect: toRectF(carRect)}.Add(gtx.Ops)
			}
		}
		if blinking {
			redraw := ui.InvalidateOp{At: nextBlink}
			redraw.Add(c.Ops)
			redraw.Add(gtx.Ops)
		}
	}
	stack.Pop()

	baseline := e.padTop + e.dims.Baseline
	pointerPadding := c.Px(ui.Dp(4))
	pointerPadding := gtx.Px(ui.Dp(4))
	r := image.Rectangle{Max: e.viewSize}
	r.Min.X -= pointerPadding
	r.Min.Y -= pointerPadding
	r.Max.X += pointerPadding
	r.Max.X += pointerPadding
	pointer.RectAreaOp{Rect: r}.Add(c.Ops)
	e.scroller.Add(c.Ops)
	e.clicker.Add(c.Ops)
	c.Dimensions = layout.Dimensions{Size: e.viewSize, Baseline: baseline}
	pointer.RectAreaOp{Rect: r}.Add(gtx.Ops)
	e.scroller.Add(gtx.Ops)
	e.clicker.Add(gtx.Ops)
	gtx.Dimensions = layout.Dimensions{Size: e.viewSize, Baseline: baseline}
}

// Text returns the contents of the editor.

M ui/text/label.go => ui/text/label.go +9 -9
@@ 92,8 92,8 @@ func (l *lineIterator) Next() (String, f32.Point, bool) {
	return String{}, f32.Point{}, false
}

func (l Label) Layout(c *layout.Context) {
	cs := c.Constraints
func (l Label) Layout(gtx *layout.Context) {
	cs := gtx.Constraints
	textLayout := l.Face.Layout(l.Text, LayoutOptions{MaxWidth: cs.Width.Max})
	lines := textLayout.Lines
	if max := l.MaxLines; max > 0 && len(lines) > max {


@@ 119,16 119,16 @@ func (l Label) Layout(c *layout.Context) {
		}
		lclip := toRectF(clip).Sub(off)
		var stack ui.StackOp
		stack.Push(c.Ops)
		ui.TransformOp{}.Offset(off).Add(c.Ops)
		l.Face.Path(str).Add(c.Ops)
		stack.Push(gtx.Ops)
		ui.TransformOp{}.Offset(off).Add(gtx.Ops)
		l.Face.Path(str).Add(gtx.Ops)
		// Set a default color in case the material is empty.
		paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(c.Ops)
		l.Material.Add(c.Ops)
		paint.PaintOp{Rect: lclip}.Add(c.Ops)
		paint.ColorOp{Color: color.RGBA{A: 0xff}}.Add(gtx.Ops)
		l.Material.Add(gtx.Ops)
		paint.PaintOp{Rect: lclip}.Add(gtx.Ops)
		stack.Pop()
	}
	c.Dimensions = dims
	gtx.Dimensions = dims
}

func toRectF(r image.Rectangle) f32.Rectangle {

M ui/widget/image.go => ui/widget/image.go +6 -6
@@ 25,17 25,17 @@ type Image struct {
	Scale float32
}

func (im Image) Layout(c *layout.Context) {
func (im Image) Layout(gtx *layout.Context) {
	size := im.Src.Bounds()
	wf, hf := float32(size.Dx()), float32(size.Dy())
	var w, h int
	if im.Scale == 0 {
		const dpPrPx = 160 / 72
		w, h = c.Px(ui.Dp(wf*dpPrPx)), c.Px(ui.Dp(hf*dpPrPx))
		w, h = gtx.Px(ui.Dp(wf*dpPrPx)), gtx.Px(ui.Dp(hf*dpPrPx))
	} else {
		w, h = int(wf*im.Scale+.5), int(hf*im.Scale+.5)
	}
	cs := c.Constraints
	cs := gtx.Constraints
	d := image.Point{X: cs.Width.Constrain(w), Y: cs.Height.Constrain(h)}
	aspect := float32(w) / float32(h)
	dw, dh := float32(d.X), float32(d.Y)


@@ 48,7 48,7 @@ func (im Image) Layout(c *layout.Context) {
	dr := f32.Rectangle{
		Max: f32.Point{X: float32(d.X), Y: float32(d.Y)},
	}
	paint.ImageOp{Src: im.Src, Rect: im.Rect}.Add(c.Ops)
	paint.PaintOp{Rect: dr}.Add(c.Ops)
	c.Dimensions = layout.Dimensions{Size: d, Baseline: d.Y}
	paint.ImageOp{Src: im.Src, Rect: im.Rect}.Add(gtx.Ops)
	paint.PaintOp{Rect: dr}.Add(gtx.Ops)
	gtx.Dimensions = layout.Dimensions{Size: d, Baseline: d.Y}
}