its all events LETS GO - I still need to make it be all events
This commit is contained in:
@@ -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})
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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})
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package events
|
|
||||||
|
|
||||||
import (
|
|
||||||
"esdi/tui/internal/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Error struct {
|
|
||||||
Error error
|
|
||||||
}
|
|
||||||
|
|
||||||
type WindowCreated struct {
|
|
||||||
Window models.Window
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "esdi/peripheral"
|
||||||
|
|
||||||
|
type DevicesTUI struct {
|
||||||
|
Serial *peripheral.PeripheralDeviceClerk
|
||||||
|
}
|
||||||
+12
-49
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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()
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user