Add basic terminal user interface
This commit is contained in:
parent
bf4e19378d
commit
5956331a28
9 changed files with 878 additions and 0 deletions
163
tui/tabs.go
Normal file
163
tui/tabs.go
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
type TabPrimitive interface {
|
||||
tview.Primitive
|
||||
ForceRedraw()
|
||||
}
|
||||
|
||||
type Tabs struct {
|
||||
*tview.Flex
|
||||
|
||||
names []string
|
||||
items map[string]tview.Primitive
|
||||
selector *tview.TextView
|
||||
pages *tview.Pages
|
||||
fallover bool
|
||||
unlock bool
|
||||
}
|
||||
|
||||
func NewTabs(selectorAtTop bool) *Tabs {
|
||||
widget := &Tabs{
|
||||
Flex: tview.NewFlex(),
|
||||
names: []string{},
|
||||
items: make(map[string]tview.Primitive),
|
||||
fallover: true,
|
||||
}
|
||||
widget.SetDirection(tview.FlexRow)
|
||||
|
||||
// Selector
|
||||
widget.selector = tview.NewTextView().
|
||||
SetDynamicColors(true).
|
||||
SetRegions(true).
|
||||
SetWrap(false).
|
||||
SetTextAlign(tview.AlignLeft)
|
||||
widget.selector.SetHighlightedFunc(
|
||||
func(added, removed, remaining []string) {
|
||||
if len(added) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
widget.pages.SwitchToPage(added[0])
|
||||
},
|
||||
)
|
||||
if selectorAtTop {
|
||||
widget.AddItem(widget.selector, 1, 0, false)
|
||||
}
|
||||
|
||||
// Pages
|
||||
widget.pages = tview.NewPages()
|
||||
widget.AddItem(widget.pages, 0, 1, false)
|
||||
|
||||
if !selectorAtTop {
|
||||
widget.AddItem(widget.selector, 1, 0, false)
|
||||
}
|
||||
|
||||
return widget
|
||||
}
|
||||
|
||||
func (widget *Tabs) AllowFallover(allow bool) {
|
||||
widget.fallover = allow
|
||||
}
|
||||
|
||||
func (widget *Tabs) AddText(text string) {
|
||||
fmt.Fprint(widget.selector, text)
|
||||
}
|
||||
|
||||
func (widget *Tabs) AddTab(name string, label string, item tview.Primitive, visible bool) {
|
||||
widget.names = append(widget.names, name)
|
||||
widget.items[name] = item
|
||||
fmt.Fprintf(widget.selector, `["%s"][darkcyan]%s[white][""] `, name, label)
|
||||
widget.pages.AddPage(name, item, true, false)
|
||||
if visible {
|
||||
widget.Select(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Tabs) Select(name string) {
|
||||
widget.selector.Highlight(name)
|
||||
}
|
||||
|
||||
func (widget *Tabs) Next() tview.Primitive {
|
||||
widget.unlock = true
|
||||
if len(widget.names) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
index := -1
|
||||
highlights := widget.selector.GetHighlights()
|
||||
if len(highlights) > 0 {
|
||||
currentName := highlights[0]
|
||||
for currentIndex, name := range widget.names {
|
||||
if name == currentName {
|
||||
index = currentIndex
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index++
|
||||
if index >= len(widget.names) {
|
||||
if widget.fallover {
|
||||
index = 0
|
||||
} else {
|
||||
index = len(widget.names) - 1
|
||||
}
|
||||
}
|
||||
|
||||
widget.selector.Highlight(widget.names[index])
|
||||
|
||||
return widget.items[widget.names[index]]
|
||||
}
|
||||
|
||||
func (widget *Tabs) Prev() tview.Primitive {
|
||||
widget.unlock = true
|
||||
if len(widget.names) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
index := len(widget.names)
|
||||
highlights := widget.selector.GetHighlights()
|
||||
if len(highlights) > 0 {
|
||||
currentName := highlights[0]
|
||||
for currentIndex, name := range widget.names {
|
||||
if name == currentName {
|
||||
index = currentIndex
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index--
|
||||
if index < 0 {
|
||||
if widget.fallover {
|
||||
index = len(widget.names) - 1
|
||||
} else {
|
||||
index = 0
|
||||
}
|
||||
}
|
||||
|
||||
widget.selector.Highlight(widget.names[index])
|
||||
|
||||
return widget.items[widget.names[index]]
|
||||
}
|
||||
|
||||
func (widget *Tabs) Focus(delegate func(p tview.Primitive)) {
|
||||
delegate(widget.pages)
|
||||
}
|
||||
|
||||
func (widget *Tabs) Draw(screen tcell.Screen) {
|
||||
if widget.unlock {
|
||||
widgetX, widgetY, widgetWidth, widgetHeight := widget.GetInnerRect()
|
||||
screen.LockRegion(widgetX, widgetY, widgetWidth, widgetHeight, false)
|
||||
widget.unlock = false
|
||||
}
|
||||
|
||||
widget.Flex.Draw(screen)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue