Skip to content

Commit

Permalink
remove NavDrawer as it can hardly be reused; remove OnSelect API of n…
Browse files Browse the repository at this point in the history
…avitem to let implementations handle clicks
  • Loading branch information
oligo committed Nov 14, 2024
1 parent 36dbf8d commit 5950b2c
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 166 deletions.
32 changes: 25 additions & 7 deletions example/basic/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

type HomeView struct {
view.ViewManager
sidebar *navi.NavDrawer
sidebar *NavDrawer
tabbar *navi.Tabbar
currentModal *view.ModalView
}
Expand All @@ -41,7 +41,7 @@ func (hv *HomeView) LayoutMain(gtx C, th *theme.Theme) layout.Dimensions {
}.Layout(gtx,
// navdrawer
layout.Rigid(func(gtx C) D {
return navi.NaviDrawerStyle{
return NaviDrawerStyle{
NavDrawer: hv.sidebar,
Inset: layout.Inset{
Top: unit.Dp(20),
Expand Down Expand Up @@ -109,13 +109,31 @@ func newHome(window *app.Window) *HomeView {

fileChooser, _ = explorer.NewFileChooser(vm)

sidebar := navi.NewNavDrawer(vm)
sidebar.AddSection(navi.SimpleItemSection(viewIcon, "Tabviews & Image", ExampleViewID, false))
sidebar.AddSection(navi.SimpleItemSection(viewIcon, "Editor Example", EditorExampleViewID, false))
sidebar.AddSection(navi.SimpleItemSection(viewIcon, "File Explorer", ExplorerViewID, false))
sidebar := NewNavDrawer(vm)
sidebar.AddSection(SimpleItemSection(viewIcon, "Tabviews & Image", func(item *navi.NavTree) {
sidebar.OnItemSelected(item)
intent := view.Intent{Target: ExampleViewID, ShowAsModal: false}
_ = vm.RequestSwitch(intent)
}))

sidebar.AddSection(SimpleItemSection(viewIcon, "Editor Example", func(item *navi.NavTree) {
sidebar.OnItemSelected(item)
intent := view.Intent{Target: EditorExampleViewID, ShowAsModal: false}
_ = vm.RequestSwitch(intent)
}))

sidebar.AddSection(SimpleItemSection(viewIcon, "File Explorer", func(item *navi.NavTree) {
sidebar.OnItemSelected(item)
intent := view.Intent{Target: ExplorerViewID, ShowAsModal: false}
_ = vm.RequestSwitch(intent)
}))

fileTree, _ := explorer.NewEntryNavItem("../../", nil, nil)
sidebar.AddSection(explorer.NewFileTreeNav(sidebar, "File Explorer", fileTree))
sidebar.AddSection(NewFileTreeNav("File Explorer", fileTree, func(item *navi.NavTree) {
sidebar.OnItemSelected(item)
//intent := view.Intent{Target: EditorExampleViewID, ShowAsModal: false}
//_ = vm.RequestSwitch(intent)
}))

vm.Register(ExampleViewID, func() view.View { return NewExampleView(vm) })
vm.Register(EditorExampleViewID, NewEditorExample)
Expand Down
93 changes: 71 additions & 22 deletions navi/nav_drawer.go → example/basic/navi.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
package navi
package main

import (
"image/color"
"log"
"slices"

"github.com/oligo/gioview/misc"
"github.com/oligo/gioview/theme"
"github.com/oligo/gioview/view"

"gioui.org/font"
"gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
"github.com/oligo/gioview/explorer"
"github.com/oligo/gioview/menu"
"github.com/oligo/gioview/misc"
"github.com/oligo/gioview/navi"
"github.com/oligo/gioview/theme"
"github.com/oligo/gioview/view"
)

type (
C = layout.Context
D = layout.Dimensions
)
type NavSection interface {
Title() string
Layout(gtx C, th *theme.Theme) D
}

type NavDrawer struct {
vm view.ViewManager
selectedItem *NavItemStyle
selectedItem *navi.NavTree
listItems []NavSection
listState *widget.List

Expand All @@ -40,6 +41,20 @@ type NaviDrawerStyle struct {
Width unit.Dp
}

type FileTreeNav struct {
title string
root *navi.NavTree
}

type simpleItemSection struct {
item *navi.NavTree
}

type simpleNavItem struct {
icon *widget.Icon
name string
}

func NewNavDrawer(vm view.ViewManager) *NavDrawer {
return &NavDrawer{
vm: vm,
Expand All @@ -52,13 +67,11 @@ func NewNavDrawer(vm view.ViewManager) *NavDrawer {
}

func (nv *NavDrawer) AddSection(item NavSection) {
item.Attach(nv)
nv.listItems = append(nv.listItems, item)
}

func (nv *NavDrawer) InsertAt(index int, item NavSection) {
nv.listItems = slices.Insert(nv.listItems, index, []NavSection{item}...)
item.Attach(nv)
}

func (nv *NavDrawer) RemoveSection(index int) {
Expand Down Expand Up @@ -103,21 +116,13 @@ func (nv *NavDrawer) Layout(gtx C, th *theme.Theme) D {
})
}

func (nv *NavDrawer) OnItemSelected(gtx C, item *NavItemStyle) {
func (nv *NavDrawer) OnItemSelected(item *navi.NavTree) {
if item != nv.selectedItem {
if nv.selectedItem != nil {
nv.selectedItem.Unselect()
}
nv.selectedItem = item
}

if item != nil {
intent := item.item.OnSelect(gtx)
// An empty also refresh the UI so do not drop it.
if err := nv.vm.RequestSwitch(intent); err != nil {
log.Printf("switching to view %s error: %v", intent.Target, err)
}
}
}

func (ns NaviDrawerStyle) Layout(gtx C, th *theme.Theme) D {
Expand All @@ -144,3 +149,47 @@ func (ns NaviDrawerStyle) Layout(gtx C, th *theme.Theme) D {
})

}

func (item simpleNavItem) Layout(gtx C, th *theme.Theme, textColor color.NRGBA) D {
label := material.Label(th.Theme, th.TextSize, item.name)
label.Color = textColor
return label.Layout(gtx)
}

func (item simpleNavItem) ContextMenuOptions(gtx C) ([][]menu.MenuOption, bool) {
return nil, false
}

func (item simpleNavItem) Children() []navi.NavItem {
return nil
}

func (ss simpleItemSection) Title() string {
return ""
}

func (ss simpleItemSection) Layout(gtx C, th *theme.Theme) D {
return ss.item.Layout(gtx, th)
}

func SimpleItemSection(icon *widget.Icon, name string, onSelect func(item *navi.NavTree)) NavSection {
item := navi.NewNavItem(simpleNavItem{icon: icon, name: name}, onSelect)
return simpleItemSection{item: item}
}

// Construct a FileTreeNav object that loads files and folders from rootDir. The skipFolders
// parameter allows you to specify folder name prefixes to exclude from the navigation.
func NewFileTreeNav(title string, navRoot *explorer.EntryNavItem, onClick func(item *navi.NavTree)) *FileTreeNav {
return &FileTreeNav{
title: title,
root: navi.NewNavItem(navRoot, onClick),
}
}

func (tn *FileTreeNav) Title() string {
return tn.title
}

func (tn *FileTreeNav) Layout(gtx C, th *theme.Theme) D {
return tn.root.Layout(gtx, th)
}
30 changes: 15 additions & 15 deletions example/basic/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,21 @@ func (vw *ExampleView) Layout(gtx layout.Context, th *theme.Theme) layout.Dimens
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),

layout.Rigid(func(gtx layout.Context) layout.Dimensions {

if vw.img == nil {
vw.img = loadImg(vw.vm)
}

//sz := 480
//gtx.Constraints = layout.Exact(image.Pt(sz, sz))
// gtx.Constraints.Max.X = 500
// gtx.Constraints.Min = gtx.Constraints.Max
return gioimg.ImageStyle{
Src: vw.img,
Radius: unit.Dp(12),
Fit: widget.Contain,
Position: layout.N,
}.Layout(gtx)
return D{}
// if vw.img == nil {
// vw.img = loadImg(vw.vm)
// }

// //sz := 480
// //gtx.Constraints = layout.Exact(image.Pt(sz, sz))
// // gtx.Constraints.Max.X = 500
// // gtx.Constraints.Min = gtx.Constraints.Max
// return gioimg.ImageStyle{
// Src: vw.img,
// Radius: unit.Dp(12),
// Fit: widget.Contain,
// Position: layout.N,
// }.Layout(gtx)
}),

layout.Rigid(layout.Spacer{Height: unit.Dp(25)}.Layout),
Expand Down
67 changes: 31 additions & 36 deletions explorer/tree_style.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"slices"
"strings"

"gioui.org/gesture"
"gioui.org/io/clipboard"
"gioui.org/io/event"
"gioui.org/io/key"
Expand All @@ -20,11 +21,12 @@ import (
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
"gioui.org/widget"
"github.com/oligo/gioview/menu"
"github.com/oligo/gioview/misc"
"github.com/oligo/gioview/navi"
"github.com/oligo/gioview/theme"
"github.com/oligo/gioview/view"
gv "github.com/oligo/gioview/widget"
"golang.org/x/exp/shiny/materialdesign/icons"
)
Expand All @@ -40,16 +42,11 @@ var (
fileIcon, _ = widget.NewIcon(icons.ActionDescription)
)

var _ navi.NavSection = (*FileTreeNav)(nil)
var _ navi.NavItem = (*EntryNavItem)(nil)

type FileTreeNav struct {
title string
root *navi.NavItemStyle
}

type EntryNavItem struct {
state *EntryNode
click gesture.Click
menuOptionFunc MenuOptionFunc
onSelectFunc OnSelectFunc

Expand All @@ -62,28 +59,7 @@ type EntryNavItem struct {
}

type MenuOptionFunc func(gtx C, item *EntryNavItem) [][]menu.MenuOption
type OnSelectFunc func(item *EntryNode) view.Intent

// Construct a FileTreeNav object that loads files and folders from rootDir. The skipFolders
// parameter allows you to specify folder name prefixes to exclude from the navigation.
func NewFileTreeNav(drawer *navi.NavDrawer, title string, navRoot *EntryNavItem) *FileTreeNav {
return &FileTreeNav{
title: title,
root: navi.NewNavItem(navRoot, drawer),
}
}

func (tn *FileTreeNav) Attach(drawer *navi.NavDrawer) {
// NOOP
}

func (tn *FileTreeNav) Title() string {
return tn.title
}

func (tn *FileTreeNav) Layout(gtx C, th *theme.Theme) D {
return tn.root.Layout(gtx, th)
}
type OnSelectFunc func(item *EntryNode)

// Construct a file tree object that loads files and folders from rootDir.
// `menuOptionFunc` is used to define the operations allowed by context menu(use right click to active it).
Expand All @@ -104,7 +80,7 @@ func NewEntryNavItem(rootDir string, menuOptionFunc MenuOptionFunc, onSelectFunc

}

func (eitem *EntryNavItem) Icon() *widget.Icon {
func (eitem *EntryNavItem) icon() *widget.Icon {
if eitem.state.Kind() == FolderNode {
if eitem.expaned {
return folderOpenIcon
Expand All @@ -115,18 +91,15 @@ func (eitem *EntryNavItem) Icon() *widget.Icon {
return fileIcon
}

func (eitem *EntryNavItem) OnSelect(gtx C) view.Intent {
func (eitem *EntryNavItem) OnSelect() {
eitem.expaned = !eitem.expaned
if eitem.expaned {
eitem.needSync = true
}

if eitem.state.Kind() == FileNode && eitem.onSelectFunc != nil {
return eitem.onSelectFunc(eitem.state)
eitem.onSelectFunc(eitem.state)
}

return view.Intent{}

}

func (eitem *EntryNavItem) Layout(gtx layout.Context, th *theme.Theme, textColor color.NRGBA) D {
Expand Down Expand Up @@ -159,7 +132,24 @@ func (eitem *EntryNavItem) layout(gtx layout.Context, th *theme.Theme, textColor

eitem.label.Color = textColor
eitem.label.TextSize = th.TextSize
return eitem.label.Layout(gtx, th)

return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D {
if eitem.icon() == nil {
return layout.Dimensions{}
}
return layout.Inset{Right: unit.Dp(6)}.Layout(gtx, func(gtx C) D {
iconColor := th.ContrastBg
return misc.Icon{Icon: eitem.icon(), Color: iconColor, Size: unit.Dp(th.TextSize)}.Layout(gtx, th)
})
}),
layout.Flexed(1, func(gtx C) D {
return layout.W.Layout(gtx, func(gtx C) D {
return eitem.label.Layout(gtx, th)
})
}),
)

}

func (eitem *EntryNavItem) IsDir() bool {
Expand Down Expand Up @@ -334,6 +324,7 @@ func (eitem *EntryNavItem) Update(gtx C) error {
for {
ke, ok := gtx.Event(
// focus conflicts with editable. so subscribe editable's key events here.
pointer.Filter{Target: eitem, Kinds: pointer.Press | pointer.Release},
key.Filter{Focus: eitem.label, Name: "C", Required: key.ModShortcut},
key.Filter{Focus: eitem.label, Name: "V", Required: key.ModShortcut},
key.Filter{Focus: eitem.label, Name: "X", Required: key.ModShortcut},
Expand Down Expand Up @@ -381,6 +372,10 @@ func (eitem *EntryNavItem) Update(gtx C) error {
}
}
}
case pointer.Event:
if event.Buttons.Contain(pointer.ButtonPrimary) && event.Kind == pointer.Press {
eitem.OnSelect()
}

}
}
Expand Down
Loading

0 comments on commit 5950b2c

Please sign in to comment.