package ui import ( "cli-mon/yabl" "fmt" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" "os" "time" ) const ( connectors_page = "Connectors" connectors_errors_page = "Connectors errors" contactors_errors_page = "Contactors errors" contactors_state_page = "Contactors states" periphery_state_page = "Periphery state" periphery_station_state_page = "Periphery station state" converters_page = "Converters" converters_errors_page = "Converters errors" cpu_page = "CPU" connectorCount = 6 contactorsCount = 18 convertersCount = 18 redrawMillis = 500 ) type page struct { left string right string primitive tview.Primitive } type UI interface { Consume(event *yabl.Event) Start() Stop() } type gui struct { app *tview.Application pages *tview.Pages redraw bool ticker *time.Ticker pu *table puErrors *table contactorsErrors *table contactorsState *table peripheryState *table peripheryStationState *table converters *table convertersErrors *table cpu *table } type log struct { } func (g *gui) Consume(event *yabl.Event) { g.pu.update(event) g.puErrors.update(event) g.contactorsErrors.update(event) g.contactorsState.update(event) g.peripheryState.update(event) g.peripheryStationState.update(event) g.converters.update(event) g.convertersErrors.update(event) g.cpu.update(event) g.redraw = true } func NewUI() UI { g := &gui{} g.app = tview.NewApplication() g.pages = tview.NewPages() var active page var layout map[string]page g.pu = newTable(pu, 1, connectorCount, false, false).header(connectors_page).columns("Connector", connectorCount) g.puErrors = newTable(pu_errors, 1, connectorCount, false, false).header(connectors_errors_page).columns("Connector", connectorCount) g.contactorsErrors = newTable(contactors_errors, 0, 0, false, false).header(contactors_errors_page) g.contactorsState = newTable(contactors_state, 1, contactorsCount, true, true).header(contactors_state_page).rows("Contactor", contactorsCount) g.peripheryState = newTable(periphery_state, 1, connectorCount, false, false).header(periphery_state_page).columns("Connector", connectorCount) g.peripheryStationState = newTable(periphery_station_state, 0, 1, false, false).header(periphery_station_state_page) g.converters = newTable(converters, 1, convertersCount, false, true).header(converters_page).columns("", convertersCount) g.convertersErrors = newTable(converters_errors, 1, convertersCount, false, true).header(converters_errors_page).columns("", convertersCount) g.cpu = newTable(cpu, 0, 0, false, false).header(cpu_page) layout = map[string]page{ connectors_page: { left: cpu_page, right: connectors_errors_page, primitive: g.pu, }, connectors_errors_page: { left: connectors_page, right: contactors_errors_page, primitive: g.puErrors, }, contactors_errors_page: { left: connectors_errors_page, right: contactors_state_page, primitive: g.contactorsErrors, }, contactors_state_page: { left: contactors_errors_page, right: periphery_state_page, primitive: g.contactorsState, }, periphery_state_page: { left: contactors_state_page, right: periphery_station_state_page, primitive: g.peripheryState, }, periphery_station_state_page: { left: periphery_state_page, right: converters_page, primitive: g.peripheryStationState, }, converters_page: { left: periphery_station_state_page, right: converters_errors_page, primitive: g.converters, }, converters_errors_page: { left: converters_page, right: cpu_page, primitive: g.convertersErrors, }, cpu_page: { left: converters_errors_page, right: connectors_page, primitive: g.cpu, }, } for k, p := range layout { g.pages.AddPage(k, p.primitive, true, true) } active = layout[connectors_page] g.pages.SwitchToPage(connectors_page) g.app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { switch event.Key() { case tcell.KeyRight: g.pages.SwitchToPage(active.right) active = layout[active.right] return nil case tcell.KeyLeft: g.pages.SwitchToPage(active.left) active = layout[active.left] return nil case tcell.KeyCtrlC: g.Stop() } return event }) g.redraw = true return g } func (g *gui) Start() { g.ticker = time.NewTicker(redrawMillis * time.Millisecond) go func() { for _ = range g.ticker.C { if g.redraw { g.app.Draw() g.redraw = false } } }() go func() { if err := g.app.SetRoot(g.pages, true).EnableMouse(true).Run(); err != nil { panic(err) } }() } func (g *gui) Stop() { g.ticker.Stop() g.app.Stop() os.Exit(0) } func NewLog() UI { return &log{} } func (l log) Consume(event *yabl.Event) { fmt.Printf( "%v %v.%v [%d] %v\n", event.Updated.Format("Jan _2 15:04:05.000"), *event.ActionName, *event.Field, event.GetUnitId(), event.Value) } func (l log) Start() { } func (l log) Stop() { }