~eliasnaur/gio-example

fb350d499d99879fac0381c1cf8857b289923935 — Chris Waldon 7 months ago b2da8c7
x/component: add demo page for Menu component

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
3 files changed, 164 insertions(+), 10 deletions(-)

M go.mod
M go.sum
M x/component/main.go
M go.mod => go.mod +2 -2
@@ 3,8 3,8 @@ module gioui.org/example
go 1.16

require (
	gioui.org v0.0.0-20210316171537-eeb045c59f86
	gioui.org/x v0.0.0-20210226015410-958111222865
	gioui.org v0.0.0-20210402191542-ce7f0da06ee3
	gioui.org/x v0.0.0-20210405014033-ab05db36ed5b
	gioui.org/x/haptic v0.0.0-20210120222453-b55819bc712b
	gioui.org/x/notify v0.0.0-20210120222453-b55819bc712b
	github.com/go-gl/gl v0.0.0-20210315015930-ae072cafe09d

M go.sum => go.sum +4 -5
@@ 33,11 33,10 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210116085804-99bfa6a33cdf/go.mod h1:Y+uS7hHMvku1Q+ooaoq6fYD5B2LGoT8JtFgvmYmRzTw=
gioui.org v0.0.0-20210225120118-f6fba7388544/go.mod h1:Y+uS7hHMvku1Q+ooaoq6fYD5B2LGoT8JtFgvmYmRzTw=
gioui.org v0.0.0-20210316171537-eeb045c59f86 h1:qv6ZEBUN8fKt1Gdz7O3hRYIbYbFgQceI1zXU6YfUNAE=
gioui.org v0.0.0-20210316171537-eeb045c59f86/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
gioui.org/x v0.0.0-20210226015410-958111222865 h1:+Oqlmqi1rRugWA//OMKrQsdulyQB6j4QRo5Dm13jcqs=
gioui.org/x v0.0.0-20210226015410-958111222865/go.mod h1:y7BpIia0O/1wgqVHlfTBaoOCcR1Xm/psmu/1M9AfX9E=
gioui.org v0.0.0-20210402191542-ce7f0da06ee3 h1:mdcDnj73Zif9+Uj9xkOtq8TTDVPWW7eWbeXNIu0Fsos=
gioui.org v0.0.0-20210402191542-ce7f0da06ee3/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
gioui.org/x v0.0.0-20210405014033-ab05db36ed5b h1:F5y0TDqXReud0BBl+SPv9c5wMlTM4rr1+gwxDtmuiO8=
gioui.org/x v0.0.0-20210405014033-ab05db36ed5b/go.mod h1:qsAS5EBzGhn3sJ98FJdA+ae+E5/DgmxjySERjjR1Zvg=
gioui.org/x/haptic v0.0.0-20210120222453-b55819bc712b h1:3lHNKrTHXJCXhtmCVdTInlNuay3jSQ0SVi9JNQTj5yM=
gioui.org/x/haptic v0.0.0-20210120222453-b55819bc712b/go.mod h1:8zNy+2M/H/zMZtZVh3ZSk7EuPqob+PNtVFzWstzT7ok=
gioui.org/x/notify v0.0.0-20210120222453-b55819bc712b h1:EhTlhP/Q0lrgDQvHC9qdvXicytUps1sRfIOk28183Ec=

M x/component/main.go => x/component/main.go +158 -3
@@ 2,6 2,8 @@ package main

import (
	"flag"
	"fmt"
	"image"
	"image/color"
	"log"
	"os"


@@ 13,6 15,7 @@ import (
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
	"gioui.org/widget"


@@ 32,6 35,26 @@ var MenuIcon *widget.Icon = func() *widget.Icon {
	return icon
}()

var RestaurantMenuIcon *widget.Icon = func() *widget.Icon {
	icon, _ := widget.NewIcon(icons.MapsRestaurantMenu)
	return icon
}()

var AccountBalanceIcon *widget.Icon = func() *widget.Icon {
	icon, _ := widget.NewIcon(icons.ActionAccountBalance)
	return icon
}()

var AccountBoxIcon *widget.Icon = func() *widget.Icon {
	icon, _ := widget.NewIcon(icons.ActionAccountBox)
	return icon
}()

var CartIcon *widget.Icon = func() *widget.Icon {
	icon, _ := widget.NewIcon(icons.ActionAddShoppingCart)
	return icon
}()

var HomeIcon *widget.Icon = func() *widget.Icon {
	icon, _ := widget.NewIcon(icons.ActionHome)
	return icon


@@ 101,7 124,7 @@ The controls below allow you to see the various features available in our App Ba
					if contextBtn.Clicked() {
						bar.SetContextualActions(
							[]component.AppBarAction{
								component.SimpleIconAction(th, &red, HeartIcon,
								component.SimpleIconAction(&red, HeartIcon,
									component.OverflowAction{
										Name: "House",
										Tag:  &red,


@@ 447,6 470,76 @@ func LayoutTextFieldPage(gtx C) D {
	)
}

func LayoutMenuPage(gtx C) D {
	if redButton.Clicked() {
		leftFillColor = color.NRGBA{R: 200, A: 255}
	}
	if greenButton.Clicked() {
		leftFillColor = color.NRGBA{G: 200, A: 255}
	}
	if blueButton.Clicked() {
		leftFillColor = color.NRGBA{B: 200, A: 255}
	}
	th := *th
	th.Palette = currentAccent
	return layout.Flex{}.Layout(gtx,
		layout.Flexed(.5, func(gtx C) D {
			return widget.Border{
				Color: color.NRGBA{A: 255},
				Width: unit.Dp(2),
			}.Layout(gtx, func(gtx C) D {
				return layout.Stack{}.Layout(gtx,
					layout.Stacked(func(gtx C) D {
						max := image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.X)
						rect := image.Rectangle{
							Max: max,
						}
						paint.FillShape(gtx.Ops, leftFillColor, clip.Rect(rect).Op())
						return D{Size: max}
					}),
					layout.Stacked(func(gtx C) D {
						return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D {
							return component.Surface(&th).Layout(gtx, func(gtx C) D {
								return layout.UniformInset(unit.Dp(12)).Layout(gtx, material.Body1(&th, "Right-click anywhere in this region").Layout)
							})
						})
					}),
					layout.Expanded(func(gtx C) D {
						return leftContextArea.Layout(gtx, func(gtx C) D {
							gtx.Constraints.Min = image.Point{}
							return component.Menu(&th, &leftMenu).Layout(gtx)
						})
					}),
				)
			})
		}),
		layout.Flexed(.5, func(gtx C) D {
			gtx.Constraints.Max.Y = gtx.Constraints.Max.X
			return layout.UniformInset(unit.Dp(12)).Layout(gtx, func(gtx C) D {
				menuDemoList.Axis = layout.Vertical
				return menuDemoList.Layout(gtx, 30, func(gtx C, index int) D {
					if len(menuDemoListStates) < index+1 {
						menuDemoListStates = append(menuDemoListStates, component.ContextArea{})
					}
					state := &menuDemoListStates[index]
					return layout.Stack{}.Layout(gtx,
						layout.Stacked(func(gtx C) D {
							gtx.Constraints.Min.X = gtx.Constraints.Max.X
							return layout.UniformInset(unit.Dp(8)).Layout(gtx, material.Body1(&th, fmt.Sprintf("Item %d", index)).Layout)
						}),
						layout.Expanded(func(gtx C) D {
							return state.Layout(gtx, func(gtx C) D {
								gtx.Constraints.Min.X = 0
								return component.Menu(&th, &rightMenu).Layout(gtx)
							})
						}),
					)
				})
			})
		}),
	)
}

type Page struct {
	layout func(layout.Context) layout.Dimensions
	component.NavItem


@@ 515,6 608,61 @@ var (
	tweetInput                                            component.TextField
	numberInput                                           component.TextField

	leftContextArea                          component.ContextArea
	redButton, greenButton, blueButton       widget.Clickable
	balanceButton, accountButton, cartButton widget.Clickable
	leftFillColor                            color.NRGBA
	menuDemoList                             layout.List
	menuDemoListStates                       []component.ContextArea
	rightMenu                                component.MenuState = component.MenuState{
		Options: []func(gtx C) D{
			func(gtx C) D {
				item := component.MenuItem(th, &balanceButton, "Balance")
				item.Icon = AccountBalanceIcon
				item.Hint = component.MenuHintText(th, "Hint")
				return item.Layout(gtx)
			},
			func(gtx C) D {
				item := component.MenuItem(th, &accountButton, "Account")
				item.Icon = AccountBoxIcon
				item.Hint = component.MenuHintText(th, "Hint")
				return item.Layout(gtx)
			},
			func(gtx C) D {
				item := component.MenuItem(th, &cartButton, "Cart")
				item.Icon = CartIcon
				item.Hint = component.MenuHintText(th, "Hint")
				return item.Layout(gtx)
			},
		},
	}
	leftMenu component.MenuState = component.MenuState{
		Options: []func(gtx C) D{
			func(gtx C) D {
				return layout.Inset{
					Left:  unit.Dp(16),
					Right: unit.Dp(16),
				}.Layout(gtx, material.Body1(th, "Menus support arbitrary widgets.\nThis is just a label!\nHere's a loader:").Layout)
			},
			component.Divider(th).Layout,
			func(gtx C) D {
				return layout.Inset{
					Top:    unit.Dp(4),
					Bottom: unit.Dp(4),
					Left:   unit.Dp(16),
					Right:  unit.Dp(16),
				}.Layout(gtx, func(gtx C) D {
					gtx.Constraints.Max.X = gtx.Px(unit.Dp(24))
					gtx.Constraints.Max.Y = gtx.Px(unit.Dp(24))
					return material.Loader(th).Layout(gtx)
				})
			},
			component.SubheadingDivider(th, "Colors").Layout,
			component.MenuItem(th, &redButton, "Red").Layout,
			component.MenuItem(th, &greenButton, "Green").Layout,
			component.MenuItem(th, &blueButton, "Blue").Layout,
		},
	}
	pages = []Page{
		{
			NavItem: component.NavItem{


@@ 529,7 677,7 @@ var (
						Tag:  &heartBtn,
					},
					Layout: func(gtx layout.Context, bg, fg color.NRGBA) layout.Dimensions {
						btn := component.SimpleIconButton(th, &heartBtn, HeartIcon)
						btn := component.SimpleIconButton(bg, fg, &heartBtn, HeartIcon)
						btn.Background = bg
						if favorited {
							btn.Color = color.NRGBA{R: 200, A: 255}


@@ 539,7 687,7 @@ var (
						return btn.Layout(gtx)
					},
				},
				component.SimpleIconAction(th, &plusBtn, PlusIcon,
				component.SimpleIconAction(&plusBtn, PlusIcon,
					component.OverflowAction{
						Name: "Create",
						Tag:  &plusBtn,


@@ 573,6 721,13 @@ var (
		},
		{
			NavItem: component.NavItem{
				Name: "Menu Features",
				Icon: RestaurantMenuIcon,
			},
			layout: LayoutMenuPage,
		},
		{
			NavItem: component.NavItem{
				Name: "About this library",
				Icon: OtherIcon,
			},