forked from go/golangs_learn
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.
119 lines
3.0 KiB
119 lines
3.0 KiB
3 years ago
|
package page
|
||
|
|
||
|
import (
|
||
|
"log"
|
||
|
"time"
|
||
|
|
||
|
"gioui.org/example/component/icon"
|
||
|
"gioui.org/layout"
|
||
|
"gioui.org/op/paint"
|
||
|
"gioui.org/widget/material"
|
||
|
"gioui.org/x/component"
|
||
|
)
|
||
|
|
||
|
type Page interface {
|
||
|
Actions() []component.AppBarAction
|
||
|
Overflow() []component.OverflowAction
|
||
|
Layout(gtx layout.Context, th *material.Theme) layout.Dimensions
|
||
|
NavItem() component.NavItem
|
||
|
}
|
||
|
|
||
|
type Router struct {
|
||
|
pages map[interface{}]Page
|
||
|
current interface{}
|
||
|
*component.ModalNavDrawer
|
||
|
NavAnim component.VisibilityAnimation
|
||
|
*component.AppBar
|
||
|
*component.ModalLayer
|
||
|
NonModalDrawer, BottomBar bool
|
||
|
}
|
||
|
|
||
|
func NewRouter() Router {
|
||
|
modal := component.NewModal()
|
||
|
|
||
|
nav := component.NewNav("Navigation Drawer", "This is an example.")
|
||
|
modalNav := component.ModalNavFrom(&nav, modal)
|
||
|
|
||
|
bar := component.NewAppBar(modal)
|
||
|
bar.NavigationIcon = icon.MenuIcon
|
||
|
|
||
|
na := component.VisibilityAnimation{
|
||
|
State: component.Invisible,
|
||
|
Duration: time.Millisecond * 250,
|
||
|
}
|
||
|
return Router{
|
||
|
pages: make(map[interface{}]Page),
|
||
|
ModalLayer: modal,
|
||
|
ModalNavDrawer: modalNav,
|
||
|
AppBar: bar,
|
||
|
NavAnim: na,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (r *Router) Register(tag interface{}, p Page) {
|
||
|
r.pages[tag] = p
|
||
|
navItem := p.NavItem()
|
||
|
navItem.Tag = tag
|
||
|
if r.current == interface{}(nil) {
|
||
|
r.current = tag
|
||
|
r.AppBar.Title = navItem.Name
|
||
|
r.AppBar.SetActions(p.Actions(), p.Overflow())
|
||
|
}
|
||
|
r.ModalNavDrawer.AddNavItem(navItem)
|
||
|
}
|
||
|
|
||
|
func (r *Router) SwitchTo(tag interface{}) {
|
||
|
p, ok := r.pages[tag]
|
||
|
if !ok {
|
||
|
return
|
||
|
}
|
||
|
navItem := p.NavItem()
|
||
|
r.current = tag
|
||
|
r.AppBar.Title = navItem.Name
|
||
|
r.AppBar.SetActions(p.Actions(), p.Overflow())
|
||
|
}
|
||
|
|
||
|
func (r *Router) Layout(gtx layout.Context, th *material.Theme) layout.Dimensions {
|
||
|
for _, event := range r.AppBar.Events(gtx) {
|
||
|
switch event := event.(type) {
|
||
|
case component.AppBarNavigationClicked:
|
||
|
if r.NonModalDrawer {
|
||
|
r.NavAnim.ToggleVisibility(gtx.Now)
|
||
|
} else {
|
||
|
r.ModalNavDrawer.Appear(gtx.Now)
|
||
|
r.NavAnim.Disappear(gtx.Now)
|
||
|
}
|
||
|
case component.AppBarContextMenuDismissed:
|
||
|
log.Printf("Context menu dismissed: %v", event)
|
||
|
case component.AppBarOverflowActionClicked:
|
||
|
log.Printf("Overflow action selected: %v", event)
|
||
|
}
|
||
|
}
|
||
|
if r.ModalNavDrawer.NavDestinationChanged() {
|
||
|
r.SwitchTo(r.ModalNavDrawer.CurrentNavDestination())
|
||
|
}
|
||
|
paint.Fill(gtx.Ops, th.Palette.Bg)
|
||
|
content := layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||
|
return layout.Flex{}.Layout(gtx,
|
||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||
|
gtx.Constraints.Max.X /= 3
|
||
|
return r.NavDrawer.Layout(gtx, th, &r.NavAnim)
|
||
|
}),
|
||
|
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||
|
return r.pages[r.current].Layout(gtx, th)
|
||
|
}),
|
||
|
)
|
||
|
})
|
||
|
bar := layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||
|
return r.AppBar.Layout(gtx, th, "Menu", "Actions")
|
||
|
})
|
||
|
flex := layout.Flex{Axis: layout.Vertical}
|
||
|
if r.BottomBar {
|
||
|
flex.Layout(gtx, content, bar)
|
||
|
} else {
|
||
|
flex.Layout(gtx, bar, content)
|
||
|
}
|
||
|
r.ModalLayer.Layout(gtx, th)
|
||
|
return layout.Dimensions{Size: gtx.Constraints.Max}
|
||
|
}
|