This commit is contained in:
2026-01-09 19:05:14 +00:00
parent 56ce6bc58d
commit 583437cd75
13 changed files with 392 additions and 47 deletions
+28
View File
@@ -0,0 +1,28 @@
package views
import (
"esdi/t/internal/dom"
"esdi/t/internal/ui"
"slices"
"github.com/rivo/tview"
)
func AddAndShowPage(root *dom.DOM, ctx *ui.UIContext,
pages *tview.Pages, page *dom.UINode) error {
if !slices.Contains(pages.GetPageNames(false), page.ID) {
pages.AddAndSwitchToPage(page.ID, page.Self, true)
} else {
// Only change to page
pages.SwitchToPage(page.ID)
}
// Set focus to our new tool
ctx.ChangeFocus(page.Self)
return nil
}
// func PageExists(pages *tview.Pages, needle string) bool {
// return slices.Contains(pages.GetPageNames(false), needle)
// }
-5
View File
@@ -1,5 +0,0 @@
package views
type UIContext struct {
Redraw func()
}
+131 -3
View File
@@ -1,14 +1,85 @@
package views
import (
"esdi/t/internal/controllers"
"esdi/t/internal/dom"
"esdi/t/internal/events"
"esdi/t/internal/ui"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
func buildLayoutToolUINode(root *dom.DOM) (*dom.UINode, error) {
const (
layoutToolFlexID = "layout-tool-flex"
)
func BindWindowEvents(
ctx *ui.UIContext,
bus *events.Bus,
tree *tview.TreeView,
) {
bus.On(events.WindowCreated{}, func(e any) {
ctx.Log("Received a window created event")
})
}
func layoutToolTreeViewEvents(root *dom.DOM, ctx *ui.UIContext,
wc *controllers.WindowingController) func(
event *tcell.EventKey) *tcell.EventKey {
return func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyEsc:
ctx.ChangeFocus(root.GetElemByID(deviceAPIListID))
}
switch event.Rune() {
case 'N':
// Create a new screen
case 'n':
// Create a new window
ctx.Log("calling new window form\n")
createNewWindowForm(root, ctx, wc)
case 'x':
// Delete selected window
case 'm':
// Go into move mode
case 'e':
// Go into edit mode
}
return event
}
}
func layoutToolUIOnSelect(root *dom.DOM, ctx *ui.UIContext, wc *controllers.WindowingController) {
ctx.Log("Opening layout tool UI\n")
var err error
// Get the api pages
apiToolPages := root.GetElemByID(apiToolPagesID).(*tview.Pages)
if apiToolPages == nil {
ctx.Log(" Failed to retrive apiToolPages UI\n")
return
}
ctx.Log(" Checking if `%s` UINode already exists\n", layoutToolFlexID)
layoutToolUINode := root.GetNodeByID(layoutToolFlexID)
if layoutToolUINode == nil {
layoutToolUINode, err = buildLayoutToolUINode(root, ctx, wc)
if err != nil {
ctx.Log(" Failed to build layout tool UI: %s\n", err.Error())
}
}
AddAndShowPage(root, ctx, apiToolPages, layoutToolUINode)
}
func buildLayoutToolUINode(root *dom.DOM, ctx *ui.UIContext,
wc *controllers.WindowingController) (*dom.UINode, error) {
// Want a TreeView at the top
layoutTree := tview.NewTreeView()
layoutTree := tview.NewTreeView().
SetInputCapture(layoutToolTreeViewEvents(root, ctx, wc))
layoutTree.SetBorder(true).SetTitle("Layout Tree")
_, err := root.NewUINode("layout-tree",
root.GetElemByID("right-flex"), layoutTree)
@@ -26,11 +97,68 @@ func buildLayoutToolUINode(root *dom.DOM) (*dom.UINode, error) {
}
layoutToolFlex := tview.NewFlex().SetDirection(tview.FlexRow)
layoutToolFlexNode, err := root.NewUINode("layout-tool-flex", root.GetElemByID("api-tool-pages"),
layoutToolFlexNode, err := root.NewUINode(layoutToolFlexID, root.GetElemByID("api-tool-pages"),
layoutToolFlex)
if err != nil {
return nil, err
}
layoutToolFlex.
AddItem(layoutTree, 0, 2, true).
AddItem(actionPages, 0, 5, false)
return layoutToolFlexNode, nil
}
// Layout tool actions
func createNewWindowForm(root *dom.DOM, ctx *ui.UIContext,
wc *controllers.WindowingController) {
var err error
x0 := tview.NewInputField().SetLabel("x")
y0 := tview.NewInputField().SetLabel("y")
width := tview.NewInputField().SetLabel("width")
height := tview.NewInputField().SetLabel("height")
title := tview.NewInputField().SetLabel("title")
form := tview.NewForm().
AddFormItem(x0).
AddFormItem(y0).
AddFormItem(width).
AddFormItem(height).
AddFormItem(title).
AddButton("Create", func() {
wc.CreateWindow(
x0.GetText(),
y0.GetText(),
width.GetText(),
height.GetText(),
title.GetText(),
)
})
form.SetBorder(true).
SetTitle("new window form").
SetTitleAlign(tview.AlignLeft).
SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey {
switch ev.Key() {
case tcell.KeyEscape:
ctx.ChangeFocus(root.GetElemByID(layoutToolFlexID))
}
return ev
})
var formNode *dom.UINode
formNode = root.GetNodeByID("new-window-form")
if formNode == nil {
formNode, err = root.NewUINode("new-window-form", root.GetElemByID("layout-action-pages"),
form)
if err != nil {
panic("failed to create UI node for the new window form: " + err.Error())
}
}
AddAndShowPage(root, ctx, root.GetElemByID("layout-action-pages").(*tview.Pages),
formNode)
}
+30 -17
View File
@@ -2,13 +2,28 @@
package views
import (
"esdi/t/internal/dom"
"fmt"
"esdi/t/internal/controllers"
"esdi/t/internal/dom"
"esdi/t/internal/ui"
"github.com/rivo/tview"
)
func buildRightSidePages(root *dom.DOM, ctx *UIContext) (*dom.UINode, error) {
const (
mainFlexID = "main-flex"
apiToolPagesID = "api-tool-pages"
rightFlexID = "right-flex"
outputPaneID = "output-window"
deviceAPIListID = "device-api-list"
)
const (
pageName = "empty-page"
)
func buildRightSidePages(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error) {
// We need to build a set of pages with an empty page
emptyPage := tview.NewTextView().
SetTextAlign(tview.AlignCenter).
@@ -20,9 +35,9 @@ func buildRightSidePages(root *dom.DOM, ctx *UIContext) (*dom.UINode, error) {
fmt.Fprintf(emptyPage, "No Tool Selected")
apiToolPages := tview.NewPages().
AddPage("emptypage", emptyPage, true, true)
AddPage(pageName, emptyPage, true, true)
apiToolPagesNode, err := root.NewUINode("api-tool-pages", root.GetElemByID("right-flex"),
apiToolPagesNode, err := root.NewUINode(apiToolPagesID, root.GetElemByID(rightFlexID),
apiToolPages)
if err != nil {
return nil, err
@@ -31,7 +46,7 @@ func buildRightSidePages(root *dom.DOM, ctx *UIContext) (*dom.UINode, error) {
return apiToolPagesNode, nil
}
func buildRightSideFlex(root *dom.DOM, ctx *UIContext) (*dom.UINode, error) {
func buildRightSideFlex(root *dom.DOM, ctx *ui.UIContext) (*dom.UINode, error) {
apiToolPagesNode, err := buildRightSidePages(root, ctx)
if err != nil {
return nil, err
@@ -39,30 +54,28 @@ func buildRightSideFlex(root *dom.DOM, ctx *UIContext) (*dom.UINode, error) {
// This will be the right side flex
flex := tview.NewFlex().SetDirection(tview.FlexRow)
flexNode, err := root.NewUINode("right-flex", root.GetElemByID("main-flex"), flex)
flexNode, err := root.NewUINode(rightFlexID, root.GetElemByID(mainFlexID), flex)
if err != nil {
return nil, err
}
// Make the output window
outputWin := tview.NewTextView().SetBorder(true).SetTitle("DebugWindow")
outputWinNode, err := root.NewUINode("debug-window", root.GetRootElem(),
outputWin)
if err != nil {
return nil, err
outputWin := root.GetElemByID(outputPaneID)
if outputWin == nil {
panic("failed to attach output win to UI")
}
flex.
AddItem(apiToolPagesNode.Self, 0, 5, false).
AddItem(outputWinNode.Self, 0, 2, false)
AddItem(outputWin, 0, 2, false)
return flexNode, nil
}
func BuildMainFlex(root *dom.DOM, ctx *UIContext) (*tview.Flex, error) {
func BuildMainFlex(root *dom.DOM, ctx *ui.UIContext,
wc *controllers.WindowingController) (*tview.Flex, error) {
// To build the main view we must set the DOM root
mainFlex := tview.NewFlex().SetDirection(tview.FlexColumn)
mainFlexUINode, err := root.NewUINode("main-flex", nil, mainFlex)
mainFlexUINode, err := root.NewUINode(mainFlexID, nil, mainFlex)
if err != nil {
return nil, err
}
@@ -71,11 +84,11 @@ func BuildMainFlex(root *dom.DOM, ctx *UIContext) (*tview.Flex, error) {
deviceAPIList := tview.NewList().
AddItem("layout", "build a layout for CDashDisplay", 0, func() {
// When clicked we want to replace the right side pages with this
layoutToolUIOnSelect(root, ctx, wc)
})
deviceAPIList.SetBorder(true).SetTitle("list")
apiListWindowUINode, err := root.NewUINode("device-api-list", root.GetRootElem(),
apiListWindowUINode, err := root.NewUINode(deviceAPIListID, root.GetRootElem(),
deviceAPIList)
if err != nil {
return nil, err
+24
View File
@@ -0,0 +1,24 @@
package views
import (
"esdi/t/internal/dom"
"esdi/t/internal/ui"
"github.com/rivo/tview"
)
func BuildOutputWindow(root *dom.DOM, ctx *ui.UIContext) error {
var outputWin *tview.TextView
outputWin = tview.NewTextView().SetChangedFunc(func() {
ctx.Redraw()
outputWin.ScrollToEnd()
})
outputWin.SetBorder(true).SetTitle("DebugWindow")
_, err := root.NewUINode("output-window", nil, outputWin)
if err != nil {
return err
}
return nil
}