mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Reimpliments the module configuration validation
Now supports displaying errors from multiple widgets.
This commit is contained in:
@@ -11,18 +11,16 @@ import (
|
||||
|
||||
//BarGraph lets make graphs
|
||||
type BarGraph struct {
|
||||
enabled bool
|
||||
focusable bool
|
||||
key string
|
||||
maxStars int
|
||||
name string
|
||||
starChar string
|
||||
commonSettings *cfg.Common
|
||||
enabled bool
|
||||
focusable bool
|
||||
key string
|
||||
maxStars int
|
||||
name string
|
||||
starChar string
|
||||
|
||||
RefreshInt int
|
||||
View *tview.TextView
|
||||
settings *cfg.Common
|
||||
|
||||
Position
|
||||
}
|
||||
|
||||
type Bar struct {
|
||||
@@ -34,22 +32,15 @@ type Bar struct {
|
||||
// NewBarGraph initialize your fancy new graph
|
||||
func NewBarGraph(app *tview.Application, name string, settings *cfg.Common, focusable bool) BarGraph {
|
||||
widget := BarGraph{
|
||||
enabled: settings.Enabled,
|
||||
focusable: focusable,
|
||||
maxStars: settings.Config.UInt("graphStars", 20),
|
||||
name: settings.Title,
|
||||
starChar: settings.Config.UString("graphIcon", "|"),
|
||||
RefreshInt: settings.RefreshInterval,
|
||||
settings: settings,
|
||||
enabled: settings.Enabled,
|
||||
focusable: focusable,
|
||||
maxStars: settings.Config.UInt("graphStars", 20),
|
||||
name: settings.Title,
|
||||
starChar: settings.Config.UString("graphIcon", "|"),
|
||||
RefreshInt: settings.RefreshInterval,
|
||||
commonSettings: settings,
|
||||
}
|
||||
|
||||
widget.Position = NewPosition(
|
||||
settings.Position.Top,
|
||||
settings.Position.Left,
|
||||
settings.Position.Width,
|
||||
settings.Position.Height,
|
||||
)
|
||||
|
||||
widget.View = widget.addView()
|
||||
widget.View.SetChangedFunc(func() {
|
||||
app.Draw()
|
||||
@@ -60,10 +51,14 @@ func NewBarGraph(app *tview.Application, name string, settings *cfg.Common, focu
|
||||
|
||||
func (widget *BarGraph) BorderColor() string {
|
||||
if widget.Focusable() {
|
||||
return widget.settings.Colors.BorderFocusable
|
||||
return widget.commonSettings.Colors.BorderFocusable
|
||||
}
|
||||
|
||||
return widget.settings.Colors.BorderNormal
|
||||
return widget.commonSettings.Colors.BorderNormal
|
||||
}
|
||||
|
||||
func (widget *BarGraph) CommonSettings() *cfg.Common {
|
||||
return widget.commonSettings
|
||||
}
|
||||
|
||||
func (widget *BarGraph) Disable() {
|
||||
@@ -86,12 +81,6 @@ func (widget *BarGraph) FocusChar() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsPositionable returns TRUE if the widget has valid position parameters, FALSE if it has
|
||||
// invalid position parameters (ie: cannot be placed onscreen)
|
||||
func (widget *BarGraph) IsPositionable() bool {
|
||||
return widget.Position.IsValid()
|
||||
}
|
||||
|
||||
func (widget *BarGraph) Key() string {
|
||||
return widget.key
|
||||
}
|
||||
@@ -120,22 +109,6 @@ func (widget *BarGraph) ConfigText() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *BarGraph) addView() *tview.TextView {
|
||||
view := tview.NewTextView()
|
||||
|
||||
view.SetBackgroundColor(ColorFor(widget.settings.Colors.Background))
|
||||
view.SetBorder(true)
|
||||
view.SetBorderColor(ColorFor(widget.BorderColor()))
|
||||
view.SetDynamicColors(true)
|
||||
view.SetTitle(widget.Name())
|
||||
view.SetTitleColor(ColorFor(widget.settings.Colors.Title))
|
||||
view.SetWrap(false)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
// BuildBars will build a string of * to represent your data of [time][value]
|
||||
// time should be passed as a int64
|
||||
func (widget *BarGraph) BuildBars(data []Bar) {
|
||||
@@ -188,4 +161,18 @@ func BuildStars(data []Bar, maxStars int, starChar string) string {
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
/* -------------------- Exported Functions -------------------- */
|
||||
/* -------------------- Unexported Functions -------------------- */
|
||||
|
||||
func (widget *BarGraph) addView() *tview.TextView {
|
||||
view := tview.NewTextView()
|
||||
|
||||
view.SetBackgroundColor(ColorFor(widget.commonSettings.Colors.Background))
|
||||
view.SetBorder(true)
|
||||
view.SetBorderColor(ColorFor(widget.BorderColor()))
|
||||
view.SetDynamicColors(true)
|
||||
view.SetTitle(widget.Name())
|
||||
view.SetTitleColor(ColorFor(widget.commonSettings.Colors.Title))
|
||||
view.SetWrap(false)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
@@ -29,16 +29,12 @@ func (display *Display) add(widget Wtfable) {
|
||||
return
|
||||
}
|
||||
|
||||
if !widget.IsPositionable() {
|
||||
return
|
||||
}
|
||||
|
||||
display.Grid.AddItem(
|
||||
widget.TextView(),
|
||||
widget.Top(),
|
||||
widget.Left(),
|
||||
widget.Height(),
|
||||
widget.Width(),
|
||||
widget.CommonSettings().Top,
|
||||
widget.CommonSettings().Left,
|
||||
widget.CommonSettings().Height,
|
||||
widget.CommonSettings().Width,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
|
||||
@@ -3,7 +3,6 @@ package wtf
|
||||
type Enabler interface {
|
||||
Disabled() bool
|
||||
Enabled() bool
|
||||
IsPositionable() bool
|
||||
|
||||
Disable()
|
||||
}
|
||||
|
||||
@@ -192,11 +192,14 @@ func (tracker *FocusTracker) focusables() []Wtfable {
|
||||
|
||||
// Sort for deterministic ordering
|
||||
sort.SliceStable(focusable[:], func(i, j int) bool {
|
||||
if focusable[i].Top() < focusable[j].Top() {
|
||||
iTop := focusable[i].CommonSettings().Top
|
||||
jTop := focusable[j].CommonSettings().Top
|
||||
|
||||
if iTop < jTop {
|
||||
return true
|
||||
}
|
||||
if focusable[i].Top() == focusable[j].Top() {
|
||||
return focusable[i].Left() < focusable[j].Left()
|
||||
if iTop == jTop {
|
||||
return focusable[i].CommonSettings().Left < focusable[j].CommonSettings().Left
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package wtf
|
||||
|
||||
type Position struct {
|
||||
top int
|
||||
left int
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
func NewPosition(top, left, width, height int) Position {
|
||||
pos := Position{
|
||||
top: top,
|
||||
left: left,
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
|
||||
return pos
|
||||
}
|
||||
|
||||
func (pos *Position) IsValid() bool {
|
||||
if pos.height < 1 || pos.left < 0 || pos.top < 0 || pos.width < 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (pos *Position) Height() int {
|
||||
return pos.height
|
||||
}
|
||||
|
||||
func (pos *Position) Left() int {
|
||||
return pos.left
|
||||
}
|
||||
|
||||
func (pos *Position) Top() int {
|
||||
return pos.top
|
||||
}
|
||||
|
||||
func (pos *Position) Width() int {
|
||||
return pos.width
|
||||
}
|
||||
@@ -42,10 +42,10 @@ func (widget *ScrollableWidget) GetSelected() int {
|
||||
|
||||
func (widget *ScrollableWidget) RowColor(idx int) string {
|
||||
if widget.View.HasFocus() && (idx == widget.Selected) {
|
||||
return widget.CommonSettings.DefaultFocusedRowColor()
|
||||
return widget.CommonSettings().DefaultFocusedRowColor()
|
||||
}
|
||||
|
||||
return widget.CommonSettings.RowColor(idx)
|
||||
return widget.CommonSettings().RowColor(idx)
|
||||
}
|
||||
|
||||
func (widget *ScrollableWidget) Next() {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type TextWidget struct {
|
||||
commonSettings *cfg.Common
|
||||
enabled bool
|
||||
focusable bool
|
||||
focusChar string
|
||||
@@ -17,14 +18,11 @@ type TextWidget struct {
|
||||
app *tview.Application
|
||||
|
||||
View *tview.TextView
|
||||
|
||||
CommonSettings *cfg.Common
|
||||
Position
|
||||
}
|
||||
|
||||
func NewTextWidget(app *tview.Application, commonSettings *cfg.Common, focusable bool) TextWidget {
|
||||
widget := TextWidget{
|
||||
CommonSettings: commonSettings,
|
||||
commonSettings: commonSettings,
|
||||
|
||||
app: app,
|
||||
enabled: commonSettings.Enabled,
|
||||
@@ -34,13 +32,6 @@ func NewTextWidget(app *tview.Application, commonSettings *cfg.Common, focusable
|
||||
refreshInterval: commonSettings.RefreshInterval,
|
||||
}
|
||||
|
||||
widget.Position = NewPosition(
|
||||
commonSettings.Position.Top,
|
||||
commonSettings.Position.Left,
|
||||
commonSettings.Position.Width,
|
||||
commonSettings.Position.Height,
|
||||
)
|
||||
|
||||
widget.View = widget.addView()
|
||||
|
||||
return widget
|
||||
@@ -50,10 +41,14 @@ func NewTextWidget(app *tview.Application, commonSettings *cfg.Common, focusable
|
||||
|
||||
func (widget *TextWidget) BorderColor() string {
|
||||
if widget.Focusable() {
|
||||
return widget.CommonSettings.Colors.BorderFocusable
|
||||
return widget.commonSettings.Colors.BorderFocusable
|
||||
}
|
||||
|
||||
return widget.CommonSettings.Colors.BorderNormal
|
||||
return widget.commonSettings.Colors.BorderNormal
|
||||
}
|
||||
|
||||
func (widget *TextWidget) CommonSettings() *cfg.Common {
|
||||
return widget.commonSettings
|
||||
}
|
||||
|
||||
func (widget *TextWidget) ContextualTitle(defaultStr string) string {
|
||||
@@ -84,12 +79,6 @@ func (widget *TextWidget) FocusChar() string {
|
||||
return widget.focusChar
|
||||
}
|
||||
|
||||
// IsPositionable returns TRUE if the widget has valid position parameters, FALSE if it has
|
||||
// invalid position parameters (ie: cannot be placed onscreen)
|
||||
func (widget *TextWidget) IsPositionable() bool {
|
||||
return widget.Position.IsValid()
|
||||
}
|
||||
|
||||
func (widget *TextWidget) Name() string {
|
||||
return widget.name
|
||||
}
|
||||
@@ -120,7 +109,7 @@ func (widget *TextWidget) Redraw(title, text string, wrap bool) {
|
||||
}
|
||||
|
||||
func (widget *TextWidget) HelpText() string {
|
||||
return fmt.Sprintf("\n There is no help available for widget %s", widget.CommonSettings.Module.Type)
|
||||
return fmt.Sprintf("\n There is no help available for widget %s", widget.commonSettings.Module.Type)
|
||||
}
|
||||
|
||||
func (widget *TextWidget) ConfigText() string {
|
||||
@@ -132,10 +121,10 @@ func (widget *TextWidget) ConfigText() string {
|
||||
func (widget *TextWidget) addView() *tview.TextView {
|
||||
view := tview.NewTextView()
|
||||
|
||||
view.SetBackgroundColor(ColorFor(widget.CommonSettings.Colors.Background))
|
||||
view.SetBackgroundColor(ColorFor(widget.commonSettings.Colors.Background))
|
||||
view.SetBorderColor(ColorFor(widget.BorderColor()))
|
||||
view.SetTextColor(ColorFor(widget.CommonSettings.Colors.Text))
|
||||
view.SetTitleColor(ColorFor(widget.CommonSettings.Colors.Title))
|
||||
view.SetTextColor(ColorFor(widget.commonSettings.Colors.Text))
|
||||
view.SetTitleColor(ColorFor(widget.commonSettings.Colors.Title))
|
||||
|
||||
view.SetBorder(true)
|
||||
view.SetDynamicColors(true)
|
||||
|
||||
51
wtf/widget_validation.go
Normal file
51
wtf/widget_validation.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package wtf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
// ValidateWidgets rolls through all the enabled widgets and looks for configuration errors.
|
||||
// If it finds any it stringifies them, writes them to the console, and kills the app gracefully
|
||||
func ValidateWidgets(widgets []Wtfable) {
|
||||
var errStr string
|
||||
hasErrors := false
|
||||
|
||||
for _, widget := range widgets {
|
||||
var widgetErrStr string
|
||||
|
||||
for _, val := range widget.CommonSettings().Validations() {
|
||||
if val.HasError() {
|
||||
hasErrors = true
|
||||
widgetErrStr += fmt.Sprintf(" - %s\t%s %v\n", val, aurora.Red("Error:"), val.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if widgetErrStr != "" {
|
||||
errStr += fmt.Sprintf(
|
||||
"%s\n",
|
||||
fmt.Sprintf(
|
||||
"%s in %s configuration",
|
||||
aurora.Red("Errors"),
|
||||
aurora.Yellow(
|
||||
fmt.Sprintf(
|
||||
"%s.position",
|
||||
widget.Name(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
errStr += widgetErrStr + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
if hasErrors {
|
||||
fmt.Println()
|
||||
fmt.Printf(errStr)
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package wtf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Check that all the loaded widgets are valid for display
|
||||
func ValidateWidgets(widgets []Wtfable) (bool, error) {
|
||||
result := true
|
||||
var err error
|
||||
|
||||
for _, widget := range widgets {
|
||||
if widget.Enabled() && !widget.IsPositionable() {
|
||||
errStr := fmt.Sprintf("Widget config has invalid values: %s", widget.Name())
|
||||
log.Fatalln(errStr)
|
||||
}
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package wtf
|
||||
|
||||
import (
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
@@ -9,16 +11,13 @@ type Wtfable interface {
|
||||
Scheduler
|
||||
|
||||
BorderColor() string
|
||||
ConfigText() string
|
||||
FocusChar() string
|
||||
Focusable() bool
|
||||
HelpText() string
|
||||
Name() string
|
||||
SetFocusChar(string)
|
||||
TextView() *tview.TextView
|
||||
HelpText() string
|
||||
ConfigText() string
|
||||
|
||||
Height() int
|
||||
Left() int
|
||||
Top() int
|
||||
Width() int
|
||||
CommonSettings() *cfg.Common
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user