PanelContainer: Implement cycling selection
This commit is contained in:
parent
459087e6d8
commit
56b89c6079
8
main.go
8
main.go
@ -295,8 +295,12 @@ func main() {
|
|||||||
|
|
||||||
panelMenu := ui.NewMenu("Panel", 0, &theme)
|
panelMenu := ui.NewMenu("Panel", 0, &theme)
|
||||||
|
|
||||||
panelMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Focus Up", QuickChar: -1, Shortcut: "Alt+Up", Callback: func() {
|
panelMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Focus Next", Shortcut: "Alt+.", Callback: func() {
|
||||||
|
panelContainer.SelectNext()
|
||||||
|
}}, &ui.ItemEntry{Name: "Focus Prev", Shortcut: "Alt+,", Callback: func() {
|
||||||
|
panelContainer.SelectPrev()
|
||||||
|
}}, &ui.ItemEntry{Name: "Focus Up", QuickChar: -1, Shortcut: "Alt+Up", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Focus Down", QuickChar: -1, Shortcut: "Alt+Down", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Focus Down", QuickChar: -1, Shortcut: "Alt+Down", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Focus Left", QuickChar: -1, Shortcut: "Alt+Left", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Focus Left", QuickChar: -1, Shortcut: "Alt+Left", Callback: func() {
|
||||||
|
35
ui/panel.go
35
ui/panel.go
@ -69,27 +69,42 @@ func (p *Panel) UpdateSplits() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Same as EachLeaf, but returns true if any call to `f` returned true.
|
// Same as EachLeaf, but returns true if any call to `f` returned true.
|
||||||
func (p *Panel) eachLeaf(f func(*Component) bool) bool {
|
func (p *Panel) eachLeaf(rightMost bool, f func(*Panel) bool) bool {
|
||||||
switch p.Kind {
|
switch p.Kind {
|
||||||
|
case PanelKindEmpty:
|
||||||
|
fallthrough
|
||||||
case PanelKindSingle:
|
case PanelKindSingle:
|
||||||
return f(&p.Left)
|
return f(p)
|
||||||
|
|
||||||
case PanelKindSplitVert:
|
case PanelKindSplitVert:
|
||||||
fallthrough
|
fallthrough
|
||||||
case PanelKindSplitHor:
|
case PanelKindSplitHor:
|
||||||
if p.Left.(*Panel).eachLeaf(f) {
|
if rightMost {
|
||||||
return true
|
if p.Right.(*Panel).eachLeaf(rightMost, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return p.Left.(*Panel).eachLeaf(rightMost, f)
|
||||||
|
} else {
|
||||||
|
if p.Left.(*Panel).eachLeaf(rightMost, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return p.Right.(*Panel).eachLeaf(rightMost, f)
|
||||||
}
|
}
|
||||||
return p.Right.(*Panel).eachLeaf(f)
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EachLeaf visits the entire tree in left-most order, and calls function `f`
|
// EachLeaf visits the entire tree, and calls function `f` at each leaf Panel.
|
||||||
// at each individual Component (never for Panels). If the function `f` returns
|
// If the function `f` returns true, then visiting stops. if `rtl` is true,
|
||||||
// true, then visiting stops.
|
// the tree is traversed in right-most order. The default is to traverse
|
||||||
func (p *Panel) EachLeaf(f func(*Component) bool) {
|
// in left-most order.
|
||||||
p.eachLeaf(f)
|
//
|
||||||
|
// The caller of this function can safely assert that Panel's Kind is always
|
||||||
|
// either `PanelKindSingle` or `PanelKindEmpty`.
|
||||||
|
func (p *Panel) EachLeaf(rightMost bool, f func(*Panel) bool) {
|
||||||
|
p.eachLeaf(rightMost, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLeaf returns whether the Panel is a leaf or not. A leaf is a panel with
|
// IsLeaf returns whether the Panel is a leaf or not. A leaf is a panel with
|
||||||
|
@ -266,6 +266,36 @@ func (c *PanelContainer) UnfloatSelected(kind SplitKind) bool {
|
|||||||
return c.SetFloatingFocused(true)
|
return c.SetFloatingFocused(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *PanelContainer) selectNext(rightMost bool) {
|
||||||
|
var nextIsIt bool
|
||||||
|
c.root.EachLeaf(rightMost, func(p *Panel) bool {
|
||||||
|
if nextIsIt {
|
||||||
|
c.selected = &p
|
||||||
|
nextIsIt = false
|
||||||
|
return true
|
||||||
|
} else if p == *c.selected {
|
||||||
|
nextIsIt = true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
// This boolean must be false if we found the next leaf.
|
||||||
|
// Therefore, if it is true, c.selected was the last leaf
|
||||||
|
// of the tree. We need to wrap around to the first leaf.
|
||||||
|
if nextIsIt {
|
||||||
|
// This gets the first leaf in left-most or right-most order
|
||||||
|
c.root.EachLeaf(rightMost, func(p *Panel) bool { c.selected = &p; return true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PanelContainer) SelectNext() {
|
||||||
|
c.selectNext(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PanelContainer) SelectPrev() {
|
||||||
|
c.selectNext(true)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *PanelContainer) Draw(s tcell.Screen) {
|
func (c *PanelContainer) Draw(s tcell.Screen) {
|
||||||
c.root.Draw(s)
|
c.root.Draw(s)
|
||||||
for i := len(c.floating)-1; i >= 0; i-- {
|
for i := len(c.floating)-1; i >= 0; i-- {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user