integrate widget order, toggling into global config and compact grid

This commit is contained in:
Bradley Cicenas 2020-01-02 14:00:55 +00:00
parent d34b9c2bf6
commit ee25f80a9c
No known key found for this signature in database
GPG Key ID: AF579ED4B93CBB5C
10 changed files with 186 additions and 14 deletions

View File

@ -16,22 +16,33 @@ var (
type File struct { type File struct {
Options map[string]string `toml:"options"` Options map[string]string `toml:"options"`
Toggles map[string]bool `toml:"toggles"` Toggles map[string]bool `toml:"toggles"`
Widgets []Widget `toml:"widget"`
} }
func exportConfig() File { func exportConfig() File {
lock.RLock()
defer lock.RUnlock()
c := File{ c := File{
Options: make(map[string]string), Options: make(map[string]string),
Toggles: make(map[string]bool), Toggles: make(map[string]bool),
Widgets: make([]Widget, len(GlobalWidgets)),
} }
for _, p := range GlobalParams { for _, p := range GlobalParams {
c.Options[p.Key] = p.Val c.Options[p.Key] = p.Val
} }
for _, sw := range GlobalSwitches { for _, sw := range GlobalSwitches {
c.Toggles[sw.Key] = sw.Val c.Toggles[sw.Key] = sw.Val
} }
for n, w := range GlobalWidgets {
c.Widgets[n] = *w
}
return c return c
} }
//
func Read() error { func Read() error {
var config File var config File
@ -50,6 +61,10 @@ func Read() error {
for k, v := range config.Toggles { for k, v := range config.Toggles {
UpdateSwitch(k, v) UpdateSwitch(k, v)
} }
for _, w := range config.Widgets {
UpdateWidget(strings.ToLower(w.Name), w.Enabled)
}
return nil return nil
} }

View File

@ -3,6 +3,7 @@ package config
import ( import (
"fmt" "fmt"
"os" "os"
"sync"
"github.com/bcicen/ctop/logging" "github.com/bcicen/ctop/logging"
) )
@ -10,17 +11,23 @@ import (
var ( var (
GlobalParams []*Param GlobalParams []*Param
GlobalSwitches []*Switch GlobalSwitches []*Switch
GlobalWidgets []*Widget
lock sync.RWMutex
log = logging.Init() log = logging.Init()
) )
func Init() { func Init() {
for _, p := range params { for _, p := range defaultParams {
GlobalParams = append(GlobalParams, p) GlobalParams = append(GlobalParams, p)
log.Infof("loaded config param: %s: %s", quote(p.Key), quote(p.Val)) log.Infof("loaded default config param: %s: %s", quote(p.Key), quote(p.Val))
} }
for _, s := range switches { for _, s := range defaultSwitches {
GlobalSwitches = append(GlobalSwitches, s) GlobalSwitches = append(GlobalSwitches, s)
log.Infof("loaded config switch: %s: %t", quote(s.Key), s.Val) log.Infof("loaded default config switch: %s: %t", quote(s.Key), s.Val)
}
for _, w := range defaultWidgets {
GlobalWidgets = append(GlobalWidgets, w)
log.Infof("loaded default widget: %s: %t", quote(w.Name), w.Enabled)
} }
} }

View File

@ -1,7 +1,7 @@
package config package config
// defaults // defaults
var params = []*Param{ var defaultParams = []*Param{
&Param{ &Param{
Key: "filterStr", Key: "filterStr",
Val: "", Val: "",
@ -27,6 +27,9 @@ type Param struct {
// Get Param by key // Get Param by key
func Get(k string) *Param { func Get(k string) *Param {
lock.RLock()
defer lock.RUnlock()
for _, p := range GlobalParams { for _, p := range GlobalParams {
if p.Key == k { if p.Key == k {
return p return p
@ -43,7 +46,10 @@ func GetVal(k string) string {
// Set param value // Set param value
func Update(k, v string) { func Update(k, v string) {
p := Get(k) p := Get(k)
log.Noticef("config change: %s: %s -> %s", k, quote(p.Val), quote(v)) log.Noticef("config change [%s]: %s -> %s", k, quote(p.Val), quote(v))
lock.Lock()
defer lock.Unlock()
p.Val = v p.Val = v
// log.Errorf("ignoring update for non-existant parameter: %s", k) // log.Errorf("ignoring update for non-existant parameter: %s", k)
} }

View File

@ -1,7 +1,7 @@
package config package config
// defaults // defaults
var switches = []*Switch{ var defaultSwitches = []*Switch{
&Switch{ &Switch{
Key: "sortReversed", Key: "sortReversed",
Val: false, Val: false,
@ -37,6 +37,9 @@ type Switch struct {
// GetSwitch returns Switch by key // GetSwitch returns Switch by key
func GetSwitch(k string) *Switch { func GetSwitch(k string) *Switch {
lock.RLock()
defer lock.RUnlock()
for _, sw := range GlobalSwitches { for _, sw := range GlobalSwitches {
if sw.Key == k { if sw.Key == k {
return sw return sw
@ -52,8 +55,12 @@ func GetSwitchVal(k string) bool {
func UpdateSwitch(k string, val bool) { func UpdateSwitch(k string, val bool) {
sw := GetSwitch(k) sw := GetSwitch(k)
lock.Lock()
defer lock.Unlock()
if sw.Val != val { if sw.Val != val {
log.Noticef("config change: %s: %t -> %t", k, sw.Val, val) log.Noticef("config change [%s]: %t -> %t", k, sw.Val, val)
sw.Val = val sw.Val = val
} }
} }
@ -61,8 +68,12 @@ func UpdateSwitch(k string, val bool) {
// Toggle a boolean switch // Toggle a boolean switch
func Toggle(k string) { func Toggle(k string) {
sw := GetSwitch(k) sw := GetSwitch(k)
lock.Lock()
defer lock.Unlock()
newVal := !sw.Val newVal := !sw.Val
log.Noticef("config change: %s: %t -> %t", k, sw.Val, newVal) log.Noticef("config change [%s]: %t -> %t", k, sw.Val, newVal)
sw.Val = newVal sw.Val = newVal
//log.Errorf("ignoring toggle for non-existant switch: %s", k) //log.Errorf("ignoring toggle for non-existant switch: %s", k)
} }

122
config/widget.go Normal file
View File

@ -0,0 +1,122 @@
package config
import (
"strings"
)
// defaults
var defaultWidgets = []*Widget{
&Widget{
Name: "status",
Enabled: true,
},
&Widget{
Name: "name",
Enabled: true,
},
&Widget{
Name: "id",
Enabled: true,
},
&Widget{
Name: "cpu",
Enabled: true,
},
&Widget{
Name: "mem",
Enabled: true,
},
&Widget{
Name: "net",
Enabled: true,
},
&Widget{
Name: "io",
Enabled: true,
},
&Widget{
Name: "pids",
Enabled: true,
},
}
type Widget struct {
Name string
Enabled bool
}
// GetWidget returns a Widget by name
func GetWidget(name string) *Widget {
lock.RLock()
defer lock.RUnlock()
for _, w := range GlobalWidgets {
if w.Name == name {
return w
}
}
log.Errorf("widget name not found: %s", name)
return &Widget{} // default
}
// Widgets returns a copy of all configurable Widgets, in order
func Widgets() []Widget {
a := make([]Widget, len(GlobalWidgets))
lock.RLock()
defer lock.RUnlock()
for n, w := range GlobalWidgets {
a[n] = *w
}
return a
}
// EnabledWidgets returns an ordered array of enabled widget names
func EnabledWidgets() (a []string) {
for _, w := range Widgets() {
if w.Enabled {
a = append(a, w.Name)
}
}
return a
}
func UpdateWidget(name string, enabled bool) {
w := GetWidget(name)
oldVal := w.Enabled
log.Noticef("config change [%s-enabled]: %t -> %t", name, oldVal, enabled)
lock.Lock()
defer lock.Unlock()
w.Enabled = enabled
}
func ToggleWidgetEnabled(name string) {
w := GetWidget(name)
newVal := !w.Enabled
log.Noticef("config change [%s-enabled]: %t -> %t", name, w.Enabled, newVal)
lock.Lock()
defer lock.Unlock()
w.Enabled = newVal
}
// UpdateWidgets replaces existing ordered widgets with those provided
func UpdateWidgets(newWidgets []Widget) {
oldOrder := widgetNames()
lock.Lock()
for n, w := range newWidgets {
GlobalWidgets[n] = &w
}
lock.Unlock()
log.Noticef("config change [widget-order]: %s -> %s", oldOrder, widgetNames())
}
func widgetNames() string {
a := make([]string, len(GlobalWidgets))
for n, w := range Widgets() {
a[n] = w.Name
}
return strings.Join(a, ", ")
}

View File

@ -5,6 +5,7 @@ import (
"github.com/bcicen/ctop/cwidgets" "github.com/bcicen/ctop/cwidgets"
"github.com/bcicen/ctop/models" "github.com/bcicen/ctop/models"
ui "github.com/gizak/termui" ui "github.com/gizak/termui"
) )

View File

@ -17,11 +17,7 @@ type CompactGrid struct {
func NewCompactGrid() *CompactGrid { func NewCompactGrid() *CompactGrid {
cg := &CompactGrid{header: NewCompactHeader()} cg := &CompactGrid{header: NewCompactHeader()}
for _, wFn := range allCols { cg.RebuildHeader()
w := wFn()
cg.cols = append(cg.cols, w)
cg.header.addFieldPar(w.Header())
}
return cg return cg
} }
@ -41,6 +37,14 @@ func (cg *CompactGrid) Align() {
} }
} }
func (cg *CompactGrid) RebuildHeader() {
cg.cols = newRowWidgets()
cg.header.clearFieldPars()
for _, col := range cg.cols {
cg.header.addFieldPar(col.Header())
}
}
func (cg *CompactGrid) Clear() { cg.Rows = []RowBufferer{} } func (cg *CompactGrid) Clear() { cg.Rows = []RowBufferer{} }
func (cg *CompactGrid) GetHeight() int { return len(cg.Rows) + cg.header.Height } func (cg *CompactGrid) GetHeight() int { return len(cg.Rows) + cg.header.Height }
func (cg *CompactGrid) SetX(x int) { cg.X = x } func (cg *CompactGrid) SetX(x int) { cg.X = x }

View File

@ -51,6 +51,10 @@ func (row *CompactHeader) Buffer() ui.Buffer {
return buf return buf
} }
func (row *CompactHeader) clearFieldPars() {
row.pars = []*ui.Par{}
}
func (row *CompactHeader) addFieldPar(s string) { func (row *CompactHeader) addFieldPar(s string) {
p := ui.NewPar(s) p := ui.NewPar(s)
p.Height = row.Height p.Height = row.Height

View File

@ -2,6 +2,7 @@ package compact
import ( import (
"github.com/bcicen/ctop/models" "github.com/bcicen/ctop/models"
ui "github.com/gizak/termui" ui "github.com/gizak/termui"
) )

View File

@ -5,6 +5,7 @@ import (
"github.com/bcicen/ctop/cwidgets" "github.com/bcicen/ctop/cwidgets"
"github.com/bcicen/ctop/models" "github.com/bcicen/ctop/models"
ui "github.com/gizak/termui" ui "github.com/gizak/termui"
) )