example,cmd: bump gio version

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-05-23 19:54:27 +02:00
parent 2451750782
commit d8000880c3
13 changed files with 236 additions and 216 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ module gioui.org/cmd
go 1.13 go 1.13
require ( require (
gioui.org v0.0.0-20200521183411-67382bec3949 gioui.org v0.0.0-20200523202849-2451750782b8
github.com/chromedp/cdproto v0.0.0-20191114225735-6626966fbae4 github.com/chromedp/cdproto v0.0.0-20191114225735-6626966fbae4
github.com/chromedp/chromedp v0.5.2 github.com/chromedp/chromedp v0.5.2
golang.org/x/image v0.0.0-20190802002840-cff245a6509b golang.org/x/image v0.0.0-20190802002840-cff245a6509b
+2 -2
View File
@@ -1,6 +1,6 @@
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20200521183411-67382bec3949 h1:Nvvyn28PT4kyRKBKg04QY2ZU6y9J1hFGJtBDV5VyBmM= gioui.org v0.0.0-20200523202849-2451750782b8 h1:TB+F3jDAVjNemdtgc8yfvsPy1xWkyn7JLOsm5r+YUuQ=
gioui.org v0.0.0-20200521183411-67382bec3949/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= gioui.org v0.0.0-20200523202849-2451750782b8/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/chromedp/cdproto v0.0.0-20191114225735-6626966fbae4 h1:QD3KxSJ59L2lxG6MXBjNHxiQO2RmxTQ3XcK+wO44WOg= github.com/chromedp/cdproto v0.0.0-20191114225735-6626966fbae4 h1:QD3KxSJ59L2lxG6MXBjNHxiQO2RmxTQ3XcK+wO44WOg=
+18 -12
View File
@@ -14,6 +14,7 @@ import (
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/io/system" "gioui.org/io/system"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint" "gioui.org/op/paint"
) )
@@ -39,6 +40,11 @@ const (
// when a frame is ready. Initially we want to notify about the first frame. // when a frame is ready. Initially we want to notify about the first frame.
var notify = notifyInvalidate var notify = notifyInvalidate
type (
C = layout.Context
D = layout.Dimensions
)
func loop(w *app.Window) error { func loop(w *app.Window) error {
topLeft := quarterWidget{ topLeft := quarterWidget{
color: color.RGBA{R: 0xde, G: 0xad, B: 0xbe, A: 0xff}, color: color.RGBA{R: 0xde, G: 0xad, B: 0xbe, A: 0xff},
@@ -53,30 +59,29 @@ func loop(w *app.Window) error {
color: color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0x80}, color: color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0x80},
} }
gtx := new(layout.Context) var ops op.Ops
for { for {
e := <-w.Events() e := <-w.Events()
switch e := e.(type) { switch e := e.(type) {
case system.DestroyEvent: case system.DestroyEvent:
return e.Err return e.Err
case system.FrameEvent: case system.FrameEvent:
gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
gtx.Reset(e.Queue, e.Config, e.Size)
layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Flexed(0.5, func() { layout.Flexed(0.5, func(gtx C) D {
layout.Flex{Axis: layout.Horizontal}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
// r1c1 // r1c1
layout.Flexed(0.5, func() { topLeft.Layout(gtx) }), layout.Flexed(0.5, func(gtx C) D { return topLeft.Layout(gtx) }),
// r1c2 // r1c2
layout.Flexed(0.5, func() { topRight.Layout(gtx) }), layout.Flexed(0.5, func(gtx C) D { return topRight.Layout(gtx) }),
) )
}), }),
layout.Flexed(0.5, func() { layout.Flexed(0.5, func(gtx C) D {
layout.Flex{Axis: layout.Horizontal}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
// r2c1 // r2c1
layout.Flexed(0.5, func() { botLeft.Layout(gtx) }), layout.Flexed(0.5, func(gtx C) D { return botLeft.Layout(gtx) }),
// r2c2 // r2c2
layout.Flexed(0.5, func() { botRight.Layout(gtx) }), layout.Flexed(0.5, func(gtx C) D { return botRight.Layout(gtx) }),
) )
}), }),
) )
@@ -105,7 +110,7 @@ type quarterWidget struct {
var red = color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff} var red = color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff}
func (w *quarterWidget) Layout(gtx *layout.Context) { func (w *quarterWidget) Layout(gtx layout.Context) layout.Dimensions {
if w.clicked { if w.clicked {
paint.ColorOp{Color: red}.Add(gtx.Ops) paint.ColorOp{Color: red}.Add(gtx.Ops)
} else { } else {
@@ -128,4 +133,5 @@ func (w *quarterWidget) Layout(gtx *layout.Context) {
notify = notifyInvalidate notify = notifyInvalidate
} }
} }
return layout.Dimensions{Size: gtx.Constraints.Max}
} }
+7 -6
View File
@@ -29,6 +29,7 @@ import (
"gioui.org/io/pointer" "gioui.org/io/pointer"
"gioui.org/io/router" "gioui.org/io/router"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
"gioui.org/unit" "gioui.org/unit"
"gioui.org/widget" "gioui.org/widget"
"gioui.org/widget/material" "gioui.org/widget/material"
@@ -71,7 +72,7 @@ func main() {
gofont.Register() gofont.Register()
f := new(goglFunctions) f := new(goglFunctions)
var queue router.Router var queue router.Router
gtx := new(layout.Context) var ops op.Ops
th := material.NewTheme() th := material.NewTheme()
backend, err := giogl.NewBackend(f) backend, err := giogl.NewBackend(f)
if err != nil { if err != nil {
@@ -92,7 +93,7 @@ func main() {
} }
width, height := window.GetSize() width, height := window.GetSize()
sz := image.Point{X: width, Y: height} sz := image.Point{X: width, Y: height}
gtx.Reset(&queue, &glfwConfig{scale}, sz) gtx := layout.NewContext(&ops, &queue, &glfwConfig{scale}, sz)
draw(gtx, th) draw(gtx, th)
gpu.Collect(sz, gtx.Ops) gpu.Collect(sz, gtx.Ops)
gpu.BeginFrame() gpu.BeginFrame()
@@ -104,10 +105,10 @@ func main() {
var button widget.Clickable var button widget.Clickable
func draw(gtx *layout.Context, th *material.Theme) { func draw(gtx layout.Context, th *material.Theme) layout.Dimensions {
layout.Center.Layout(gtx, func() { return layout.Center.Layout(gtx,
material.Button(th, "Button").Layout(gtx, &button) material.Button(th, &button, "Button").Layout,
}) )
} }
func registerCallbacks(window *glfw.Window, q *router.Router) { func registerCallbacks(window *glfw.Window, q *router.Router) {
+1 -1
View File
@@ -3,7 +3,7 @@ module gioui.org/example
go 1.13 go 1.13
require ( require (
gioui.org v0.0.0-20200521183411-67382bec3949 gioui.org v0.0.0-20200523202849-2451750782b8
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72
github.com/google/go-github/v24 v24.0.1 github.com/google/go-github/v24 v24.0.1
+2 -2
View File
@@ -1,7 +1,7 @@
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20200521183411-67382bec3949 h1:Nvvyn28PT4kyRKBKg04QY2ZU6y9J1hFGJtBDV5VyBmM= gioui.org v0.0.0-20200523202849-2451750782b8 h1:TB+F3jDAVjNemdtgc8yfvsPy1xWkyn7JLOsm5r+YUuQ=
gioui.org v0.0.0-20200521183411-67382bec3949/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= gioui.org v0.0.0-20200523202849-2451750782b8/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
+3 -2
View File
@@ -20,6 +20,7 @@ import (
"gioui.org/io/key" "gioui.org/io/key"
"gioui.org/io/system" "gioui.org/io/system"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
"gioui.org/unit" "gioui.org/unit"
"github.com/google/go-github/v24/github" "github.com/google/go-github/v24/github"
@@ -77,7 +78,7 @@ func initProfiling() {
func (a *App) run() error { func (a *App) run() error {
a.ui.profiling = *stats a.ui.profiling = *stats
gtx := new(layout.Context) var ops op.Ops
for { for {
select { select {
case users := <-a.updateUsers: case users := <-a.updateUsers:
@@ -125,7 +126,7 @@ func (a *App) run() error {
} }
} }
case system.FrameEvent: case system.FrameEvent:
gtx.Reset(e.Queue, e.Config, e.Size) gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
a.ui.Layout(gtx) a.ui.Layout(gtx)
e.Frame(gtx.Ops) e.Frame(gtx.Ops)
} }
+6 -2
View File
@@ -7,14 +7,18 @@ import (
"testing" "testing"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
) )
func BenchmarkUI(b *testing.B) { func BenchmarkUI(b *testing.B) {
fetch := func(_ string) {} fetch := func(_ string) {}
u := newUI(fetch) u := newUI(fetch)
gtx := new(layout.Context) var ops op.Ops
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
gtx.Reset(nil, nil, image.Point{800, 600}) gtx := layout.Context{
Ops: &ops,
Constraints: layout.Exact(image.Pt(800, 600)),
}
u.Layout(gtx) u.Layout(gtx)
} }
} }
+74 -73
View File
@@ -65,6 +65,11 @@ type user struct {
var theme *material.Theme var theme *material.Theme
type (
C = layout.Context
D = layout.Dimensions
)
func init() { func init() {
gofont.Register() gofont.Register()
theme = material.NewTheme() theme = material.NewTheme()
@@ -106,7 +111,7 @@ func argb(c uint32) color.RGBA {
return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)} return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)}
} }
func (u *UI) layoutTimings(gtx *layout.Context) { func (u *UI) layoutTimings(gtx layout.Context) {
if !u.profiling { if !u.profiling {
return return
} }
@@ -120,17 +125,17 @@ func (u *UI) layoutTimings(gtx *layout.Context) {
runtime.ReadMemStats(&mstats) runtime.ReadMemStats(&mstats)
mallocs := mstats.Mallocs - u.lastMallocs mallocs := mstats.Mallocs - u.lastMallocs
u.lastMallocs = mstats.Mallocs u.lastMallocs = mstats.Mallocs
layout.NE.Layout(gtx, func() { layout.NE.Layout(gtx, func(gtx C) D {
layout.Inset{Top: unit.Dp(16)}.Layout(gtx, func() { return layout.Inset{Top: unit.Dp(16)}.Layout(gtx, func(gtx C) D {
txt := fmt.Sprintf("m: %d %s", mallocs, u.profile.Timings) txt := fmt.Sprintf("m: %d %s", mallocs, u.profile.Timings)
lbl := material.Caption(theme, txt) lbl := material.Caption(theme, txt)
lbl.Font.Variant = "Mono" lbl.Font.Variant = "Mono"
lbl.Layout(gtx) return lbl.Layout(gtx)
}) })
}) })
} }
func (u *UI) Layout(gtx *layout.Context) { func (u *UI) Layout(gtx layout.Context) {
for i := range u.userClicks { for i := range u.userClicks {
click := &u.userClicks[i] click := &u.userClicks[i]
for _, e := range click.Events(gtx) { for _, e := range click.Events(gtx) {
@@ -156,159 +161,155 @@ func (u *UI) newUserPage(user *user) *userPage {
return up return up
} }
func (up *userPage) Layout(gtx *layout.Context) { func (up *userPage) Layout(gtx layout.Context) {
l := up.commitsList l := up.commitsList
if l.Dragging() { if l.Dragging() {
key.HideInputOp{}.Add(gtx.Ops) key.HideInputOp{}.Add(gtx.Ops)
} }
l.Layout(gtx, len(up.commits), func(i int) { l.Layout(gtx, len(up.commits), func(gtx C, i int) D {
up.commit(gtx, i) return up.commit(gtx, i)
}) })
} }
func (up *userPage) commit(gtx *layout.Context, index int) { func (up *userPage) commit(gtx layout.Context, index int) layout.Dimensions {
u := up.user u := up.user
msg := up.commits[index].GetMessage() msg := up.commits[index].GetMessage()
label := material.Caption(theme, msg) label := material.Caption(theme, msg)
in := layout.Inset{Top: unit.Dp(16), Right: unit.Dp(8), Left: unit.Dp(8)} in := layout.Inset{Top: unit.Dp(16), Right: unit.Dp(8), Left: unit.Dp(8)}
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
layout.Flex{Axis: layout.Horizontal}.Layout(gtx, return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
sz := gtx.Px(unit.Dp(48)) sz := gtx.Px(unit.Dp(48))
cc := clipCircle{} cc := clipCircle{}
cc.Layout(gtx, func() { return cc.Layout(gtx, func(gtx C) D {
gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(image.Point{X: sz, Y: sz})) gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(image.Point{X: sz, Y: sz}))
u.layoutAvatar(gtx) return u.layoutAvatar(gtx)
}) })
}), }),
layout.Flexed(1, func() { layout.Flexed(1, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
layout.Inset{Left: unit.Dp(8)}.Layout(gtx, func() { return layout.Inset{Left: unit.Dp(8)}.Layout(gtx, label.Layout)
label.Layout(gtx)
})
}), }),
) )
}) })
} }
func (u *UI) layoutUsers(gtx *layout.Context) { func (u *UI) layoutUsers(gtx layout.Context) {
layout.Stack{Alignment: layout.SE}.Layout(gtx, layout.Stack{Alignment: layout.SE}.Layout(gtx,
layout.Expanded(func() { layout.Expanded(func(gtx C) D {
layout.Flex{Axis: layout.Vertical}.Layout(gtx, return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
layout.UniformInset(unit.Dp(16)).Layout(gtx, func() { return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D {
sz := gtx.Px(unit.Dp(200)) sz := gtx.Px(unit.Dp(200))
cs := gtx.Constraints cs := gtx.Constraints
gtx.Constraints = layout.Exact(cs.Constrain(image.Point{X: sz, Y: sz})) gtx.Constraints = layout.Exact(cs.Constrain(image.Point{X: sz, Y: sz}))
material.Editor(theme, "Hint").Layout(gtx, u.edit) return material.Editor(theme, u.edit, "Hint").Layout(gtx)
}) })
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
in := layout.Inset{Bottom: unit.Dp(16), Left: unit.Dp(16), Right: unit.Dp(16)} in := layout.Inset{Bottom: unit.Dp(16), Left: unit.Dp(16), Right: unit.Dp(16)}
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
e := material.Editor(theme, "Hint") e := material.Editor(theme, u.edit2, "Hint")
e.TextSize = unit.Sp(14) e.TextSize = unit.Sp(14)
e.Font.Style = text.Italic e.Font.Style = text.Italic
e.Layout(gtx, u.edit2) return e.Layout(gtx)
}) })
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
layout.Stack{}.Layout(gtx, return layout.Stack{}.Layout(gtx,
layout.Expanded(func() { layout.Expanded(func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
fill{rgb(0xf2f2f2)}.Layout(gtx) return fill{rgb(0xf2f2f2)}.Layout(gtx)
}), }),
layout.Stacked(func() { layout.Stacked(func(gtx C) D {
in := layout.Inset{Top: unit.Dp(16), Right: unit.Dp(8), Bottom: unit.Dp(8), Left: unit.Dp(8)} in := layout.Inset{Top: unit.Dp(16), Right: unit.Dp(8), Bottom: unit.Dp(8), Left: unit.Dp(8)}
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
lbl := material.Caption(theme, "GOPHERS") lbl := material.Caption(theme, "GOPHERS")
lbl.Color = rgb(0x888888) lbl.Color = rgb(0x888888)
lbl.Layout(gtx) return lbl.Layout(gtx)
}) })
}), }),
) )
}), }),
layout.Flexed(1, func() { layout.Flexed(1, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
u.layoutContributors(gtx) return u.layoutContributors(gtx)
}), }),
) )
}), }),
layout.Stacked(func() { layout.Stacked(func(gtx C) D {
in := layout.UniformInset(unit.Dp(16)) in := layout.UniformInset(unit.Dp(16))
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
for u.fab.Clicked(gtx) { for u.fab.Clicked(gtx) {
} }
material.IconButton(theme, u.fabIcon).Layout(gtx, u.fab) return material.IconButton(theme, u.fab, u.fabIcon).Layout(gtx)
}) })
}), }),
) )
} }
func (u *UI) layoutContributors(gtx *layout.Context) { func (u *UI) layoutContributors(gtx layout.Context) layout.Dimensions {
l := u.usersList l := u.usersList
if l.Dragging() { if l.Dragging() {
key.HideInputOp{}.Add(gtx.Ops) key.HideInputOp{}.Add(gtx.Ops)
} }
l.Layout(gtx, len(u.users), func(i int) { return l.Layout(gtx, len(u.users), func(gtx C, i int) D {
u.user(gtx, i) return u.user(gtx, i)
}) })
} }
func (u *UI) user(gtx *layout.Context, index int) { func (u *UI) user(gtx layout.Context, index int) layout.Dimensions {
user := u.users[index] user := u.users[index]
in := layout.UniformInset(unit.Dp(8)) in := layout.UniformInset(unit.Dp(8))
in.Layout(gtx, func() { dims := in.Layout(gtx, func(gtx C) D {
centerRowOpts().Layout(gtx, return centerRowOpts().Layout(gtx,
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in := layout.Inset{Right: unit.Dp(8)} in := layout.Inset{Right: unit.Dp(8)}
cc := clipCircle{} cc := clipCircle{}
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
cc.Layout(gtx, func() { return cc.Layout(gtx, func(gtx C) D {
dim := gtx.Px(unit.Dp(48)) dim := gtx.Px(unit.Dp(48))
sz := image.Point{X: dim, Y: dim} sz := image.Point{X: dim, Y: dim}
gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(sz)) gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(sz))
user.layoutAvatar(gtx) return user.layoutAvatar(gtx)
}) })
}) })
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
column().Layout(gtx, return column().Layout(gtx,
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
baseline().Layout(gtx, return baseline().Layout(gtx,
layout.Rigid(func() { layout.Rigid(material.Body1(theme, user.name).Layout),
material.Body1(theme, user.name).Layout(gtx) layout.Flexed(1, func(gtx C) D {
}),
layout.Flexed(1, func() {
gtx.Constraints.Min.X = gtx.Constraints.Max.X gtx.Constraints.Min.X = gtx.Constraints.Max.X
layout.E.Layout(gtx, func() { return layout.E.Layout(gtx, func(gtx C) D {
layout.Inset{Left: unit.Dp(2)}.Layout(gtx, func() { return layout.Inset{Left: unit.Dp(2)}.Layout(gtx,
material.Caption(theme, "3 hours ago").Layout(gtx) material.Caption(theme, "3 hours ago").Layout)
})
}) })
}), }),
) )
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in := layout.Inset{Top: unit.Dp(4)} in := layout.Inset{Top: unit.Dp(4)}
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
lbl := material.Caption(theme, user.company) lbl := material.Caption(theme, user.company)
lbl.Color = rgb(0xbbbbbb) lbl.Color = rgb(0xbbbbbb)
lbl.Layout(gtx) return lbl.Layout(gtx)
}) })
}), }),
) )
}), }),
) )
}) })
pointer.Rect(image.Rectangle{Max: gtx.Dimensions.Size}).Add(gtx.Ops) pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops)
click := &u.userClicks[index] click := &u.userClicks[index]
click.Add(gtx.Ops) click.Add(gtx.Ops)
return dims
} }
func (u *user) layoutAvatar(gtx *layout.Context) { func (u *user) layoutAvatar(gtx layout.Context) layout.Dimensions {
sz := gtx.Constraints.Min.X sz := gtx.Constraints.Min.X
if u.avatarOp.Size().X != sz { if u.avatarOp.Size().X != sz {
img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: sz}}) img := image.NewRGBA(image.Rectangle{Max: image.Point{X: sz, Y: sz}})
@@ -317,14 +318,14 @@ func (u *user) layoutAvatar(gtx *layout.Context) {
} }
img := widget.Image{Src: u.avatarOp} img := widget.Image{Src: u.avatarOp}
img.Scale = float32(sz) / float32(gtx.Px(unit.Dp(float32(sz)))) img.Scale = float32(sz) / float32(gtx.Px(unit.Dp(float32(sz))))
img.Layout(gtx) return img.Layout(gtx)
} }
type fill struct { type fill struct {
col color.RGBA col color.RGBA
} }
func (f fill) Layout(gtx *layout.Context) { func (f fill) Layout(gtx layout.Context) layout.Dimensions {
cs := gtx.Constraints cs := gtx.Constraints
d := cs.Min d := cs.Min
dr := f32.Rectangle{ dr := f32.Rectangle{
@@ -332,7 +333,7 @@ func (f fill) Layout(gtx *layout.Context) {
} }
paint.ColorOp{Color: f.col}.Add(gtx.Ops) paint.ColorOp{Color: f.col}.Add(gtx.Ops)
paint.PaintOp{Rect: dr}.Add(gtx.Ops) paint.PaintOp{Rect: dr}.Add(gtx.Ops)
gtx.Dimensions = layout.Dimensions{Size: d} return layout.Dimensions{Size: d}
} }
func column() layout.Flex { func column() layout.Flex {
@@ -350,12 +351,11 @@ func baseline() layout.Flex {
type clipCircle struct { type clipCircle struct {
} }
func (c *clipCircle) Layout(gtx *layout.Context, w layout.Widget) { func (c *clipCircle) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
var m op.MacroOp var m op.MacroOp
m.Record(gtx.Ops) m.Record(gtx.Ops)
w() dims := w(gtx)
m.Stop() m.Stop()
dims := gtx.Dimensions
max := dims.Size.X max := dims.Size.X
if dy := dims.Size.Y; dy > max { if dy := dims.Size.Y; dy > max {
max = dy max = dy
@@ -370,6 +370,7 @@ func (c *clipCircle) Layout(gtx *layout.Context, w layout.Widget) {
}.Op(gtx.Ops).Add(gtx.Ops) }.Op(gtx.Ops).Add(gtx.Ops)
m.Add() m.Add()
stack.Pop() stack.Pop()
return dims
} }
const longTextSample = `1. I learned from my grandfather, Verus, to use good manners, and to const longTextSample = `1. I learned from my grandfather, Verus, to use good manners, and to
+3 -2
View File
@@ -11,6 +11,7 @@ import (
"gioui.org/app" "gioui.org/app"
"gioui.org/io/system" "gioui.org/io/system"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
"gioui.org/text" "gioui.org/text"
"gioui.org/widget/material" "gioui.org/widget/material"
@@ -30,14 +31,14 @@ func main() {
func loop(w *app.Window) error { func loop(w *app.Window) error {
gofont.Register() gofont.Register()
th := material.NewTheme() th := material.NewTheme()
gtx := new(layout.Context) var ops op.Ops
for { for {
e := <-w.Events() e := <-w.Events()
switch e := e.(type) { switch e := e.(type) {
case system.DestroyEvent: case system.DestroyEvent:
return e.Err return e.Err
case system.FrameEvent: case system.FrameEvent:
gtx.Reset(e.Queue, e.Config, e.Size) gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
l := material.H1(th, "Hello, Gio") l := material.H1(th, "Hello, Gio")
maroon := color.RGBA{127, 0, 0, 255} maroon := color.RGBA{127, 0, 0, 255}
l.Color = maroon l.Color = maroon
+75 -77
View File
@@ -22,6 +22,7 @@ import (
"gioui.org/font/gofont" "gioui.org/font/gofont"
"gioui.org/io/system" "gioui.org/io/system"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
"gioui.org/text" "gioui.org/text"
"gioui.org/unit" "gioui.org/unit"
"gioui.org/widget" "gioui.org/widget"
@@ -37,7 +38,10 @@ type scaledConfig struct {
} }
type iconAndTextButton struct { type iconAndTextButton struct {
theme *material.Theme theme *material.Theme
button *widget.Clickable
icon *widget.Icon
word string
} }
func main() { func main() {
@@ -81,8 +85,11 @@ func saveScreenshot(f string) error {
if err != nil { if err != nil {
return err return err
} }
gtx := new(layout.Context) gtx := layout.Context{
gtx.Reset(nil, &scaledConfig{scale}, sz) Ops: new(op.Ops),
Config: &scaledConfig{scale},
Constraints: layout.Exact(sz),
}
th := material.NewTheme() th := material.NewTheme()
kitchen(gtx, th) kitchen(gtx, th)
w.Frame(gtx.Ops) w.Frame(gtx.Ops)
@@ -100,7 +107,7 @@ func saveScreenshot(f string) error {
func loop(w *app.Window) error { func loop(w *app.Window) error {
th := material.NewTheme() th := material.NewTheme()
gtx := new(layout.Context) var ops op.Ops
for { for {
select { select {
case e := <-w.Events(): case e := <-w.Events():
@@ -110,7 +117,7 @@ func loop(w *app.Window) error {
case system.DestroyEvent: case system.DestroyEvent:
return e.Err return e.Err
case system.FrameEvent: case system.FrameEvent:
gtx.Reset(e.Queue, e.Config, e.Size) gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
for iconButton.Clicked(gtx) { for iconButton.Clicked(gtx) {
w.WriteClipboard(lineEditor.Text()) w.WriteClipboard(lineEditor.Text())
} }
@@ -154,134 +161,125 @@ var (
swtch = new(widget.Bool) swtch = new(widget.Bool)
) )
func (b iconAndTextButton) Layout(gtx *layout.Context, button *widget.Clickable, icon *widget.Icon, word string) { type (
material.ButtonLayout(b.theme).Layout(gtx, button, func() { D = layout.Dimensions
C = layout.Context
)
func (b iconAndTextButton) Layout(gtx layout.Context) layout.Dimensions {
return material.ButtonLayout(b.theme, b.button).Layout(gtx, func(gtx C) D {
iconAndLabel := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle} iconAndLabel := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}
textIconSpacer := unit.Dp(5) textIconSpacer := unit.Dp(5)
layIcon := layout.Rigid(func() { layIcon := layout.Rigid(func(gtx C) D {
layout.Inset{Right: textIconSpacer}.Layout(gtx, func() { return layout.Inset{Right: textIconSpacer}.Layout(gtx, func(gtx C) D {
size := gtx.Px(unit.Dp(56)) - 2*gtx.Px(unit.Dp(16)) var d D
if icon != nil { if icon != nil {
icon.Layout(gtx, unit.Px(float32(size))) size := gtx.Px(unit.Dp(56)) - 2*gtx.Px(unit.Dp(16))
gtx.Dimensions = layout.Dimensions{ b.icon.Layout(gtx, unit.Px(float32(size)))
d = layout.Dimensions{
Size: image.Point{X: size, Y: size}, Size: image.Point{X: size, Y: size},
} }
} }
return d
}) })
}) })
layLabel := layout.Rigid(func() { layLabel := layout.Rigid(func(gtx C) D {
layout.Inset{Left: textIconSpacer}.Layout(gtx, func() { return layout.Inset{Left: textIconSpacer}.Layout(gtx, func(gtx C) D {
l := material.Body1(b.theme, word) l := material.Body1(b.theme, b.word)
l.Color = b.theme.Color.InvText l.Color = b.theme.Color.InvText
l.Layout(gtx) return l.Layout(gtx)
}) })
}) })
iconAndLabel.Layout(gtx, layIcon, layLabel) return iconAndLabel.Layout(gtx, layIcon, layLabel)
}) })
} }
func kitchen(gtx *layout.Context, th *material.Theme) { func kitchen(gtx layout.Context, th *material.Theme) layout.Dimensions {
widgets := []func(){ widgets := []layout.Widget{
func() { material.H3(th, topLabel).Layout,
material.H3(th, topLabel).Layout(gtx) func(gtx C) D {
},
func() {
gtx.Constraints.Max.Y = gtx.Px(unit.Dp(200)) gtx.Constraints.Max.Y = gtx.Px(unit.Dp(200))
material.Editor(th, "Hint").Layout(gtx, editor) return material.Editor(th, editor, "Hint").Layout(gtx)
}, },
func() { func(gtx C) D {
e := material.Editor(th, "Hint")
e.Font.Style = text.Italic
e.Layout(gtx, lineEditor)
for _, e := range lineEditor.Events(gtx) { for _, e := range lineEditor.Events(gtx) {
if e, ok := e.(widget.SubmitEvent); ok { if e, ok := e.(widget.SubmitEvent); ok {
topLabel = e.Text topLabel = e.Text
lineEditor.SetText("") lineEditor.SetText("")
} }
} }
e := material.Editor(th, lineEditor, "Hint")
e.Font.Style = text.Italic
return e.Layout(gtx)
}, },
func() { func(gtx C) D {
in := layout.UniformInset(unit.Dp(8)) in := layout.UniformInset(unit.Dp(8))
layout.Flex{Alignment: layout.Middle}.Layout(gtx, return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in.Layout(gtx, func() { return in.Layout(gtx, material.IconButton(th, iconButton, icon).Layout)
material.IconButton(th, icon).Layout(gtx, iconButton)
})
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in.Layout(gtx, func() { return in.Layout(gtx, iconAndTextButton{theme: th, icon: icon, word: "Icon", button: iconTextButton}.Layout)
iconAndTextButton{th}.Layout(gtx, iconTextButton, icon, "Icon")
})
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
for button.Clicked(gtx) { for button.Clicked(gtx) {
green = !green green = !green
} }
material.Button(th, "Click me!").Layout(gtx, button) return material.Button(th, button, "Click me!").Layout(gtx)
}) })
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
l := "Green" l := "Green"
if !green { if !green {
l = "Blue" l = "Blue"
} }
btn := material.Button(th, l) btn := material.Button(th, greenButton, l)
if green { if green {
btn.Background = color.RGBA{A: 0xff, R: 0x9e, G: 0x9d, B: 0x24} btn.Background = color.RGBA{A: 0xff, R: 0x9e, G: 0x9d, B: 0x24}
} }
btn.Layout(gtx, greenButton) return btn.Layout(gtx)
}) })
}), }),
layout.Rigid(func() { layout.Rigid(func(gtx C) D {
in.Layout(gtx, func() { return in.Layout(gtx, func(gtx C) D {
material.Clickable(gtx, flatBtn, func() { return material.Clickable(gtx, flatBtn, func(gtx C) D {
layout.UniformInset(unit.Dp(12)).Layout(gtx, func() { return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D {
layout.Center.Layout(gtx, func() { return layout.Center.Layout(gtx, material.Body1(th, "Flat").Layout)
material.Body1(th, "Flat").Layout(gtx)
})
}) })
}) })
}) })
}), }),
) )
}, },
func() { material.ProgressBar(th, progress).Layout,
material.ProgressBar(th).Layout(gtx, progress) func(gtx C) D {
}, return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
func() { layout.Rigid(
layout.Flex{Alignment: layout.Middle}.Layout(gtx, material.CheckBox(th, checkbox, "Checkbox").Layout,
layout.Rigid(func() { ),
material.CheckBox(th, "Checkbox").Layout(gtx, checkbox) layout.Rigid(func(gtx C) D {
}), return layout.Inset{Left: unit.Dp(16)}.Layout(gtx,
layout.Rigid(func() { material.Switch(th, swtch).Layout,
layout.Inset{Left: unit.Dp(16)}.Layout(gtx, func() { )
material.Switch(th).Layout(gtx, swtch)
})
}), }),
) )
}, },
func() { func(gtx C) D {
layout.Flex{}.Layout(gtx, return layout.Flex{}.Layout(gtx,
layout.Rigid(func() { layout.Rigid(material.RadioButton(th, radioButtonsGroup, "r1", "RadioButton1").Layout),
material.RadioButton(th, "r1", "RadioButton1").Layout(gtx, radioButtonsGroup) layout.Rigid(material.RadioButton(th, radioButtonsGroup, "r2", "RadioButton2").Layout),
}), layout.Rigid(material.RadioButton(th, radioButtonsGroup, "r3", "RadioButton3").Layout),
layout.Rigid(func() {
material.RadioButton(th, "r2", "RadioButton2").Layout(gtx, radioButtonsGroup)
}),
layout.Rigid(func() {
material.RadioButton(th, "r3", "RadioButton3").Layout(gtx, radioButtonsGroup)
}),
) )
}, },
} }
list.Layout(gtx, len(widgets), func(i int) { return list.Layout(gtx, len(widgets), func(gtx C, i int) D {
layout.UniformInset(unit.Dp(16)).Layout(gtx, widgets[i]) return layout.UniformInset(unit.Dp(16)).Layout(gtx, widgets[i])
}) })
} }
+12 -11
View File
@@ -26,13 +26,13 @@ type Slider struct {
} }
// PushLeft pushes the existing widget to the left. // PushLeft pushes the existing widget to the left.
func (s *Slider) PushLeft(gtx *layout.Context) { s.push = 1 } func (s *Slider) PushLeft() { s.push = 1 }
// PushRight pushes the existing widget to the right. // PushRight pushes the existing widget to the right.
func (s *Slider) PushRight(gtx *layout.Context) { s.push = -1 } func (s *Slider) PushRight() { s.push = -1 }
// Layout lays out widget that can be pushed. // Layout lays out widget that can be pushed.
func (s *Slider) Layout(gtx *layout.Context, w layout.Widget) { func (s *Slider) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
if s.push != 0 { if s.push != 0 {
s.last, s.next = s.next, new(op.Ops) s.last, s.next = s.next, new(op.Ops)
s.offset = float32(s.push) s.offset = float32(s.push)
@@ -68,20 +68,20 @@ func (s *Slider) Layout(gtx *layout.Context, w layout.Widget) {
op.InvalidateOp{}.Add(gtx.Ops) op.InvalidateOp{}.Add(gtx.Ops)
} }
var dims layout.Dimensions
{ {
prev := gtx.Ops
if s.next == nil { if s.next == nil {
s.next = new(op.Ops) s.next = new(op.Ops)
} }
s.next.Reset() s.next.Reset()
gtx := gtx
gtx.Ops = s.next gtx.Ops = s.next
w() dims = w(gtx)
gtx.Ops = prev
} }
if s.offset == 0 { if s.offset == 0 {
op.CallOp{Ops: s.next}.Add(gtx.Ops) op.CallOp{Ops: s.next}.Add(gtx.Ops)
return return dims
} }
var stack op.StackOp var stack op.StackOp
@@ -92,25 +92,26 @@ func (s *Slider) Layout(gtx *layout.Context, w layout.Widget) {
if s.offset > 0 { if s.offset > 0 {
op.TransformOp{}.Offset(f32.Point{ op.TransformOp{}.Offset(f32.Point{
X: float32(gtx.Dimensions.Size.X) * (offset - 1), X: float32(dims.Size.X) * (offset - 1),
}).Add(gtx.Ops) }).Add(gtx.Ops)
op.CallOp{Ops: s.last}.Add(gtx.Ops) op.CallOp{Ops: s.last}.Add(gtx.Ops)
op.TransformOp{}.Offset(f32.Point{ op.TransformOp{}.Offset(f32.Point{
X: float32(gtx.Dimensions.Size.X), X: float32(dims.Size.X),
}).Add(gtx.Ops) }).Add(gtx.Ops)
op.CallOp{Ops: s.next}.Add(gtx.Ops) op.CallOp{Ops: s.next}.Add(gtx.Ops)
} else { } else {
op.TransformOp{}.Offset(f32.Point{ op.TransformOp{}.Offset(f32.Point{
X: float32(gtx.Dimensions.Size.X) * (offset + 1), X: float32(dims.Size.X) * (offset + 1),
}).Add(gtx.Ops) }).Add(gtx.Ops)
op.CallOp{Ops: s.last}.Add(gtx.Ops) op.CallOp{Ops: s.last}.Add(gtx.Ops)
op.TransformOp{}.Offset(f32.Point{ op.TransformOp{}.Offset(f32.Point{
X: float32(-gtx.Dimensions.Size.X), X: float32(-dims.Size.X),
}).Add(gtx.Ops) }).Add(gtx.Ops)
op.CallOp{Ops: s.next}.Add(gtx.Ops) op.CallOp{Ops: s.next}.Add(gtx.Ops)
} }
return dims
} }
// smooth handles -1 to 1 with ease-in-out cubic easing func. // smooth handles -1 to 1 with ease-in-out cubic easing func.
+32 -25
View File
@@ -13,6 +13,7 @@ import (
"gioui.org/f32" "gioui.org/f32"
"gioui.org/io/system" "gioui.org/io/system"
"gioui.org/layout" "gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint" "gioui.org/op/paint"
"gioui.org/unit" "gioui.org/unit"
"gioui.org/widget" "gioui.org/widget"
@@ -34,14 +35,14 @@ func main() {
func loop(w *app.Window) error { func loop(w *app.Window) error {
gofont.Register() gofont.Register()
th := material.NewTheme() th := material.NewTheme()
gtx := new(layout.Context) var ops op.Ops
for { for {
e := <-w.Events() e := <-w.Events()
switch e := e.(type) { switch e := e.(type) {
case system.DestroyEvent: case system.DestroyEvent:
return e.Err return e.Err
case system.FrameEvent: case system.FrameEvent:
gtx.Reset(e.Queue, e.Config, e.Size) gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
drawTabs(gtx, th) drawTabs(gtx, th)
e.Frame(gtx.Ops) e.Frame(gtx.Ops)
} }
@@ -70,32 +71,38 @@ func init() {
} }
} }
func drawTabs(gtx *layout.Context, th *material.Theme) { type (
layout.Flex{Axis: layout.Vertical}.Layout(gtx, C = layout.Context
layout.Rigid(func() { D = layout.Dimensions
tabs.list.Layout(gtx, len(tabs.tabs), func(tabIdx int) { )
func drawTabs(gtx layout.Context, th *material.Theme) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx C) D {
return tabs.list.Layout(gtx, len(tabs.tabs), func(gtx C, tabIdx int) D {
t := &tabs.tabs[tabIdx] t := &tabs.tabs[tabIdx]
if t.btn.Clicked(gtx) { if t.btn.Clicked(gtx) {
if tabs.selected < tabIdx { if tabs.selected < tabIdx {
slider.PushLeft(gtx) slider.PushLeft()
} else if tabs.selected > tabIdx { } else if tabs.selected > tabIdx {
slider.PushRight(gtx) slider.PushRight()
} }
tabs.selected = tabIdx tabs.selected = tabIdx
} }
var tabWidth int var tabWidth int
layout.Stack{Alignment: layout.S}.Layout(gtx, return layout.Stack{Alignment: layout.S}.Layout(gtx,
layout.Stacked(func() { layout.Stacked(func(gtx C) D {
material.Clickable(gtx, &t.btn, func() { dims := material.Clickable(gtx, &t.btn, func(gtx C) D {
layout.UniformInset(unit.Sp(12)).Layout(gtx, func() { return layout.UniformInset(unit.Sp(12)).Layout(gtx,
material.H6(th, t.Title).Layout(gtx) material.H6(th, t.Title).Layout,
}) )
}) })
tabWidth = gtx.Dimensions.Size.X tabWidth = dims.Size.X
return dims
}), }),
layout.Stacked(func() { layout.Stacked(func(gtx C) D {
if tabs.selected != tabIdx { if tabs.selected != tabIdx {
return return layout.Dimensions{}
} }
paint.ColorOp{Color: th.Color.Primary}.Add(gtx.Ops) paint.ColorOp{Color: th.Color.Primary}.Add(gtx.Ops)
tabHeight := gtx.Px(unit.Dp(4)) tabHeight := gtx.Px(unit.Dp(4))
@@ -105,25 +112,25 @@ func drawTabs(gtx *layout.Context, th *material.Theme) {
Y: float32(tabHeight), Y: float32(tabHeight),
}, },
}}.Add(gtx.Ops) }}.Add(gtx.Ops)
gtx.Dimensions = layout.Dimensions{ return layout.Dimensions{
Size: image.Point{X: tabWidth, Y: tabHeight}, Size: image.Point{X: tabWidth, Y: tabHeight},
} }
}), }),
) )
}) })
}), }),
layout.Flexed(1, func() { layout.Flexed(1, func(gtx C) D {
slider.Layout(gtx, func() { return slider.Layout(gtx, func(gtx C) D {
fill(gtx, dynamicColor(tabs.selected)) fill(gtx, dynamicColor(tabs.selected))
layout.Center.Layout(gtx, func() { return layout.Center.Layout(gtx,
material.H1(th, fmt.Sprintf("Tab content #%d", tabs.selected+1)).Layout(gtx) material.H1(th, fmt.Sprintf("Tab content #%d", tabs.selected+1)).Layout,
}) )
}) })
}), }),
) )
} }
func bounds(gtx *layout.Context) f32.Rectangle { func bounds(gtx layout.Context) f32.Rectangle {
cs := gtx.Constraints cs := gtx.Constraints
d := cs.Min d := cs.Min
return f32.Rectangle{ return f32.Rectangle{
@@ -131,7 +138,7 @@ func bounds(gtx *layout.Context) f32.Rectangle {
} }
} }
func fill(gtx *layout.Context, col color.RGBA) { func fill(gtx layout.Context, col color.RGBA) {
dr := bounds(gtx) dr := bounds(gtx)
paint.ColorOp{Color: col}.Add(gtx.Ops) paint.ColorOp{Color: col}.Add(gtx.Ops)
paint.PaintOp{Rect: dr}.Add(gtx.Ops) paint.PaintOp{Rect: dr}.Add(gtx.Ops)