combine common functionality in Component struct
This commit is contained in:
parent
dcfdc16a41
commit
fec7eefd9f
|
@ -6,14 +6,11 @@ import (
|
|||
"github.com/sqshq/sampler/asset"
|
||||
"github.com/sqshq/sampler/component"
|
||||
"github.com/sqshq/sampler/config"
|
||||
"github.com/sqshq/sampler/data"
|
||||
"image"
|
||||
)
|
||||
|
||||
type AsciiBox struct {
|
||||
ui.Block
|
||||
data.Consumer
|
||||
*component.Alerter
|
||||
*component.Component
|
||||
text string
|
||||
ascii string
|
||||
style ui.Style
|
||||
|
@ -25,10 +22,6 @@ const asciiFontExtension = ".flf"
|
|||
|
||||
func NewAsciiBox(c config.AsciiBoxConfig) *AsciiBox {
|
||||
|
||||
consumer := data.NewConsumer()
|
||||
block := *ui.NewBlock()
|
||||
block.Title = c.Title
|
||||
|
||||
options := fl.NewRenderOptions()
|
||||
options.FontName = string(*c.Font)
|
||||
|
||||
|
@ -36,33 +29,28 @@ func NewAsciiBox(c config.AsciiBoxConfig) *AsciiBox {
|
|||
if err != nil {
|
||||
panic("Can't load the font: " + err.Error())
|
||||
}
|
||||
|
||||
render := fl.NewAsciiRender()
|
||||
_ = render.LoadBindataFont(fontStr, options.FontName)
|
||||
|
||||
box := AsciiBox{
|
||||
Block: block,
|
||||
Consumer: consumer,
|
||||
Alerter: component.NewAlerter(consumer.AlertChannel),
|
||||
Component: component.NewComponent(c.ComponentConfig, config.TypeAsciiBox),
|
||||
style: ui.NewStyle(*c.Color),
|
||||
render: render,
|
||||
options: options,
|
||||
}
|
||||
|
||||
go box.consume()
|
||||
|
||||
return &box
|
||||
}
|
||||
|
||||
func (a *AsciiBox) consume() {
|
||||
go func() {
|
||||
for {
|
||||
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
|
||||
case sample := <-box.SampleChannel:
|
||||
box.text = sample.Value
|
||||
box.ascii, _ = box.render.RenderOpts(sample.Value, box.options)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return &box
|
||||
}
|
||||
|
||||
func (a *AsciiBox) Draw(buffer *ui.Buffer) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
ui "github.com/gizak/termui/v3"
|
||||
rw "github.com/mattn/go-runewidth"
|
||||
"github.com/sqshq/sampler/component"
|
||||
"github.com/sqshq/sampler/config"
|
||||
"github.com/sqshq/sampler/console"
|
||||
"github.com/sqshq/sampler/data"
|
||||
"image"
|
||||
|
@ -17,9 +18,7 @@ const (
|
|||
)
|
||||
|
||||
type BarChart struct {
|
||||
ui.Block
|
||||
data.Consumer
|
||||
*component.Alerter
|
||||
*component.Component
|
||||
bars []Bar
|
||||
scale int
|
||||
maxValue float64
|
||||
|
@ -33,33 +32,29 @@ type Bar struct {
|
|||
delta float64
|
||||
}
|
||||
|
||||
func NewBarChart(title string, scale int) *BarChart {
|
||||
consumer := data.NewConsumer()
|
||||
block := *ui.NewBlock()
|
||||
block.Title = title
|
||||
func NewBarChart(c config.BarChartConfig) *BarChart {
|
||||
|
||||
chart := BarChart{
|
||||
Block: block,
|
||||
Consumer: consumer,
|
||||
Alerter: component.NewAlerter(consumer.AlertChannel),
|
||||
Component: component.NewComponent(c.ComponentConfig, config.TypeBarChart),
|
||||
bars: []Bar{},
|
||||
scale: scale,
|
||||
scale: *c.Scale,
|
||||
maxValue: -math.MaxFloat64,
|
||||
}
|
||||
|
||||
go chart.consume()
|
||||
for _, i := range c.Items {
|
||||
chart.AddBar(*i.Label, *i.Color)
|
||||
}
|
||||
|
||||
return &chart
|
||||
}
|
||||
|
||||
func (b *BarChart) consume() {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case sample := <-b.SampleChannel:
|
||||
b.consumeSample(sample)
|
||||
//case alert := <-b.alertChannel:
|
||||
// TODO base alerting mechanism
|
||||
case sample := <-chart.SampleChannel:
|
||||
chart.consumeSample(sample)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return &chart
|
||||
}
|
||||
|
||||
func (b *BarChart) consumeSample(sample data.Sample) {
|
||||
|
|
|
@ -3,17 +3,38 @@ package component
|
|||
import (
|
||||
ui "github.com/gizak/termui/v3"
|
||||
"github.com/sqshq/sampler/config"
|
||||
"github.com/sqshq/sampler/data"
|
||||
)
|
||||
|
||||
type Component struct {
|
||||
ui.Block
|
||||
data.Consumer
|
||||
*Alerter
|
||||
Type config.ComponentType
|
||||
Drawable ui.Drawable
|
||||
Title string
|
||||
Position config.Position
|
||||
Size config.Size
|
||||
RefreshRateMs int
|
||||
}
|
||||
|
||||
func NewComponent(c config.ComponentConfig, t config.ComponentType) *Component {
|
||||
|
||||
consumer := data.NewConsumer()
|
||||
block := *ui.NewBlock()
|
||||
block.Title = c.Title
|
||||
|
||||
return &Component{
|
||||
Block: block,
|
||||
Consumer: consumer,
|
||||
Alerter: NewAlerter(consumer.AlertChannel),
|
||||
Type: t,
|
||||
Title: c.Title,
|
||||
Position: c.Position,
|
||||
Size: c.Size,
|
||||
RefreshRateMs: *c.RefreshRateMs,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Component) Move(x, y int) {
|
||||
c.Position.X += x
|
||||
c.Position.Y += y
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
ui "github.com/gizak/termui/v3"
|
||||
"github.com/sqshq/sampler/component"
|
||||
"github.com/sqshq/sampler/config"
|
||||
"github.com/sqshq/sampler/console"
|
||||
"github.com/sqshq/sampler/data"
|
||||
"image"
|
||||
|
@ -18,49 +19,39 @@ const (
|
|||
)
|
||||
|
||||
type Gauge struct {
|
||||
ui.Block
|
||||
data.Consumer
|
||||
*component.Alerter
|
||||
*component.Component
|
||||
minValue float64
|
||||
maxValue float64
|
||||
curValue float64
|
||||
scale int
|
||||
color ui.Color
|
||||
scale int
|
||||
}
|
||||
|
||||
func NewGauge(title string, scale int, color ui.Color) *Gauge {
|
||||
consumer := data.NewConsumer()
|
||||
block := *ui.NewBlock()
|
||||
block.Title = title
|
||||
func NewGauge(c config.GaugeConfig) *Gauge {
|
||||
|
||||
gauge := Gauge{
|
||||
Block: block,
|
||||
Consumer: consumer,
|
||||
Alerter: component.NewAlerter(consumer.AlertChannel),
|
||||
scale: scale,
|
||||
color: color,
|
||||
Component: component.NewComponent(c.ComponentConfig, config.TypeGauge),
|
||||
scale: *c.Scale,
|
||||
color: *c.Color,
|
||||
}
|
||||
|
||||
go gauge.consume()
|
||||
|
||||
return &gauge
|
||||
}
|
||||
|
||||
func (g *Gauge) consume() {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case sample := <-g.SampleChannel:
|
||||
g.ConsumeSample(sample)
|
||||
//case alert := <-g.alertChannel:
|
||||
// TODO base alerting mechanism
|
||||
case sample := <-gauge.SampleChannel:
|
||||
gauge.ConsumeSample(sample)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return &gauge
|
||||
}
|
||||
|
||||
func (g *Gauge) ConsumeSample(sample data.Sample) {
|
||||
|
||||
float, err := strconv.ParseFloat(sample.Value, 64)
|
||||
if err != nil {
|
||||
// TODO visual notification + check sample.Error
|
||||
// TODO handle in Component
|
||||
}
|
||||
|
||||
switch sample.Label {
|
||||
|
@ -87,7 +78,7 @@ func (g *Gauge) Draw(buf *ui.Buffer) {
|
|||
|
||||
label := fmt.Sprintf("%v%% (%v)", formatValue(percent, g.scale), g.curValue)
|
||||
|
||||
// plot bar
|
||||
// draw bar
|
||||
barWidth := int((percent / 100) * float64(g.Inner.Dx()))
|
||||
if barWidth == 0 {
|
||||
barWidth = 1
|
||||
|
@ -99,7 +90,7 @@ func (g *Gauge) Draw(buf *ui.Buffer) {
|
|||
image.Rect(g.Inner.Min.X+1, g.Inner.Min.Y, g.Inner.Min.X+barWidth, g.Inner.Max.Y),
|
||||
)
|
||||
|
||||
// plot label
|
||||
// draw label
|
||||
labelXCoordinate := g.Inner.Min.X + (g.Inner.Dx() / 2) - int(float64(len(label))/2)
|
||||
labelYCoordinate := g.Inner.Min.Y + ((g.Inner.Dy() - 1) / 2)
|
||||
if labelYCoordinate < g.Inner.Max.Y {
|
||||
|
|
|
@ -5,28 +5,28 @@ import (
|
|||
"math"
|
||||
)
|
||||
|
||||
func GetRectLeftAgeCenter(rect image.Rectangle) image.Point {
|
||||
func GetRectLeftSideCenter(rect image.Rectangle) image.Point {
|
||||
return image.Point{
|
||||
X: rect.Min.X,
|
||||
Y: rect.Min.Y + rect.Dy()/2,
|
||||
}
|
||||
}
|
||||
|
||||
func GetRectRightAgeCenter(rect image.Rectangle) image.Point {
|
||||
func GetRectRightSideCenter(rect image.Rectangle) image.Point {
|
||||
return image.Point{
|
||||
X: rect.Max.X,
|
||||
Y: rect.Min.Y + rect.Dy()/2,
|
||||
}
|
||||
}
|
||||
|
||||
func GetRectTopAgeCenter(rect image.Rectangle) image.Point {
|
||||
func GetRectTopSideCenter(rect image.Rectangle) image.Point {
|
||||
return image.Point{
|
||||
X: rect.Min.X + rect.Dx()/2,
|
||||
Y: rect.Min.Y,
|
||||
}
|
||||
}
|
||||
|
||||
func GetRectBottomAgeCenter(rect image.Rectangle) image.Point {
|
||||
func GetRectBottomSideCenter(rect image.Rectangle) image.Point {
|
||||
return image.Point{
|
||||
X: rect.Min.X + rect.Dx()/2,
|
||||
Y: rect.Max.Y,
|
||||
|
|
|
@ -6,16 +6,17 @@ import (
|
|||
"github.com/sqshq/sampler/component/runchart"
|
||||
"github.com/sqshq/sampler/config"
|
||||
"github.com/sqshq/sampler/console"
|
||||
"github.com/sqshq/sampler/data"
|
||||
"image"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Layout struct {
|
||||
ui.Block
|
||||
Components []component.Component
|
||||
ChangeModeEvents chan Mode
|
||||
Components []*component.Component
|
||||
statusbar *component.StatusBar
|
||||
menu *component.Menu
|
||||
ChangeModeEvents chan Mode
|
||||
mode Mode
|
||||
selection int
|
||||
}
|
||||
|
@ -47,7 +48,7 @@ func NewLayout(width, height int, statusline *component.StatusBar, menu *compone
|
|||
|
||||
return &Layout{
|
||||
Block: block,
|
||||
Components: make([]component.Component, 0),
|
||||
Components: make([]*component.Component, 0),
|
||||
statusbar: statusline,
|
||||
menu: menu,
|
||||
mode: ModeDefault,
|
||||
|
@ -56,28 +57,8 @@ func NewLayout(width, height int, statusline *component.StatusBar, menu *compone
|
|||
}
|
||||
}
|
||||
|
||||
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.Component{
|
||||
Type: Type,
|
||||
Drawable: drawable,
|
||||
Title: title,
|
||||
Position: position,
|
||||
Size: size,
|
||||
RefreshRateMs: refreshRateMs,
|
||||
})
|
||||
}
|
||||
|
||||
func (l *Layout) GetComponents(Type config.ComponentType) []component.Component {
|
||||
|
||||
var components []component.Component
|
||||
|
||||
for _, c := range l.Components {
|
||||
if c.Type == Type {
|
||||
components = append(components, c)
|
||||
}
|
||||
}
|
||||
|
||||
return components
|
||||
func (l *Layout) AddComponent(cpt *component.Component, Type config.ComponentType) {
|
||||
l.Components = append(l.Components, cpt)
|
||||
}
|
||||
|
||||
func (l *Layout) changeMode(m Mode) {
|
||||
|
@ -86,14 +67,16 @@ func (l *Layout) changeMode(m Mode) {
|
|||
}
|
||||
|
||||
func (l *Layout) HandleConsoleEvent(e string) {
|
||||
|
||||
selected := l.getSelection()
|
||||
|
||||
switch e {
|
||||
case console.KeyPause:
|
||||
if l.mode == ModePause {
|
||||
l.changeMode(ModeDefault)
|
||||
} else {
|
||||
if l.getSelectedComponent().Type == config.TypeRunChart {
|
||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||
chart.DisableSelection()
|
||||
if selected.Type == config.TypeRunChart {
|
||||
selected.CommandChannel <- data.Command{Type: runchart.CommandDisableSelection}
|
||||
}
|
||||
l.menu.Idle()
|
||||
l.changeMode(ModePause)
|
||||
|
@ -115,8 +98,7 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
|||
case component.MenuOptionPinpoint:
|
||||
l.changeMode(ModeChartPinpoint)
|
||||
l.menu.Idle()
|
||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||
chart.MoveSelection(0)
|
||||
selected.CommandChannel <- data.Command{Type: runchart.CommandMoveSelection, Value: 0}
|
||||
case component.MenuOptionResume:
|
||||
l.changeMode(ModeDefault)
|
||||
l.menu.Idle()
|
||||
|
@ -130,8 +112,7 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
|||
case console.KeyEsc:
|
||||
switch l.mode {
|
||||
case ModeChartPinpoint:
|
||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||
chart.DisableSelection()
|
||||
selected.CommandChannel <- data.Command{Type: runchart.CommandDisableSelection}
|
||||
fallthrough
|
||||
case ModeComponentSelect:
|
||||
fallthrough
|
||||
|
@ -145,15 +126,14 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
|||
l.changeMode(ModeComponentSelect)
|
||||
l.menu.Highlight(l.getComponent(l.selection))
|
||||
case ModeChartPinpoint:
|
||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||
chart.MoveSelection(-1)
|
||||
selected.CommandChannel <- data.Command{Type: runchart.CommandMoveSelection, Value: -1}
|
||||
case ModeComponentSelect:
|
||||
l.moveSelection(e)
|
||||
l.menu.Highlight(l.getComponent(l.selection))
|
||||
case ModeComponentMove:
|
||||
l.getSelectedComponent().Move(-1, 0)
|
||||
selected.Move(-1, 0)
|
||||
case ModeComponentResize:
|
||||
l.getSelectedComponent().Resize(-1, 0)
|
||||
selected.Resize(-1, 0)
|
||||
}
|
||||
case console.KeyRight:
|
||||
switch l.mode {
|
||||
|
@ -161,15 +141,14 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
|||
l.changeMode(ModeComponentSelect)
|
||||
l.menu.Highlight(l.getComponent(l.selection))
|
||||
case ModeChartPinpoint:
|
||||
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
|
||||
chart.MoveSelection(1)
|
||||
selected.CommandChannel <- data.Command{Type: runchart.CommandMoveSelection, Value: 1}
|
||||
case ModeComponentSelect:
|
||||
l.moveSelection(e)
|
||||
l.menu.Highlight(l.getComponent(l.selection))
|
||||
case ModeComponentMove:
|
||||
l.getSelectedComponent().Move(1, 0)
|
||||
selected.Move(1, 0)
|
||||
case ModeComponentResize:
|
||||
l.getSelectedComponent().Resize(1, 0)
|
||||
selected.Resize(1, 0)
|
||||
}
|
||||
case console.KeyUp:
|
||||
switch l.mode {
|
||||
|
@ -182,9 +161,9 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
|||
case ModeMenuOptionSelect:
|
||||
l.menu.Up()
|
||||
case ModeComponentMove:
|
||||
l.getSelectedComponent().Move(0, -1)
|
||||
selected.Move(0, -1)
|
||||
case ModeComponentResize:
|
||||
l.getSelectedComponent().Resize(0, -1)
|
||||
selected.Resize(0, -1)
|
||||
}
|
||||
case console.KeyDown:
|
||||
switch l.mode {
|
||||
|
@ -197,9 +176,9 @@ func (l *Layout) HandleConsoleEvent(e string) {
|
|||
case ModeMenuOptionSelect:
|
||||
l.menu.Down()
|
||||
case ModeComponentMove:
|
||||
l.getSelectedComponent().Move(0, 1)
|
||||
selected.Move(0, 1)
|
||||
case ModeComponentResize:
|
||||
l.getSelectedComponent().Resize(0, 1)
|
||||
selected.Resize(0, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,16 +188,16 @@ func (l *Layout) ChangeDimensions(width, height int) {
|
|||
}
|
||||
|
||||
func (l *Layout) getComponent(i int) *component.Component {
|
||||
return &l.Components[i]
|
||||
return l.Components[i]
|
||||
}
|
||||
|
||||
func (l *Layout) getSelectedComponent() *component.Component {
|
||||
return &l.Components[l.selection]
|
||||
func (l *Layout) getSelection() *component.Component {
|
||||
return l.Components[l.selection]
|
||||
}
|
||||
|
||||
func (l *Layout) moveSelection(direction string) {
|
||||
|
||||
previouslySelected := *l.getSelectedComponent()
|
||||
previouslySelected := l.getSelection()
|
||||
newlySelectedIndex := l.selection
|
||||
|
||||
for i, current := range l.Components {
|
||||
|
@ -237,21 +216,21 @@ func (l *Layout) moveSelection(direction string) {
|
|||
|
||||
switch direction {
|
||||
case console.KeyLeft:
|
||||
previouslySelectedCornerPoint = component.GetRectLeftAgeCenter(previouslySelected.Drawable.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectRightAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||
currentCornerPoint = component.GetRectRightAgeCenter(current.Drawable.GetRect())
|
||||
previouslySelectedCornerPoint = component.GetRectLeftSideCenter(previouslySelected.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectRightSideCenter(l.getComponent(newlySelectedIndex).GetRect())
|
||||
currentCornerPoint = component.GetRectRightSideCenter(current.GetRect())
|
||||
case console.KeyRight:
|
||||
previouslySelectedCornerPoint = component.GetRectRightAgeCenter(previouslySelected.Drawable.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectLeftAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||
currentCornerPoint = component.GetRectLeftAgeCenter(current.Drawable.GetRect())
|
||||
previouslySelectedCornerPoint = component.GetRectRightSideCenter(previouslySelected.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectLeftSideCenter(l.getComponent(newlySelectedIndex).GetRect())
|
||||
currentCornerPoint = component.GetRectLeftSideCenter(current.GetRect())
|
||||
case console.KeyUp:
|
||||
previouslySelectedCornerPoint = component.GetRectTopAgeCenter(previouslySelected.Drawable.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectBottomAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||
currentCornerPoint = component.GetRectBottomAgeCenter(current.Drawable.GetRect())
|
||||
previouslySelectedCornerPoint = component.GetRectTopSideCenter(previouslySelected.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectBottomSideCenter(l.getComponent(newlySelectedIndex).GetRect())
|
||||
currentCornerPoint = component.GetRectBottomSideCenter(current.GetRect())
|
||||
case console.KeyDown:
|
||||
previouslySelectedCornerPoint = component.GetRectBottomAgeCenter(previouslySelected.Drawable.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectTopAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
|
||||
currentCornerPoint = component.GetRectTopAgeCenter(current.Drawable.GetRect())
|
||||
previouslySelectedCornerPoint = component.GetRectBottomSideCenter(previouslySelected.GetRect())
|
||||
newlySelectedCornerPoint = component.GetRectTopSideCenter(l.getComponent(newlySelectedIndex).GetRect())
|
||||
currentCornerPoint = component.GetRectTopSideCenter(current.GetRect())
|
||||
}
|
||||
|
||||
if component.GetDistance(previouslySelectedCornerPoint, currentCornerPoint) <
|
||||
|
@ -283,8 +262,8 @@ func (l *Layout) Draw(buffer *ui.Buffer) {
|
|||
y2 = y1 + minDimension
|
||||
}
|
||||
|
||||
c.Drawable.SetRect(int(x1), int(y1), int(x2), int(y2))
|
||||
c.Drawable.Draw(buffer)
|
||||
c.SetRect(int(x1), int(y1), int(x2), int(y2))
|
||||
c.Draw(buffer)
|
||||
}
|
||||
|
||||
l.statusbar.SetRect(
|
||||
|
|
|
@ -219,7 +219,7 @@ func (m *Menu) renderOptions(buffer *ui.Buffer) {
|
|||
}
|
||||
|
||||
func (m *Menu) updateDimensions() {
|
||||
r := m.component.Drawable.GetRect()
|
||||
r := m.component.Block.GetRect()
|
||||
m.SetRect(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,7 @@ const (
|
|||
xAxisGridWidth = xAxisLabelsIndent + xAxisLabelsWidth
|
||||
yAxisLabelsHeight = 1
|
||||
yAxisLabelsIndent = 1
|
||||
|
||||
historyReserveMin = 20
|
||||
|
||||
xBrailleMultiplier = 2
|
||||
yBrailleMultiplier = 4
|
||||
)
|
||||
|
@ -36,10 +34,13 @@ const (
|
|||
ModePinpoint Mode = 1
|
||||
)
|
||||
|
||||
const (
|
||||
CommandDisableSelection = "DISABLE_SELECTION"
|
||||
CommandMoveSelection = "MOVE_SELECTION"
|
||||
)
|
||||
|
||||
type RunChart struct {
|
||||
ui.Block
|
||||
data.Consumer
|
||||
*component.Alerter
|
||||
*component.Component
|
||||
lines []TimeLine
|
||||
grid ChartGrid
|
||||
timescale time.Duration
|
||||
|
@ -75,38 +76,39 @@ type ValueExtrema struct {
|
|||
min float64
|
||||
}
|
||||
|
||||
func NewRunChart(c config.RunChartConfig, l Legend) *RunChart {
|
||||
|
||||
consumer := data.NewConsumer()
|
||||
block := *ui.NewBlock()
|
||||
block.Title = c.Title
|
||||
func NewRunChart(c config.RunChartConfig) *RunChart {
|
||||
|
||||
chart := RunChart{
|
||||
Block: block,
|
||||
Consumer: consumer,
|
||||
Alerter: component.NewAlerter(consumer.AlertChannel),
|
||||
Component: component.NewComponent(c.ComponentConfig, config.TypeRunChart),
|
||||
lines: []TimeLine{},
|
||||
timescale: calculateTimescale(*c.RefreshRateMs),
|
||||
mutex: &sync.Mutex{},
|
||||
scale: *c.Scale,
|
||||
mode: ModeDefault,
|
||||
legend: l,
|
||||
legend: Legend{Enabled: c.Legend.Enabled, Details: c.Legend.Details},
|
||||
}
|
||||
|
||||
go chart.consume()
|
||||
for _, i := range c.Items {
|
||||
chart.AddLine(*i.Label, *i.Color)
|
||||
}
|
||||
|
||||
return &chart
|
||||
}
|
||||
|
||||
func (c *RunChart) consume() {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case sample := <-c.SampleChannel:
|
||||
c.consumeSample(sample)
|
||||
//case alert := <-c.alertChannel:
|
||||
// TODO base alerting mechanism
|
||||
case sample := <-chart.SampleChannel:
|
||||
chart.consumeSample(sample)
|
||||
case command := <-chart.CommandChannel:
|
||||
switch command.Type {
|
||||
case CommandDisableSelection:
|
||||
chart.disableSelection()
|
||||
case CommandMoveSelection:
|
||||
chart.moveSelection(command.Value.(int))
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return &chart
|
||||
}
|
||||
|
||||
func (c *RunChart) newTimePoint(value float64) TimePoint {
|
||||
|
@ -151,7 +153,11 @@ func (c *RunChart) consumeSample(sample data.Sample) {
|
|||
float, err := strconv.ParseFloat(sample.Value, 64)
|
||||
|
||||
if err != nil {
|
||||
// TODO visual notification
|
||||
c.AlertChannel <- data.Alert{
|
||||
Title: "SAMPLING FAILURE",
|
||||
Text: err.Error(),
|
||||
Color: sample.Color,
|
||||
}
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
|
@ -320,7 +326,7 @@ func (c *RunChart) getMaxValueLength() int {
|
|||
return maxValueLength
|
||||
}
|
||||
|
||||
func (c *RunChart) MoveSelection(shift int) {
|
||||
func (c *RunChart) moveSelection(shift int) {
|
||||
|
||||
if c.mode == ModeDefault {
|
||||
c.mode = ModePinpoint
|
||||
|
@ -340,7 +346,7 @@ func (c *RunChart) MoveSelection(shift int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *RunChart) DisableSelection() {
|
||||
func (c *RunChart) disableSelection() {
|
||||
if c.mode == ModePinpoint {
|
||||
c.mode = ModeDefault
|
||||
return
|
||||
|
|
|
@ -24,16 +24,16 @@ type Flags struct {
|
|||
|
||||
func Load() (Config, Flags) {
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
println("Please specify config file location. See www.github.com/sqshq/sampler for the reference")
|
||||
os.Exit(0)
|
||||
}
|
||||
//if len(os.Args) < 2 {
|
||||
// println("Please specify config file location. See www.github.com/sqshq/sampler for the reference")
|
||||
// os.Exit(0)
|
||||
//}
|
||||
|
||||
cfg := readFile(os.Args[1])
|
||||
cfg := readFile("config.yml")
|
||||
cfg.validate()
|
||||
cfg.setDefaults()
|
||||
|
||||
flg := Flags{ConfigFileName: os.Args[1]}
|
||||
flg := Flags{ConfigFileName: "config.yml"}
|
||||
|
||||
return *cfg, flg
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@ const (
|
|||
AppVersion = "0.1.0"
|
||||
)
|
||||
|
||||
const (
|
||||
BellCharacter = "\a"
|
||||
)
|
||||
|
||||
type AsciiFont string
|
||||
|
||||
const (
|
||||
|
@ -21,13 +25,7 @@ const (
|
|||
AsciiFont3D AsciiFont = "3d"
|
||||
)
|
||||
|
||||
type Console struct{}
|
||||
|
||||
const (
|
||||
BellCharacter = "\a"
|
||||
)
|
||||
|
||||
func (self *Console) Init() {
|
||||
func Init() {
|
||||
|
||||
fmt.Printf("\033]0;%s\007", AppTitle)
|
||||
|
||||
|
@ -36,6 +34,6 @@ func (self *Console) Init() {
|
|||
}
|
||||
}
|
||||
|
||||
func (self *Console) Close() {
|
||||
func Close() {
|
||||
ui.Close()
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package data
|
|||
|
||||
import ui "github.com/gizak/termui/v3"
|
||||
|
||||
// TODO interface here, move fields declaration in the Component
|
||||
type Consumer struct {
|
||||
SampleChannel chan Sample
|
||||
AlertChannel chan Alert
|
||||
CommandChannel chan Command
|
||||
}
|
||||
|
||||
type Sample struct {
|
||||
|
@ -19,9 +21,15 @@ type Alert struct {
|
|||
Color *ui.Color
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
Type string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
func NewConsumer() Consumer {
|
||||
return Consumer{
|
||||
SampleChannel: make(chan Sample),
|
||||
AlertChannel: make(chan Alert),
|
||||
CommandChannel: make(chan Command),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@ type Handler struct {
|
|||
renderRate time.Duration
|
||||
}
|
||||
|
||||
func NewHandler(layout *layout.Layout) Handler {
|
||||
func NewHandler(layout *layout.Layout) *Handler {
|
||||
renderRate := calcMinRenderRate(layout)
|
||||
return Handler{
|
||||
return &Handler{
|
||||
layout: layout,
|
||||
consoleEvents: ui.PollEvents(),
|
||||
renderTicker: time.NewTicker(renderRate),
|
||||
|
|
47
main.go
47
main.go
|
@ -18,57 +18,42 @@ import (
|
|||
func main() {
|
||||
|
||||
cfg, flg := config.Load()
|
||||
csl := console.Console{}
|
||||
csl.Init()
|
||||
defer csl.Close()
|
||||
|
||||
width, height := ui.TerminalDimensions()
|
||||
lout := layout.NewLayout(width, height, component.NewStatusLine(flg.ConfigFileName), component.NewMenu())
|
||||
console.Init()
|
||||
defer console.Close()
|
||||
|
||||
player := asset.NewAudioPlayer()
|
||||
defer player.Close()
|
||||
|
||||
width, height := ui.TerminalDimensions()
|
||||
lout := layout.NewLayout(width, height, component.NewStatusLine(flg.ConfigFileName), component.NewMenu())
|
||||
|
||||
for _, c := range cfg.RunCharts {
|
||||
|
||||
legend := runchart.Legend{Enabled: c.Legend.Enabled, Details: c.Legend.Details}
|
||||
chart := runchart.NewRunChart(c, legend)
|
||||
lout.AddComponent(config.TypeRunChart, chart, c.Title, c.Position, c.Size, *c.RefreshRateMs)
|
||||
chart := runchart.NewRunChart(c)
|
||||
triggers := data.NewTriggers(c.Triggers, chart.Consumer, player)
|
||||
items := data.NewItems(c.Items)
|
||||
data.NewSampler(chart.Consumer, items, triggers, *c.RefreshRateMs)
|
||||
|
||||
for _, i := range c.Items {
|
||||
chart.AddLine(*i.Label, *i.Color)
|
||||
}
|
||||
data.NewSampler(chart.Consumer, data.NewItems(c.Items), triggers, *c.RefreshRateMs)
|
||||
lout.AddComponent(chart.Component, config.TypeRunChart)
|
||||
}
|
||||
|
||||
for _, a := range cfg.AsciiBoxes {
|
||||
box := asciibox.NewAsciiBox(a)
|
||||
item := data.Item{Label: *a.Label, Script: a.Script, Color: a.Color}
|
||||
lout.AddComponent(config.TypeAsciiBox, box, a.Title, a.Position, a.Size, *a.RefreshRateMs)
|
||||
triggers := data.NewTriggers(a.Triggers, box.Consumer, player)
|
||||
data.NewSampler(box.Consumer, []data.Item{item}, triggers, *a.RefreshRateMs)
|
||||
data.NewSampler(box.Consumer, data.NewItems([]config.Item{a.Item}), triggers, *a.RefreshRateMs)
|
||||
lout.AddComponent(box.Component, config.TypeAsciiBox)
|
||||
}
|
||||
|
||||
for _, b := range cfg.BarCharts {
|
||||
|
||||
chart := barchart.NewBarChart(b.Title, *b.Scale)
|
||||
chart := barchart.NewBarChart(b)
|
||||
triggers := data.NewTriggers(b.Triggers, chart.Consumer, player)
|
||||
lout.AddComponent(config.TypeBarChart, chart, b.Title, b.Position, b.Size, *b.RefreshRateMs)
|
||||
items := data.NewItems(b.Items)
|
||||
data.NewSampler(chart.Consumer, items, triggers, *b.RefreshRateMs)
|
||||
|
||||
for _, i := range b.Items {
|
||||
chart.AddBar(*i.Label, *i.Color)
|
||||
}
|
||||
data.NewSampler(chart.Consumer, data.NewItems(b.Items), triggers, *b.RefreshRateMs)
|
||||
lout.AddComponent(chart.Component, config.TypeBarChart)
|
||||
}
|
||||
|
||||
for _, gc := range cfg.Gauges {
|
||||
g := gauge.NewGauge(gc.Title, *gc.Scale, *gc.Color)
|
||||
g := gauge.NewGauge(gc)
|
||||
triggers := data.NewTriggers(gc.Triggers, g.Consumer, player)
|
||||
lout.AddComponent(config.TypeGauge, g, gc.Title, gc.Position, gc.Size, *gc.RefreshRateMs)
|
||||
items := data.NewItems(gc.Items)
|
||||
data.NewSampler(g.Consumer, items, triggers, *gc.RefreshRateMs)
|
||||
data.NewSampler(g.Consumer, data.NewItems(gc.Items), triggers, *gc.RefreshRateMs)
|
||||
lout.AddComponent(g.Component, config.TypeGauge)
|
||||
}
|
||||
|
||||
handler := event.NewHandler(lout)
|
||||
|
|
Loading…
Reference in New Issue