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
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/chromedp v0.5.2
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=
gioui.org v0.0.0-20200521183411-67382bec3949 h1:Nvvyn28PT4kyRKBKg04QY2ZU6y9J1hFGJtBDV5VyBmM=
gioui.org v0.0.0-20200521183411-67382bec3949/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04=
gioui.org v0.0.0-20200523202849-2451750782b8 h1:TB+F3jDAVjNemdtgc8yfvsPy1xWkyn7JLOsm5r+YUuQ=
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/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
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/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint"
)
@@ -39,6 +40,11 @@ const (
// when a frame is ready. Initially we want to notify about the first frame.
var notify = notifyInvalidate
type (
C = layout.Context
D = layout.Dimensions
)
func loop(w *app.Window) error {
topLeft := quarterWidget{
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},
}
gtx := new(layout.Context)
var ops op.Ops
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
case system.FrameEvent:
gtx.Reset(e.Queue, e.Config, e.Size)
gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Flexed(0.5, func() {
layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Flexed(0.5, func(gtx C) D {
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
// r1c1
layout.Flexed(0.5, func() { topLeft.Layout(gtx) }),
layout.Flexed(0.5, func(gtx C) D { return topLeft.Layout(gtx) }),
// 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.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Flexed(0.5, func(gtx C) D {
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
// r2c1
layout.Flexed(0.5, func() { botLeft.Layout(gtx) }),
layout.Flexed(0.5, func(gtx C) D { return botLeft.Layout(gtx) }),
// 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}
func (w *quarterWidget) Layout(gtx *layout.Context) {
func (w *quarterWidget) Layout(gtx layout.Context) layout.Dimensions {
if w.clicked {
paint.ColorOp{Color: red}.Add(gtx.Ops)
} else {
@@ -128,4 +133,5 @@ func (w *quarterWidget) Layout(gtx *layout.Context) {
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/router"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
@@ -71,7 +72,7 @@ func main() {
gofont.Register()
f := new(goglFunctions)
var queue router.Router
gtx := new(layout.Context)
var ops op.Ops
th := material.NewTheme()
backend, err := giogl.NewBackend(f)
if err != nil {
@@ -92,7 +93,7 @@ func main() {
}
width, height := window.GetSize()
sz := image.Point{X: width, Y: height}
gtx.Reset(&queue, &glfwConfig{scale}, sz)
gtx := layout.NewContext(&ops, &queue, &glfwConfig{scale}, sz)
draw(gtx, th)
gpu.Collect(sz, gtx.Ops)
gpu.BeginFrame()
@@ -104,10 +105,10 @@ func main() {
var button widget.Clickable
func draw(gtx *layout.Context, th *material.Theme) {
layout.Center.Layout(gtx, func() {
material.Button(th, "Button").Layout(gtx, &button)
})
func draw(gtx layout.Context, th *material.Theme) layout.Dimensions {
return layout.Center.Layout(gtx,
material.Button(th, &button, "Button").Layout,
)
}
func registerCallbacks(window *glfw.Window, q *router.Router) {
+1 -1
View File
@@ -3,7 +3,7 @@ module gioui.org/example
go 1.13
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/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72
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=
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-20200521183411-67382bec3949/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04=
gioui.org v0.0.0-20200523202849-2451750782b8 h1:TB+F3jDAVjNemdtgc8yfvsPy1xWkyn7JLOsm5r+YUuQ=
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/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=
+3 -2
View File
@@ -20,6 +20,7 @@ import (
"gioui.org/io/key"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/unit"
"github.com/google/go-github/v24/github"
@@ -77,7 +78,7 @@ func initProfiling() {
func (a *App) run() error {
a.ui.profiling = *stats
gtx := new(layout.Context)
var ops op.Ops
for {
select {
case users := <-a.updateUsers:
@@ -125,7 +126,7 @@ func (a *App) run() error {
}
}
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)
e.Frame(gtx.Ops)
}
+6 -2
View File
@@ -7,14 +7,18 @@ import (
"testing"
"gioui.org/layout"
"gioui.org/op"
)
func BenchmarkUI(b *testing.B) {
fetch := func(_ string) {}
u := newUI(fetch)
gtx := new(layout.Context)
var ops op.Ops
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)
}
}
+74 -73
View File
@@ -65,6 +65,11 @@ type user struct {
var theme *material.Theme
type (
C = layout.Context
D = layout.Dimensions
)
func init() {
gofont.Register()
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)}
}
func (u *UI) layoutTimings(gtx *layout.Context) {
func (u *UI) layoutTimings(gtx layout.Context) {
if !u.profiling {
return
}
@@ -120,17 +125,17 @@ func (u *UI) layoutTimings(gtx *layout.Context) {
runtime.ReadMemStats(&mstats)
mallocs := mstats.Mallocs - u.lastMallocs
u.lastMallocs = mstats.Mallocs
layout.NE.Layout(gtx, func() {
layout.Inset{Top: unit.Dp(16)}.Layout(gtx, func() {
layout.NE.Layout(gtx, func(gtx C) D {
return layout.Inset{Top: unit.Dp(16)}.Layout(gtx, func(gtx C) D {
txt := fmt.Sprintf("m: %d %s", mallocs, u.profile.Timings)
lbl := material.Caption(theme, txt)
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 {
click := &u.userClicks[i]
for _, e := range click.Events(gtx) {
@@ -156,159 +161,155 @@ func (u *UI) newUserPage(user *user) *userPage {
return up
}
func (up *userPage) Layout(gtx *layout.Context) {
func (up *userPage) Layout(gtx layout.Context) {
l := up.commitsList
if l.Dragging() {
key.HideInputOp{}.Add(gtx.Ops)
}
l.Layout(gtx, len(up.commits), func(i int) {
up.commit(gtx, i)
l.Layout(gtx, len(up.commits), func(gtx C, i int) D {
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
msg := up.commits[index].GetMessage()
label := material.Caption(theme, msg)
in := layout.Inset{Top: unit.Dp(16), Right: unit.Dp(8), Left: unit.Dp(8)}
in.Layout(gtx, func() {
layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Rigid(func() {
return in.Layout(gtx, func(gtx C) D {
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
layout.Rigid(func(gtx C) D {
sz := gtx.Px(unit.Dp(48))
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}))
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
layout.Inset{Left: unit.Dp(8)}.Layout(gtx, func() {
label.Layout(gtx)
})
return layout.Inset{Left: unit.Dp(8)}.Layout(gtx, label.Layout)
}),
)
})
}
func (u *UI) layoutUsers(gtx *layout.Context) {
func (u *UI) layoutUsers(gtx layout.Context) {
layout.Stack{Alignment: layout.SE}.Layout(gtx,
layout.Expanded(func() {
layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func() {
layout.Expanded(func(gtx C) D {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx C) D {
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))
cs := gtx.Constraints
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
in := layout.Inset{Bottom: unit.Dp(16), Left: unit.Dp(16), Right: unit.Dp(16)}
in.Layout(gtx, func() {
e := material.Editor(theme, "Hint")
return in.Layout(gtx, func(gtx C) D {
e := material.Editor(theme, u.edit2, "Hint")
e.TextSize = unit.Sp(14)
e.Font.Style = text.Italic
e.Layout(gtx, u.edit2)
return e.Layout(gtx)
})
}),
layout.Rigid(func() {
layout.Stack{}.Layout(gtx,
layout.Expanded(func() {
layout.Rigid(func(gtx C) D {
return layout.Stack{}.Layout(gtx,
layout.Expanded(func(gtx C) D {
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(gtx, func() {
return in.Layout(gtx, func(gtx C) D {
lbl := material.Caption(theme, "GOPHERS")
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
u.layoutContributors(gtx)
return u.layoutContributors(gtx)
}),
)
}),
layout.Stacked(func() {
layout.Stacked(func(gtx C) D {
in := layout.UniformInset(unit.Dp(16))
in.Layout(gtx, func() {
return in.Layout(gtx, func(gtx C) D {
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
if l.Dragging() {
key.HideInputOp{}.Add(gtx.Ops)
}
l.Layout(gtx, len(u.users), func(i int) {
u.user(gtx, i)
return l.Layout(gtx, len(u.users), func(gtx C, i int) D {
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]
in := layout.UniformInset(unit.Dp(8))
in.Layout(gtx, func() {
centerRowOpts().Layout(gtx,
layout.Rigid(func() {
dims := in.Layout(gtx, func(gtx C) D {
return centerRowOpts().Layout(gtx,
layout.Rigid(func(gtx C) D {
in := layout.Inset{Right: unit.Dp(8)}
cc := clipCircle{}
in.Layout(gtx, func() {
cc.Layout(gtx, func() {
return in.Layout(gtx, func(gtx C) D {
return cc.Layout(gtx, func(gtx C) D {
dim := gtx.Px(unit.Dp(48))
sz := image.Point{X: dim, Y: dim}
gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(sz))
user.layoutAvatar(gtx)
return user.layoutAvatar(gtx)
})
})
}),
layout.Rigid(func() {
column().Layout(gtx,
layout.Rigid(func() {
baseline().Layout(gtx,
layout.Rigid(func() {
material.Body1(theme, user.name).Layout(gtx)
}),
layout.Flexed(1, func() {
layout.Rigid(func(gtx C) D {
return column().Layout(gtx,
layout.Rigid(func(gtx C) D {
return baseline().Layout(gtx,
layout.Rigid(material.Body1(theme, user.name).Layout),
layout.Flexed(1, func(gtx C) D {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
layout.E.Layout(gtx, func() {
layout.Inset{Left: unit.Dp(2)}.Layout(gtx, func() {
material.Caption(theme, "3 hours ago").Layout(gtx)
})
return layout.E.Layout(gtx, func(gtx C) D {
return layout.Inset{Left: unit.Dp(2)}.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(gtx, func() {
return in.Layout(gtx, func(gtx C) D {
lbl := material.Caption(theme, user.company)
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.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
if u.avatarOp.Size().X != 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.Scale = float32(sz) / float32(gtx.Px(unit.Dp(float32(sz))))
img.Layout(gtx)
return img.Layout(gtx)
}
type fill struct {
col color.RGBA
}
func (f fill) Layout(gtx *layout.Context) {
func (f fill) Layout(gtx layout.Context) layout.Dimensions {
cs := gtx.Constraints
d := cs.Min
dr := f32.Rectangle{
@@ -332,7 +333,7 @@ func (f fill) Layout(gtx *layout.Context) {
}
paint.ColorOp{Color: f.col}.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 {
@@ -350,12 +351,11 @@ func baseline() layout.Flex {
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
m.Record(gtx.Ops)
w()
dims := w(gtx)
m.Stop()
dims := gtx.Dimensions
max := dims.Size.X
if dy := dims.Size.Y; dy > max {
max = dy
@@ -370,6 +370,7 @@ func (c *clipCircle) Layout(gtx *layout.Context, w layout.Widget) {
}.Op(gtx.Ops).Add(gtx.Ops)
m.Add()
stack.Pop()
return dims
}
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/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/text"
"gioui.org/widget/material"
@@ -30,14 +31,14 @@ func main() {
func loop(w *app.Window) error {
gofont.Register()
th := material.NewTheme()
gtx := new(layout.Context)
var ops op.Ops
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
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")
maroon := color.RGBA{127, 0, 0, 255}
l.Color = maroon
+75 -77
View File
@@ -22,6 +22,7 @@ import (
"gioui.org/font/gofont"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/text"
"gioui.org/unit"
"gioui.org/widget"
@@ -37,7 +38,10 @@ type scaledConfig struct {
}
type iconAndTextButton struct {
theme *material.Theme
theme *material.Theme
button *widget.Clickable
icon *widget.Icon
word string
}
func main() {
@@ -81,8 +85,11 @@ func saveScreenshot(f string) error {
if err != nil {
return err
}
gtx := new(layout.Context)
gtx.Reset(nil, &scaledConfig{scale}, sz)
gtx := layout.Context{
Ops: new(op.Ops),
Config: &scaledConfig{scale},
Constraints: layout.Exact(sz),
}
th := material.NewTheme()
kitchen(gtx, th)
w.Frame(gtx.Ops)
@@ -100,7 +107,7 @@ func saveScreenshot(f string) error {
func loop(w *app.Window) error {
th := material.NewTheme()
gtx := new(layout.Context)
var ops op.Ops
for {
select {
case e := <-w.Events():
@@ -110,7 +117,7 @@ func loop(w *app.Window) error {
case system.DestroyEvent:
return e.Err
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) {
w.WriteClipboard(lineEditor.Text())
}
@@ -154,134 +161,125 @@ var (
swtch = new(widget.Bool)
)
func (b iconAndTextButton) Layout(gtx *layout.Context, button *widget.Clickable, icon *widget.Icon, word string) {
material.ButtonLayout(b.theme).Layout(gtx, button, func() {
type (
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}
textIconSpacer := unit.Dp(5)
layIcon := layout.Rigid(func() {
layout.Inset{Right: textIconSpacer}.Layout(gtx, func() {
size := gtx.Px(unit.Dp(56)) - 2*gtx.Px(unit.Dp(16))
layIcon := layout.Rigid(func(gtx C) D {
return layout.Inset{Right: textIconSpacer}.Layout(gtx, func(gtx C) D {
var d D
if icon != nil {
icon.Layout(gtx, unit.Px(float32(size)))
gtx.Dimensions = layout.Dimensions{
size := gtx.Px(unit.Dp(56)) - 2*gtx.Px(unit.Dp(16))
b.icon.Layout(gtx, unit.Px(float32(size)))
d = layout.Dimensions{
Size: image.Point{X: size, Y: size},
}
}
return d
})
})
layLabel := layout.Rigid(func() {
layout.Inset{Left: textIconSpacer}.Layout(gtx, func() {
l := material.Body1(b.theme, word)
layLabel := layout.Rigid(func(gtx C) D {
return layout.Inset{Left: textIconSpacer}.Layout(gtx, func(gtx C) D {
l := material.Body1(b.theme, b.word)
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) {
widgets := []func(){
func() {
material.H3(th, topLabel).Layout(gtx)
},
func() {
func kitchen(gtx layout.Context, th *material.Theme) layout.Dimensions {
widgets := []layout.Widget{
material.H3(th, topLabel).Layout,
func(gtx C) D {
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() {
e := material.Editor(th, "Hint")
e.Font.Style = text.Italic
e.Layout(gtx, lineEditor)
func(gtx C) D {
for _, e := range lineEditor.Events(gtx) {
if e, ok := e.(widget.SubmitEvent); ok {
topLabel = e.Text
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))
layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func() {
in.Layout(gtx, func() {
material.IconButton(th, icon).Layout(gtx, iconButton)
})
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D {
return in.Layout(gtx, material.IconButton(th, iconButton, icon).Layout)
}),
layout.Rigid(func() {
in.Layout(gtx, func() {
iconAndTextButton{th}.Layout(gtx, iconTextButton, icon, "Icon")
})
layout.Rigid(func(gtx C) D {
return in.Layout(gtx, iconAndTextButton{theme: th, icon: icon, word: "Icon", button: iconTextButton}.Layout)
}),
layout.Rigid(func() {
in.Layout(gtx, func() {
layout.Rigid(func(gtx C) D {
return in.Layout(gtx, func(gtx C) D {
for button.Clicked(gtx) {
green = !green
}
material.Button(th, "Click me!").Layout(gtx, button)
return material.Button(th, button, "Click me!").Layout(gtx)
})
}),
layout.Rigid(func() {
in.Layout(gtx, func() {
layout.Rigid(func(gtx C) D {
return in.Layout(gtx, func(gtx C) D {
l := "Green"
if !green {
l = "Blue"
}
btn := material.Button(th, l)
btn := material.Button(th, greenButton, l)
if green {
btn.Background = color.RGBA{A: 0xff, R: 0x9e, G: 0x9d, B: 0x24}
}
btn.Layout(gtx, greenButton)
return btn.Layout(gtx)
})
}),
layout.Rigid(func() {
in.Layout(gtx, func() {
material.Clickable(gtx, flatBtn, func() {
layout.UniformInset(unit.Dp(12)).Layout(gtx, func() {
layout.Center.Layout(gtx, func() {
material.Body1(th, "Flat").Layout(gtx)
})
layout.Rigid(func(gtx C) D {
return in.Layout(gtx, func(gtx C) D {
return material.Clickable(gtx, flatBtn, func(gtx C) D {
return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D {
return layout.Center.Layout(gtx, material.Body1(th, "Flat").Layout)
})
})
})
}),
)
},
func() {
material.ProgressBar(th).Layout(gtx, progress)
},
func() {
layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func() {
material.CheckBox(th, "Checkbox").Layout(gtx, checkbox)
}),
layout.Rigid(func() {
layout.Inset{Left: unit.Dp(16)}.Layout(gtx, func() {
material.Switch(th).Layout(gtx, swtch)
})
material.ProgressBar(th, progress).Layout,
func(gtx C) D {
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(
material.CheckBox(th, checkbox, "Checkbox").Layout,
),
layout.Rigid(func(gtx C) D {
return layout.Inset{Left: unit.Dp(16)}.Layout(gtx,
material.Switch(th, swtch).Layout,
)
}),
)
},
func() {
layout.Flex{}.Layout(gtx,
layout.Rigid(func() {
material.RadioButton(th, "r1", "RadioButton1").Layout(gtx, radioButtonsGroup)
}),
layout.Rigid(func() {
material.RadioButton(th, "r2", "RadioButton2").Layout(gtx, radioButtonsGroup)
}),
layout.Rigid(func() {
material.RadioButton(th, "r3", "RadioButton3").Layout(gtx, radioButtonsGroup)
}),
func(gtx C) D {
return layout.Flex{}.Layout(gtx,
layout.Rigid(material.RadioButton(th, radioButtonsGroup, "r1", "RadioButton1").Layout),
layout.Rigid(material.RadioButton(th, radioButtonsGroup, "r2", "RadioButton2").Layout),
layout.Rigid(material.RadioButton(th, radioButtonsGroup, "r3", "RadioButton3").Layout),
)
},
}
list.Layout(gtx, len(widgets), func(i int) {
layout.UniformInset(unit.Dp(16)).Layout(gtx, widgets[i])
return list.Layout(gtx, len(widgets), func(gtx C, i int) D {
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.
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.
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.
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 {
s.last, s.next = s.next, new(op.Ops)
s.offset = float32(s.push)
@@ -68,20 +68,20 @@ func (s *Slider) Layout(gtx *layout.Context, w layout.Widget) {
op.InvalidateOp{}.Add(gtx.Ops)
}
var dims layout.Dimensions
{
prev := gtx.Ops
if s.next == nil {
s.next = new(op.Ops)
}
s.next.Reset()
gtx := gtx
gtx.Ops = s.next
w()
gtx.Ops = prev
dims = w(gtx)
}
if s.offset == 0 {
op.CallOp{Ops: s.next}.Add(gtx.Ops)
return
return dims
}
var stack op.StackOp
@@ -92,25 +92,26 @@ func (s *Slider) Layout(gtx *layout.Context, w layout.Widget) {
if s.offset > 0 {
op.TransformOp{}.Offset(f32.Point{
X: float32(gtx.Dimensions.Size.X) * (offset - 1),
X: float32(dims.Size.X) * (offset - 1),
}).Add(gtx.Ops)
op.CallOp{Ops: s.last}.Add(gtx.Ops)
op.TransformOp{}.Offset(f32.Point{
X: float32(gtx.Dimensions.Size.X),
X: float32(dims.Size.X),
}).Add(gtx.Ops)
op.CallOp{Ops: s.next}.Add(gtx.Ops)
} else {
op.TransformOp{}.Offset(f32.Point{
X: float32(gtx.Dimensions.Size.X) * (offset + 1),
X: float32(dims.Size.X) * (offset + 1),
}).Add(gtx.Ops)
op.CallOp{Ops: s.last}.Add(gtx.Ops)
op.TransformOp{}.Offset(f32.Point{
X: float32(-gtx.Dimensions.Size.X),
X: float32(-dims.Size.X),
}).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.
+32 -25
View File
@@ -13,6 +13,7 @@ import (
"gioui.org/f32"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget"
@@ -34,14 +35,14 @@ func main() {
func loop(w *app.Window) error {
gofont.Register()
th := material.NewTheme()
gtx := new(layout.Context)
var ops op.Ops
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
case system.FrameEvent:
gtx.Reset(e.Queue, e.Config, e.Size)
gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size)
drawTabs(gtx, th)
e.Frame(gtx.Ops)
}
@@ -70,32 +71,38 @@ func init() {
}
}
func drawTabs(gtx *layout.Context, th *material.Theme) {
layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func() {
tabs.list.Layout(gtx, len(tabs.tabs), func(tabIdx int) {
type (
C = layout.Context
D = layout.Dimensions
)
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]
if t.btn.Clicked(gtx) {
if tabs.selected < tabIdx {
slider.PushLeft(gtx)
slider.PushLeft()
} else if tabs.selected > tabIdx {
slider.PushRight(gtx)
slider.PushRight()
}
tabs.selected = tabIdx
}
var tabWidth int
layout.Stack{Alignment: layout.S}.Layout(gtx,
layout.Stacked(func() {
material.Clickable(gtx, &t.btn, func() {
layout.UniformInset(unit.Sp(12)).Layout(gtx, func() {
material.H6(th, t.Title).Layout(gtx)
})
return layout.Stack{Alignment: layout.S}.Layout(gtx,
layout.Stacked(func(gtx C) D {
dims := material.Clickable(gtx, &t.btn, func(gtx C) D {
return layout.UniformInset(unit.Sp(12)).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 {
return
return layout.Dimensions{}
}
paint.ColorOp{Color: th.Color.Primary}.Add(gtx.Ops)
tabHeight := gtx.Px(unit.Dp(4))
@@ -105,25 +112,25 @@ func drawTabs(gtx *layout.Context, th *material.Theme) {
Y: float32(tabHeight),
},
}}.Add(gtx.Ops)
gtx.Dimensions = layout.Dimensions{
return layout.Dimensions{
Size: image.Point{X: tabWidth, Y: tabHeight},
}
}),
)
})
}),
layout.Flexed(1, func() {
slider.Layout(gtx, func() {
layout.Flexed(1, func(gtx C) D {
return slider.Layout(gtx, func(gtx C) D {
fill(gtx, dynamicColor(tabs.selected))
layout.Center.Layout(gtx, func() {
material.H1(th, fmt.Sprintf("Tab content #%d", tabs.selected+1)).Layout(gtx)
})
return layout.Center.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
d := cs.Min
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)
paint.ColorOp{Color: col}.Add(gtx.Ops)
paint.PaintOp{Rect: dr}.Add(gtx.Ops)