diff --git a/keys.go b/keys.go index 477a4f8..2127cc2 100644 --- a/keys.go +++ b/keys.go @@ -12,22 +12,6 @@ type Binding struct { Handler func(g *gocui.Gui, v *gocui.View) error } -var bindings = [...]Binding{ - Binding{gocui.KeyCtrlC, gocui.ModNone, quit}, - Binding{gocui.KeyArrowUp, gocui.ModNone, HandlerCursorDispenser(-1)}, - Binding{gocui.KeyArrowDown, gocui.ModNone, HandlerCursorDispenser(1)}, -} - -func keybindings(g *gocui.Gui) error { - for _, b := range bindings { - // 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 -} - func HandlerCursorDispenser(mod int) func(g *gocui.Gui, v *gocui.View) error { return func(g *gocui.Gui, v *gocui.View) error { if v == nil { diff --git a/main.go b/main.go index 67e28f5..d628bb0 100644 --- a/main.go +++ b/main.go @@ -28,15 +28,48 @@ func main() { } defer g.Close() + views := []*View{ + &View{ + Name: "main", + Title: "Peers", + Placeholder: "Loading peers...", + Cursor: true, + Highlight: true, + Current: true, + SelFgColor: gocui.ColorBlack, + SelBgColor: gocui.ColorGreen, + Keybindings: []Binding{ + Binding{gocui.KeyCtrlC, gocui.ModNone, quit}, + Binding{gocui.KeyArrowUp, gocui.ModNone, HandlerCursorDispenser(-1)}, + Binding{gocui.KeyArrowDown, gocui.ModNone, HandlerCursorDispenser(1)}, + }, + TopLeft: func(mx, my int) (int, int) { + return 0, 0 + }, + BotRight: func(mx, my int) (int, int) { + return mx - 1, my / 2 + }, + }, + &View{ + Name: "info", + Title: "Details", + Placeholder: "Loading details...", + TopLeft: func(mx, my int) (int, int) { + return 0, my/2 + 1 + }, + BotRight: func(mx, my int) (int, int) { + return mx - 1, my - 1 + }, + }, + } + + vm := NewViewManager(g, views) + g.SelFgColor = gocui.ColorGreen g.Highlight = true g.Cursor = true - g.SetManagerFunc(layout) - - if err := keybindings(g); err != nil { - log.Panicln(err) - } + g.SetManagerFunc(vm.Layout) url := fmt.Sprintf("http://%s:%d", host, port) c, err := newClient(url) @@ -52,30 +85,6 @@ func main() { } } -func layout(g *gocui.Gui) error { - maxX, maxY := g.Size() - if v, err := g.SetView("main", 0, 0, maxX-1, maxY/2); err != nil { - if err != gocui.ErrUnknownView { - return err - } - v.SelFgColor = gocui.ColorBlack - v.SelBgColor = gocui.ColorGreen - v.Title = "Peers" - v.Highlight = true - v.SetCursor(0, 0) - g.SetCurrentView("main") - fmt.Fprintln(v, "Loading peers...") - } - if v, err := g.SetView("info", 0, maxY/2+1, maxX-1, maxY-1); err != nil { - if err != gocui.ErrUnknownView { - return err - } - v.Title = "Details" - fmt.Fprintln(v, "Loading details...") - } - return nil -} - func quit(g *gocui.Gui, v *gocui.View) error { close(threadDone) return gocui.ErrQuit diff --git a/view.go b/view.go new file mode 100644 index 0000000..30b8f5c --- /dev/null +++ b/view.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + + "github.com/jroimartin/gocui" +) + +type View struct { + Name string + Title string + Placeholder string + Cursor bool + Current bool + Highlight bool + TopLeft func(int, int) (int, int) + BotRight func(int, int) (int, int) + SelBgColor gocui.Attribute + SelFgColor gocui.Attribute + Keybindings []Binding + Manager ViewManager +} + +type ViewManager struct { + g *gocui.Gui + views []*View +} + +func NewViewManager(g *gocui.Gui, views []*View) *ViewManager { + vm := ViewManager{ + g: g, + views: views, + } + // Attach a ViewManager instance to Views + for _, v := range vm.views { + v.Manager = vm + } + return &vm +} + +func (m *ViewManager) Layout(g *gocui.Gui) error { + mx, my := g.Size() + + for _, cfg := range m.views { + x0, y0 := cfg.TopLeft(mx, my) + x1, y1 := cfg.BotRight(mx, my) + + v, err := g.SetView(cfg.Name, x0, y0, x1, y1) + if err == nil && err != gocui.ErrUnknownView { + return err + } + v.SelFgColor = cfg.SelFgColor + v.SelBgColor = cfg.SelBgColor + v.Title = cfg.Title + v.Highlight = cfg.Highlight + + if cfg.Cursor { + v.SetCursor(0, 0) + } + if cfg.Current { + g.SetCurrentView("main") + } + fmt.Fprintln(v, cfg.Placeholder) + cfg.SetKeybindings(g) + } + return nil +} + +func (v *View) SetKeybindings(g *gocui.Gui) error { + 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 +}