diff --git a/container.go b/container.go index f5fd2ae..fb960b6 100644 --- a/container.go +++ b/container.go @@ -37,7 +37,7 @@ func (c *Container) Expand() { curWidgets = c.widgets c.widgets = widgets.NewExpanded(c.ShortID(), c.ShortName()) - c.widgets.Render() + c.widgets.Render(0, 0) c.widgets = curWidgets } diff --git a/grid.go b/grid.go index e052487..a526233 100644 --- a/grid.go +++ b/grid.go @@ -8,23 +8,27 @@ import ( ui "github.com/gizak/termui" ) +var cGrid = &widgets.CompactGrid{} + func maxRows() int { - return ui.TermHeight() - widgets.CompactHeader.Height - ui.Body.Y + return ui.TermHeight() - 2 - cGrid.Y } type Grid struct { - cursorID string // id of currently selected container - cmap *ContainerMap - containers Containers // sorted slice of containers - header *widgets.CTopHeader + cursorID string // id of currently selected container + cmap *ContainerMap + containers Containers // sorted slice of containers + header *widgets.CTopHeader + fieldHeader *widgets.CompactHeader } func NewGrid() *Grid { cmap := NewContainerMap() g := &Grid{ - cmap: cmap, - containers: cmap.All(), - header: widgets.NewCTopHeader(), + cmap: cmap, + containers: cmap.All(), + header: widgets.NewCTopHeader(), + fieldHeader: widgets.NewCompactHeader(), } return g } @@ -60,7 +64,7 @@ func (g *Grid) cursorUp() { g.cursorID = next.id next.widgets.Highlight() - ui.Render(ui.Body) + ui.Render(cGrid) } func (g *Grid) cursorDown() { @@ -78,69 +82,50 @@ func (g *Grid) cursorDown() { active.widgets.UnHighlight() g.cursorID = next.id next.widgets.Highlight() - ui.Render(ui.Body) + ui.Render(cGrid) } func (g *Grid) redrawRows() { // reinit body rows - ui.Body.Rows = []*ui.Row{} + cGrid.Rows = []widgets.ContainerWidgets{} ui.Clear() // build layout + y := 1 if config.GetSwitchVal("enableHeader") { - ui.Body.Y = g.header.Height() g.header.SetCount(len(g.containers)) g.header.SetFilter(config.GetVal("filterStr")) g.header.Render() - } else { - ui.Body.Y = 0 + y += g.header.Height() } - ui.Body.AddRows(widgets.CompactHeader) - var cursorVisible bool max := maxRows() + y += 2 // for field header for n, c := range g.containers.Filter() { if n >= max { break } + cGrid.Rows = append(cGrid.Rows, c.widgets) if c.id == g.cursorID { cursorVisible = true } - ui.Body.AddRows(c.widgets.Row()) } + cGrid.SetY(y) + cGrid.SetWidth(ui.TermWidth()) + + //log.Infof("rows: %d", len(cGrid.Rows)) + //log.Infof("Width: %d", cGrid.Width) + //log.Infof("Height: %d", cGrid.Height) + //log.Infof("X: %d", cGrid.X) + //log.Infof("Y: %d", cGrid.Y) if !cursorVisible { g.cursorReset() } - ui.Body.Align() - resizeIndicator() - ui.Render(ui.Body) - - // dump aligned widget positions and sizes - //for i, w := range ui.Body.Rows[1].Cols { - //log.Infof("w%v: x=%v y=%v w=%v h=%v", i, w.X, w.Y, w.Width, w.Height) - //} - -} - -// override Align()'d size for indicator column -func resizeIndicator() { - xShift := 1 - toWidth := 3 - for _, r := range ui.Body.Rows { - wDiff := r.Cols[0].Width - (toWidth + xShift) - // set indicator x, width - r.Cols[0].SetX(xShift) - r.Cols[0].SetWidth(toWidth) - - // shift remainder of columns left by wDiff - for _, c := range r.Cols[1:] { - c.SetX(c.X - wDiff) - c.SetWidth(c.Width - wDiff) - } - } + ui.Render(g.fieldHeader) + ui.Render(cGrid) } func (g *Grid) ExpandView() { @@ -164,6 +149,7 @@ func Display(g *Grid) bool { var menu func() var expand bool + cGrid.SetWidth(ui.TermWidth()) ui.DefaultEvtStream.Hook(logEvent) // initial draw @@ -214,8 +200,8 @@ func Display(g *Grid) bool { ui.Handle("/sys/wnd/resize", func(e ui.Event) { g.header.Align() - ui.Body.Width = ui.TermWidth() - log.Infof("resize: width=%v max-rows=%v", ui.Body.Width, maxRows()) + cGrid.SetWidth(ui.TermWidth()) + log.Infof("resize: width=%v max-rows=%v", cGrid.Width, maxRows()) g.redrawRows() }) diff --git a/widgets/compact.go b/widgets/compact.go index e2ff9a6..15c8801 100644 --- a/widgets/compact.go +++ b/widgets/compact.go @@ -4,34 +4,83 @@ import ( "fmt" "strconv" + "github.com/bcicen/ctop/logging" ui "github.com/gizak/termui" ) +var log = logging.Init() + const ( mark = string('\u25C9') vBar = string('\u25AE') ) +type CompactGrid struct { + ui.GridBufferer + Rows []ContainerWidgets + X, Y int + Width int + Height int +} + +func (c CompactGrid) SetX(x int) { c.X = x } +func (c CompactGrid) SetY(y int) { + c.Y = y + for n, r := range c.Rows { + log.Infof("row %d: y=%d", n, c.Y+n) + r.SetY(c.Y + n) + } +} +func (c CompactGrid) GetHeight() int { return len(c.Rows) } +func (c CompactGrid) SetWidth(w int) { + c.Width = w + for _, r := range c.Rows { + r.SetWidth(w) + } +} + +func (c CompactGrid) Buffer() ui.Buffer { + buf := ui.NewBuffer() + for _, r := range c.Rows { + buf.Merge(r.Buffer()) + } + return buf +} + type ContainerWidgets interface { - Row() *ui.Row - Render() + Render(int, int) Reset() + Buffer() ui.Buffer Highlight() UnHighlight() + SetY(int) + SetWidth(int) SetStatus(string) SetCPU(int) SetNet(int64, int64) SetMem(int64, int64, int) } -var CompactHeader = ui.NewRow( - ui.NewCol(1, 0, slimHeaderPar("")), - ui.NewCol(2, 0, slimHeaderPar("NAME")), - ui.NewCol(2, 0, slimHeaderPar("CID")), - ui.NewCol(2, 0, slimHeaderPar("CPU")), - ui.NewCol(2, 0, slimHeaderPar("MEM")), - ui.NewCol(2, 0, slimHeaderPar("NET RX/TX")), -) +type CompactHeader struct { + pars []*ui.Par +} + +func NewCompactHeader() *CompactHeader { + fields := []string{"", "NAME", "CID", "CPU", "MEM", "NET RX/TX"} + header := &CompactHeader{} + for _, f := range fields { + header.pars = append(header.pars, slimHeaderPar(f)) + } + return header +} + +func (c *CompactHeader) Buffer() ui.Buffer { + buf := ui.NewBuffer() + for _, p := range c.pars { + buf.Merge(p.Buffer()) + } + return buf +} type Compact struct { Status *ui.Par @@ -40,7 +89,6 @@ type Compact struct { Name *ui.Par Cpu *ui.Gauge Memory *ui.Gauge - row *ui.Row } func NewCompact(id, name, status string) *Compact { @@ -59,21 +107,56 @@ func (w *Compact) Reset() { w.Net = slimPar("-") w.Cpu = slimGauge() w.Memory = slimGauge() - w.row = ui.NewRow( - ui.NewCol(1, 0, w.Status), - ui.NewCol(2, 0, w.Name), - ui.NewCol(2, 0, w.Cid), - ui.NewCol(2, 0, w.Cpu), - ui.NewCol(2, 0, w.Memory), - ui.NewCol(2, 0, w.Net), - ) } -func (w *Compact) Render() { +func (w *Compact) all() []ui.GridBufferer { + return []ui.GridBufferer{ + w.Status, + w.Name, + w.Cid, + w.Cpu, + w.Memory, + w.Net, + } } -func (w *Compact) Row() *ui.Row { - return w.row +func (w *Compact) SetY(y int) { + for _, col := range w.all() { + col.SetY(y) + } +} + +func (w *Compact) SetWidth(width int) { + x := 1 + statusWidth := 3 + autoWidth := (width - statusWidth) / 5 + log.Infof("autowidth: %d", autoWidth) + for n, col := range w.all() { + if n == 0 { + col.SetX(x) + col.SetWidth(statusWidth) + x += statusWidth + continue + } + col.SetX(x) + col.SetWidth(autoWidth) + x += autoWidth + } +} + +func (w *Compact) Render(y, rowWidth int) {} + +func (w *Compact) Buffer() ui.Buffer { + buf := ui.NewBuffer() + + buf.Merge(w.Status.Buffer()) + buf.Merge(w.Name.Buffer()) + buf.Merge(w.Cid.Buffer()) + buf.Merge(w.Cpu.Buffer()) + buf.Merge(w.Memory.Buffer()) + buf.Merge(w.Net.Buffer()) + + return buf } func (w *Compact) Highlight() { @@ -149,6 +232,7 @@ func centerParText(p *ui.Par) { func slimHeaderPar(s string) *ui.Par { p := slimPar(s) + p.Y = 2 p.Height = 2 return p } diff --git a/widgets/expanded.go b/widgets/expanded.go index 5584589..4f474a6 100644 --- a/widgets/expanded.go +++ b/widgets/expanded.go @@ -33,10 +33,18 @@ func NewInfo(id, name string) *ui.Table { return p } -func (w *Expanded) Reset() { +func (w *Expanded) Buffer() ui.Buffer { + return ui.NewBuffer() } -func (w *Expanded) Render() { +func (w *Expanded) Reset() {} +func (w *Expanded) SetY(_ int) {} +func (w *Expanded) SetWidth(_ int) {} +func (w *Expanded) Highlight() {} +func (w *Expanded) UnHighlight() {} +func (w *Expanded) SetStatus(val string) {} + +func (w *Expanded) Render(_, _ int) { ui.Render(w.Info, w.Cpu, w.Mem, w.Net) ui.Handle("/timer/1s", func(ui.Event) { ui.Render(w.Info, w.Cpu, w.Mem, w.Net) @@ -47,23 +55,6 @@ func (w *Expanded) Render() { ui.Loop() } -func (w *Expanded) Row() *ui.Row { - return ui.NewRow( - ui.NewCol(2, 0, w.Cpu), - ui.NewCol(2, 0, w.Mem), - ui.NewCol(2, 0, w.Net), - ) -} - -func (w *Expanded) Highlight() { -} - -func (w *Expanded) UnHighlight() { -} - -func (w *Expanded) SetStatus(val string) { -} - func (w *Expanded) SetCPU(val int) { w.Cpu.Update(val) }