170 lines
3.7 KiB
Go
170 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/gizak/termui"
|
|
)
|
|
|
|
const HeaderHeight = 3
|
|
|
|
// UI represents UI layout.
|
|
type UI struct {
|
|
Headers []*termui.Par
|
|
Sparklines *termui.Sparklines
|
|
|
|
CPULine *termui.Sparkline
|
|
|
|
// fields needed only for UI display
|
|
interval time.Duration
|
|
maxCPU float64
|
|
}
|
|
|
|
func initUI(pid int64, interval time.Duration) *UI {
|
|
err := termui.Init()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
ui := &UI{
|
|
interval: interval,
|
|
}
|
|
ui.createHeader(pid)
|
|
ui.createSparklines()
|
|
ui.createLayout()
|
|
|
|
ui.Align()
|
|
ui.Render()
|
|
|
|
return ui
|
|
}
|
|
|
|
func stopUI() {
|
|
termui.Close()
|
|
}
|
|
|
|
// UpdateCPU updates CPU widget with new values from data.
|
|
func (ui *UI) UpdateCPU(data []float64) {
|
|
intData := make([]int, len(data))
|
|
|
|
// multiply by 100, to account for 2 decimals after the point
|
|
for i := range data {
|
|
intData[i] = int(data[i] * 100)
|
|
}
|
|
ui.Sparklines.Lines[0].Data = intData
|
|
|
|
if len(data) == 0 {
|
|
return
|
|
}
|
|
|
|
currentCPU := data[len(data)-1]
|
|
if currentCPU > ui.maxCPU {
|
|
ui.maxCPU = currentCPU
|
|
}
|
|
ui.Sparklines.Lines[0].TitleColor = termui.ColorYellow
|
|
ui.Sparklines.Lines[0].Title = fmt.Sprintf("Current: %.2f%%, Max: %.2f%%", currentCPU, ui.maxCPU)
|
|
}
|
|
|
|
// Render rerenders UI.
|
|
func (ui *UI) Render() {
|
|
termui.Body.Align()
|
|
|
|
// Update widgets:
|
|
// history time estimation based on new size and interval
|
|
ui.Sparklines.BorderLabel = fmt.Sprintf("CPU (last %v)", time.Duration(termui.TermWidth()-2)*ui.interval)
|
|
// time in header
|
|
ui.Headers[3].Text = fmt.Sprintf("%v", time.Now().Format("15:04:05"))
|
|
|
|
// TODO: prettify this
|
|
termui.Render(ui.Headers[0], ui.Headers[1], ui.Headers[2], ui.Headers[3], ui.Sparklines)
|
|
}
|
|
|
|
// Align recalculates layout and aligns widgets.
|
|
func (ui *UI) Align() {
|
|
termui.Body.Align()
|
|
}
|
|
|
|
func (ui *UI) createLayout() {
|
|
if len(ui.Headers) != 4 {
|
|
panic("update headers code")
|
|
}
|
|
termui.Body.AddRows(
|
|
termui.NewRow(
|
|
termui.NewCol(6, 0, ui.Headers[0]),
|
|
termui.NewCol(2, 0, ui.Headers[1]),
|
|
termui.NewCol(2, 0, ui.Headers[2]),
|
|
termui.NewCol(2, 0, ui.Headers[3]),
|
|
),
|
|
termui.NewRow(
|
|
termui.NewCol(12, 0, ui.Sparklines),
|
|
),
|
|
)
|
|
}
|
|
|
|
func (ui *UI) createHeader(pid int64) {
|
|
p := termui.NewPar("")
|
|
p.Height = HeaderHeight
|
|
p.TextFgColor = termui.ColorWhite
|
|
p.BorderLabel = "Monitoring Status.im via adb"
|
|
p.BorderFg = termui.ColorCyan
|
|
p.Text = "press 'q' to exit"
|
|
|
|
p1 := termui.NewPar("")
|
|
p1.Height = HeaderHeight
|
|
p1.TextFgColor = termui.ColorWhite
|
|
p1.BorderLabel = "PID"
|
|
p1.BorderFg = termui.ColorCyan
|
|
p1.Text = fmt.Sprintf("%d", pid)
|
|
|
|
p2 := termui.NewPar("")
|
|
p2.Height = HeaderHeight
|
|
p2.TextFgColor = termui.ColorWhite
|
|
p2.BorderLabel = "Polling interval"
|
|
p2.BorderFg = termui.ColorCyan
|
|
p2.Text = fmt.Sprintf("%v", ui.interval)
|
|
|
|
p3 := termui.NewPar("")
|
|
p3.Height = HeaderHeight
|
|
p3.TextFgColor = termui.ColorYellow
|
|
p3.BorderLabel = "Time"
|
|
p3.BorderFg = termui.ColorCyan
|
|
p3.Text = fmt.Sprintf("%v", time.Now().Format("15:04:05"))
|
|
|
|
ui.Headers = []*termui.Par{p, p1, p2, p3}
|
|
}
|
|
|
|
func (ui *UI) createSparklines() {
|
|
s := termui.NewSparkline()
|
|
s.Height = termui.TermHeight() - HeaderHeight - 3 // - border
|
|
s.LineColor = termui.ColorGreen
|
|
|
|
ui.CPULine = &s
|
|
|
|
// single
|
|
ss := termui.NewSparklines(s)
|
|
ss.Height = termui.TermHeight() - HeaderHeight
|
|
ss.Border = true
|
|
ss.BorderLabel = fmt.Sprintf("CPU (last %v)", time.Duration(termui.TermWidth()-2)*ui.interval)
|
|
|
|
ui.Sparklines = ss
|
|
}
|
|
|
|
func (ui *UI) HandleKeys() {
|
|
// handle key q pressing
|
|
termui.Handle("/sys/kbd/q", func(termui.Event) {
|
|
termui.StopLoop()
|
|
})
|
|
}
|
|
|
|
// AddTimer adds handler for repeatable functions that interact with UI.
|
|
func (ui *UI) AddTimer(d time.Duration, fn func(e termui.Event)) {
|
|
durationStr := fmt.Sprintf("/timer/%s", d)
|
|
termui.Handle(durationStr, fn)
|
|
}
|
|
|
|
// Loop starts event loop and blocks.
|
|
func (ui *UI) Loop() {
|
|
termui.Loop()
|
|
}
|