2016-12-22 16:15:22 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2016-12-27 02:24:02 +00:00
|
|
|
"fmt"
|
2016-12-22 16:15:22 +00:00
|
|
|
"sort"
|
|
|
|
|
|
|
|
ui "github.com/gizak/termui"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Grid struct {
|
2016-12-26 18:39:15 +00:00
|
|
|
cursorPos uint
|
2016-12-22 16:15:22 +00:00
|
|
|
containers map[string]*Container
|
|
|
|
}
|
|
|
|
|
2016-12-27 15:32:45 +00:00
|
|
|
func (g *Grid) AddContainer(id, names string) {
|
2016-12-27 02:24:02 +00:00
|
|
|
g.containers[id] = NewContainer(id, names)
|
2016-12-22 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2016-12-26 18:39:15 +00:00
|
|
|
// Return number of containers/rows
|
|
|
|
func (g *Grid) Len() uint {
|
|
|
|
return uint(len(g.containers))
|
|
|
|
}
|
|
|
|
|
2016-12-22 16:15:22 +00:00
|
|
|
// Return sorted list of active container IDs
|
|
|
|
func (g *Grid) CIDs() []string {
|
|
|
|
var ids []string
|
|
|
|
for id, _ := range g.containers {
|
|
|
|
ids = append(ids, id)
|
|
|
|
}
|
|
|
|
sort.Strings(ids)
|
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
2016-12-26 18:39:15 +00:00
|
|
|
// Redraw the cursor with the currently selected row
|
|
|
|
func (g *Grid) Cursor() {
|
|
|
|
for n, id := range g.CIDs() {
|
|
|
|
c := g.containers[id]
|
|
|
|
if uint(n) == g.cursorPos {
|
|
|
|
c.widgets.cid.TextFgColor = ui.ColorDefault
|
|
|
|
c.widgets.cid.TextBgColor = ui.ColorWhite
|
|
|
|
} else {
|
|
|
|
c.widgets.cid.TextFgColor = ui.ColorWhite
|
|
|
|
c.widgets.cid.TextBgColor = ui.ColorDefault
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ui.Render(ui.Body)
|
|
|
|
}
|
|
|
|
|
2016-12-22 16:15:22 +00:00
|
|
|
func (g *Grid) Rows() (rows []*ui.Row) {
|
|
|
|
for _, cid := range g.CIDs() {
|
|
|
|
c := g.containers[cid]
|
2016-12-27 02:24:02 +00:00
|
|
|
rows = append(rows, c.widgets.MakeRow())
|
2016-12-22 16:15:22 +00:00
|
|
|
}
|
|
|
|
return rows
|
|
|
|
}
|
|
|
|
|
|
|
|
func header() *ui.Row {
|
|
|
|
return ui.NewRow(
|
2016-12-27 02:24:02 +00:00
|
|
|
ui.NewCol(1, 0, headerPar("CID")),
|
|
|
|
ui.NewCol(2, 0, headerPar("CPU")),
|
|
|
|
ui.NewCol(2, 0, headerPar("MEM")),
|
|
|
|
ui.NewCol(2, 0, headerPar("NET RX/TX")),
|
2016-12-27 15:32:45 +00:00
|
|
|
ui.NewCol(2, 0, headerPar("NAME")),
|
2016-12-22 16:15:22 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2016-12-27 02:24:02 +00:00
|
|
|
func headerPar(s string) *ui.Par {
|
|
|
|
p := ui.NewPar(fmt.Sprintf(" %s", s))
|
|
|
|
p.Border = false
|
|
|
|
p.Height = 2
|
|
|
|
p.Width = 20
|
|
|
|
p.TextFgColor = ui.ColorWhite
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2016-12-22 22:04:21 +00:00
|
|
|
func Display(g *Grid) {
|
2016-12-22 16:15:22 +00:00
|
|
|
if err := ui.Init(); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer ui.Close()
|
|
|
|
|
|
|
|
// build layout
|
2016-12-22 22:04:21 +00:00
|
|
|
ui.Body.AddRows(header())
|
2016-12-22 16:15:22 +00:00
|
|
|
|
|
|
|
for _, row := range g.Rows() {
|
|
|
|
ui.Body.AddRows(row)
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate layout
|
|
|
|
ui.Body.Align()
|
2016-12-26 18:39:15 +00:00
|
|
|
g.Cursor()
|
2016-12-22 16:15:22 +00:00
|
|
|
ui.Render(ui.Body)
|
|
|
|
|
2016-12-26 18:39:15 +00:00
|
|
|
ui.Handle("/sys/kbd/<up>", func(ui.Event) {
|
|
|
|
if g.cursorPos > 0 {
|
|
|
|
g.cursorPos -= 1
|
|
|
|
g.Cursor()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
ui.Handle("/sys/kbd/<down>", func(ui.Event) {
|
|
|
|
if g.cursorPos < (g.Len() - 1) {
|
|
|
|
g.cursorPos += 1
|
|
|
|
g.Cursor()
|
|
|
|
}
|
|
|
|
})
|
2016-12-22 16:15:22 +00:00
|
|
|
ui.Handle("/sys/kbd/q", func(ui.Event) {
|
|
|
|
ui.StopLoop()
|
|
|
|
})
|
|
|
|
ui.Handle("/timer/1s", func(e ui.Event) {
|
|
|
|
ui.Render(ui.Body)
|
|
|
|
})
|
|
|
|
|
|
|
|
ui.Handle("/sys/wnd/resize", func(e ui.Event) {
|
|
|
|
ui.Body.Width = ui.TermWidth()
|
|
|
|
ui.Body.Align()
|
|
|
|
ui.Clear()
|
|
|
|
ui.Render(ui.Body)
|
|
|
|
})
|
|
|
|
|
|
|
|
ui.Loop()
|
|
|
|
}
|