diff --git a/component/asciibox/asciibox.go b/component/asciibox/asciibox.go index 16a5af7..ccb71a0 100644 --- a/component/asciibox/asciibox.go +++ b/component/asciibox/asciibox.go @@ -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,35 +29,30 @@ 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), - style: ui.NewStyle(*c.Color), - render: render, - options: options, + Component: component.NewComponent(c.ComponentConfig, config.TypeAsciiBox), + style: ui.NewStyle(*c.Color), + render: render, + options: options, } - go box.consume() + go func() { + for { + select { + case sample := <-box.SampleChannel: + box.text = sample.Value + box.ascii, _ = box.render.RenderOpts(sample.Value, box.options) + } + } + }() return &box } -func (a *AsciiBox) consume() { - 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 - } - } -} - func (a *AsciiBox) Draw(buffer *ui.Buffer) { buffer.Fill(ui.NewCell(' ', ui.NewStyle(ui.ColorBlack)), a.GetRect()) diff --git a/component/barchart/barchart.go b/component/barchart/barchart.go index a79d826..f67cc3b 100644 --- a/component/barchart/barchart.go +++ b/component/barchart/barchart.go @@ -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,35 +32,31 @@ 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), - bars: []Bar{}, - scale: scale, - maxValue: -math.MaxFloat64, + Component: component.NewComponent(c.ComponentConfig, config.TypeBarChart), + bars: []Bar{}, + scale: *c.Scale, + maxValue: -math.MaxFloat64, } - go chart.consume() + for _, i := range c.Items { + chart.AddBar(*i.Label, *i.Color) + } + + go func() { + for { + select { + case sample := <-chart.SampleChannel: + chart.consumeSample(sample) + } + } + }() return &chart } -func (b *BarChart) consume() { - for { - select { - case sample := <-b.SampleChannel: - b.consumeSample(sample) - //case alert := <-b.alertChannel: - // TODO base alerting mechanism - } - } -} - func (b *BarChart) consumeSample(sample data.Sample) { b.count++ diff --git a/component/component.go b/component/component.go index f69a7b2..e3fe121 100644 --- a/component/component.go +++ b/component/component.go @@ -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 diff --git a/component/gauge/gauge.go b/component/gauge/gauge.go index cb9d6ac..a22760e 100644 --- a/component/gauge/gauge.go +++ b/component/gauge/gauge.go @@ -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() + go func() { + for { + select { + case sample := <-gauge.SampleChannel: + gauge.ConsumeSample(sample) + } + } + }() return &gauge } -func (g *Gauge) consume() { - for { - select { - case sample := <-g.SampleChannel: - g.ConsumeSample(sample) - //case alert := <-g.alertChannel: - // TODO base alerting mechanism - } - } -} - 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 { diff --git a/component/geometry.go b/component/geometry.go index 9bc7699..f8e6811 100644 --- a/component/geometry.go +++ b/component/geometry.go @@ -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, diff --git a/component/layout/layout.go b/component/layout/layout.go index 65ecace..242a5b6 100644 --- a/component/layout/layout.go +++ b/component/layout/layout.go @@ -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( diff --git a/component/menu.go b/component/menu.go index 40accc8..fb0c55c 100644 --- a/component/menu.go +++ b/component/menu.go @@ -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) } diff --git a/component/runchart/runchart.go b/component/runchart/runchart.go index af127f4..0f88f35 100644 --- a/component/runchart/runchart.go +++ b/component/runchart/runchart.go @@ -16,15 +16,13 @@ import ( ) const ( - xAxisLabelsHeight = 1 - xAxisLabelsWidth = 8 - xAxisLabelsIndent = 2 - xAxisGridWidth = xAxisLabelsIndent + xAxisLabelsWidth - yAxisLabelsHeight = 1 - yAxisLabelsIndent = 1 - - historyReserveMin = 20 - + xAxisLabelsHeight = 1 + xAxisLabelsWidth = 8 + xAxisLabelsIndent = 2 + 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,40 +76,41 @@ 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) + } + + go func() { + for { + select { + 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) consume() { - for { - select { - case sample := <-c.SampleChannel: - c.consumeSample(sample) - //case alert := <-c.alertChannel: - // TODO base alerting mechanism - } - } -} - func (c *RunChart) newTimePoint(value float64) TimePoint { now := time.Now() return 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 diff --git a/config/config.go b/config/config.go index ce64c29..3ad3716 100644 --- a/config/config.go +++ b/config/config.go @@ -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 } diff --git a/console/console.go b/console/console.go index 13412a1..082e2dc 100644 --- a/console/console.go +++ b/console/console.go @@ -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() } diff --git a/data/consumer.go b/data/consumer.go index a60db48..8a1b2dd 100644 --- a/data/consumer.go +++ b/data/consumer.go @@ -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 + 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), + SampleChannel: make(chan Sample), + AlertChannel: make(chan Alert), + CommandChannel: make(chan Command), } } diff --git a/event/handler.go b/event/handler.go index c084e69..b5f4c6f 100644 --- a/event/handler.go +++ b/event/handler.go @@ -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), diff --git a/main.go b/main.go index f013a61..0aea187 100644 --- a/main.go +++ b/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)