its all events LETS GO - I still need to make it be all events

This commit is contained in:
2026-01-13 21:11:44 +00:00
parent 98e569d9be
commit 306929b8d3
12 changed files with 263 additions and 189 deletions
+39
View File
@@ -0,0 +1,39 @@
// Package controllers
package controllers
import (
"fmt"
"esdi/tui/internal/events"
"esdi/tui/internal/models"
"esdi/tui/internal/ui"
)
type LayoutController struct {
EvBus *events.Bus
}
func NewLayoutController(bus *events.Bus) *LayoutController {
lc := &LayoutController{
EvBus: bus,
}
bus.On(ui.CreateWindowEv{}, func(e any) {
ev := e.(ui.CreateWindowEv)
lc.createWindow(ev.Window)
})
return lc
}
func (lc *LayoutController) createWindow(win models.Window) {
lc.EvBus.Emit(ui.LogEv{
Log: fmt.Sprintf("x : %d\n"+
"y : %d\n"+
"width : %d\n"+
"height: %d\n"+
"title : %s\n", win.X, win.Y, win.Width, win.Height, win.Title),
})
lc.EvBus.Emit(ui.WindowCreatedEv{Window: win})
}
+38
View File
@@ -1,5 +1,43 @@
// Package controllers defines our controller layer // Package controllers defines our controller layer
package controllers package controllers
import (
"esdi/tui/internal/dom"
"esdi/tui/internal/events"
"esdi/tui/internal/ui"
"github.com/rivo/tview"
)
type Ctrls struct {
MC *MainController
WindowingController *LayoutController
}
type MainController struct { type MainController struct {
App *tview.Application
Dom *dom.DOM
EvBus *events.Bus
}
func NewMainController() *MainController {
mc := &MainController{
App: tview.NewApplication(),
Dom: dom.NewDOM(),
EvBus: events.NewBus(),
}
mc.EvBus.On(ui.RedrawEv{}, func(e any) {
mc.App.QueueUpdateDraw(func() {})
})
mc.EvBus.On(ui.ChangeFocusEv{}, func(e any) {
mc.App.SetFocus(e.(ui.ChangeFocusEv).Target)
})
mc.EvBus.On(ui.LogEv{}, func(e any) {
mc.EvBus.Emit(ui.PrintLogEv{Log: e.(ui.LogEv).Log})
})
return mc
} }
-55
View File
@@ -1,55 +0,0 @@
// Package controllers
package controllers
import (
"esdi/tui/internal/events"
"esdi/tui/internal/models"
"esdi/tui/internal/ui"
"strconv"
)
type WindowingController struct {
Ctx *ui.UIContext
Events *events.Bus
}
func (wc *WindowingController) CreateWindow(x, y,
width, height, title string) {
wc.Ctx.Log("x : %s\n", x)
wc.Ctx.Log("y : %s\n", y)
wc.Ctx.Log("width : %s\n", width)
wc.Ctx.Log("height: %s\n", height)
wc.Ctx.Log("title : %s\n", title)
// newWindow := tview.NewTreeNode(title)
xValue, err := strconv.ParseUint(x, 10, 64)
if err != nil {
wc.Events.Emit(events.Error{Error: err})
return
}
yValue, err := strconv.ParseUint(y, 10, 64)
if err != nil {
wc.Events.Emit(events.Error{Error: err})
return
}
widthValue, err := strconv.ParseUint(width, 10, 64)
if err != nil {
wc.Events.Emit(events.Error{Error: err})
return
}
heightValue, err := strconv.ParseUint(height, 10, 64)
if err != nil {
wc.Events.Emit(events.Error{Error: err})
return
}
window := models.Window{
X: uint16(xValue),
Y: uint16(yValue),
Width: uint16(widthValue),
Height: uint16(heightValue),
Title: title,
}
wc.Events.Emit(events.WindowCreated{Window: window})
}
-13
View File
@@ -1,13 +0,0 @@
package events
import (
"esdi/tui/internal/models"
)
type Error struct {
Error error
}
type WindowCreated struct {
Window models.Window
}
+7
View File
@@ -0,0 +1,7 @@
package models
import "esdi/peripheral"
type DevicesTUI struct {
Serial *peripheral.PeripheralDeviceClerk
}
+12 -49
View File
@@ -3,91 +3,54 @@ package tui
import ( import (
"esdi/tui/internal/controllers" "esdi/tui/internal/controllers"
"esdi/tui/internal/dom"
"esdi/tui/internal/events"
"esdi/tui/internal/ui"
"esdi/tui/internal/views" "esdi/tui/internal/views"
"fmt" "fmt"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
) )
type TUI struct { func Start() error {
App *tview.Application
Dom *dom.DOM
Events *events.Bus
}
func NewTUI() *TUI {
return &TUI{
App: tview.NewApplication(),
Dom: dom.NewDOM(),
Events: events.NewBus(),
}
}
func (t *TUI) log(formatter string, args ...any) {
outputWin := t.Dom.GetElemByID("output-window").(*tview.TextView)
fmt.Fprintf(outputWin, formatter, args...)
}
func (t *TUI) Start() error {
// The app starts running here! // The app starts running here!
// //
// Set the event capture for the global app itself here // Set the event capture for the global app itself here
t.App.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { mc := controllers.NewMainController()
mc.App.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyCtrlC || event.Rune() == 'q' { if event.Key() == tcell.KeyCtrlC || event.Rune() == 'q' {
t.App.Stop() mc.App.Stop()
return nil return nil
} }
return event return event
}) })
ctx := &ui.UIContext{ controllers.NewLayoutController(mc.EvBus)
Redraw: func() {
t.App.QueueUpdateDraw(func() {})
},
Log: func(formatter string, args ...any) {
t.log(formatter, args...)
},
ChangeFocus: func(p tview.Primitive) {
t.App.SetFocus(p)
},
}
// Create the controllers
windowingController := &controllers.WindowingController{
Events: t.Events,
Ctx: ctx,
}
// Make the output window // Make the output window
err := views.BuildOutputWindow(t.Dom, ctx) err := views.BuildOutputWindow(mc.EvBus, mc.Dom)
if err != nil { if err != nil {
panic("failed to create output window") panic("failed to create output window")
} }
// Set the main view // Set the main view
mainUINode, err := views.BuildMainFlex(t.Dom, ctx, windowingController) mainUINode, err := views.BuildMainFlex(mc.EvBus, mc.Dom)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to build main flex - %s", err.Error())) panic(fmt.Errorf("failed to build main flex - %s", err.Error()))
} }
rootNode, err := t.Dom.NewUINode("root", nil, mainUINode) rootNode, err := mc.Dom.NewUINode("root", nil, mainUINode)
if err != nil { if err != nil {
panic(fmt.Errorf("failed to create root node - %s", err.Error())) panic(fmt.Errorf("failed to create root node - %s", err.Error()))
} }
t.Dom.SetRoot(rootNode) mc.Dom.SetRoot(rootNode)
firstFocus := t.Dom.GetElemByID("device-api-list") firstFocus := mc.Dom.GetElemByID("device-api-list")
if firstFocus == nil { if firstFocus == nil {
panic(fmt.Errorf("`list-window` isn't registered")) panic(fmt.Errorf("`list-window` isn't registered"))
} }
// Star the app // Star the app
err = t.App.SetRoot(t.Dom.GetRootElem(), true).SetFocus(firstFocus).Run() err = mc.App.SetRoot(mc.Dom.GetRootElem(), true).SetFocus(firstFocus).Run()
if err != nil { if err != nil {
return err return err
} }
+43
View File
@@ -0,0 +1,43 @@
package ui
import (
"esdi/tui/internal/models"
"github.com/rivo/tview"
)
// Main controller events
type LogEv struct {
Log string
}
type PrintLogEv struct {
Log string
}
type RedrawEv struct{}
type ChangeFocusEv struct {
Target tview.Primitive
}
// ----------------------------------------------------------------------------
// Layout events
type CreateWindowEv struct {
Window models.Window
}
type WindowCreatedEv struct {
Window models.Window
}
type ErrorCreateWindowEv struct {
Error error
}
type ErrorFormParseEv struct {
Error error
}
+3 -2
View File
@@ -2,13 +2,14 @@ package views
import ( import (
"esdi/tui/internal/dom" "esdi/tui/internal/dom"
"esdi/tui/internal/events"
"esdi/tui/internal/ui" "esdi/tui/internal/ui"
"slices" "slices"
"github.com/rivo/tview" "github.com/rivo/tview"
) )
func AddAndShowPage(root *dom.DOM, ctx *ui.UIContext, func AddAndShowPage(bus *events.Bus, doc *dom.DOM,
pages *tview.Pages, page *dom.UINode) error { pages *tview.Pages, page *dom.UINode) error {
if !slices.Contains(pages.GetPageNames(false), page.ID) { if !slices.Contains(pages.GetPageNames(false), page.ID) {
pages.AddAndSwitchToPage(page.ID, page.Self, true) pages.AddAndSwitchToPage(page.ID, page.Self, true)
@@ -18,7 +19,7 @@ func AddAndShowPage(root *dom.DOM, ctx *ui.UIContext,
} }
// Set focus to our new tool // Set focus to our new tool
ctx.ChangeFocus(page.Self) bus.Emit(ui.ChangeFocusEv{Target: page.Self})
return nil return nil
} }
+88 -49
View File
@@ -1,10 +1,12 @@
package views package views
import ( import (
"esdi/tui/internal/controllers"
"esdi/tui/internal/dom" "esdi/tui/internal/dom"
"esdi/tui/internal/events" "esdi/tui/internal/events"
"esdi/tui/internal/models"
"esdi/tui/internal/ui" "esdi/tui/internal/ui"
"fmt"
"strconv"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
"github.com/rivo/tview" "github.com/rivo/tview"
@@ -17,40 +19,42 @@ const (
) )
func BindWindowEvents( func BindWindowEvents(
ctx *ui.UIContext,
bus *events.Bus, bus *events.Bus,
doc *dom.DOM,
tree *tview.TreeView, tree *tview.TreeView,
) { ) {
// I recon I have to change this for some type os event system that // I recon I have to change this for some type os event system that
// triggers directly on the UINodes I want them to be triggered on // triggers directly on the UINodes I want them to be triggered on
bus.On(events.WindowCreated{}, func(e any) { bus.On(ui.WindowCreatedEv{}, func(e any) {
ctx.Log("Received a window created event\n") bus.Emit(ui.LogEv{Log: "Received a window created event\n"})
if tree == nil { if tree == nil {
ctx.Log("tree view is nil") bus.Emit(ui.LogEv{Log: "tree view is nil"})
return return
} }
root := tree.GetRoot() root := tree.GetRoot()
if root == nil { if root == nil {
ctx.Log("unable to get root of tree view") bus.Emit(ui.LogEv{Log: "unable to get root of tree view"})
return return
} }
newWindow := tview.NewTreeNode(e.(events.WindowCreated).Window.Title) newWindow := tview.NewTreeNode(e.(ui.WindowCreatedEv).Window.Title)
root.AddChild(newWindow) root.AddChild(newWindow)
}) })
bus.On(events.Error{}, func(e any) { bus.On(ui.ErrorCreateWindowEv{}, func(e any) {
ctx.Log("Error performing action: %s\n", e.(events.Error).Error.Error()) bus.Emit(ui.LogEv{
Log: fmt.Sprintf(
"Error performing action: %s\n", e.(ui.ErrorCreateWindowEv).Error.Error(),
)})
}) })
} }
func layoutToolTreeViewEvents(root *dom.DOM, ctx *ui.UIContext, func layoutToolTreeViewEvents(bus *events.Bus, doc *dom.DOM,
tree *tview.TreeView, wc *controllers.WindowingController) func( tree *tview.TreeView) func(event *tcell.EventKey) *tcell.EventKey {
event *tcell.EventKey) *tcell.EventKey {
return func(event *tcell.EventKey) *tcell.EventKey { return func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() { switch event.Key() {
case tcell.KeyEsc: case tcell.KeyEsc:
ctx.ChangeFocus(root.GetElemByID(deviceAPIListID)) bus.Emit(ui.ChangeFocusEv{Target: doc.GetElemByID(deviceAPIListID)})
} }
switch event.Rune() { switch event.Rune() {
@@ -59,20 +63,20 @@ func layoutToolTreeViewEvents(root *dom.DOM, ctx *ui.UIContext,
// I think I will leave this one for later // I think I will leave this one for later
case 'n': case 'n':
// Create a new window // Create a new window
ctx.Log("calling new window form\n") bus.Emit(ui.LogEv{Log: "calling new window form\n"})
createNewWindowForm(root, ctx, wc) createNewWindowForm(bus, doc)
case 'x': case 'x':
// Delete selected window // Delete selected window
ctx.Log("calling delete window\n") bus.Emit(ui.LogEv{Log: "calling delete window\n"})
curNode := tree.GetCurrentNode() curNode := tree.GetCurrentNode()
if curNode == nil { if curNode == nil {
ctx.Log("unable to get current tree node") bus.Emit(ui.LogEv{Log: "unable to get current tree node"})
break break
} }
root := tree.GetRoot() root := tree.GetRoot()
if root == nil { if root == nil {
ctx.Log("unable to get current tree node") bus.Emit(ui.LogEv{Log: "unable to get current tree node"})
break break
} }
@@ -87,36 +91,38 @@ func layoutToolTreeViewEvents(root *dom.DOM, ctx *ui.UIContext,
} }
} }
func layoutToolUIOnSelect(root *dom.DOM, ctx *ui.UIContext, wc *controllers.WindowingController) { func layoutToolUIOnSelect(bus *events.Bus, doc *dom.DOM) {
ctx.Log("Opening layout tool UI\n") bus.Emit(ui.LogEv{Log: "Opening layout tool UI\n"})
var err error var err error
// Get the api pages // Get the api pages
apiToolPages := root.GetElemByID(apiToolPagesID).(*tview.Pages) apiToolPages := doc.GetElemByID(apiToolPagesID).(*tview.Pages)
if apiToolPages == nil { if apiToolPages == nil {
ctx.Log(" Failed to retrive apiToolPages UI\n") bus.Emit(ui.LogEv{Log: " Failed to retrive apiToolPages UI\n"})
return return
} }
ctx.Log(" Checking if `%s` UINode already exists\n", layoutToolFlexID) bus.Emit(ui.LogEv{
layoutToolUINode := root.GetNodeByID(layoutToolFlexID) Log: fmt.Sprintf(" Checking if `%s` UINode already exists\n", layoutToolFlexID),
})
layoutToolUINode := doc.GetNodeByID(layoutToolFlexID)
if layoutToolUINode == nil { if layoutToolUINode == nil {
layoutToolUINode, err = buildLayoutFlexComponent(root, ctx, wc) layoutToolUINode, err = buildLayoutFlexComponent(bus, doc)
if err != nil { if err != nil {
ctx.Log(" Failed to build layout tool UI: %s\n", err.Error()) bus.Emit(ui.LogEv{
Log: fmt.Sprintf(" Failed to build layout tool UI: %s\n", err.Error()),
})
} }
} }
AddAndShowPage(root, ctx, apiToolPages, layoutToolUINode) AddAndShowPage(bus, doc, apiToolPages, layoutToolUINode)
} }
func buildLayoutTreeComponent(doc *dom.DOM, ctx *ui.UIContext, func buildLayoutTreeComponent(bus *events.Bus, doc *dom.DOM) (*dom.UINode, error) {
wc *controllers.WindowingController) (*dom.UINode, error) {
layoutTree := tview.NewTreeView() layoutTree := tview.NewTreeView()
layoutTree.SetBorder(true).SetTitle("Layout Tree"). layoutTree.SetBorder(true).SetTitle("Layout Tree").
SetInputCapture(layoutToolTreeViewEvents(doc, ctx, layoutTree, wc)) SetInputCapture(layoutToolTreeViewEvents(bus, doc, layoutTree))
layoutTreeUINode, err := doc.NewUINode(layoutToolTreeID, layoutTreeUINode, err := doc.NewUINode(layoutToolTreeID,
doc.GetElemByID(rightFlexID), layoutTree) doc.GetElemByID(rightFlexID), layoutTree)
@@ -125,7 +131,7 @@ func buildLayoutTreeComponent(doc *dom.DOM, ctx *ui.UIContext,
} }
// Bind the events for the treeview // Bind the events for the treeview
BindWindowEvents(ctx, wc.Events, layoutTreeUINode.Self.(*tview.TreeView)) BindWindowEvents(bus, doc, layoutTreeUINode.Self.(*tview.TreeView))
// Create a root element // Create a root element
rootElem := tview.NewTreeNode(".") rootElem := tview.NewTreeNode(".")
@@ -134,9 +140,7 @@ func buildLayoutTreeComponent(doc *dom.DOM, ctx *ui.UIContext,
return layoutTreeUINode, nil return layoutTreeUINode, nil
} }
func buildLayoutActionPagesComponent(doc *dom.DOM, _ *ui.UIContext, func buildLayoutActionPagesComponent(_ *events.Bus, doc *dom.DOM) (*dom.UINode, error) {
_ *controllers.WindowingController) (*dom.UINode, error) {
actionPages := tview.NewPages() actionPages := tview.NewPages()
actionPages.SetBorder(true).SetTitle("Action Page") actionPages.SetBorder(true).SetTitle("Action Page")
@@ -150,23 +154,22 @@ func buildLayoutActionPagesComponent(doc *dom.DOM, _ *ui.UIContext,
return actionPagesUINode, nil return actionPagesUINode, nil
} }
func buildLayoutFlexComponent(root *dom.DOM, ctx *ui.UIContext, func buildLayoutFlexComponent(bus *events.Bus, doc *dom.DOM) (*dom.UINode, error) {
wc *controllers.WindowingController) (*dom.UINode, error) {
// Want a TreeView at the top // Want a TreeView at the top
layoutTreeUINode, err := buildLayoutTreeComponent(root, ctx, wc) layoutTreeUINode, err := buildLayoutTreeComponent(bus, doc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Want pages below to run actions // Want pages below to run actions
actionPagesUINode, err := buildLayoutActionPagesComponent(root, ctx, wc) actionPagesUINode, err := buildLayoutActionPagesComponent(bus, doc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
layoutToolFlex := tview.NewFlex().SetDirection(tview.FlexRow) layoutToolFlex := tview.NewFlex().SetDirection(tview.FlexRow)
layoutToolFlexNode, err := root.NewUINode(layoutToolFlexID, layoutToolFlexNode, err := doc.NewUINode(layoutToolFlexID,
root.GetElemByID(apiToolPagesID), layoutToolFlex) doc.GetElemByID(apiToolPagesID), layoutToolFlex)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -179,8 +182,36 @@ func buildLayoutFlexComponent(root *dom.DOM, ctx *ui.UIContext,
} }
// Layout tool actions // Layout tool actions
func createNewWindowForm(root *dom.DOM, ctx *ui.UIContext,
wc *controllers.WindowingController) { // Validate the form inputs
func validateFormInputs(x, y, w, h, title string) (models.Window, error) {
xValue, err := strconv.ParseUint(x, 10, 64)
if err != nil {
return models.Window{}, err
}
yValue, err := strconv.ParseUint(y, 10, 64)
if err != nil {
return models.Window{}, err
}
widthValue, err := strconv.ParseUint(w, 10, 64)
if err != nil {
return models.Window{}, err
}
heightValue, err := strconv.ParseUint(h, 10, 64)
if err != nil {
return models.Window{}, err
}
return models.Window{
X: uint16(xValue),
Y: uint16(yValue),
Width: uint16(widthValue),
Height: uint16(heightValue),
Title: title,
}, nil
}
func createNewWindowForm(bus *events.Bus, doc *dom.DOM) {
var err error var err error
x0 := tview.NewInputField().SetLabel("x") x0 := tview.NewInputField().SetLabel("x")
@@ -196,13 +227,21 @@ func createNewWindowForm(root *dom.DOM, ctx *ui.UIContext,
AddFormItem(height). AddFormItem(height).
AddFormItem(title). AddFormItem(title).
AddButton("Create", func() { AddButton("Create", func() {
wc.CreateWindow( // Validate the inputs
window, err := validateFormInputs(
x0.GetText(), x0.GetText(),
y0.GetText(), y0.GetText(),
width.GetText(), width.GetText(),
height.GetText(), height.GetText(),
title.GetText(), title.GetText(),
) )
if err != nil {
bus.Emit(ui.LogEv{Log: fmt.Sprintf("failed to parse form: %s\n", err.Error())})
return
}
bus.Emit(ui.CreateWindowEv{Window: window})
}) })
form.SetBorder(true). form.SetBorder(true).
@@ -211,22 +250,22 @@ func createNewWindowForm(root *dom.DOM, ctx *ui.UIContext,
SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey {
switch ev.Key() { switch ev.Key() {
case tcell.KeyEscape: case tcell.KeyEscape:
ctx.ChangeFocus(root.GetElemByID(layoutToolFlexID)) bus.Emit(ui.ChangeFocusEv{Target: doc.GetElemByID(layoutToolFlexID)})
} }
return ev return ev
}) })
var formNode *dom.UINode var formNode *dom.UINode
formNode = root.GetNodeByID("new-window-form") formNode = doc.GetNodeByID("new-window-form")
if formNode == nil { if formNode == nil {
formNode, err = root.NewUINode("new-window-form", formNode, err = doc.NewUINode("new-window-form",
root.GetElemByID(layoutToolActionPagesID), form) doc.GetElemByID(layoutToolActionPagesID), form)
if err != nil { if err != nil {
panic("failed to create UI node for the new window form: " + err.Error()) panic("failed to create UI node for the new window form: " + err.Error())
} }
} }
AddAndShowPage(root, ctx, root.GetElemByID(layoutToolActionPagesID).(*tview.Pages), AddAndShowPage(bus, doc, doc.GetElemByID(layoutToolActionPagesID).(*tview.Pages),
formNode) formNode)
} }
+14 -15
View File
@@ -4,8 +4,8 @@ package views
import ( import (
"fmt" "fmt"
"esdi/tui/internal/controllers"
"esdi/tui/internal/dom" "esdi/tui/internal/dom"
"esdi/tui/internal/events"
"esdi/tui/internal/ui" "esdi/tui/internal/ui"
"github.com/rivo/tview" "github.com/rivo/tview"
@@ -23,12 +23,12 @@ const (
pageName = "empty-page" pageName = "empty-page"
) )
func buildRightSidePages(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error) { func buildRightSidePages(bus *events.Bus, doc *dom.DOM) (*dom.UINode, error) {
// We need to build a set of pages with an empty page // We need to build a set of pages with an empty page
emptyPage := tview.NewTextView(). emptyPage := tview.NewTextView().
SetTextAlign(tview.AlignCenter). SetTextAlign(tview.AlignCenter).
SetChangedFunc(func() { SetChangedFunc(func() {
ctx.Redraw() bus.Emit(ui.RedrawEv{})
}) })
emptyPage.SetBorder(true).SetTitle("-- Tool Area --") emptyPage.SetBorder(true).SetTitle("-- Tool Area --")
@@ -37,7 +37,7 @@ func buildRightSidePages(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error)
apiToolPages := tview.NewPages(). apiToolPages := tview.NewPages().
AddPage(pageName, emptyPage, true, true) AddPage(pageName, emptyPage, true, true)
apiToolPagesNode, err := root.NewUINode(apiToolPagesID, root.GetElemByID(rightFlexID), apiToolPagesNode, err := doc.NewUINode(apiToolPagesID, doc.GetElemByID(rightFlexID),
apiToolPages) apiToolPages)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -46,20 +46,20 @@ func buildRightSidePages(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error)
return apiToolPagesNode, nil return apiToolPagesNode, nil
} }
func buildRightSideFlex(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error) { func buildRightSideFlex(bus *events.Bus, doc *dom.DOM) (*dom.UINode, error) {
apiToolPagesNode, err := buildRightSidePages(root, ctx) apiToolPagesNode, err := buildRightSidePages(bus, doc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// This will be the right side flex // This will be the right side flex
flex := tview.NewFlex().SetDirection(tview.FlexRow) flex := tview.NewFlex().SetDirection(tview.FlexRow)
flexNode, err := root.NewUINode(rightFlexID, root.GetElemByID(mainFlexID), flex) flexNode, err := doc.NewUINode(rightFlexID, doc.GetElemByID(mainFlexID), flex)
if err != nil { if err != nil {
return nil, err return nil, err
} }
outputWin := root.GetElemByID(outputPaneID) outputWin := doc.GetElemByID(outputPaneID)
if outputWin == nil { if outputWin == nil {
panic("failed to attach output win to UI") panic("failed to attach output win to UI")
} }
@@ -71,30 +71,29 @@ func buildRightSideFlex(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error) {
return flexNode, nil return flexNode, nil
} }
func BuildMainFlex(root *dom.DOM, ctx *ui.UIContext, func BuildMainFlex(bus *events.Bus, doc *dom.DOM) (*tview.Flex, error) {
wc *controllers.WindowingController) (*tview.Flex, error) {
// To build the main view we must set the DOM root // To build the main view we must set the DOM root
mainFlex := tview.NewFlex().SetDirection(tview.FlexColumn) mainFlex := tview.NewFlex().SetDirection(tview.FlexColumn)
mainFlexUINode, err := root.NewUINode(mainFlexID, nil, mainFlex) mainFlexUINode, err := doc.NewUINode(mainFlexID, nil, mainFlex)
if err != nil { if err != nil {
return nil, err return nil, err
} }
root.SetRoot(mainFlexUINode) doc.SetRoot(mainFlexUINode)
deviceAPIList := tview.NewList(). deviceAPIList := tview.NewList().
AddItem("layout", "build a layout for CDashDisplay", 0, func() { AddItem("layout", "build a layout for CDashDisplay", 0, func() {
layoutToolUIOnSelect(root, ctx, wc) layoutToolUIOnSelect(bus, doc)
}) })
deviceAPIList.SetBorder(true).SetTitle("list") deviceAPIList.SetBorder(true).SetTitle("list")
apiListWindowUINode, err := root.NewUINode(deviceAPIListID, root.GetRootElem(), apiListWindowUINode, err := doc.NewUINode(deviceAPIListID, doc.GetRootElem(),
deviceAPIList) deviceAPIList)
if err != nil { if err != nil {
return nil, err return nil, err
} }
rightSideFlex, err := buildRightSideFlex(root, ctx) rightSideFlex, err := buildRightSideFlex(bus, doc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+17 -3
View File
@@ -2,23 +2,37 @@ package views
import ( import (
"esdi/tui/internal/dom" "esdi/tui/internal/dom"
"esdi/tui/internal/events"
"esdi/tui/internal/ui" "esdi/tui/internal/ui"
"fmt"
"github.com/rivo/tview" "github.com/rivo/tview"
) )
func BuildOutputWindow(root *dom.DOM, ctx *ui.UIContext) error { func bindOutputWindowEvents(
bus *events.Bus,
output *tview.TextView,
) {
bus.On(ui.PrintLogEv{}, func(e any) {
le, _ := e.(ui.PrintLogEv)
fmt.Fprintf(output, le.Log)
})
}
func BuildOutputWindow(bus *events.Bus, doc *dom.DOM) error {
var outputWin *tview.TextView var outputWin *tview.TextView
outputWin = tview.NewTextView().SetChangedFunc(func() { outputWin = tview.NewTextView().SetChangedFunc(func() {
ctx.Redraw() bus.Emit(ui.RedrawEv{})
outputWin.ScrollToEnd() outputWin.ScrollToEnd()
}) })
outputWin.SetBorder(true).SetTitle("DebugWindow") outputWin.SetBorder(true).SetTitle("DebugWindow")
_, err := root.NewUINode("output-window", nil, outputWin) _, err := doc.NewUINode("output-window", nil, outputWin)
if err != nil { if err != nil {
return err return err
} }
bindOutputWindowEvents(bus, outputWin)
return nil return nil
} }
+2 -3
View File
@@ -1,9 +1,8 @@
// Package tui // Package tui
package tui package tui
import "esdi/tui/internal/tui" import t "esdi/tui/internal/tui"
func Run() error { func Run() error {
app := tui.NewTUI() return t.Start()
return app.Start()
} }