You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.4 KiB

package menu
import (
"fmt"
"image"
"image/color"
"gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
"gioui.org/x/component"
"gioui.org/example/component/icon"
page "gioui.org/example/component/pages"
)
type (
C = layout.Context
D = layout.Dimensions
)
// Page holds the state for a page demonstrating the features of
// the Menu component.
type Page struct {
redButton, greenButton, blueButton widget.Clickable
balanceButton, accountButton, cartButton widget.Clickable
leftFillColor color.NRGBA
leftContextArea component.ContextArea
leftMenu, rightMenu component.MenuState
menuInit bool
menuDemoList layout.List
menuDemoListStates []component.ContextArea
widget.List
*page.Router
}
// New constructs a Page with the provided router.
func New(router *page.Router) *Page {
return &Page{
Router: router,
}
}
var _ page.Page = &Page{}
func (p *Page) Actions() []component.AppBarAction {
return []component.AppBarAction{}
}
func (p *Page) Overflow() []component.OverflowAction {
return []component.OverflowAction{}
}
func (p *Page) NavItem() component.NavItem {
return component.NavItem{
Name: "Menu Features",
Icon: icon.RestaurantMenuIcon,
}
}
func (p *Page) Layout(gtx C, th *material.Theme) D {
p.List.Axis = layout.Vertical
return material.List(th, &p.List).Layout(gtx, 1, func(gtx C, _ int) D {
if !p.menuInit {
p.leftMenu = 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, &p.redButton, "Red").Layout,
component.MenuItem(th, &p.greenButton, "Green").Layout,
component.MenuItem(th, &p.blueButton, "Blue").Layout,
},
}
p.rightMenu = component.MenuState{
Options: []func(gtx C) D{
func(gtx C) D {
item := component.MenuItem(th, &p.balanceButton, "Balance")
item.Icon = icon.AccountBalanceIcon
item.Hint = component.MenuHintText(th, "Hint")
return item.Layout(gtx)
},
func(gtx C) D {
item := component.MenuItem(th, &p.accountButton, "Account")
item.Icon = icon.AccountBoxIcon
item.Hint = component.MenuHintText(th, "Hint")
return item.Layout(gtx)
},
func(gtx C) D {
item := component.MenuItem(th, &p.cartButton, "Cart")
item.Icon = icon.CartIcon
item.Hint = component.MenuHintText(th, "Hint")
return item.Layout(gtx)
},
},
}
}
if p.redButton.Clicked() {
p.leftFillColor = color.NRGBA{R: 200, A: 255}
}
if p.greenButton.Clicked() {
p.leftFillColor = color.NRGBA{G: 200, A: 255}
}
if p.blueButton.Clicked() {
p.leftFillColor = color.NRGBA{B: 200, A: 255}
}
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, p.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 p.leftContextArea.Layout(gtx, func(gtx C) D {
gtx.Constraints.Min = image.Point{}
return component.Menu(th, &p.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 {
p.menuDemoList.Axis = layout.Vertical
return p.menuDemoList.Layout(gtx, 30, func(gtx C, index int) D {
if len(p.menuDemoListStates) < index+1 {
p.menuDemoListStates = append(p.menuDemoListStates, component.ContextArea{})
}
state := &p.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, &p.rightMenu).Layout(gtx)
})
}),
)
})
})
}),
)
})
}