triggers mechanism integration
This commit is contained in:
parent
9b22083af8
commit
9b487ada89
|
@ -3,6 +3,7 @@ package asciibox
|
||||||
import (
|
import (
|
||||||
fl "github.com/mbndr/figlet4go"
|
fl "github.com/mbndr/figlet4go"
|
||||||
"github.com/sqshq/sampler/asset"
|
"github.com/sqshq/sampler/asset"
|
||||||
|
"github.com/sqshq/sampler/config"
|
||||||
"github.com/sqshq/sampler/data"
|
"github.com/sqshq/sampler/data"
|
||||||
ui "github.com/sqshq/termui"
|
ui "github.com/sqshq/termui"
|
||||||
"image"
|
"image"
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
|
|
||||||
type AsciiBox struct {
|
type AsciiBox struct {
|
||||||
ui.Block
|
ui.Block
|
||||||
|
data.Consumer
|
||||||
text string
|
text string
|
||||||
ascii string
|
ascii string
|
||||||
style ui.Style
|
style ui.Style
|
||||||
|
@ -17,22 +19,15 @@ type AsciiBox struct {
|
||||||
options *fl.RenderOptions
|
options *fl.RenderOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
type AsciiFont string
|
|
||||||
|
|
||||||
const (
|
|
||||||
AsciiFontFlat AsciiFont = "flat"
|
|
||||||
AsciiFont3D AsciiFont = "3d"
|
|
||||||
)
|
|
||||||
|
|
||||||
const asciiFontExtension = ".flf"
|
const asciiFontExtension = ".flf"
|
||||||
|
|
||||||
func NewAsciiBox(title string, font AsciiFont, color ui.Color) *AsciiBox {
|
func NewAsciiBox(c config.AsciiBoxConfig) *AsciiBox {
|
||||||
|
|
||||||
block := *ui.NewBlock()
|
block := *ui.NewBlock()
|
||||||
block.Title = title
|
block.Title = c.Title
|
||||||
|
|
||||||
options := fl.NewRenderOptions()
|
options := fl.NewRenderOptions()
|
||||||
options.FontName = string(font)
|
options.FontName = string(*c.Font)
|
||||||
|
|
||||||
fontStr, err := asset.Asset(options.FontName + asciiFontExtension)
|
fontStr, err := asset.Asset(options.FontName + asciiFontExtension)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -41,17 +36,29 @@ func NewAsciiBox(title string, font AsciiFont, color ui.Color) *AsciiBox {
|
||||||
render := fl.NewAsciiRender()
|
render := fl.NewAsciiRender()
|
||||||
_ = render.LoadBindataFont(fontStr, options.FontName)
|
_ = render.LoadBindataFont(fontStr, options.FontName)
|
||||||
|
|
||||||
return &AsciiBox{
|
box := AsciiBox{
|
||||||
Block: block,
|
Block: block,
|
||||||
style: ui.NewStyle(color),
|
Consumer: data.NewConsumer(),
|
||||||
render: render,
|
style: ui.NewStyle(*c.Color),
|
||||||
options: options,
|
render: render,
|
||||||
|
options: options,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go box.consume()
|
||||||
|
|
||||||
|
return &box
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AsciiBox) ConsumeSample(sample data.Sample) {
|
func (a *AsciiBox) consume() {
|
||||||
a.text = sample.Value
|
for {
|
||||||
a.ascii, _ = a.render.RenderOpts(sample.Value, a.options)
|
select {
|
||||||
|
case sample := <-a.SampleChannel:
|
||||||
|
a.text = sample.Value
|
||||||
|
a.ascii, _ = a.render.RenderOpts(sample.Value, a.options)
|
||||||
|
//case alert := <-a.alertChannel:
|
||||||
|
// TODO base alerting mechanism
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AsciiBox) Draw(buffer *ui.Buffer) {
|
func (a *AsciiBox) Draw(buffer *ui.Buffer) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ const (
|
||||||
|
|
||||||
type BarChart struct {
|
type BarChart struct {
|
||||||
ui.Block
|
ui.Block
|
||||||
|
data.Consumer
|
||||||
bars []Bar
|
bars []Bar
|
||||||
scale int
|
scale int
|
||||||
maxValue float64
|
maxValue float64
|
||||||
|
@ -33,19 +34,31 @@ type Bar struct {
|
||||||
func NewBarChart(title string, scale int) *BarChart {
|
func NewBarChart(title string, scale int) *BarChart {
|
||||||
block := *ui.NewBlock()
|
block := *ui.NewBlock()
|
||||||
block.Title = title
|
block.Title = title
|
||||||
return &BarChart{
|
chart := BarChart{
|
||||||
Block: block,
|
Block: block,
|
||||||
|
Consumer: data.NewConsumer(),
|
||||||
bars: []Bar{},
|
bars: []Bar{},
|
||||||
scale: scale,
|
scale: scale,
|
||||||
maxValue: -math.MaxFloat64,
|
maxValue: -math.MaxFloat64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go chart.consume()
|
||||||
|
|
||||||
|
return &chart
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BarChart) AddBar(label string, color ui.Color) {
|
func (b *BarChart) consume() {
|
||||||
b.bars = append(b.bars, Bar{label: label, color: color, value: 0})
|
for {
|
||||||
|
select {
|
||||||
|
case sample := <-b.SampleChannel:
|
||||||
|
b.consumeSample(sample)
|
||||||
|
//case alert := <-b.alertChannel:
|
||||||
|
// TODO base alerting mechanism
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BarChart) ConsumeSample(sample data.Sample) {
|
func (b *BarChart) consumeSample(sample data.Sample) {
|
||||||
|
|
||||||
b.count++
|
b.count++
|
||||||
|
|
||||||
|
@ -76,6 +89,10 @@ func (b *BarChart) ConsumeSample(sample data.Sample) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BarChart) AddBar(label string, color ui.Color) {
|
||||||
|
b.bars = append(b.bars, Bar{label: label, color: color, value: 0})
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BarChart) reselectMaxValue() {
|
func (b *BarChart) reselectMaxValue() {
|
||||||
maxValue := -math.MaxFloat64
|
maxValue := -math.MaxFloat64
|
||||||
for _, bar := range b.bars {
|
for _, bar := range b.bars {
|
||||||
|
|
|
@ -18,6 +18,7 @@ const (
|
||||||
|
|
||||||
type Gauge struct {
|
type Gauge struct {
|
||||||
ui.Block
|
ui.Block
|
||||||
|
data.Consumer
|
||||||
minValue float64
|
minValue float64
|
||||||
maxValue float64
|
maxValue float64
|
||||||
curValue float64
|
curValue float64
|
||||||
|
@ -26,12 +27,30 @@ type Gauge struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGauge(title string, scale int, color ui.Color) *Gauge {
|
func NewGauge(title string, scale int, color ui.Color) *Gauge {
|
||||||
|
|
||||||
block := *ui.NewBlock()
|
block := *ui.NewBlock()
|
||||||
block.Title = title
|
block.Title = title
|
||||||
return &Gauge{
|
|
||||||
Block: block,
|
gauge := Gauge{
|
||||||
scale: scale,
|
Block: block,
|
||||||
color: color,
|
Consumer: data.NewConsumer(),
|
||||||
|
scale: scale,
|
||||||
|
color: color,
|
||||||
|
}
|
||||||
|
|
||||||
|
go gauge.consume()
|
||||||
|
|
||||||
|
return &gauge
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Gauge) consume() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case sample := <-g.SampleChannel:
|
||||||
|
g.ConsumeSample(sample)
|
||||||
|
//case alert := <-g.alertChannel:
|
||||||
|
// TODO base alerting mechanism
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,35 +5,35 @@ import (
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getRectLeftAgeCenter(rect image.Rectangle) image.Point {
|
func GetRectLeftAgeCenter(rect image.Rectangle) image.Point {
|
||||||
return image.Point{
|
return image.Point{
|
||||||
X: rect.Min.X,
|
X: rect.Min.X,
|
||||||
Y: rect.Min.Y + rect.Dy()/2,
|
Y: rect.Min.Y + rect.Dy()/2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRectRightAgeCenter(rect image.Rectangle) image.Point {
|
func GetRectRightAgeCenter(rect image.Rectangle) image.Point {
|
||||||
return image.Point{
|
return image.Point{
|
||||||
X: rect.Max.X,
|
X: rect.Max.X,
|
||||||
Y: rect.Min.Y + rect.Dy()/2,
|
Y: rect.Min.Y + rect.Dy()/2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRectTopAgeCenter(rect image.Rectangle) image.Point {
|
func GetRectTopAgeCenter(rect image.Rectangle) image.Point {
|
||||||
return image.Point{
|
return image.Point{
|
||||||
X: rect.Min.X + rect.Dx()/2,
|
X: rect.Min.X + rect.Dx()/2,
|
||||||
Y: rect.Min.Y,
|
Y: rect.Min.Y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRectBottomAgeCenter(rect image.Rectangle) image.Point {
|
func GetRectBottomAgeCenter(rect image.Rectangle) image.Point {
|
||||||
return image.Point{
|
return image.Point{
|
||||||
X: rect.Min.X + rect.Dx()/2,
|
X: rect.Min.X + rect.Dx()/2,
|
||||||
Y: rect.Max.Y,
|
Y: rect.Max.Y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDistance(p1 image.Point, p2 image.Point) float64 {
|
func GetDistance(p1 image.Point, p2 image.Point) float64 {
|
||||||
x := math.Abs(float64(p1.X - p2.X))
|
x := math.Abs(float64(p1.X - p2.X))
|
||||||
y := math.Abs(float64(p1.Y - p2.Y))
|
y := math.Abs(float64(p1.Y - p2.Y))
|
||||||
return math.Sqrt(x*x + y*y)
|
return math.Sqrt(x*x + y*y)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package component
|
package layout
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/sqshq/sampler/component"
|
||||||
"github.com/sqshq/sampler/component/runchart"
|
"github.com/sqshq/sampler/component/runchart"
|
||||||
"github.com/sqshq/sampler/config"
|
"github.com/sqshq/sampler/config"
|
||||||
"github.com/sqshq/sampler/console"
|
"github.com/sqshq/sampler/console"
|
||||||
|
@ -11,10 +12,10 @@ import (
|
||||||
|
|
||||||
type Layout struct {
|
type Layout struct {
|
||||||
ui.Block
|
ui.Block
|
||||||
Components []Component
|
Components []component.Component
|
||||||
ChangeModeEvents chan Mode
|
ChangeModeEvents chan Mode
|
||||||
statusbar *StatusBar
|
statusbar *component.StatusBar
|
||||||
menu *Menu
|
menu *component.Menu
|
||||||
mode Mode
|
mode Mode
|
||||||
selection int
|
selection int
|
||||||
}
|
}
|
||||||
|
@ -38,7 +39,7 @@ const (
|
||||||
statusbarHeight = 1
|
statusbarHeight = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewLayout(width, height int, statusline *StatusBar, menu *Menu) *Layout {
|
func NewLayout(width, height int, statusline *component.StatusBar, menu *component.Menu) *Layout {
|
||||||
|
|
||||||
block := *ui.NewBlock()
|
block := *ui.NewBlock()
|
||||||
block.SetRect(0, 0, width, height)
|
block.SetRect(0, 0, width, height)
|
||||||
|
@ -46,7 +47,7 @@ func NewLayout(width, height int, statusline *StatusBar, menu *Menu) *Layout {
|
||||||
|
|
||||||
return &Layout{
|
return &Layout{
|
||||||
Block: block,
|
Block: block,
|
||||||
Components: make([]Component, 0),
|
Components: make([]component.Component, 0),
|
||||||
statusbar: statusline,
|
statusbar: statusline,
|
||||||
menu: menu,
|
menu: menu,
|
||||||
mode: ModeDefault,
|
mode: ModeDefault,
|
||||||
|
@ -56,16 +57,23 @@ func NewLayout(width, height int, statusline *StatusBar, menu *Menu) *Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Layout) AddComponent(Type config.ComponentType, drawable ui.Drawable, title string, position config.Position, size config.Size, refreshRateMs int) {
|
func (l *Layout) AddComponent(Type config.ComponentType, drawable ui.Drawable, title string, position config.Position, size config.Size, refreshRateMs int) {
|
||||||
l.Components = append(l.Components, Component{Type, drawable, title, position, size, refreshRateMs})
|
l.Components = append(l.Components, component.Component{
|
||||||
|
Type: Type,
|
||||||
|
Drawable: drawable,
|
||||||
|
Title: title,
|
||||||
|
Position: position,
|
||||||
|
Size: size,
|
||||||
|
RefreshRateMs: refreshRateMs,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Layout) GetComponents(Type config.ComponentType) []ui.Drawable {
|
func (l *Layout) GetComponents(Type config.ComponentType) []component.Component {
|
||||||
|
|
||||||
var components []ui.Drawable
|
var components []component.Component
|
||||||
|
|
||||||
for _, component := range l.Components {
|
for _, c := range l.Components {
|
||||||
if component.Type == Type {
|
if c.Type == Type {
|
||||||
components = append(components, component.Drawable)
|
components = append(components, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,36 +95,36 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
||||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||||
chart.DisableSelection()
|
chart.DisableSelection()
|
||||||
}
|
}
|
||||||
l.menu.idle()
|
l.menu.Idle()
|
||||||
l.changeMode(ModePause)
|
l.changeMode(ModePause)
|
||||||
}
|
}
|
||||||
case console.KeyEnter:
|
case console.KeyEnter:
|
||||||
switch l.mode {
|
switch l.mode {
|
||||||
case ModeComponentSelect:
|
case ModeComponentSelect:
|
||||||
l.menu.choose()
|
l.menu.Choose()
|
||||||
l.changeMode(ModeMenuOptionSelect)
|
l.changeMode(ModeMenuOptionSelect)
|
||||||
case ModeMenuOptionSelect:
|
case ModeMenuOptionSelect:
|
||||||
option := l.menu.getSelectedOption()
|
option := l.menu.GetSelectedOption()
|
||||||
switch option {
|
switch option {
|
||||||
case MenuOptionMove:
|
case component.MenuOptionMove:
|
||||||
l.changeMode(ModeComponentMove)
|
l.changeMode(ModeComponentMove)
|
||||||
l.menu.moveOrResize()
|
l.menu.MoveOrResize()
|
||||||
case MenuOptionResize:
|
case component.MenuOptionResize:
|
||||||
l.changeMode(ModeComponentResize)
|
l.changeMode(ModeComponentResize)
|
||||||
l.menu.moveOrResize()
|
l.menu.MoveOrResize()
|
||||||
case MenuOptionPinpoint:
|
case component.MenuOptionPinpoint:
|
||||||
l.changeMode(ModeChartPinpoint)
|
l.changeMode(ModeChartPinpoint)
|
||||||
l.menu.idle()
|
l.menu.Idle()
|
||||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||||
chart.MoveSelection(0)
|
chart.MoveSelection(0)
|
||||||
case MenuOptionResume:
|
case component.MenuOptionResume:
|
||||||
l.changeMode(ModeDefault)
|
l.changeMode(ModeDefault)
|
||||||
l.menu.idle()
|
l.menu.Idle()
|
||||||
}
|
}
|
||||||
case ModeComponentMove:
|
case ModeComponentMove:
|
||||||
fallthrough
|
fallthrough
|
||||||
case ModeComponentResize:
|
case ModeComponentResize:
|
||||||
l.menu.idle()
|
l.menu.Idle()
|
||||||
l.changeMode(ModeDefault)
|
l.changeMode(ModeDefault)
|
||||||
}
|
}
|
||||||
case console.KeyEsc:
|
case console.KeyEsc:
|
||||||
|
@ -128,20 +136,20 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
||||||
case ModeComponentSelect:
|
case ModeComponentSelect:
|
||||||
fallthrough
|
fallthrough
|
||||||
case ModeMenuOptionSelect:
|
case ModeMenuOptionSelect:
|
||||||
l.menu.idle()
|
l.menu.Idle()
|
||||||
l.changeMode(ModeDefault)
|
l.changeMode(ModeDefault)
|
||||||
}
|
}
|
||||||
case console.KeyLeft:
|
case console.KeyLeft:
|
||||||
switch l.mode {
|
switch l.mode {
|
||||||
case ModeDefault:
|
case ModeDefault:
|
||||||
l.changeMode(ModeComponentSelect)
|
l.changeMode(ModeComponentSelect)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeChartPinpoint:
|
case ModeChartPinpoint:
|
||||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||||
chart.MoveSelection(-1)
|
chart.MoveSelection(-1)
|
||||||
case ModeComponentSelect:
|
case ModeComponentSelect:
|
||||||
l.moveSelection(e)
|
l.moveSelection(e)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeComponentMove:
|
case ModeComponentMove:
|
||||||
l.getSelectedComponent().Move(-1, 0)
|
l.getSelectedComponent().Move(-1, 0)
|
||||||
case ModeComponentResize:
|
case ModeComponentResize:
|
||||||
|
@ -151,13 +159,13 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
||||||
switch l.mode {
|
switch l.mode {
|
||||||
case ModeDefault:
|
case ModeDefault:
|
||||||
l.changeMode(ModeComponentSelect)
|
l.changeMode(ModeComponentSelect)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeChartPinpoint:
|
case ModeChartPinpoint:
|
||||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||||
chart.MoveSelection(1)
|
chart.MoveSelection(1)
|
||||||
case ModeComponentSelect:
|
case ModeComponentSelect:
|
||||||
l.moveSelection(e)
|
l.moveSelection(e)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeComponentMove:
|
case ModeComponentMove:
|
||||||
l.getSelectedComponent().Move(1, 0)
|
l.getSelectedComponent().Move(1, 0)
|
||||||
case ModeComponentResize:
|
case ModeComponentResize:
|
||||||
|
@ -167,12 +175,12 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
||||||
switch l.mode {
|
switch l.mode {
|
||||||
case ModeDefault:
|
case ModeDefault:
|
||||||
l.changeMode(ModeComponentSelect)
|
l.changeMode(ModeComponentSelect)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeComponentSelect:
|
case ModeComponentSelect:
|
||||||
l.moveSelection(e)
|
l.moveSelection(e)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeMenuOptionSelect:
|
case ModeMenuOptionSelect:
|
||||||
l.menu.up()
|
l.menu.Up()
|
||||||
case ModeComponentMove:
|
case ModeComponentMove:
|
||||||
l.getSelectedComponent().Move(0, -1)
|
l.getSelectedComponent().Move(0, -1)
|
||||||
case ModeComponentResize:
|
case ModeComponentResize:
|
||||||
|
@ -182,12 +190,12 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
||||||
switch l.mode {
|
switch l.mode {
|
||||||
case ModeDefault:
|
case ModeDefault:
|
||||||
l.changeMode(ModeComponentSelect)
|
l.changeMode(ModeComponentSelect)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeComponentSelect:
|
case ModeComponentSelect:
|
||||||
l.moveSelection(e)
|
l.moveSelection(e)
|
||||||
l.menu.highlight(l.getComponent(l.selection))
|
l.menu.Highlight(l.getComponent(l.selection))
|
||||||
case ModeMenuOptionSelect:
|
case ModeMenuOptionSelect:
|
||||||
l.menu.down()
|
l.menu.Down()
|
||||||
case ModeComponentMove:
|
case ModeComponentMove:
|
||||||
l.getSelectedComponent().Move(0, 1)
|
l.getSelectedComponent().Move(0, 1)
|
||||||
case ModeComponentResize:
|
case ModeComponentResize:
|
||||||
|
@ -200,11 +208,11 @@ func (l *Layout) ChangeDimensions(width, height int) {
|
||||||
l.SetRect(0, 0, width, height)
|
l.SetRect(0, 0, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Layout) getComponent(i int) Component {
|
func (l *Layout) getComponent(i int) *component.Component {
|
||||||
return l.Components[i]
|
return &l.Components[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Layout) getSelectedComponent() *Component {
|
func (l *Layout) getSelectedComponent() *component.Component {
|
||||||
return &l.Components[l.selection]
|
return &l.Components[l.selection]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,24 +237,25 @@ func (l *Layout) moveSelection(direction string) {
|
||||||
|
|
||||||
switch direction {
|
switch direction {
|
||||||
case console.KeyLeft:
|
case console.KeyLeft:
|
||||||
previouslySelectedCornerPoint = getRectLeftAgeCenter(previouslySelected.Drawable.GetRect())
|
previouslySelectedCornerPoint = component.GetRectLeftAgeCenter(previouslySelected.Drawable.GetRect())
|
||||||
newlySelectedCornerPoint = getRectRightAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
newlySelectedCornerPoint = component.GetRectRightAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||||
currentCornerPoint = getRectRightAgeCenter(current.Drawable.GetRect())
|
currentCornerPoint = component.GetRectRightAgeCenter(current.Drawable.GetRect())
|
||||||
case console.KeyRight:
|
case console.KeyRight:
|
||||||
previouslySelectedCornerPoint = getRectRightAgeCenter(previouslySelected.Drawable.GetRect())
|
previouslySelectedCornerPoint = component.GetRectRightAgeCenter(previouslySelected.Drawable.GetRect())
|
||||||
newlySelectedCornerPoint = getRectLeftAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
newlySelectedCornerPoint = component.GetRectLeftAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||||
currentCornerPoint = getRectLeftAgeCenter(current.Drawable.GetRect())
|
currentCornerPoint = component.GetRectLeftAgeCenter(current.Drawable.GetRect())
|
||||||
case console.KeyUp:
|
case console.KeyUp:
|
||||||
previouslySelectedCornerPoint = getRectTopAgeCenter(previouslySelected.Drawable.GetRect())
|
previouslySelectedCornerPoint = component.GetRectTopAgeCenter(previouslySelected.Drawable.GetRect())
|
||||||
newlySelectedCornerPoint = getRectBottomAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
newlySelectedCornerPoint = component.GetRectBottomAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||||
currentCornerPoint = getRectBottomAgeCenter(current.Drawable.GetRect())
|
currentCornerPoint = component.GetRectBottomAgeCenter(current.Drawable.GetRect())
|
||||||
case console.KeyDown:
|
case console.KeyDown:
|
||||||
previouslySelectedCornerPoint = getRectBottomAgeCenter(previouslySelected.Drawable.GetRect())
|
previouslySelectedCornerPoint = component.GetRectBottomAgeCenter(previouslySelected.Drawable.GetRect())
|
||||||
newlySelectedCornerPoint = getRectTopAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
newlySelectedCornerPoint = component.GetRectTopAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||||
currentCornerPoint = getRectTopAgeCenter(current.Drawable.GetRect())
|
currentCornerPoint = component.GetRectTopAgeCenter(current.Drawable.GetRect())
|
||||||
}
|
}
|
||||||
|
|
||||||
if getDistance(previouslySelectedCornerPoint, currentCornerPoint) < getDistance(previouslySelectedCornerPoint, newlySelectedCornerPoint) {
|
if component.GetDistance(previouslySelectedCornerPoint, currentCornerPoint) <
|
||||||
|
component.GetDistance(previouslySelectedCornerPoint, newlySelectedCornerPoint) {
|
||||||
newlySelectedIndex = i
|
newlySelectedIndex = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,12 +268,12 @@ func (l *Layout) Draw(buffer *ui.Buffer) {
|
||||||
columnWidth := float64(l.GetRect().Dx()) / float64(columnsCount)
|
columnWidth := float64(l.GetRect().Dx()) / float64(columnsCount)
|
||||||
rowHeight := float64(l.GetRect().Dy()-statusbarHeight) / float64(rowsCount)
|
rowHeight := float64(l.GetRect().Dy()-statusbarHeight) / float64(rowsCount)
|
||||||
|
|
||||||
for _, component := range l.Components {
|
for _, c := range l.Components {
|
||||||
|
|
||||||
x1 := math.Floor(float64(component.Position.X) * columnWidth)
|
x1 := math.Floor(float64(c.Position.X) * columnWidth)
|
||||||
y1 := math.Floor(float64(component.Position.Y) * rowHeight)
|
y1 := math.Floor(float64(c.Position.Y) * rowHeight)
|
||||||
x2 := x1 + math.Floor(float64(component.Size.X))*columnWidth
|
x2 := x1 + math.Floor(float64(c.Size.X))*columnWidth
|
||||||
y2 := y1 + math.Floor(float64(component.Size.Y))*rowHeight
|
y2 := y1 + math.Floor(float64(c.Size.Y))*rowHeight
|
||||||
|
|
||||||
if x2-x1 < minDimension {
|
if x2-x1 < minDimension {
|
||||||
x2 = x1 + minDimension
|
x2 = x1 + minDimension
|
||||||
|
@ -274,8 +283,8 @@ func (l *Layout) Draw(buffer *ui.Buffer) {
|
||||||
y2 = y1 + minDimension
|
y2 = y1 + minDimension
|
||||||
}
|
}
|
||||||
|
|
||||||
component.Drawable.SetRect(int(x1), int(y1), int(x2), int(y2))
|
c.Drawable.SetRect(int(x1), int(y1), int(x2), int(y2))
|
||||||
component.Drawable.Draw(buffer)
|
c.Drawable.Draw(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.statusbar.SetRect(
|
l.statusbar.SetRect(
|
|
@ -48,26 +48,26 @@ func NewMenu() *Menu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) getSelectedOption() MenuOption {
|
func (m *Menu) GetSelectedOption() MenuOption {
|
||||||
return m.option
|
return m.option
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) highlight(component Component) {
|
func (m *Menu) Highlight(component *Component) {
|
||||||
m.component = component
|
m.component = *component
|
||||||
m.updateDimensions()
|
m.updateDimensions()
|
||||||
m.mode = MenuModeHighlight
|
m.mode = MenuModeHighlight
|
||||||
m.Title = component.Title
|
m.Title = component.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) choose() {
|
func (m *Menu) Choose() {
|
||||||
m.mode = MenuModeOptionSelect
|
m.mode = MenuModeOptionSelect
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) idle() {
|
func (m *Menu) Idle() {
|
||||||
m.mode = MenuModeIdle
|
m.mode = MenuModeIdle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) up() {
|
func (m *Menu) Up() {
|
||||||
for i := 1; i < len(m.options); i++ {
|
for i := 1; i < len(m.options); i++ {
|
||||||
if m.options[i] == m.option {
|
if m.options[i] == m.option {
|
||||||
m.option = m.options[i-1]
|
m.option = m.options[i-1]
|
||||||
|
@ -75,11 +75,11 @@ func (m *Menu) up() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.option == MenuOptionPinpoint && m.component.Type != config.TypeRunChart {
|
if m.option == MenuOptionPinpoint && m.component.Type != config.TypeRunChart {
|
||||||
m.up()
|
m.Up()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) down() {
|
func (m *Menu) Down() {
|
||||||
for i := 0; i < len(m.options)-1; i++ {
|
for i := 0; i < len(m.options)-1; i++ {
|
||||||
if m.options[i] == m.option {
|
if m.options[i] == m.option {
|
||||||
m.option = m.options[i+1]
|
m.option = m.options[i+1]
|
||||||
|
@ -87,11 +87,11 @@ func (m *Menu) down() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.option == MenuOptionPinpoint && m.component.Type != config.TypeRunChart {
|
if m.option == MenuOptionPinpoint && m.component.Type != config.TypeRunChart {
|
||||||
m.down()
|
m.Down()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Menu) moveOrResize() {
|
func (m *Menu) MoveOrResize() {
|
||||||
m.mode = MenuModeMoveAndResize
|
m.mode = MenuModeMoveAndResize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,13 +35,13 @@ func (c *RunChart) newChartGrid() ChartGrid {
|
||||||
func (c *RunChart) renderAxes(buffer *ui.Buffer) {
|
func (c *RunChart) renderAxes(buffer *ui.Buffer) {
|
||||||
// draw origin cell
|
// draw origin cell
|
||||||
buffer.SetCell(
|
buffer.SetCell(
|
||||||
ui.NewCell(ui.BOTTOM_LEFT, ui.NewStyle(ui.ColorWhite)),
|
ui.NewCell(ui.BOTTOM_LEFT, ui.NewStyle(console.ColorWhite)),
|
||||||
image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, c.Inner.Max.Y-xAxisLabelsHeight-1))
|
image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, c.Inner.Max.Y-xAxisLabelsHeight-1))
|
||||||
|
|
||||||
// draw x axis line
|
// draw x axis line
|
||||||
for i := c.grid.minTimeWidth + 1; i < c.Inner.Dx(); i++ {
|
for i := c.grid.minTimeWidth + 1; i < c.Inner.Dx(); i++ {
|
||||||
buffer.SetCell(
|
buffer.SetCell(
|
||||||
ui.NewCell(ui.HORIZONTAL_DASH, ui.NewStyle(ui.ColorWhite)),
|
ui.NewCell(ui.HORIZONTAL_DASH, ui.NewStyle(console.ColorWhite)),
|
||||||
image.Pt(i+c.Inner.Min.X, c.Inner.Max.Y-xAxisLabelsHeight-1))
|
image.Pt(i+c.Inner.Min.X, c.Inner.Max.Y-xAxisLabelsHeight-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
|
||||||
// draw y axis line
|
// draw y axis line
|
||||||
for i := 0; i < c.Inner.Dy()-xAxisLabelsHeight-1; i++ {
|
for i := 0; i < c.Inner.Dy()-xAxisLabelsHeight-1; i++ {
|
||||||
buffer.SetCell(
|
buffer.SetCell(
|
||||||
ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(ui.ColorWhite)),
|
ui.NewCell(ui.VERTICAL_DASH, ui.NewStyle(console.ColorWhite)),
|
||||||
image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, i+c.Inner.Min.Y))
|
image.Pt(c.Inner.Min.X+c.grid.minTimeWidth, i+c.Inner.Min.Y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
|
||||||
labelTime := c.grid.timeRange.max.Add(time.Duration(-i) * c.timescale)
|
labelTime := c.grid.timeRange.max.Add(time.Duration(-i) * c.timescale)
|
||||||
buffer.SetString(
|
buffer.SetString(
|
||||||
labelTime.Format("15:04:05"),
|
labelTime.Format("15:04:05"),
|
||||||
ui.NewStyle(ui.ColorWhite),
|
ui.NewStyle(console.ColorWhite),
|
||||||
image.Pt(c.grid.maxTimeWidth-xAxisLabelsWidth/2-i*(xAxisGridWidth), c.Inner.Max.Y-1))
|
image.Pt(c.grid.maxTimeWidth-xAxisLabelsWidth/2-i*(xAxisGridWidth), c.Inner.Max.Y-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +78,13 @@ func (c *RunChart) renderAxes(buffer *ui.Buffer) {
|
||||||
value := c.grid.valueExtrema.max - (valuePerY * float64(i) * (yAxisLabelsIndent + yAxisLabelsHeight))
|
value := c.grid.valueExtrema.max - (valuePerY * float64(i) * (yAxisLabelsIndent + yAxisLabelsHeight))
|
||||||
buffer.SetString(
|
buffer.SetString(
|
||||||
formatValue(value, c.scale),
|
formatValue(value, c.scale),
|
||||||
ui.NewStyle(ui.ColorWhite),
|
ui.NewStyle(console.ColorWhite),
|
||||||
image.Pt(c.Inner.Min.X, 1+c.Inner.Min.Y+i*(yAxisLabelsIndent+yAxisLabelsHeight)))
|
image.Pt(c.Inner.Min.X, 1+c.Inner.Min.Y+i*(yAxisLabelsIndent+yAxisLabelsHeight)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buffer.SetString(
|
buffer.SetString(
|
||||||
formatValue(c.grid.valueExtrema.max, c.scale),
|
formatValue(c.grid.valueExtrema.max, c.scale),
|
||||||
ui.NewStyle(ui.ColorWhite),
|
ui.NewStyle(console.ColorWhite),
|
||||||
image.Pt(c.Inner.Min.X, c.Inner.Min.Y+c.Inner.Dy()/2))
|
image.Pt(c.Inner.Min.X, c.Inner.Min.Y+c.Inner.Dy()/2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package runchart
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/sqshq/sampler/console"
|
||||||
ui "github.com/sqshq/termui"
|
ui "github.com/sqshq/termui"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
"math"
|
||||||
|
@ -54,7 +55,7 @@ func (c *RunChart) renderLegend(buffer *ui.Buffer, rectangle image.Rectangle) {
|
||||||
y := c.Inner.Min.Y + yAxisLegendIndent + row*height
|
y := c.Inner.Min.Y + yAxisLegendIndent + row*height
|
||||||
|
|
||||||
titleStyle := ui.NewStyle(line.color)
|
titleStyle := ui.NewStyle(line.color)
|
||||||
detailsStyle := ui.NewStyle(ui.ColorWhite)
|
detailsStyle := ui.NewStyle(console.ColorWhite)
|
||||||
|
|
||||||
buffer.SetString(string(ui.DOT), titleStyle, image.Pt(x-2, y))
|
buffer.SetString(string(ui.DOT), titleStyle, image.Pt(x-2, y))
|
||||||
buffer.SetString(line.label, titleStyle, image.Pt(x, y))
|
buffer.SetString(line.label, titleStyle, image.Pt(x, y))
|
||||||
|
|
|
@ -2,9 +2,10 @@ package runchart
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/sqshq/sampler/component/trigger"
|
"github.com/sqshq/sampler/config"
|
||||||
"github.com/sqshq/sampler/console"
|
"github.com/sqshq/sampler/console"
|
||||||
"github.com/sqshq/sampler/data"
|
"github.com/sqshq/sampler/data"
|
||||||
|
"github.com/sqshq/sampler/trigger"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -37,6 +38,7 @@ const (
|
||||||
|
|
||||||
type RunChart struct {
|
type RunChart struct {
|
||||||
ui.Block
|
ui.Block
|
||||||
|
data.Consumer
|
||||||
triggers []trigger.Trigger
|
triggers []trigger.Trigger
|
||||||
lines []TimeLine
|
lines []TimeLine
|
||||||
grid ChartGrid
|
grid ChartGrid
|
||||||
|
@ -73,17 +75,35 @@ type ValueExtrema struct {
|
||||||
min float64
|
min float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRunChart(title string, scale int, refreshRateMs int, legend Legend) *RunChart {
|
func NewRunChart(c config.RunChartConfig, l Legend) *RunChart {
|
||||||
|
|
||||||
block := *ui.NewBlock()
|
block := *ui.NewBlock()
|
||||||
block.Title = title
|
block.Title = c.Title
|
||||||
return &RunChart{
|
|
||||||
|
chart := RunChart{
|
||||||
Block: block,
|
Block: block,
|
||||||
|
Consumer: data.NewConsumer(),
|
||||||
lines: []TimeLine{},
|
lines: []TimeLine{},
|
||||||
timescale: calculateTimescale(refreshRateMs),
|
timescale: calculateTimescale(*c.RefreshRateMs),
|
||||||
mutex: &sync.Mutex{},
|
mutex: &sync.Mutex{},
|
||||||
scale: scale,
|
scale: *c.Scale,
|
||||||
mode: ModeDefault,
|
mode: ModeDefault,
|
||||||
legend: legend,
|
legend: l,
|
||||||
|
}
|
||||||
|
|
||||||
|
go chart.consume()
|
||||||
|
|
||||||
|
return &chart
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RunChart) consume() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case sample := <-c.SampleChannel:
|
||||||
|
c.consumeSample(sample)
|
||||||
|
//case alert := <-c.alertChannel:
|
||||||
|
// TODO base alerting mechanism
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +143,12 @@ func (c *RunChart) AddLine(Label string, color ui.Color) {
|
||||||
c.lines = append(c.lines, line)
|
c.lines = append(c.lines, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RunChart) ConsumeSample(sample data.Sample) {
|
func (c *RunChart) consumeSample(sample data.Sample) {
|
||||||
|
|
||||||
float, err := strconv.ParseFloat(sample.Value, 64)
|
float, err := strconv.ParseFloat(sample.Value, 64)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO visual notification + check sample.Error
|
// TODO visual notification
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
|
|
|
@ -27,7 +27,7 @@ func NewStatusLine(configFileName string) *StatusBar {
|
||||||
"(Q) quit",
|
"(Q) quit",
|
||||||
"(P) pause",
|
"(P) pause",
|
||||||
"(<->) selection",
|
"(<->) selection",
|
||||||
"(ESC) reset alarm",
|
"(ESC) reset alerts",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/sqshq/sampler/component/asciibox"
|
"github.com/sqshq/sampler/console"
|
||||||
"github.com/sqshq/sampler/data"
|
|
||||||
ui "github.com/sqshq/termui"
|
ui "github.com/sqshq/termui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ComponentType rune
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeRunChart ComponentType = 0
|
||||||
|
TypeBarChart ComponentType = 1
|
||||||
|
TypeTextBox ComponentType = 2
|
||||||
|
TypeAsciiBox ComponentType = 3
|
||||||
|
TypeGauge ComponentType = 4
|
||||||
|
)
|
||||||
|
|
||||||
type ComponentConfig struct {
|
type ComponentConfig struct {
|
||||||
Title string `yaml:"title"`
|
Title string `yaml:"title"`
|
||||||
RefreshRateMs *int `yaml:"refresh-rate-ms,omitempty"`
|
RefreshRateMs *int `yaml:"refresh-rate-ms,omitempty"`
|
||||||
|
@ -32,26 +41,26 @@ type GaugeConfig struct {
|
||||||
Scale *int `yaml:"scale,omitempty"`
|
Scale *int `yaml:"scale,omitempty"`
|
||||||
Color *ui.Color `yaml:"color,omitempty"`
|
Color *ui.Color `yaml:"color,omitempty"`
|
||||||
Values map[string]string `yaml:"values"`
|
Values map[string]string `yaml:"values"`
|
||||||
Items []data.Item `yaml:",omitempty"`
|
Items []Item `yaml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BarChartConfig struct {
|
type BarChartConfig struct {
|
||||||
ComponentConfig `yaml:",inline"`
|
ComponentConfig `yaml:",inline"`
|
||||||
Scale *int `yaml:"scale,omitempty"`
|
Scale *int `yaml:"scale,omitempty"`
|
||||||
Items []data.Item `yaml:"items"`
|
Items []Item `yaml:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AsciiBoxConfig struct {
|
type AsciiBoxConfig struct {
|
||||||
ComponentConfig `yaml:",inline"`
|
ComponentConfig `yaml:",inline"`
|
||||||
data.Item `yaml:",inline"`
|
Item `yaml:",inline"`
|
||||||
Font *asciibox.AsciiFont `yaml:"font,omitempty"`
|
Font *console.AsciiFont `yaml:"font,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RunChartConfig struct {
|
type RunChartConfig struct {
|
||||||
ComponentConfig `yaml:",inline"`
|
ComponentConfig `yaml:",inline"`
|
||||||
Legend *LegendConfig `yaml:"legend,omitempty"`
|
Legend *LegendConfig `yaml:"legend,omitempty"`
|
||||||
Scale *int `yaml:"scale,omitempty"`
|
Scale *int `yaml:"scale,omitempty"`
|
||||||
Items []data.Item `yaml:"items"`
|
Items []Item `yaml:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LegendConfig struct {
|
type LegendConfig struct {
|
||||||
|
@ -69,15 +78,11 @@ type Size struct {
|
||||||
Y int `yaml:"h"`
|
Y int `yaml:"h"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComponentType rune
|
type Item struct {
|
||||||
|
Label *string `yaml:"label,omitempty"`
|
||||||
const (
|
Script string `yaml:"value"`
|
||||||
TypeRunChart ComponentType = 0
|
Color *ui.Color `yaml:"color,omitempty"`
|
||||||
TypeBarChart ComponentType = 1
|
}
|
||||||
TypeTextBox ComponentType = 2
|
|
||||||
TypeAsciiBox ComponentType = 3
|
|
||||||
TypeGauge ComponentType = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
type ComponentSettings struct {
|
type ComponentSettings struct {
|
||||||
Type ComponentType
|
Type ComponentType
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/sqshq/sampler/component/asciibox"
|
|
||||||
"github.com/sqshq/sampler/console"
|
"github.com/sqshq/sampler/console"
|
||||||
"github.com/sqshq/sampler/data"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -71,10 +69,10 @@ func (c *Config) setDefaultValues() {
|
||||||
p := defaultScale
|
p := defaultScale
|
||||||
g.Scale = &p
|
g.Scale = &p
|
||||||
}
|
}
|
||||||
var items []data.Item
|
var items []Item
|
||||||
for label, script := range g.Values {
|
for label, script := range g.Values {
|
||||||
l := label
|
l := label
|
||||||
items = append(items, data.Item{Label: &l, Script: script})
|
items = append(items, Item{Label: &l, Script: script})
|
||||||
}
|
}
|
||||||
g.Items = items
|
g.Items = items
|
||||||
c.Gauges[i] = g
|
c.Gauges[i] = g
|
||||||
|
@ -93,7 +91,7 @@ func (c *Config) setDefaultValues() {
|
||||||
box.Label = &label
|
box.Label = &label
|
||||||
}
|
}
|
||||||
if box.Font == nil {
|
if box.Font == nil {
|
||||||
font := asciibox.AsciiFontFlat
|
font := console.AsciiFontFlat
|
||||||
box.Font = &font
|
box.Font = &font
|
||||||
}
|
}
|
||||||
if box.Color == nil {
|
if box.Color == nil {
|
||||||
|
|
|
@ -14,6 +14,13 @@ const (
|
||||||
AppVersion = "0.1.0"
|
AppVersion = "0.1.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type AsciiFont string
|
||||||
|
|
||||||
|
const (
|
||||||
|
AsciiFontFlat AsciiFont = "flat"
|
||||||
|
AsciiFont3D AsciiFont = "3d"
|
||||||
|
)
|
||||||
|
|
||||||
type Console struct{}
|
type Console struct{}
|
||||||
|
|
||||||
func (self *Console) Init() {
|
func (self *Console) Init() {
|
||||||
|
|
|
@ -20,7 +20,7 @@ const (
|
||||||
ColorOrange ui.Color = 166
|
ColorOrange ui.Color = 166
|
||||||
ColorPurple ui.Color = 129
|
ColorPurple ui.Color = 129
|
||||||
ColorGreen ui.Color = 64
|
ColorGreen ui.Color = 64
|
||||||
ColorDarkGrey ui.Color = 240
|
ColorDarkGrey ui.Color = 235
|
||||||
ColorGrey ui.Color = 242
|
ColorGrey ui.Color = 242
|
||||||
ColorWhite ui.Color = 15
|
ColorWhite ui.Color = 15
|
||||||
ColorBlack ui.Color = 0
|
ColorBlack ui.Color = 0
|
||||||
|
@ -28,7 +28,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MenuColorBackground ui.Color = 234
|
MenuColorBackground ui.Color = 235
|
||||||
MenuColorText ui.Color = 255
|
MenuColorText ui.Color = 255
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
package data
|
package data
|
||||||
|
|
||||||
type Consumer interface {
|
type Consumer struct {
|
||||||
ConsumeSample(sample Sample)
|
SampleChannel chan Sample
|
||||||
|
AlertChannel chan Alert
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sample struct {
|
type Sample struct {
|
||||||
Label string
|
Label string
|
||||||
Value string
|
Value string
|
||||||
Error error
|
}
|
||||||
|
|
||||||
|
type Alert struct {
|
||||||
|
Text string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConsumer() Consumer {
|
||||||
|
return Consumer{
|
||||||
|
SampleChannel: make(chan Sample),
|
||||||
|
AlertChannel: make(chan Alert),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
Label *string `yaml:"label,omitempty"`
|
Label string
|
||||||
Script string `yaml:"value"`
|
Script string
|
||||||
Color *ui.Color `yaml:"color,omitempty"`
|
Color ui.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Item) nextValue() (value string, err error) {
|
func (i *Item) nextValue() (value string, err error) {
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
package data
|
package data
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/sqshq/sampler/trigger"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Sampler struct {
|
type Sampler struct {
|
||||||
consumer Consumer
|
consumer Consumer
|
||||||
item Item
|
item Item
|
||||||
|
triggers []trigger.Trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSampler(consumer Consumer, item Item, rateMs int) Sampler {
|
func NewSampler(consumer Consumer, item Item, triggers []trigger.Trigger, rateMs int) Sampler {
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Duration(rateMs * int(time.Millisecond)))
|
ticker := time.NewTicker(time.Duration(rateMs * int(time.Millisecond)))
|
||||||
sampler := Sampler{consumer, item}
|
sampler := Sampler{consumer, item, triggers}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
sampler.sample()
|
sampler.sample()
|
||||||
|
@ -26,6 +28,10 @@ func NewSampler(consumer Consumer, item Item, rateMs int) Sampler {
|
||||||
|
|
||||||
func (s *Sampler) sample() {
|
func (s *Sampler) sample() {
|
||||||
value, err := s.item.nextValue()
|
value, err := s.item.nextValue()
|
||||||
sample := Sample{Value: value, Error: err, Label: *s.item.Label}
|
if err == nil {
|
||||||
s.consumer.ConsumeSample(sample)
|
sample := Sample{Value: value, Label: s.item.Label}
|
||||||
|
s.consumer.SampleChannel <- sample
|
||||||
|
} else {
|
||||||
|
s.consumer.AlertChannel <- Alert{Text: err.Error()}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package event
|
package event
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/sqshq/sampler/component"
|
"github.com/sqshq/sampler/component/layout"
|
||||||
"github.com/sqshq/sampler/config"
|
"github.com/sqshq/sampler/config"
|
||||||
"github.com/sqshq/sampler/console"
|
"github.com/sqshq/sampler/console"
|
||||||
ui "github.com/sqshq/termui"
|
ui "github.com/sqshq/termui"
|
||||||
|
@ -13,13 +13,13 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
layout *component.Layout
|
layout *layout.Layout
|
||||||
renderTicker *time.Ticker
|
renderTicker *time.Ticker
|
||||||
consoleEvents <-chan ui.Event
|
consoleEvents <-chan ui.Event
|
||||||
renderRate time.Duration
|
renderRate time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(layout *component.Layout) Handler {
|
func NewHandler(layout *layout.Layout) Handler {
|
||||||
renderRate := calcMinRenderRate(layout)
|
renderRate := calcMinRenderRate(layout)
|
||||||
return Handler{
|
return Handler{
|
||||||
layout: layout,
|
layout: layout,
|
||||||
|
@ -55,16 +55,16 @@ func (h *Handler) HandleEvents() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) handleModeChange(m component.Mode) {
|
func (h *Handler) handleModeChange(m layout.Mode) {
|
||||||
|
|
||||||
// render the change before switching the tickers
|
// render the change before switching the tickers
|
||||||
ui.Render(h.layout)
|
ui.Render(h.layout)
|
||||||
h.renderTicker.Stop()
|
h.renderTicker.Stop()
|
||||||
|
|
||||||
switch m {
|
switch m {
|
||||||
case component.ModeDefault:
|
case layout.ModeDefault:
|
||||||
h.renderTicker = time.NewTicker(h.renderRate)
|
h.renderTicker = time.NewTicker(h.renderRate)
|
||||||
case component.ModePause:
|
case layout.ModePause:
|
||||||
// proceed with stopped timer
|
// proceed with stopped timer
|
||||||
default:
|
default:
|
||||||
h.renderTicker = time.NewTicker(console.MinRenderInterval)
|
h.renderTicker = time.NewTicker(console.MinRenderInterval)
|
||||||
|
@ -80,7 +80,7 @@ func (h *Handler) handleExit() {
|
||||||
config.Update(settings)
|
config.Update(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func calcMinRenderRate(layout *component.Layout) time.Duration {
|
func calcMinRenderRate(layout *layout.Layout) time.Duration {
|
||||||
|
|
||||||
minRefreshRateMs := layout.Components[0].RefreshRateMs
|
minRefreshRateMs := layout.Components[0].RefreshRateMs
|
||||||
for _, c := range layout.Components {
|
for _, c := range layout.Components {
|
||||||
|
|
44
main.go
44
main.go
|
@ -5,11 +5,13 @@ import (
|
||||||
"github.com/sqshq/sampler/component/asciibox"
|
"github.com/sqshq/sampler/component/asciibox"
|
||||||
"github.com/sqshq/sampler/component/barchart"
|
"github.com/sqshq/sampler/component/barchart"
|
||||||
"github.com/sqshq/sampler/component/gauge"
|
"github.com/sqshq/sampler/component/gauge"
|
||||||
|
"github.com/sqshq/sampler/component/layout"
|
||||||
"github.com/sqshq/sampler/component/runchart"
|
"github.com/sqshq/sampler/component/runchart"
|
||||||
"github.com/sqshq/sampler/config"
|
"github.com/sqshq/sampler/config"
|
||||||
"github.com/sqshq/sampler/console"
|
"github.com/sqshq/sampler/console"
|
||||||
"github.com/sqshq/sampler/data"
|
"github.com/sqshq/sampler/data"
|
||||||
"github.com/sqshq/sampler/event"
|
"github.com/sqshq/sampler/event"
|
||||||
|
"github.com/sqshq/sampler/trigger"
|
||||||
ui "github.com/sqshq/termui"
|
ui "github.com/sqshq/termui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,47 +23,55 @@ func main() {
|
||||||
defer csl.Close()
|
defer csl.Close()
|
||||||
|
|
||||||
width, height := ui.TerminalDimensions()
|
width, height := ui.TerminalDimensions()
|
||||||
layout := component.NewLayout(width, height, component.NewStatusLine(flg.ConfigFileName), component.NewMenu())
|
lout := layout.NewLayout(width, height, component.NewStatusLine(flg.ConfigFileName), component.NewMenu())
|
||||||
|
|
||||||
for _, c := range cfg.RunCharts {
|
for _, c := range cfg.RunCharts {
|
||||||
|
|
||||||
legend := runchart.Legend{Enabled: c.Legend.Enabled, Details: c.Legend.Details}
|
legend := runchart.Legend{Enabled: c.Legend.Enabled, Details: c.Legend.Details}
|
||||||
chart := runchart.NewRunChart(c.Title, *c.Scale, *c.RefreshRateMs, legend)
|
chart := runchart.NewRunChart(c, legend)
|
||||||
layout.AddComponent(config.TypeRunChart, chart, c.Title, c.Position, c.Size, *c.RefreshRateMs)
|
lout.AddComponent(config.TypeRunChart, chart, c.Title, c.Position, c.Size, *c.RefreshRateMs)
|
||||||
|
triggers := trigger.NewTriggers(c.Triggers)
|
||||||
|
|
||||||
for _, item := range c.Items {
|
for _, i := range c.Items {
|
||||||
chart.AddLine(*item.Label, *item.Color)
|
item := data.Item{Label: *i.Label, Script: i.Script, Color: *i.Color}
|
||||||
data.NewSampler(chart, item, *c.RefreshRateMs)
|
chart.AddLine(item.Label, item.Color)
|
||||||
|
data.NewSampler(chart.Consumer, item, triggers, *c.RefreshRateMs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range cfg.AsciiBoxes {
|
for _, a := range cfg.AsciiBoxes {
|
||||||
box := asciibox.NewAsciiBox(a.Title, *a.Font, *a.Item.Color)
|
box := asciibox.NewAsciiBox(a)
|
||||||
layout.AddComponent(config.TypeAsciiBox, box, a.Title, a.Position, a.Size, *a.RefreshRateMs)
|
item := data.Item{Label: *a.Label, Script: a.Script, Color: *a.Color}
|
||||||
data.NewSampler(box, a.Item, *a.RefreshRateMs)
|
triggers := trigger.NewTriggers(a.Triggers)
|
||||||
|
lout.AddComponent(config.TypeAsciiBox, box, a.Title, a.Position, a.Size, *a.RefreshRateMs)
|
||||||
|
data.NewSampler(box.Consumer, item, triggers, *a.RefreshRateMs)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, b := range cfg.BarCharts {
|
for _, b := range cfg.BarCharts {
|
||||||
|
|
||||||
chart := barchart.NewBarChart(b.Title, *b.Scale)
|
chart := barchart.NewBarChart(b.Title, *b.Scale)
|
||||||
layout.AddComponent(config.TypeBarChart, chart, b.Title, b.Position, b.Size, *b.RefreshRateMs)
|
triggers := trigger.NewTriggers(b.Triggers)
|
||||||
|
lout.AddComponent(config.TypeBarChart, chart, b.Title, b.Position, b.Size, *b.RefreshRateMs)
|
||||||
|
|
||||||
for _, item := range b.Items {
|
for _, i := range b.Items {
|
||||||
chart.AddBar(*item.Label, *item.Color)
|
item := data.Item{Label: *i.Label, Script: i.Script, Color: *i.Color}
|
||||||
data.NewSampler(chart, item, *b.RefreshRateMs)
|
chart.AddBar(*i.Label, *i.Color)
|
||||||
|
data.NewSampler(chart.Consumer, item, triggers, *b.RefreshRateMs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, gc := range cfg.Gauges {
|
for _, gc := range cfg.Gauges {
|
||||||
|
|
||||||
g := gauge.NewGauge(gc.Title, *gc.Scale, *gc.Color)
|
g := gauge.NewGauge(gc.Title, *gc.Scale, *gc.Color)
|
||||||
layout.AddComponent(config.TypeGauge, g, gc.Title, gc.Position, gc.Size, *gc.RefreshRateMs)
|
triggers := trigger.NewTriggers(gc.Triggers)
|
||||||
|
lout.AddComponent(config.TypeGauge, g, gc.Title, gc.Position, gc.Size, *gc.RefreshRateMs)
|
||||||
|
|
||||||
for _, item := range gc.Items {
|
for _, i := range gc.Items {
|
||||||
data.NewSampler(g, item, *gc.RefreshRateMs)
|
item := data.Item{Label: *i.Label, Script: i.Script}
|
||||||
|
data.NewSampler(g.Consumer, item, triggers, *gc.RefreshRateMs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler := event.NewHandler(layout)
|
handler := event.NewHandler(lout)
|
||||||
handler.HandleEvents()
|
handler.HandleEvents()
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,17 @@ type Data struct {
|
||||||
currentValue interface{}
|
currentValue interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewTriggers(configs []config.TriggerConfig) []Trigger {
|
||||||
|
|
||||||
|
triggers := make([]Trigger, len(configs))
|
||||||
|
|
||||||
|
for _, c := range configs {
|
||||||
|
triggers = append(triggers, NewTrigger(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
return triggers
|
||||||
|
}
|
||||||
|
|
||||||
func NewTrigger(config config.TriggerConfig) Trigger {
|
func NewTrigger(config config.TriggerConfig) Trigger {
|
||||||
return Trigger{
|
return Trigger{
|
||||||
title: config.Title,
|
title: config.Title,
|
Loading…
Reference in New Issue