refact app view

mine
derailed 2019-06-21 23:08:50 -06:00
parent 8515f70fbf
commit 1ffb11dbd6
4 changed files with 119 additions and 106 deletions

View File

@ -50,7 +50,6 @@ type (
appView struct {
*shellView
cmdBuff *cmdBuff
command *command
cancel context.CancelFunc
informer *watch.Informer
@ -63,19 +62,13 @@ type (
func NewApp(cfg *config.Config) *appView {
v := appView{
shellView: newShellView(),
cmdBuff: newCmdBuff(':'),
forwarders: make(map[string]forwarder),
}
v.config = cfg
v.initBench(cfg.K9s.CurrentCluster)
v.refreshStyles()
v.command = newCommand(&v)
v.views["menu"] = newMenuView(v.styles)
v.views["logo"] = newLogoView(v.styles)
v.views["cmd"] = newCmdView(v.styles, '🐶')
v.views["flash"] = newFlashView(&v, "Initializing...")
v.views["crumbs"] = newCrumbsView(v.styles)
v.views["clusterInfo"] = newClusterInfoView(&v, k8s.NewMetricsServer(cfg.GetConnection()))
v.actions = keyActions{
@ -180,10 +173,6 @@ func (a *appView) stopForwarders() {
}
}
func (a *appView) conn() k8s.Connection {
return a.config.GetConnection()
}
// Run starts the application loop
func (a *appView) Run() {
ctx, cancel := context.WithCancel(context.Background())
@ -210,14 +199,8 @@ func (a *appView) Run() {
}
}
func (a *appView) statusReset() {
a.logo().reset()
a.Draw()
}
func (a *appView) status(l flashLevel, msg string) {
a.flash().info(msg)
switch l {
case flashErr:
a.logo().err(msg)
@ -231,47 +214,6 @@ func (a *appView) status(l flashLevel, msg string) {
a.Draw()
}
func (a *appView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
key := evt.Key()
if key == tcell.KeyRune {
if a.cmdBuff.isActive() && evt.Modifiers() == tcell.ModNone {
a.cmdBuff.add(evt.Rune())
return nil
}
key = tcell.Key(evt.Rune())
if evt.Modifiers() == tcell.ModAlt {
key = tcell.Key(int16(evt.Rune()) * int16(evt.Modifiers()))
}
}
if a, ok := a.actions[key]; ok {
log.Debug().Msgf(">> AppView handled key: %s", tcell.KeyNames[key])
return a.action(evt)
}
return evt
}
func (a *appView) redrawCmd(evt *tcell.EventKey) *tcell.EventKey {
a.Draw()
return evt
}
func (a *appView) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
if a.cmdBuff.isActive() {
a.cmdBuff.del()
return nil
}
return evt
}
func (a *appView) escapeCmd(evt *tcell.EventKey) *tcell.EventKey {
if a.cmdBuff.isActive() {
a.cmdBuff.reset()
}
return evt
}
func (a *appView) prevCmd(evt *tcell.EventKey) *tcell.EventKey {
if top, ok := a.command.previousCmd(); ok {
log.Debug().Msgf("Previous command %s", top)
@ -298,6 +240,7 @@ func (a *appView) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
a.flash().info("Command mode activated.")
a.cmdBuff.setActive(true)
a.cmdBuff.clear()
return nil
}
@ -318,10 +261,6 @@ func (a *appView) helpCmd(evt *tcell.EventKey) *tcell.EventKey {
return nil
}
func (a *appView) currentView() igniter {
return a.content.GetPrimitive("main").(igniter)
}
func (a *appView) aliasCmd(evt *tcell.EventKey) *tcell.EventKey {
if a.inCmdMode() {
return evt
@ -360,29 +299,3 @@ func (a *appView) inject(i igniter) {
func (a *appView) inCmdMode() bool {
return a.cmd().inCmdMode()
}
func (a *appView) setHints(h hints) {
a.views["menu"].(*menuView).populateMenu(h)
}
// View Accessors...
func (a *appView) crumbs() *crumbsView {
return a.views["crumbs"].(*crumbsView)
}
func (a *appView) logo() *logoView {
return a.views["logo"].(*logoView)
}
func (a *appView) clusterInfo() *clusterInfoView {
return a.views["clusterInfo"].(*clusterInfoView)
}
func (a *appView) flash() *flashView {
return a.views["flash"].(*flashView)
}
func (a *appView) cmd() *cmdView {
return a.views["cmd"].(*cmdView)
}

View File

@ -18,6 +18,7 @@ type resTable struct {
currentNS string
data resource.TableData
actions keyActions
colorerFn colorerFn
}
func newResTable(app *appView, title string) *resTable {
@ -45,6 +46,24 @@ func newResTable(app *appView, title string) *resTable {
return &v
}
func (v *resTable) buildRow(row int, data resource.TableData, sk string, pads maxyPad) {
f := v.colorerFn
if f == nil {
f = defaultColorer
}
for col, field := range data.Rows[sk].Fields {
header := data.Header[col]
field, align := v.formatCell(data.NumCols[header], header, field+deltas(data.Rows[sk].Deltas[col], field), pads[col])
c := tview.NewTableCell(field)
{
c.SetExpansion(1)
c.SetAlign(align)
c.SetTextColor(f(data.Namespace, data.Rows[sk]))
}
v.SetCell(row, col, c)
}
}
func (v *resTable) formatCell(numerical bool, header, field string, padding int) (string, int) {
if header == "AGE" {
dur, err := time.ParseDuration(field)

View File

@ -1,8 +1,10 @@
package views
import (
"github.com/derailed/k9s/internal/k8s"
"github.com/derailed/tview"
"github.com/gdamore/tcell"
"github.com/rs/zerolog/log"
)
type (
@ -20,15 +22,109 @@ type (
pages *tview.Pages
content *tview.Pages
views map[string]tview.Primitive
cmdBuff *cmdBuff
}
)
func newShellView() *shellView {
return &shellView{
s := shellView{
Application: tview.NewApplication(),
actions: make(keyActions),
pages: tview.NewPages(),
content: tview.NewPages(),
views: make(map[string]tview.Primitive),
cmdBuff: newCmdBuff(':'),
}
s.refreshStyles()
s.views["menu"] = newMenuView(s.styles)
s.views["logo"] = newLogoView(s.styles)
s.views["cmd"] = newCmdView(s.styles, '🐶')
s.views["crumbs"] = newCrumbsView(s.styles)
return &s
}
func (s *shellView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
key := evt.Key()
if key == tcell.KeyRune {
if s.cmdBuff.isActive() && evt.Modifiers() == tcell.ModNone {
s.cmdBuff.add(evt.Rune())
return nil
}
key = tcell.Key(evt.Rune())
if evt.Modifiers() == tcell.ModAlt {
key = tcell.Key(int16(evt.Rune()) * int16(evt.Modifiers()))
}
}
if a, ok := s.actions[key]; ok {
log.Debug().Msgf(">> AppView handled key: %s", tcell.KeyNames[key])
return a.action(evt)
}
return evt
}
func (s *shellView) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
if s.cmdBuff.isActive() {
s.cmdBuff.del()
return nil
}
return evt
}
func (s *shellView) escapeCmd(evt *tcell.EventKey) *tcell.EventKey {
if s.cmdBuff.isActive() {
s.cmdBuff.reset()
}
return evt
}
func (s *shellView) conn() k8s.Connection {
return s.config.GetConnection()
}
func (s *shellView) init() {
}
func (s *shellView) redrawCmd(evt *tcell.EventKey) *tcell.EventKey {
s.Draw()
return evt
}
func (s *shellView) currentView() igniter {
return s.content.GetPrimitive("main").(igniter)
}
func (s *shellView) setHints(h hints) {
s.views["menu"].(*menuView).populateMenu(h)
}
func (s *shellView) statusReset() {
s.logo().reset()
s.Draw()
}
// View Accessors...
func (s *shellView) crumbs() *crumbsView {
return s.views["crumbs"].(*crumbsView)
}
func (s *shellView) logo() *logoView {
return s.views["logo"].(*logoView)
}
func (s *appView) clusterInfo() *clusterInfoView {
return s.views["clusterInfo"].(*clusterInfoView)
}
func (s *appView) flash() *flashView {
return s.views["flash"].(*flashView)
}
func (s *appView) cmd() *cmdView {
return s.views["cmd"].(*cmdView)
}

View File

@ -17,11 +17,10 @@ type tableView struct {
*resTable
cmdBuff *cmdBuff
colorerFn colorerFn
sortCol sortColumn
sortFn sortFn
cleanseFn cleanseFn
filterFn func(string)
sortCol sortColumn
}
func newTableView(app *appView, title string) *tableView {
@ -249,23 +248,9 @@ func (v *tableView) sort(data resource.TableData, row int) {
sortFn = v.sortFn
}
prim, sec := sortAllRows(v.sortCol, data.Rows, sortFn)
fgColor := config.AsColor(v.app.styles.Table().FgColor)
for _, pk := range prim {
for _, sk := range sec[pk] {
if v.colorerFn != nil {
fgColor = v.colorerFn(data.Namespace, data.Rows[sk])
}
for col, field := range data.Rows[sk].Fields {
header := data.Header[col]
field, align := v.formatCell(data.NumCols[header], header, field+deltas(data.Rows[sk].Deltas[col], field), pads[col])
c := tview.NewTableCell(field)
{
c.SetExpansion(1)
c.SetAlign(align)
c.SetTextColor(fgColor)
}
v.SetCell(row, col, c)
}
v.buildRow(row, data, sk, pads)
row++
}
}