172 lines
4.0 KiB
Go
172 lines
4.0 KiB
Go
package pages
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"sync"
|
|
"time"
|
|
|
|
"gioui.org/layout"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/widget"
|
|
"gioui.org/widget/material"
|
|
"gioui.org/x/component"
|
|
"github.com/bedrock-tool/bedrocktool/ui/messages"
|
|
"github.com/bedrock-tool/bedrocktool/utils"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type HandlerFunc = func(data interface{}) messages.MessageResponse
|
|
|
|
type Page interface {
|
|
Actions() []component.AppBarAction
|
|
Overflow() []component.OverflowAction
|
|
Layout(gtx layout.Context, th *material.Theme) layout.Dimensions
|
|
NavItem() component.NavItem
|
|
|
|
// handle events from program
|
|
Handler(data any) messages.MessageResponse
|
|
}
|
|
|
|
type Router struct {
|
|
Ctx context.Context
|
|
Wg sync.WaitGroup
|
|
Invalidate func()
|
|
|
|
Theme *material.Theme
|
|
|
|
pages map[string]Page
|
|
current string
|
|
*component.ModalNavDrawer
|
|
NavAnim component.VisibilityAnimation
|
|
*component.AppBar
|
|
*component.ModalLayer
|
|
NonModalDrawer, BottomBar bool
|
|
|
|
UpdateButton *widget.Clickable
|
|
}
|
|
|
|
func NewRouter(ctx context.Context, invalidate func(), th *material.Theme) 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{
|
|
Ctx: ctx,
|
|
Invalidate: invalidate,
|
|
Theme: th,
|
|
pages: make(map[string]Page),
|
|
ModalLayer: modal,
|
|
ModalNavDrawer: modalNav,
|
|
AppBar: bar,
|
|
NavAnim: na,
|
|
|
|
UpdateButton: &widget.Clickable{},
|
|
}
|
|
}
|
|
|
|
func (r *Router) Register(tag string, p Page) {
|
|
r.pages[tag] = p
|
|
navItem := p.NavItem()
|
|
navItem.Tag = tag
|
|
if r.current == "" {
|
|
r.current = tag
|
|
r.AppBar.Title = navItem.Name
|
|
r.AppBar.SetActions(p.Actions(), p.Overflow())
|
|
}
|
|
r.ModalNavDrawer.AddNavItem(navItem)
|
|
}
|
|
|
|
func (r *Router) SwitchTo(tag string) {
|
|
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 {
|
|
if r.UpdateButton.Clicked() {
|
|
r.SwitchTo("update")
|
|
}
|
|
|
|
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().(string))
|
|
}
|
|
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}
|
|
}
|
|
|
|
func (r *Router) Handler(data interface{}) messages.MessageResponse {
|
|
page, ok := r.pages[r.current]
|
|
if ok {
|
|
return page.Handler(data)
|
|
}
|
|
return messages.MessageResponse{}
|
|
}
|
|
|
|
func (r *Router) Execute(cmd utils.Command) {
|
|
r.Wg.Add(1)
|
|
go func() {
|
|
defer r.Wg.Done()
|
|
|
|
err := cmd.Execute(r.Ctx, utils.CurrentUI)
|
|
if err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
var Pages = map[string]func(*Router) Page{}
|
|
|
|
func Register(name string, fun func(*Router) Page) {
|
|
Pages[name] = fun
|
|
}
|