From 0ca5235ae5edc72070e87b3c0f5a996cef7c0fb1 Mon Sep 17 00:00:00 2001 From: Bradley Cicenas Date: Fri, 5 Jul 2019 23:05:21 +0000 Subject: [PATCH] continuing compact widget refactor --- container/main.go | 6 +- cwidgets/compact/gauge.go | 20 +++-- cwidgets/compact/grid.go | 54 ++++++++++--- cwidgets/compact/header.go | 65 +++++++--------- cwidgets/compact/main.go | 152 ------------------------------------- cwidgets/compact/status.go | 2 + cwidgets/compact/text.go | 46 ++++++++--- cwidgets/compact/util.go | 13 ---- models/main.go | 18 ++++- 9 files changed, 143 insertions(+), 233 deletions(-) delete mode 100644 cwidgets/compact/main.go diff --git a/container/main.go b/container/main.go index 660e5cc..88b3619 100644 --- a/container/main.go +++ b/container/main.go @@ -22,7 +22,7 @@ type Container struct { models.Metrics Id string Meta models.Meta - Widgets *compact.Compact + Widgets *compact.CompactRow Display bool // display this container in compact view updater cwidgets.WidgetUpdater collector collector.Collector @@ -30,11 +30,11 @@ type Container struct { } func New(id string, collector collector.Collector, manager manager.Manager) *Container { - widgets := compact.NewCompact(id) + widgets := compact.NewCompactRow() return &Container{ Metrics: models.NewMetrics(), Id: id, - Meta: models.NewMeta(), + Meta: models.NewMeta("id", id), Widgets: widgets, updater: widgets, collector: collector, diff --git a/cwidgets/compact/gauge.go b/cwidgets/compact/gauge.go index b22042f..fdf3a03 100644 --- a/cwidgets/compact/gauge.go +++ b/cwidgets/compact/gauge.go @@ -12,6 +12,10 @@ type CPUCol struct { *GaugeCol } +func NewCPUCol() CompactCol { + return &CPUCol{NewGaugeCol("CPU")} +} + func (w *CPUCol) SetMetrics(m models.Metrics) { val := m.CPUUtil w.BarColor = colorScale(val) @@ -27,6 +31,10 @@ type MemCol struct { *GaugeCol } +func NewMemCol() CompactCol { + return &MemCol{NewGaugeCol("MEM")} +} + func (w *MemCol) SetMetrics(m models.Metrics) { w.BarColor = ui.ThemeAttr("gauge.bar.bg") w.Label = fmt.Sprintf("%s / %s", cwidgets.ByteFormat(m.MemUsage), cwidgets.ByteFormat(m.MemLimit)) @@ -35,10 +43,12 @@ func (w *MemCol) SetMetrics(m models.Metrics) { type GaugeCol struct { *ui.Gauge + header string + fWidth int } -func NewGaugeCol() *GaugeCol { - g := &GaugeCol{ui.NewGauge()} +func NewGaugeCol(header string) *GaugeCol { + g := &GaugeCol{ui.NewGauge(), header, 0} g.Height = 1 g.Border = false g.PaddingBottom = 0 @@ -63,10 +73,10 @@ func (w *GaugeCol) Buffer() ui.Buffer { } // GaugeCol implements CompactCol -func (w *GaugeCol) SetMeta(models.Meta) {} - -// GaugeCol implements CompactCol +func (w *GaugeCol) SetMeta(models.Meta) {} func (w *GaugeCol) SetMetrics(models.Metrics) {} +func (w *GaugeCol) Header() string { return w.header } +func (w *GaugeCol) FixedWidth() int { return w.fWidth } // GaugeCol implements CompactCol func (w *GaugeCol) Highlight() { diff --git a/cwidgets/compact/grid.go b/cwidgets/compact/grid.go index 8b483c2..710d7f2 100644 --- a/cwidgets/compact/grid.go +++ b/cwidgets/compact/grid.go @@ -4,11 +4,11 @@ import ( ui "github.com/gizak/termui" ) -var header *CompactHeader - type CompactGrid struct { ui.GridBufferer - Rows []ui.GridBufferer + header *CompactHeader + cols []CompactCol // reference columns + Rows []RowBufferer X, Y int Width int Height int @@ -16,8 +16,13 @@ type CompactGrid struct { } func NewCompactGrid() *CompactGrid { - header = NewCompactHeader() // init column header - return &CompactGrid{} + cg := &CompactGrid{header: NewCompactHeader()} + for _, wFn := range allCols { + w := wFn() + cg.cols = append(cg.cols, w) + cg.header.addFieldPar(w.Header()) + } + return cg } func (cg *CompactGrid) Align() { @@ -28,22 +33,47 @@ func (cg *CompactGrid) Align() { } // update row ypos, width recursively + colWidths := cg.calcWidths() for _, r := range cg.pageRows() { r.SetY(y) y += r.GetHeight() - r.SetWidth(cg.Width) + r.SetWidths(cg.Width, colWidths) } } -func (cg *CompactGrid) Clear() { cg.Rows = []ui.GridBufferer{} } -func (cg *CompactGrid) GetHeight() int { return len(cg.Rows) + header.Height } +func (cg *CompactGrid) Clear() { cg.Rows = []RowBufferer{} } +func (cg *CompactGrid) GetHeight() int { return len(cg.Rows) + cg.header.Height } func (cg *CompactGrid) SetX(x int) { cg.X = x } func (cg *CompactGrid) SetY(y int) { cg.Y = y } func (cg *CompactGrid) SetWidth(w int) { cg.Width = w } -func (cg *CompactGrid) MaxRows() int { return ui.TermHeight() - header.Height - cg.Y } +func (cg *CompactGrid) MaxRows() int { return ui.TermHeight() - cg.header.Height - cg.Y } -func (cg *CompactGrid) pageRows() (rows []ui.GridBufferer) { - rows = append(rows, header) +// calculate and return per-column width +func (cg *CompactGrid) calcWidths() []int { + var autoCols int + width := cg.Width + colWidths := make([]int, len(cg.cols)) + + for n, w := range cg.cols { + colWidths[n] = w.FixedWidth() + width -= w.FixedWidth() + if w.FixedWidth() == 0 { + autoCols++ + } + } + + spacing := colSpacing * len(cg.cols) + autoWidth := (width - spacing) / autoCols + for n, val := range colWidths { + if val == 0 { + colWidths[n] = autoWidth + } + } + return colWidths +} + +func (cg *CompactGrid) pageRows() (rows []RowBufferer) { + rows = append(rows, cg.header) rows = append(rows, cg.Rows[cg.Offset:]...) return rows } @@ -56,6 +86,6 @@ func (cg *CompactGrid) Buffer() ui.Buffer { return buf } -func (cg *CompactGrid) AddRows(rows ...ui.GridBufferer) { +func (cg *CompactGrid) AddRows(rows ...RowBufferer) { cg.Rows = append(cg.Rows, rows...) } diff --git a/cwidgets/compact/header.go b/cwidgets/compact/header.go index 6dbd298..2d5ecc9 100644 --- a/cwidgets/compact/header.go +++ b/cwidgets/compact/header.go @@ -8,63 +8,52 @@ type CompactHeader struct { X, Y int Width int Height int + cols []CompactCol + widths []int pars []*ui.Par } func NewCompactHeader() *CompactHeader { - fields := []string{"", "NAME", "CID", "CPU", "MEM", "NET RX/TX", "IO R/W", "PIDS"} - ch := &CompactHeader{} - ch.Height = 2 - for _, f := range fields { - ch.addFieldPar(f) + return &CompactHeader{Height: 2} +} + +func (row *CompactHeader) GetHeight() int { + return row.Height +} + +func (row *CompactHeader) SetWidths(totalWidth int, widths []int) { + x := row.X + + for n, w := range row.pars { + w.SetX(x) + w.SetWidth(widths[n]) + x += widths[n] + colSpacing } - return ch + row.Width = totalWidth } -func (ch *CompactHeader) GetHeight() int { - return ch.Height +func (row *CompactHeader) SetX(x int) { + row.X = x } -func (ch *CompactHeader) SetWidth(w int) { - x := ch.X - autoWidth := calcWidth(w) - for n, col := range ch.pars { - // set column to static width - if colWidths[n] != 0 { - col.SetX(x) - col.SetWidth(colWidths[n]) - x += colWidths[n] - continue - } - col.SetX(x) - col.SetWidth(autoWidth) - x += autoWidth + colSpacing - } - ch.Width = w -} - -func (ch *CompactHeader) SetX(x int) { - ch.X = x -} - -func (ch *CompactHeader) SetY(y int) { - for _, p := range ch.pars { +func (row *CompactHeader) SetY(y int) { + for _, p := range row.pars { p.SetY(y) } - ch.Y = y + row.Y = y } -func (ch *CompactHeader) Buffer() ui.Buffer { +func (row *CompactHeader) Buffer() ui.Buffer { buf := ui.NewBuffer() - for _, p := range ch.pars { + for _, p := range row.pars { buf.Merge(p.Buffer()) } return buf } -func (ch *CompactHeader) addFieldPar(s string) { +func (row *CompactHeader) addFieldPar(s string) { p := ui.NewPar(s) - p.Height = ch.Height + p.Height = row.Height p.Border = false - ch.pars = append(ch.pars, p) + row.pars = append(row.pars, p) } diff --git a/cwidgets/compact/main.go b/cwidgets/compact/main.go deleted file mode 100644 index 9f6cef4..0000000 --- a/cwidgets/compact/main.go +++ /dev/null @@ -1,152 +0,0 @@ -package compact - -import ( - "github.com/bcicen/ctop/config" - "github.com/bcicen/ctop/logging" - "github.com/bcicen/ctop/models" - ui "github.com/gizak/termui" -) - -var log = logging.Init() - -type CompactCol interface { - ui.GridBufferer - Reset() - Highlight() - UnHighlight() - SetMeta(models.Meta) - SetMetrics(models.Metrics) -} - -type Compact struct { - Bg *RowBg - Cols []CompactCol - X, Y int - Width int - Height int -} - -func NewCompact(id string) *Compact { - // truncate container id - if len(id) > 12 { - id = id[:12] - } - row := &Compact{ - Bg: NewRowBg(), - Cols: []CompactCol{ - NewStatus(), - &NameCol{NewTextCol("-")}, - &CIDCol{NewTextCol(id)}, - &CPUCol{NewGaugeCol()}, - &MemCol{NewGaugeCol()}, - &NetCol{NewTextCol("-")}, - &IOCol{NewTextCol("-")}, - &PIDCol{NewTextCol("-")}, - }, - X: 1, - Height: 1, - } - return row -} - -func (row *Compact) SetMeta(m models.Meta) { - for _, w := range row.Cols { - w.SetMeta(m) - } -} - -func (row *Compact) SetMetrics(m models.Metrics) { - for _, w := range row.Cols { - w.SetMetrics(m) - } -} - -// Set gauges, counters, etc. to default unread values -func (row *Compact) Reset() { - for _, w := range row.Cols { - w.Reset() - } -} - -func (row *Compact) GetHeight() int { return row.Height } -func (row *Compact) SetX(x int) { row.X = x } - -func (row *Compact) SetY(y int) { - if y == row.Y { - return - } - - row.Bg.Y = y - for _, w := range row.Cols { - w.SetY(y) - } - row.Y = y -} - -func (row *Compact) SetWidth(width int) { - if width == row.Width { - return - } - x := row.X - - row.Bg.SetX(x + colWidths[0] + 1) - row.Bg.SetWidth(width) - - autoWidth := calcWidth(width) - for n, w := range row.Cols { - // set static width, if provided - if colWidths[n] != 0 { - w.SetX(x) - w.SetWidth(colWidths[n]) - x += colWidths[n] - continue - } - // else use auto width - w.SetX(x) - w.SetWidth(autoWidth) - x += autoWidth + colSpacing - } - row.Width = width -} - -func (row *Compact) Buffer() ui.Buffer { - buf := ui.NewBuffer() - buf.Merge(row.Bg.Buffer()) - for _, w := range row.Cols { - buf.Merge(w.Buffer()) - } - return buf -} - -func (row *Compact) Highlight() { - row.Cols[1].Highlight() - if config.GetSwitchVal("fullRowCursor") { - for _, w := range row.Cols { - w.Highlight() - } - } -} - -func (row *Compact) UnHighlight() { - row.Cols[1].UnHighlight() - if config.GetSwitchVal("fullRowCursor") { - for _, w := range row.Cols { - w.UnHighlight() - } - } -} - -type RowBg struct { - *ui.Par -} - -func NewRowBg() *RowBg { - bg := ui.NewPar("") - bg.Height = 1 - bg.Border = false - bg.Bg = ui.ThemeAttr("par.text.bg") - return &RowBg{bg} -} - -func (w *RowBg) Highlight() { w.Bg = ui.ThemeAttr("par.text.fg") } -func (w *RowBg) UnHighlight() { w.Bg = ui.ThemeAttr("par.text.bg") } diff --git a/cwidgets/compact/status.go b/cwidgets/compact/status.go index 43c838b..74e30f9 100644 --- a/cwidgets/compact/status.go +++ b/cwidgets/compact/status.go @@ -54,6 +54,8 @@ func (s *Status) Reset() {} func (s *Status) SetMetrics(models.Metrics) {} func (s *Status) Highlight() {} func (s *Status) UnHighlight() {} +func (s *Status) Header() string { return "" } +func (s *Status) FixedWidth() int { return 3 } func (s *Status) setState(val string) { // defaults diff --git a/cwidgets/compact/text.go b/cwidgets/compact/text.go index ed690a6..3ff9440 100644 --- a/cwidgets/compact/text.go +++ b/cwidgets/compact/text.go @@ -12,23 +12,38 @@ type NameCol struct { *TextCol } -func (w *NameCol) SetMeta(m models.Meta) { - if s, ok := m["name"]; ok { - w.Text = s - } +func NewNameCol() CompactCol { + return &NameCol{NewTextCol("NAME")} } -func (w *NameCol) SetMetrics(m models.Metrics) { +func (w *NameCol) SetMeta(m models.Meta) { + w.Text = m.Get("name") + // truncate container id + if len(w.Text) > 12 { + w.Text = w.Text[:12] + } } type CIDCol struct { *TextCol } +func NewCIDCol() CompactCol { + return &CIDCol{NewTextCol("CID")} +} + +func (w *CIDCol) SetMeta(m models.Meta) { + w.Text = m.Get("id") +} + type NetCol struct { *TextCol } +func NewNetCol() CompactCol { + return &NetCol{NewTextCol("NET RX/TX")} +} + func (w *NetCol) SetMetrics(m models.Metrics) { label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat(m.NetRx), cwidgets.ByteFormat(m.NetTx)) w.Text = label @@ -38,6 +53,10 @@ type IOCol struct { *TextCol } +func NewIOCol() CompactCol { + return &IOCol{NewTextCol("IO R/W")} +} + func (w *IOCol) SetMetrics(m models.Metrics) { label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat(m.IOBytesRead), cwidgets.ByteFormat(m.IOBytesWrite)) w.Text = label @@ -47,20 +66,28 @@ type PIDCol struct { *TextCol } +func NewPIDCol() CompactCol { + w := &PIDCol{NewTextCol("PIDS")} + w.fWidth = 4 + return w +} + func (w *PIDCol) SetMetrics(m models.Metrics) { w.Text = fmt.Sprintf("%d", m.Pids) } type TextCol struct { *ui.Par + header string + fWidth int } -func NewTextCol(s string) *TextCol { - p := ui.NewPar(s) +func NewTextCol(header string) *TextCol { + p := ui.NewPar("-") p.Border = false p.Height = 1 p.Width = 20 - return &TextCol{p} + return &TextCol{p, header, 0} } func (w *TextCol) Highlight() { @@ -75,7 +102,8 @@ func (w *TextCol) UnHighlight() { w.TextBgColor = ui.ThemeAttr("par.text.bg") } -//func (w *TextCol) Set(s string) { w.Text = s } func (w *TextCol) Reset() { w.Text = "-" } func (w *TextCol) SetMeta(models.Meta) {} func (w *TextCol) SetMetrics(models.Metrics) {} +func (w *TextCol) Header() string { return w.header } +func (w *TextCol) FixedWidth() int { return w.fWidth } diff --git a/cwidgets/compact/util.go b/cwidgets/compact/util.go index 9bd8f66..ec9b149 100644 --- a/cwidgets/compact/util.go +++ b/cwidgets/compact/util.go @@ -22,19 +22,6 @@ var colWidths = []int{ 4, // pids } -// Calculate per-column width, given total width -func calcWidth(width int) int { - spacing := colSpacing * len(colWidths) - var staticCols int - for _, w := range colWidths { - width -= w - if w == 0 { - staticCols++ - } - } - return (width - spacing) / staticCols -} - func centerParText(p *ui.Par) { var text string var padding string diff --git a/models/main.go b/models/main.go index dfbb30e..86168b2 100644 --- a/models/main.go +++ b/models/main.go @@ -9,7 +9,23 @@ type Log struct { type Meta map[string]string -func NewMeta() Meta { return make(Meta) } +// NewMeta returns an initialized Meta map. +// An optional series of key, values may be provided to populate the map prior to returning +func NewMeta(kvs ...string) Meta { + m := make(Meta) + + var k string + for i := 0; i < len(kvs)-1; i++ { + if k == "" { + k = kvs[i] + } else { + m[k] = kvs[i] + k = "" + } + } + + return m +} func (m Meta) Get(k string) string { if s, ok := m[k]; ok {