2019-06-26 21:40:31 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-06-27 12:24:01 +00:00
|
|
|
"log"
|
2019-06-26 21:40:31 +00:00
|
|
|
|
|
|
|
"github.com/jroimartin/gocui"
|
|
|
|
)
|
|
|
|
|
2019-06-28 20:25:56 +00:00
|
|
|
// Struct for more succint definitions of key bindings
|
|
|
|
type Binding struct {
|
|
|
|
Key interface{} // so both gocui.Key and rune work
|
|
|
|
Mod gocui.Modifier
|
|
|
|
Handler func(g *gocui.Gui, v *gocui.View) error
|
|
|
|
}
|
|
|
|
|
2019-06-27 19:50:10 +00:00
|
|
|
// Default Gocui views arent granular enough
|
|
|
|
// so I'm adding a custom one to have more control.
|
2019-06-26 23:54:04 +00:00
|
|
|
type ViewController struct {
|
2019-06-26 21:40:31 +00:00
|
|
|
Name string
|
|
|
|
Title string
|
|
|
|
Placeholder string
|
2019-06-27 05:36:07 +00:00
|
|
|
Enabled bool
|
2019-06-27 02:48:21 +00:00
|
|
|
Wrap bool
|
2019-06-26 21:40:31 +00:00
|
|
|
Cursor bool
|
|
|
|
Current bool
|
|
|
|
Highlight bool
|
2019-06-27 05:36:07 +00:00
|
|
|
OnTop bool
|
2019-06-26 21:40:31 +00:00
|
|
|
TopLeft func(int, int) (int, int)
|
|
|
|
BotRight func(int, int) (int, int)
|
|
|
|
SelBgColor gocui.Attribute
|
|
|
|
SelFgColor gocui.Attribute
|
|
|
|
Keybindings []Binding
|
2019-06-27 19:50:10 +00:00
|
|
|
// Extra field for view state. Might need different name.
|
2019-06-27 18:21:51 +00:00
|
|
|
State *State
|
2019-06-26 21:40:31 +00:00
|
|
|
}
|
|
|
|
|
2019-06-27 19:50:10 +00:00
|
|
|
// To combine all existing views into one
|
2019-06-26 21:40:31 +00:00
|
|
|
type ViewManager struct {
|
|
|
|
g *gocui.Gui
|
2019-06-26 23:54:04 +00:00
|
|
|
views []*ViewController
|
2019-06-26 21:40:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *ViewManager) Layout(g *gocui.Gui) error {
|
|
|
|
mx, my := g.Size()
|
|
|
|
|
|
|
|
for _, cfg := range m.views {
|
2019-06-27 05:36:07 +00:00
|
|
|
if !cfg.Enabled {
|
|
|
|
continue
|
|
|
|
}
|
2019-06-26 21:40:31 +00:00
|
|
|
x0, y0 := cfg.TopLeft(mx, my)
|
|
|
|
x1, y1 := cfg.BotRight(mx, my)
|
|
|
|
|
|
|
|
v, err := g.SetView(cfg.Name, x0, y0, x1, y1)
|
2019-06-27 13:14:28 +00:00
|
|
|
|
2019-06-27 12:46:51 +00:00
|
|
|
// Some settings can be set only once
|
|
|
|
if err == gocui.ErrUnknownView {
|
|
|
|
cfg.SetKeybindings(g)
|
|
|
|
if cfg.Cursor {
|
|
|
|
v.SetCursor(0, 0)
|
|
|
|
}
|
|
|
|
if cfg.Placeholder != "" {
|
|
|
|
fmt.Fprintln(v, cfg.Placeholder)
|
|
|
|
}
|
|
|
|
} else if err != nil {
|
2019-06-27 12:24:01 +00:00
|
|
|
log.Panicln(err)
|
2019-06-26 21:40:31 +00:00
|
|
|
}
|
2019-06-27 13:14:28 +00:00
|
|
|
|
2019-06-27 02:48:21 +00:00
|
|
|
v.Title = cfg.Title
|
|
|
|
v.Wrap = cfg.Wrap
|
2019-06-26 21:40:31 +00:00
|
|
|
v.SelFgColor = cfg.SelFgColor
|
|
|
|
v.SelBgColor = cfg.SelBgColor
|
|
|
|
v.Highlight = cfg.Highlight
|
|
|
|
|
|
|
|
if cfg.Current {
|
2019-06-27 05:36:07 +00:00
|
|
|
g.SetCurrentView(cfg.Name)
|
|
|
|
}
|
|
|
|
if cfg.OnTop {
|
|
|
|
g.SetViewOnTop(cfg.Name)
|
2019-06-26 21:40:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-06-26 23:54:04 +00:00
|
|
|
func (v *ViewController) SetKeybindings(g *gocui.Gui) error {
|
2019-06-26 21:40:31 +00:00
|
|
|
for _, b := range v.Keybindings {
|
|
|
|
// IDEA: I can pass a method instead of a function here
|
|
|
|
if err := g.SetKeybinding("", b.Key, b.Mod, b.Handler); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2019-06-28 20:25:56 +00:00
|
|
|
|
|
|
|
func (vc *ViewController) CursorUp(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
// TODO propper error handling?
|
|
|
|
vc.State.SetCurrent(vc.State.GetState().Current - 1)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (vc *ViewController) CursorDown(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
// TODO propper error handling?
|
|
|
|
vc.State.SetCurrent(vc.State.GetState().Current + 1)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (vc *ViewController) HandleDelete(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
currentPeer := vc.State.GetCurrent()
|
|
|
|
err := vc.State.Remove(currentPeer)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|