summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean E. Russell <ser@ser1.net>2020-02-20 08:19:15 -0600
committerSean E. Russell <ser@ser1.net>2020-02-20 08:19:15 -0600
commit7b09a00230e059129e010039a159ef9ce7aecc11 (patch)
tree7583287cfc2fdc277d7d361ec484e17c3016a0af
parent66ad0f878540dee82ae2c2b5c561754b6480a157 (diff)
Issue #56. Slight improvement in layout algorithm. Still doesn't handle > 2 columns well, but it's more correct and lays the foundation for a correct solution. It's clear, however, that a full table model parser will require a substantial rewrite and, possibly, a change in the layout syntax. That would add substantial complexity, so maybe for some future effort. I'll fix the basic column layout (rowspans at the edges), and then shelve it.
-rw-r--r--cmd/gotop/main.go1
-rw-r--r--layout/layout.go39
-rw-r--r--layout/layout_test.go27
-rw-r--r--layouts/kitchensink9
-rw-r--r--layouts/many_columns_test4
5 files changed, 59 insertions, 21 deletions
diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go
index a85f147..9d1f0a5 100644
--- a/cmd/gotop/main.go
+++ b/cmd/gotop/main.go
@@ -423,7 +423,6 @@ func getLayout(conf gotop.Config) io.Reader {
case "battery":
return strings.NewReader(batteryUI)
default:
- log.Printf("layout = %s", conf.Layout)
fp := filepath.Join(conf.ConfigDir, conf.Layout)
fin, err := os.Open(fp)
if err != nil {
diff --git a/layout/layout.go b/layout/layout.go
index 359b47e..0ab6b54 100644
--- a/layout/layout.go
+++ b/layout/layout.go
@@ -31,17 +31,17 @@ var widgetNames []string = []string{"cpu", "disk", "mem", "temp", "net", "procs"
func Layout(wl layout, c gotop.Config) (*MyGrid, error) {
rowDefs := wl.Rows
- uiRows := make([]ui.GridItem, 0)
+ uiRows := make([][]interface{}, 0)
numRows := countNumRows(wl.Rows)
- var uiRow ui.GridItem
+ var uiRow []interface{}
for len(rowDefs) > 0 {
uiRow, rowDefs = processRow(c, numRows, rowDefs)
uiRows = append(uiRows, uiRow)
}
rgs := make([]interface{}, 0)
+ rh := 1.0 / float64(len(uiRows))
for _, ur := range uiRows {
- ur.HeightRatio = ur.HeightRatio / float64(numRows)
- rgs = append(rgs, ur)
+ rgs = append(rgs, ui.NewRow(rh, ur...))
}
grid := &MyGrid{ui.NewGrid(), nil, nil}
grid.Set(rgs...)
@@ -58,11 +58,10 @@ func Layout(wl layout, c gotop.Config) (*MyGrid, error) {
// if there's a row span widget in the row; in this case, it'll consume as many
// rows as the largest row span object in the row, and produce an uber-row
// containing all that stuff. It returns a slice without the consumed elements.
-func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridItem, [][]widgetRule) {
- // FIXME: 3\:A 2\:B\nC should stop consuming rows when all columns are full
+func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) ([]interface{}, [][]widgetRule) {
// Recursive function #3. See the comment in deepFindProc.
if len(rowDefs) < 1 {
- return ui.GridItem{}, [][]widgetRule{}
+ return nil, [][]widgetRule{}
}
// The height of the tallest widget in this row; the number of rows that
// will be consumed, and the overall height of the row that will be
@@ -87,6 +86,7 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridIte
columns = append(columns, make([]interface{}, 0))
}
colHeights := make([]int, numCols)
+outer:
for i, row := range processing {
// A definition may fill up the columns before all rows are consumed,
// e.g. wid1/2 wid2/2. This block checks for that and, if it occurs,
@@ -102,16 +102,25 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridIte
rowDefs = append(processing[i:], rowDefs...)
break
}
- // Not all rows have been consumed, so go ahead and place the row's widgets in columns
- for _, wid := range row {
- for j, ch := range colHeights {
- if ch+wid.Height <= maxHeight {
- widget := makeWidget(c, wid)
- columns[j] = append(columns[j], ui.NewRow(float64(wid.Height)/float64(maxHeight), widget))
- colHeights[j] += wid.Height
+ // Not all rows have been consumed, so go ahead and place the row's
+ // widgets in columns
+ for w, widg := range row {
+ placed := false
+ for k := w; k < len(colHeights); k++ { // there are enough columns
+ ch := colHeights[k]
+ if ch+widg.Height <= maxHeight {
+ widget := makeWidget(c, widg)
+ columns[k] = append(columns[k], ui.NewRow(float64(widg.Height)/float64(maxHeight), widget))
+ colHeights[k] += widg.Height
+ placed = true
break
}
}
+ // If all columns are full, break out, return the row, and continue processing
+ if !placed {
+ rowDefs = processing[i:]
+ break outer
+ }
}
}
var uiColumns []interface{}
@@ -121,7 +130,7 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (ui.GridIte
}
}
- return ui.NewRow(1.0/float64(numRows), uiColumns...), rowDefs
+ return uiColumns, rowDefs
}
type Metric interface {
diff --git a/layout/layout_test.go b/layout/layout_test.go
index d1f016d..568bbee 100644
--- a/layout/layout_test.go
+++ b/layout/layout_test.go
@@ -101,6 +101,33 @@ func TestParsing(t *testing.T) {
assert.Equal(t, 1, l.Rows[1][0].Height)
assert.Equal(t, 1.0, l.Rows[1][0].Weight)
}},
+ {"cpu/2 mem/1 6:procs\n3:temp/1 2:disk/2\npower\nnet procs", func(l layout) {
+ assert.Equal(t, 4, len(l.Rows))
+ // First row
+ assert.Equal(t, 3, len(l.Rows[0]))
+ assert.Equal(t, 1, l.Rows[0][0].Height)
+ assert.Equal(t, 0.5, l.Rows[0][0].Weight)
+ assert.Equal(t, 1, l.Rows[0][1].Height)
+ assert.Equal(t, 0.25, l.Rows[0][1].Weight)
+ assert.Equal(t, 6, l.Rows[0][2].Height)
+ assert.Equal(t, 0.25, l.Rows[0][2].Weight)
+ // Second row
+ assert.Equal(t, 2, len(l.Rows[1]))
+ assert.Equal(t, 3, l.Rows[1][0].Height)
+ assert.Equal(t, 1/3.0, l.Rows[1][0].Weight)
+ assert.Equal(t, 2, l.Rows[1][1].Height)
+ assert.Equal(t, 2/3.0, l.Rows[1][1].Weight)
+ // Third row
+ assert.Equal(t, 1, len(l.Rows[2]))
+ assert.Equal(t, 1, l.Rows[2][0].Height)
+ assert.Equal(t, 1.0, l.Rows[2][0].Weight)
+ // Fourth row
+ assert.Equal(t, 2, len(l.Rows[3]))
+ assert.Equal(t, 1, l.Rows[3][0].Height)
+ assert.Equal(t, 0.5, l.Rows[3][0].Weight)
+ assert.Equal(t, 1, l.Rows[3][1].Height)
+ assert.Equal(t, 0.5, l.Rows[3][1].Weight)
+ }},
}
for _, tc := range tests {
diff --git a/layouts/kitchensink b/layouts/kitchensink
index 762ff91..5e25894 100644
--- a/layouts/kitchensink
+++ b/layouts/kitchensink
@@ -1,5 +1,4 @@
-cpu/2 mem/1
-3:temp/1 2:disk/2
- power
- power
-net procs
+cpu/2 mem/1
+3:temp/1 2:disk/2
+ power
+net procs
diff --git a/layouts/many_columns_test b/layouts/many_columns_test
new file mode 100644
index 0000000..f2d57e3
--- /dev/null
+++ b/layouts/many_columns_test
@@ -0,0 +1,4 @@
+cpu/2 mem/1 6:procs/2
+3:temp/1 2:disk/2
+power
+net procs