From 2e48524cc9b8ccb874a3e65a0152c0a874337178 Mon Sep 17 00:00:00 2001 From: Caleb Bassi Date: Mon, 31 Dec 2018 16:55:50 -0800 Subject: [PATCH] Port to termui 2.0 --- README.md | 10 ++-- go.mod | 7 +-- go.sum | 12 ++--- main.go | 102 +++++++++++++++++++++++----------------- src/termui/linegraph.go | 36 +++++++------- src/termui/sparkline.go | 67 +++++++++++++------------- src/termui/table.go | 70 ++++++++++++++------------- src/widgets/cpu.go | 4 +- src/widgets/disk.go | 8 ++-- src/widgets/help.go | 33 ++++++++----- src/widgets/mem.go | 4 +- src/widgets/net.go | 4 +- src/widgets/proc.go | 9 ++-- src/widgets/temp.go | 36 +++++++++----- 14 files changed, 220 insertions(+), 182 deletions(-) diff --git a/README.md b/README.md index 0f667e20..f651bed4 100644 --- a/README.md +++ b/README.md @@ -113,11 +113,11 @@ This will place the built packages into the `dist` folder. ## Built With -- [cjbassi/termui](https://github.com/cjbassi/termui) - - [drawille-go](https://github.com/exrook/drawille-go) - - [termbox](https://github.com/nsf/termbox-go) -- [gopsutil](https://github.com/shirou/gopsutil) -- [goreleaser](https://github.com/goreleaser/goreleaser) +- [gizak/termui](https://github.com/gizak/termui) + - [nsf/termbox](https://github.com/nsf/termbox-go) +- [exrook/drawille-go](https://github.com/exrook/drawille-go) +- [shirou/gopsutil](https://github.com/shirou/gopsutil) +- [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser) ## Stargazers over time diff --git a/go.mod b/go.mod index e2f7ec6d..f2148813 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,11 @@ module github.com/cjbassi/gotop require ( github.com/ProtonMail/go-appdir v0.0.0-20180220133335-7c788d1b45c6 github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect - github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd // indirect - github.com/cjbassi/termui v0.0.0-20181208033036-e8dd23f6146c + github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd github.com/davecgh/go-spew v1.1.1 // indirect - github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 + github.com/gizak/termui v0.0.0-20190101005313-46c77dca8480 github.com/go-ole/go-ole v1.2.1 // indirect - github.com/mattn/go-runewidth v0.0.2 // indirect - github.com/nsf/termbox-go v0.0.0-20180407224525-3e24a7b6661e // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/shirou/gopsutil v2.18.11+incompatible github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect diff --git a/go.sum b/go.sum index b869d58c..de5c0f72 100644 --- a/go.sum +++ b/go.sum @@ -4,20 +4,20 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIO github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd h1:nSJpATLVvFa19BEHX4ys+VGNWfI4FUGMweEI6QXs8wg= github.com/cjbassi/drawille-go v0.0.0-20180329221028-ad535d0f92cd/go.mod h1:vjcQJUZJYD3MeVGhtZXSMnCHfUNZxsyYzJt90eCYxK4= -github.com/cjbassi/termui v0.0.0-20181208033036-e8dd23f6146c h1:vcaCtK8ObawtpQRW8GdbKZ+eJGEUn41xJ8Snagd/c6I= -github.com/cjbassi/termui v0.0.0-20181208033036-e8dd23f6146c/go.mod h1:rqXckrwz+i0fH/zNwU6AdBNULHwmZsgehnSlhKP5i2Q= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 h1:HMAfwOa33y82IaQEKQDfUCiwNlxtM1iw7HLM9ru0RNc= github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:l7JNRynTRuqe45tpIyItHNqZWTxywYjp87MWTOnU5cg= +github.com/gizak/termui v0.0.0-20190101005313-46c77dca8480 h1:+NHS7QUnQqEwIuhrHaFT6R78LMGbja4fYTu6wny7Q4s= +github.com/gizak/termui v0.0.0-20190101005313-46c77dca8480/go.mod h1:S3xz8JHXNDPSNFsvXCdG7bHlEGrwvUG3a0joR/xYZ5M= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/nsf/termbox-go v0.0.0-20180407224525-3e24a7b6661e h1:w2JDz0jtOlFFdvtUXISyYPFwmbZnwKL1mRDT0tKDvuk= -github.com/nsf/termbox-go v0.0.0-20180407224525-3e24a7b6661e/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/nsf/termbox-go v0.0.0-20180613055208-5c94acc5e6eb h1:YahEjAGkJtCrkqgVHhX6n8ZX+CZ3hDRL9fjLYugLfSs= +github.com/nsf/termbox-go v0.0.0-20180613055208-5c94acc5e6eb/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shirou/gopsutil v2.18.11+incompatible h1:PMFTKnFTr/YTRW5rbLK4vWALV3a+IGXse5nvhSjztmg= diff --git a/main.go b/main.go index 60df7d53..48adc7dc 100644 --- a/main.go +++ b/main.go @@ -18,8 +18,8 @@ import ( "github.com/cjbassi/gotop/colorschemes" "github.com/cjbassi/gotop/src/logging" w "github.com/cjbassi/gotop/src/widgets" - ui "github.com/cjbassi/termui" docopt "github.com/docopt/docopt.go" + ui "github.com/gizak/termui" ) var version = "1.7.1" @@ -38,6 +38,8 @@ var ( configDir = appdir.New("gotop").UserConfig() logPath = filepath.Join(configDir, "errors.log") stderrLogger = log.New(os.Stderr, "", 0) + termWidth int + termHeight int cpu *w.CPU mem *w.Mem @@ -46,6 +48,7 @@ var ( disk *w.Disk temp *w.Temp help *w.HelpMenu + grid *ui.Grid ) func cliArguments() error { @@ -137,41 +140,46 @@ func getCustomColorscheme(name string) (colorschemes.Colorscheme, error) { } func setupGrid() { - ui.Body.Cols = 12 - ui.Body.Rows = 12 + grid = ui.NewGrid() + grid.SetRect(0, 0, termWidth, termHeight) if minimal { - ui.Body.Set(0, 0, 12, 6, cpu) - ui.Body.Set(0, 6, 6, 12, mem) - ui.Body.Set(6, 6, 12, 12, proc) + grid.Set( + ui.NewRow(1.0/2, cpu), + ui.NewRow(1.0/2, + ui.NewCol(1.0/2, mem), + ui.NewCol(1.0/2, proc), + ), + ) } else { - ui.Body.Set(0, 0, 12, 4, cpu) - - ui.Body.Set(0, 4, 4, 6, disk) - ui.Body.Set(0, 6, 4, 8, temp) - ui.Body.Set(4, 4, 12, 8, mem) - - ui.Body.Set(0, 8, 6, 12, net) - ui.Body.Set(6, 8, 12, 12, proc) + grid.Set( + ui.NewRow(1.0/3, cpu), + ui.NewRow(1.0/3, + ui.NewCol(1.0/3, + ui.NewRow(1.0/2, disk), + ui.NewRow(1.0/2, temp), + ), + ui.NewCol(2.0/3, mem), + ), + ui.NewRow(1.0/3, + ui.NewCol(1.0/2, net), + ui.NewCol(1.0/2, proc), + ), + ) } } func termuiColors() { - ui.Theme.Fg = ui.Color(colorscheme.Fg) - ui.Theme.Bg = ui.Color(colorscheme.Bg) - ui.Theme.LabelFg = ui.Color(colorscheme.BorderLabel) - ui.Theme.LabelBg = ui.Color(colorscheme.Bg) - ui.Theme.BorderFg = ui.Color(colorscheme.BorderLine) - ui.Theme.BorderBg = ui.Color(colorscheme.Bg) - - ui.Theme.TableCursor = ui.Color(colorscheme.ProcCursor) - ui.Theme.Sparkline = ui.Color(colorscheme.Sparkline) - ui.Theme.GaugeColor = ui.Color(colorscheme.DiskBar) + ui.Theme.Default = ui.AttrPair{ui.Attribute(colorscheme.Fg), ui.Attribute(colorscheme.Bg)} + ui.Theme.Block.Title = ui.AttrPair{ui.Attribute(colorscheme.BorderLabel), ui.Attribute(colorscheme.Bg)} + ui.Theme.Block.Border = ui.AttrPair{ui.Attribute(colorscheme.BorderLine), ui.Attribute(colorscheme.Bg)} } func widgetColors() { - mem.LineColor["Main"] = ui.Color(colorscheme.MainMem) - mem.LineColor["Swap"] = ui.Color(colorscheme.SwapMem) + mem.LineColor["Main"] = ui.Attribute(colorscheme.MainMem) + mem.LineColor["Swap"] = ui.Attribute(colorscheme.SwapMem) + + proc.CursorColor = ui.Attribute(colorscheme.ProcCursor) var keys []string for key := range cpu.Data { @@ -185,13 +193,18 @@ func widgetColors() { i = 0 } c := colorscheme.CPULines[i] - cpu.LineColor[v] = ui.Color(c) + cpu.LineColor[v] = ui.Attribute(c) i++ } if !minimal { - temp.TempLow = ui.Color(colorscheme.TempLow) - temp.TempHigh = ui.Color(colorscheme.TempHigh) + temp.TempLow = ui.Attribute(colorscheme.TempLow) + temp.TempHigh = ui.Attribute(colorscheme.TempHigh) + + net.Lines[0].LineColor = ui.Attribute(colorscheme.Sparkline) + net.Lines[0].TitleColor = ui.Attribute(colorscheme.BorderLabel) + net.Lines[1].LineColor = ui.Attribute(colorscheme.Sparkline) + net.Lines[1].TitleColor = ui.Attribute(colorscheme.BorderLabel) } } @@ -246,7 +259,7 @@ func eventLoop() { return case <-drawTicker: if !helpVisible { - ui.Render(ui.Body) + ui.Render(grid) } case e := <-uiEvents: switch e.ID { @@ -258,7 +271,7 @@ func eventLoop() { ui.Clear() ui.Render(help) } else { - ui.Render(ui.Body) + ui.Render(grid) } case "h": if !helpVisible { @@ -279,27 +292,27 @@ func eventLoop() { case "": if helpVisible { helpVisible = false - ui.Render(ui.Body) + ui.Render(grid) } case "": payload := e.Payload.(ui.Resize) - ui.Body.Width, ui.Body.Height = payload.Width, payload.Height - ui.Body.Resize() + grid.SetRect(0, 0, payload.Width, payload.Height) + help.Resize(payload.Width, payload.Height) ui.Clear() if helpVisible { ui.Render(help) } else { - ui.Render(ui.Body) + ui.Render(grid) } case "": payload := e.Payload.(ui.Mouse) proc.Click(payload.X, payload.Y) ui.Render(proc) - case "", "", "k": + case "k", "", "": proc.Up() ui.Render(proc) - case "", "", "j": + case "j", "", "": proc.Down() ui.Render(proc) case "g", "": @@ -373,11 +386,6 @@ func main() { stderrLogger.Fatalf("failed to parse cli args: %v", err) } - termuiColors() // need to do this before initializing widgets so that they can inherit the colors - initWidgets() - widgetColors() - help = w.NewHelpMenu() - if err := ui.Init(); err != nil { stderrLogger.Fatalf("failed to initialize termui: %v", err) } @@ -385,8 +393,16 @@ func main() { logging.StderrToLogfile(lf) + termWidth, termHeight = ui.TerminalSize() + + termuiColors() // need to do this before initializing widgets so that they can inherit the colors + initWidgets() + widgetColors() + help = w.NewHelpMenu() + help.Resize(termWidth, termHeight) + setupGrid() - ui.Render(ui.Body) + ui.Render(grid) eventLoop() } diff --git a/src/termui/linegraph.go b/src/termui/linegraph.go index 631a9bda..72f48b69 100644 --- a/src/termui/linegraph.go +++ b/src/termui/linegraph.go @@ -1,20 +1,22 @@ package termui import ( + "image" "sort" drawille "github.com/cjbassi/drawille-go" + . "github.com/gizak/termui" ) // LineGraph implements a line graph of data points. type LineGraph struct { *Block Data map[string][]float64 - LineColor map[string]Color + LineColor map[string]Attribute Zoom int Labels map[string]string - DefaultLineColor Color + DefaultLineColor Attribute } // NewLineGraph returns a new LineGraph with current theme. @@ -22,24 +24,22 @@ func NewLineGraph() *LineGraph { return &LineGraph{ Block: NewBlock(), Data: make(map[string][]float64), - LineColor: make(map[string]Color), + LineColor: make(map[string]Attribute), Labels: make(map[string]string), Zoom: 5, - - DefaultLineColor: Theme.LineGraph, } } // Buffer implements Bufferer interface. -func (self *LineGraph) Buffer() *Buffer { - buf := self.Block.Buffer() +func (self *LineGraph) Draw(buf *Buffer) { + self.Block.Draw(buf) // we render each data point on to the canvas then copy over the braille to the buffer at the end // fyi braille characters have 2x4 dots for each character c := drawille.NewCanvas() // used to keep track of the braille colors until the end when we render the braille to the buffer - colors := make([][]Color, self.X+2) + colors := make([][]Attribute, self.Inner.Dx()+2) for i := range colors { - colors[i] = make([]Color, self.Y+2) + colors[i] = make([]Attribute, self.Inner.Dy()+2) } // sort the series so that overlapping data will overlap the same way each time @@ -64,8 +64,8 @@ func (self *LineGraph) Buffer() *Buffer { lastY, lastX := -1, -1 // assign colors to `colors` and lines/points to the canvas for i := len(seriesData) - 1; i >= 0; i-- { - x := ((self.X + 1) * 2) - 1 - (((len(seriesData) - 1) - i) * self.Zoom) - y := ((self.Y + 1) * 4) - 1 - int((float64((self.Y)*4)-1)*(seriesData[i]/100)) + x := ((self.Inner.Dx() + 1) * 2) - 1 - (((len(seriesData) - 1) - i) * self.Zoom) + y := ((self.Inner.Dy() + 1) * 4) - 1 - int((float64((self.Inner.Dy())*4)-1)*(seriesData[i]/100)) if x < 0 { // render the line to the last point up to the wall if x > 0-self.Zoom { @@ -98,7 +98,10 @@ func (self *LineGraph) Buffer() *Buffer { continue } if char != 10240 { // empty braille character - buf.SetCell(x, y, Cell{char, colors[x][y], self.Bg}) + buf.SetCell( + Cell{char, AttrPair{colors[x][y], -1}}, + image.Pt(self.Inner.Min.X+x-1, self.Inner.Min.Y+y-1), + ) } } } @@ -106,7 +109,7 @@ func (self *LineGraph) Buffer() *Buffer { // renders key/label ontop for i, seriesName := range seriesList { - if i+2 > self.Y { + if i+2 > self.Inner.Dy() { continue } seriesLineColor, ok := self.LineColor[seriesName] @@ -118,11 +121,12 @@ func (self *LineGraph) Buffer() *Buffer { str := seriesName + " " + self.Labels[seriesName] for k, char := range str { if char != ' ' { - buf.SetCell(3+k, i+2, Cell{char, seriesLineColor, self.Bg}) + buf.SetCell( + Cell{char, AttrPair{seriesLineColor, -1}}, + image.Pt(self.Inner.Min.X+2+k, self.Inner.Min.Y+i+1), + ) } } } - - return buf } diff --git a/src/termui/sparkline.go b/src/termui/sparkline.go index e9073d3f..52963fa4 100644 --- a/src/termui/sparkline.go +++ b/src/termui/sparkline.go @@ -1,7 +1,9 @@ package termui import ( - "fmt" + "image" + + . "github.com/gizak/termui" ) var SPARKS = [8]rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'} @@ -11,8 +13,8 @@ type Sparkline struct { Data []int Title1 string Title2 string - TitleColor Color - LineColor Color + TitleColor Attribute + LineColor Attribute } // Sparklines is a renderable widget which groups together the given sparklines. @@ -28,10 +30,7 @@ func (self *Sparklines) Add(sl Sparkline) { // NewSparkline returns an unrenderable single sparkline that intended to be added into a Sparklines. func NewSparkline() *Sparkline { - return &Sparkline{ - TitleColor: Theme.Fg, - LineColor: Theme.Sparkline, - } + return &Sparkline{} } // NewSparklines return a new *Sparklines with given Sparklines, you can always add a new Sparkline later. @@ -43,8 +42,8 @@ func NewSparklines(ss ...*Sparkline) *Sparklines { } // Buffer implements Bufferer interface. -func (self *Sparklines) Buffer() *Buffer { - buf := self.Block.Buffer() +func (self *Sparklines) Draw(buf *Buffer) { + self.Block.Draw(buf) lc := len(self.Lines) // lineCount @@ -52,48 +51,46 @@ func (self *Sparklines) Buffer() *Buffer { for i, line := range self.Lines { // prints titles - title1Y := 2 + (self.Y/lc)*i - title2Y := (2 + (self.Y/lc)*i) + 1 - title1 := MaxString(line.Title1, self.X) - title2 := MaxString(line.Title2, self.X) - buf.SetString(1, title1Y, title1, line.TitleColor|AttrBold, self.Bg) - buf.SetString(1, title2Y, title2, line.TitleColor|AttrBold, self.Bg) + title1Y := 2 + (self.Inner.Dy()/lc)*i + title2Y := (2 + (self.Inner.Dy()/lc)*i) + 1 + title1 := TrimString(line.Title1, self.Inner.Dx()) + title2 := TrimString(line.Title2, self.Inner.Dx()) + buf.SetString( + title1, + image.Pt(self.Inner.Min.X, self.Inner.Min.Y+title1Y-1), + AttrPair{line.TitleColor | AttrBold, -1}, + ) + buf.SetString( + title2, + image.Pt(self.Inner.Min.X, self.Inner.Min.Y+title2Y-1), + AttrPair{line.TitleColor | AttrBold, -1}, + ) - sparkY := (self.Y / lc) * (i + 1) + sparkY := (self.Inner.Dy() / lc) * (i + 1) // finds max data in current view used for relative heights max := 1 - for i := len(line.Data) - 1; i >= 0 && self.X-((len(line.Data)-1)-i) >= 1; i-- { + for i := len(line.Data) - 1; i >= 0 && self.Inner.Dx()-((len(line.Data)-1)-i) >= 1; i-- { if line.Data[i] > max { max = line.Data[i] } } // prints sparkline - for x := self.X; x >= 1; x-- { + for x := self.Inner.Dx(); x >= 1; x-- { char := SPARKS[0] - if (self.X - x) < len(line.Data) { - offset := self.X - x + if (self.Inner.Dx() - x) < len(line.Data) { + offset := self.Inner.Dx() - x cur_item := line.Data[(len(line.Data)-1)-offset] percent := float64(cur_item) / float64(max) index := int(percent * 7) if index < 0 || index >= len(SPARKS) { - Error("sparkline", - fmt.Sprint( - "len(line.Data): ", len(line.Data), "\n", - "max: ", max, "\n", - "x: ", x, "\n", - "self.X: ", self.X, "\n", - "offset: ", offset, "\n", - "cur_item: ", cur_item, "\n", - "percent: ", percent, "\n", - "index: ", index, "\n", - "len(SPARKS): ", len(SPARKS), - )) + panic("TODO") } char = SPARKS[index] } - buf.SetCell(x, sparkY, Cell{char, line.LineColor, self.Bg}) + buf.SetCell( + Cell{char, AttrPair{line.LineColor, -1}}, + image.Pt(self.Inner.Min.X+x-1, self.Inner.Min.Y+sparkY-1), + ) } } - - return buf } diff --git a/src/termui/table.go b/src/termui/table.go index 7f18f1a3..bb62eec0 100644 --- a/src/termui/table.go +++ b/src/termui/table.go @@ -1,8 +1,10 @@ package termui import ( - "fmt" + "image" "strings" + + . "github.com/gizak/termui" ) // Table tracks all the attributes of a Table instance @@ -19,7 +21,7 @@ type Table struct { PadLeft int Cursor bool - CursorColor Color + CursorColor Attribute UniqueCol int // the column used to identify the selected item SelectedItem string // used to keep the cursor on the correct item if the data changes @@ -30,8 +32,8 @@ type Table struct { // NewTable returns a new Table instance func NewTable() *Table { self := &Table{ - Block: NewBlock(), - CursorColor: Theme.TableCursor, + Block: NewBlock(), + // CursorColor: Theme.TableCursor, SelectedRow: 0, TopRow: 0, UniqueCol: 0, @@ -46,8 +48,8 @@ func (self *Table) ColResize() { } // Buffer implements the Bufferer interface. -func (self *Table) Buffer() *Buffer { - buf := self.Block.Buffer() +func (self *Table) Draw(buf *Buffer) { + self.Block.Draw(buf) self.ColResizer() @@ -67,28 +69,26 @@ func (self *Table) Buffer() *Buffer { continue } // don't render column if it doesn't fit in widget - if width > (self.X-self.CellXPos[i])+1 { + if width > (self.Inner.Dx()-self.CellXPos[i])+1 { continue } - buf.SetString(self.CellXPos[i], 1, h, self.Fg|AttrBold, self.Bg) + buf.SetString( + h, + image.Pt(self.Inner.Min.X+self.CellXPos[i]-1, self.Inner.Min.Y), + AttrPair{Theme.Default.Fg | AttrBold, -1}, + ) } // prints each row - for rowNum := self.TopRow; rowNum < self.TopRow+self.Y-1 && rowNum < len(self.Rows); rowNum++ { + for rowNum := self.TopRow; rowNum < self.TopRow+self.Inner.Dy()-1 && rowNum < len(self.Rows); rowNum++ { if rowNum < 0 || rowNum >= len(self.Rows) { - Error("table rows", - fmt.Sprint( - "rowNum: ", rowNum, "\n", - "self.TopRow: ", self.TopRow, "\n", - "len(self.Rows): ", len(self.Rows), "\n", - "self.Y: ", self.Y, - )) + panic("TODO") } row := self.Rows[rowNum] y := (rowNum + 2) - self.TopRow // prints cursor - fg := self.Fg + fg := Theme.Default.Fg if self.Cursor { if (self.SelectedItem == "" && rowNum == self.SelectedRow) || (self.SelectedItem != "" && self.SelectedItem == row[self.UniqueCol]) { fg = self.CursorColor | AttrReverse @@ -96,7 +96,11 @@ func (self *Table) Buffer() *Buffer { if width == 0 { continue } - buf.SetString(1, y, strings.Repeat(" ", self.X), fg, self.Bg) + buf.SetString( + strings.Repeat(" ", self.Inner.Dx()), + image.Pt(self.Inner.Min.X, self.Inner.Min.Y+y-1), + AttrPair{fg, -1}, + ) } self.SelectedItem = row[self.UniqueCol] self.SelectedRow = rowNum @@ -109,15 +113,17 @@ func (self *Table) Buffer() *Buffer { continue } // don't render column if width is greater than distance to end of widget - if width > (self.X-self.CellXPos[i])+1 { + if width > (self.Inner.Dx()-self.CellXPos[i])+1 { continue } - r := MaxString(row[i], width) - buf.SetString(self.CellXPos[i], y, r, fg, self.Bg) + r := TrimString(row[i], width) + buf.SetString( + r, + image.Pt(self.Inner.Min.X+self.CellXPos[i]-1, self.Inner.Min.Y+y-1), + AttrPair{fg, -1}, + ) } } - - return buf } ///////////////////////////////////////////////////////////////////////////////// @@ -138,8 +144,8 @@ func (self *Table) calcPos() { if self.SelectedRow > len(self.Rows)-1 { self.SelectedRow = len(self.Rows) - 1 } - if self.SelectedRow > self.TopRow+(self.Y-2) { - self.TopRow = self.SelectedRow - (self.Y - 2) + if self.SelectedRow > self.TopRow+(self.Inner.Dy()-2) { + self.TopRow = self.SelectedRow - (self.Inner.Dy() - 2) } } @@ -166,29 +172,29 @@ func (self *Table) Bottom() { // The number of lines in a page is equal to the height of the widgeself. func (self *Table) HalfPageUp() { - self.SelectedRow = self.SelectedRow - (self.Y-2)/2 + self.SelectedRow = self.SelectedRow - (self.Inner.Dy()-2)/2 self.calcPos() } func (self *Table) HalfPageDown() { - self.SelectedRow = self.SelectedRow + (self.Y-2)/2 + self.SelectedRow = self.SelectedRow + (self.Inner.Dy()-2)/2 self.calcPos() } func (self *Table) PageUp() { - self.SelectedRow -= (self.Y - 2) + self.SelectedRow -= (self.Inner.Dy() - 2) self.calcPos() } func (self *Table) PageDown() { - self.SelectedRow += (self.Y - 2) + self.SelectedRow += (self.Inner.Dy() - 2) self.calcPos() } func (self *Table) Click(x, y int) { - x = x - self.XOffset - y = y - self.YOffset - if (x > 0 && x <= self.X) && (y > 0 && y <= self.Y) { + x = x - self.Min.X + y = y - self.Min.Y + if (x > 0 && x <= self.Inner.Dx()) && (y > 0 && y <= self.Inner.Dy()) { self.SelectedRow = (self.TopRow + y) - 2 self.calcPos() } diff --git a/src/widgets/cpu.go b/src/widgets/cpu.go index 649f50d3..c041e67f 100644 --- a/src/widgets/cpu.go +++ b/src/widgets/cpu.go @@ -5,7 +5,7 @@ import ( "log" "time" - ui "github.com/cjbassi/termui" + ui "github.com/cjbassi/gotop/src/termui" psCPU "github.com/shirou/gopsutil/cpu" ) @@ -35,7 +35,7 @@ func NewCPU(interval time.Duration, zoom int, average bool, percpu bool) *CPU { PerCPU: percpu, formatString: formatString, } - self.Label = "CPU Usage" + self.Title = " CPU Usage " self.Zoom = zoom if !(self.Average || self.PerCPU) { diff --git a/src/widgets/disk.go b/src/widgets/disk.go index e8d8f68d..fe2315b7 100644 --- a/src/widgets/disk.go +++ b/src/widgets/disk.go @@ -7,8 +7,8 @@ import ( "strings" "time" + ui "github.com/cjbassi/gotop/src/termui" "github.com/cjbassi/gotop/src/utils" - ui "github.com/cjbassi/termui" psDisk "github.com/shirou/gopsutil/disk" ) @@ -35,7 +35,7 @@ func NewDisk() *Disk { interval: time.Second, Partitions: make(map[string]*Partition), } - self.Label = "Disk Usage" + self.Title = " Disk Usage " self.Header = []string{"Disk", "Mount", "Used", "Free", "R/s", "W/s"} self.Gap = 2 self.ColResizer = self.ColResize @@ -154,8 +154,8 @@ func (self *Disk) update() { // ColResize overrides the default ColResize in the termui table. func (self *Disk) ColResize() { self.ColWidths = []int{ - utils.Max(4, (self.X-29)/2), - utils.Max(5, (self.X-29)/2), + utils.Max(4, (self.Inner.Dx()-29)/2), + utils.Max(5, (self.Inner.Dx()-29)/2), 4, 5, 5, 5, } diff --git a/src/widgets/help.go b/src/widgets/help.go index 19fa302c..ff2fcc4f 100644 --- a/src/widgets/help.go +++ b/src/widgets/help.go @@ -1,9 +1,10 @@ package widgets import ( + "image" "strings" - ui "github.com/cjbassi/termui" + ui "github.com/gizak/termui" ) const KEYBINDS = ` @@ -34,27 +35,33 @@ CPU and Mem graph scaling: ` type HelpMenu struct { - *ui.Block + ui.Block } func NewHelpMenu() *HelpMenu { - block := ui.NewBlock() - block.X = 51 // width - 1 - block.Y = 24 // height - 1 - return &HelpMenu{block} + return &HelpMenu{ + Block: *ui.NewBlock(), + } } -func (self *HelpMenu) Buffer() *ui.Buffer { - buf := self.Block.Buffer() +func (self *HelpMenu) Resize(termWidth, termHeight int) { + textWidth := 53 + textHeight := 22 + x := (termWidth - textWidth) / 2 + y := (termHeight - textHeight) / 2 + + self.Block.SetRect(x, y, textWidth+x, textHeight+y) +} - self.Block.XOffset = (ui.Body.Width - self.Block.X) / 2 // X coordinate - self.Block.YOffset = (ui.Body.Height - self.Block.Y) / 2 // Y coordinate +func (self *HelpMenu) Draw(buf *ui.Buffer) { + self.Block.Draw(buf) for y, line := range strings.Split(KEYBINDS, "\n") { for x, char := range line { - buf.SetCell(x+1, y, ui.NewCell(char, ui.Color(7), self.Bg)) + buf.SetCell( + ui.Cell{char, ui.AttrPair{ui.Attribute(7), -1}}, + image.Pt(self.Inner.Min.X+x, self.Inner.Min.Y+y-1), + ) } } - - return buf } diff --git a/src/widgets/mem.go b/src/widgets/mem.go index 86f3a45c..1e5718c2 100644 --- a/src/widgets/mem.go +++ b/src/widgets/mem.go @@ -5,8 +5,8 @@ import ( "log" "time" + ui "github.com/cjbassi/gotop/src/termui" "github.com/cjbassi/gotop/src/utils" - ui "github.com/cjbassi/termui" psMem "github.com/shirou/gopsutil/mem" ) @@ -20,7 +20,7 @@ func NewMem(interval time.Duration, zoom int) *Mem { LineGraph: ui.NewLineGraph(), interval: interval, } - self.Label = "Memory Usage" + self.Title = " Memory Usage " self.Zoom = zoom self.Data["Main"] = []float64{0} self.Data["Swap"] = []float64{0} diff --git a/src/widgets/net.go b/src/widgets/net.go index c47ae258..1a3c2632 100644 --- a/src/widgets/net.go +++ b/src/widgets/net.go @@ -5,8 +5,8 @@ import ( "log" "time" + ui "github.com/cjbassi/gotop/src/termui" "github.com/cjbassi/gotop/src/utils" - ui "github.com/cjbassi/termui" psNet "github.com/shirou/gopsutil/net" ) @@ -30,7 +30,7 @@ func NewNet() *Net { Sparklines: spark, interval: time.Second, } - self.Label = "Network Usage" + self.Title = " Network Usage " self.update() diff --git a/src/widgets/proc.go b/src/widgets/proc.go index dc04216f..d4ba7392 100644 --- a/src/widgets/proc.go +++ b/src/widgets/proc.go @@ -8,8 +8,9 @@ import ( "strconv" "time" + ui "github.com/cjbassi/gotop/src/termui" "github.com/cjbassi/gotop/src/utils" - ui "github.com/cjbassi/termui" + "github.com/gizak/termui" psCPU "github.com/shirou/gopsutil/cpu" ) @@ -49,7 +50,7 @@ func NewProc() *Proc { sortMethod: "c", group: true, } - self.Label = "Processes" + self.Title = " Processes " self.ColResizer = self.ColResize self.Cursor = true self.Gap = 3 @@ -108,11 +109,11 @@ func (self *Proc) Sort() { // ColResize overrides the default ColResize in the termui table. func (self *Proc) ColResize() { self.ColWidths = []int{ - 5, utils.Max(self.X-26, 10), 4, 4, + 5, utils.Max(self.Inner.Dx()-26, 10), 4, 4, } } -func (self *Proc) ChangeSort(e ui.Event) { +func (self *Proc) ChangeSort(e termui.Event) { if self.sortMethod != e.ID { self.sortMethod = e.ID self.Top() diff --git a/src/widgets/temp.go b/src/widgets/temp.go index ab1ac5ae..f065ad4b 100644 --- a/src/widgets/temp.go +++ b/src/widgets/temp.go @@ -5,10 +5,11 @@ package widgets import ( "fmt" + "image" "sort" "time" - ui "github.com/cjbassi/termui" + ui "github.com/gizak/termui" ) type Temp struct { @@ -16,8 +17,8 @@ type Temp struct { interval time.Duration Data map[string]int Threshold int - TempLow ui.Color - TempHigh ui.Color + TempLow ui.Attribute + TempHigh ui.Attribute Fahrenheit bool } @@ -28,7 +29,7 @@ func NewTemp(fahrenheit bool) *Temp { Data: make(map[string]int), Threshold: 80, // temp at which color should change } - self.Label = "Temperatures" + self.Title = " Temperatures " if fahrenheit { self.Fahrenheit = true @@ -48,8 +49,8 @@ func NewTemp(fahrenheit bool) *Temp { } // Buffer implements ui.Bufferer interface and renders the widget. -func (self *Temp) Buffer() *ui.Buffer { - buf := self.Block.Buffer() +func (self *Temp) Draw(buf *ui.Buffer) { + self.Block.Draw(buf) var keys []string for key := range self.Data { @@ -58,7 +59,7 @@ func (self *Temp) Buffer() *ui.Buffer { sort.Strings(keys) for y, key := range keys { - if y+1 > self.Y { + if y+1 > self.Inner.Dy() { break } @@ -67,14 +68,23 @@ func (self *Temp) Buffer() *ui.Buffer { fg = self.TempHigh } - s := ui.MaxString(key, (self.X - 4)) - buf.SetString(1, y+1, s, self.Fg, self.Bg) + s := ui.TrimString(key, (self.Inner.Dx() - 4)) + buf.SetString(s, + image.Pt(self.Inner.Min.X, self.Inner.Min.Y+y), + ui.Theme.Default, + ) if self.Fahrenheit { - buf.SetString(self.X-3, y+1, fmt.Sprintf("%3dF", self.Data[key]), fg, self.Bg) + buf.SetString( + fmt.Sprintf("%3dF", self.Data[key]), + image.Pt(self.Inner.Dx()-3, y+1), + ui.AttrPair{fg, -1}, + ) } else { - buf.SetString(self.X-3, y+1, fmt.Sprintf("%3dC", self.Data[key]), fg, self.Bg) + buf.SetString( + fmt.Sprintf("%3dC", self.Data[key]), + image.Pt(self.Inner.Max.X-4, self.Inner.Min.Y+y), + ui.AttrPair{fg, -1}, + ) } } - - return buf }