From c0e33c35853998963ade38f547a384433b4f9e92 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Fri, 13 Feb 2026 23:36:27 +0000 Subject: [PATCH] Added the window updated command, can update titles now. Very nice --- DEVELOPMENT.md | 8 +- cdashdisplay/display.go | 57 ++++++++------ cdashdisplay/layoutManager.go | 4 + cdashdisplay/transportPackets.go | 33 ++++++++ tui/internal/controllers/mainc.go | 24 +++++- tui/internal/ui/events.go | 9 ++- tui/internal/views/aux.go | 13 +++- tui/internal/views/layoutTool.go | 58 +++++++++++--- tui/internal/views/layoutTool_NewWindow.go | 77 ++++++++++++++++++- .../views/layoutTool_WindowManipulation.go | 2 +- 10 files changed, 237 insertions(+), 48 deletions(-) create mode 100644 cdashdisplay/layoutManager.go create mode 100644 cdashdisplay/transportPackets.go diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 25481e3..0627686 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,7 +1,5 @@ # TASK - [ ] Add a way to manage the windows in the layout tool UI -we need to be able to create a new windw: --> creates a new form we can edit --> on creation updates that form to be an updatable window -when traversing the layouttreeview: --> update the tool page so we can jump to edit and update window info + - [X] need to create the new form that changes in the action pages + - [ ] form must reflect updates to the window data on other tools like + the move tool. Can update it OnChange function diff --git a/cdashdisplay/display.go b/cdashdisplay/display.go index 80babbe..985c0b6 100644 --- a/cdashdisplay/display.go +++ b/cdashdisplay/display.go @@ -32,7 +32,8 @@ const ( newWindowCMDID types.Command = 3 destroyWindowCMDID types.Command = 4 updateWindowDimsCMDID types.Command = 5 - newLayoutCMDID types.Command = 6 + updateWindowCMDID types.Command = 6 // Change this to a move cmd instead + newLayoutCMDID types.Command = 7 ) const ( @@ -53,29 +54,11 @@ var DefaultDecorations = UIDecorations{ Padding: 0x00, } -type UIDimensions struct { - X0 uint16 `yaml:"X0"` - Y0 uint16 `yaml:"Y0"` - Width uint16 `yaml:"Width"` - Height uint16 `yaml:"Height"` -} - type UpdateDimsPacket struct { ID int16 Dims UIDimensions } -type UIDecorations struct { - BGColour uint16 `yaml:"BGColour"` - FGColour uint16 `yaml:"FGColour"` - TitleColour uint16 `yaml:"TitleColour"` - BorderColour uint16 `yaml:"BorderColour"` - TitleSize uint8 `yaml:"TitleSize"` - TextSize uint8 `yaml:"TextSize"` - HasBorder uint8 `yaml:"HasBorder"` - Padding uint8 `yaml:"Padding"` -} - type FString32 [32]byte func (s FString32) String() string { @@ -115,12 +98,6 @@ func (s *FString32) UnmarshalYAML(value *yaml.Node) error { return nil } -type UIWindow struct { - Dims UIDimensions `yaml:"Dims"` - Decor UIDecorations `yaml:"Decor"` - Title FString32 `yaml:"Title"` -} - type LayoutTree struct { Windows map[int16]*UIWindow `yaml:"Windows"` } @@ -195,6 +172,36 @@ func (d *CDashDisplay) CreateWindow(win UIWindow) (int16, error) { return wID.ID, nil } +func (d *CDashDisplay) UpdateWindow(wID int16, win *UIWindow) error { + data := UIWindowUpdatePacket{ + WinID: wID, + Window: *win, + } + + bytes, err := helper.StructToBytes(data) + if err != nil { + return err + } + + err = d.WT.SendCommand(updateWindowCMDID, bytes, nil) + if err != nil { + return err + } + + // NOTE: need to check the flow of this because: + // windows has a pointer to a UIWindow stored + // I get it and update it in the controller + // I send the pointer here + // -> it should be the same pointer then right? + pLogger.Debug(fmt.Sprintf("PreUpdate ID: %p", win)) + d.State.Layout.Windows[wID] = win + pLogger.Debug(fmt.Sprintf("PostUpdate ID: %p", win)) + // Yeah, same address as suspected + // I can't think about it right now. I'll think about that tomorrow + + return nil +} + func (d *CDashDisplay) DestroyWindow(wID int16) error { type UIWindowDestructPacket struct { WinID int16 diff --git a/cdashdisplay/layoutManager.go b/cdashdisplay/layoutManager.go new file mode 100644 index 0000000..19318f5 --- /dev/null +++ b/cdashdisplay/layoutManager.go @@ -0,0 +1,4 @@ +package cdashdisplay + +type layoutManager struct { +} diff --git a/cdashdisplay/transportPackets.go b/cdashdisplay/transportPackets.go new file mode 100644 index 0000000..79faf79 --- /dev/null +++ b/cdashdisplay/transportPackets.go @@ -0,0 +1,33 @@ +package cdashdisplay + +// In this file we will place all structs that are 1:1 representation of the +// types in the device transport layer -> + +type UIDimensions struct { + X0 uint16 `yaml:"X0"` + Y0 uint16 `yaml:"Y0"` + Width uint16 `yaml:"Width"` + Height uint16 `yaml:"Height"` +} + +type UIDecorations struct { + BGColour uint16 `yaml:"BGColour"` + FGColour uint16 `yaml:"FGColour"` + TitleColour uint16 `yaml:"TitleColour"` + BorderColour uint16 `yaml:"BorderColour"` + TitleSize uint8 `yaml:"TitleSize"` + TextSize uint8 `yaml:"TextSize"` + HasBorder uint8 `yaml:"HasBorder"` + Padding uint8 `yaml:"Padding"` +} + +type UIWindow struct { + Dims UIDimensions `yaml:"Dims"` + Decor UIDecorations `yaml:"Decor"` + Title FString32 `yaml:"Title"` +} + +type UIWindowUpdatePacket struct { + WinID int16 + Window UIWindow +} diff --git a/tui/internal/controllers/mainc.go b/tui/internal/controllers/mainc.go index 8939cb6..5128e3e 100644 --- a/tui/internal/controllers/mainc.go +++ b/tui/internal/controllers/mainc.go @@ -84,11 +84,33 @@ func NewMainController(logger *slog.Logger) *MainController { return } - mc.EvBus.Emit(ui.WindowCreatedEv{ID: wID, Title: win.Title}) + mc.EvBus.Emit(ui.WindowCreatedEv{ID: wID, Win: uiWindow}) mc.EvBus.Emit(ui.PrintLogEv{Log: "Window created!\n"}) }() }) + mc.EvBus.On(ui.UpdateWindowEv{}, func(e any) { + winModel := e.(ui.UpdateWindowEv) + + // Build a new UIWindow here I guess + curWindow, ok := mc.CDash.State.Layout.Windows[winModel.ID] + if !ok { + mc.EvBus.Emit(ui.PrintLogEv{Log: "could not acquire window from display state"}) + return + } + + curWindow.Dims.X0 = winModel.Window.X + curWindow.Dims.Y0 = winModel.Window.Y + curWindow.Dims.Width = winModel.Window.Width + curWindow.Dims.Height = winModel.Window.Height + curWindow.Title = helper.B32(winModel.Window.Title) + + err := mc.CDash.UpdateWindow(winModel.ID, curWindow) + if err != nil { + mc.EvBus.Emit(ui.PrintLogEv{Log: "failed to update window"}) + } + }) + mc.EvBus.On(ui.DestroyWindowEv{}, func(e any) { go func() { pLogger.Info(fmt.Sprintf("Called in to destroy win: %d", e.(ui.DestroyWindowEv).ID)) diff --git a/tui/internal/ui/events.go b/tui/internal/ui/events.go index 6868c21..3fad454 100644 --- a/tui/internal/ui/events.go +++ b/tui/internal/ui/events.go @@ -37,6 +37,11 @@ type RegisterLoadedLayout struct { Layout cdashdisplay.LayoutTree } +type UpdateWindowEv struct { + ID int16 + Window models.Window +} + type CreateWindowEv struct { Window models.Window } @@ -60,8 +65,8 @@ type ResizeWindowEv struct { } type WindowCreatedEv struct { - ID int16 - Title string + ID int16 + Win cdashdisplay.UIWindow } type WindowDestroyedEv struct { diff --git a/tui/internal/views/aux.go b/tui/internal/views/aux.go index 135605e..fa4e9fa 100644 --- a/tui/internal/views/aux.go +++ b/tui/internal/views/aux.go @@ -9,8 +9,13 @@ import ( "github.com/rivo/tview" ) -func AddAndShowPage(bus *events.Bus, doc *dom.DOM, - pages *tview.Pages, page *dom.UINode) error { +func AddAndShowPage( + bus *events.Bus, + doc *dom.DOM, + pages *tview.Pages, + page *dom.UINode, + changeFocus bool, +) error { if !slices.Contains(pages.GetPageNames(false), page.ID) { pages.AddAndSwitchToPage(page.ID, page.Self, true) } else { @@ -19,7 +24,9 @@ func AddAndShowPage(bus *events.Bus, doc *dom.DOM, } // Set focus to our new tool - bus.Emit(ui.ChangeFocusEv{Target: page.Self}) + if changeFocus { + bus.Emit(ui.ChangeFocusEv{Target: page.Self}) + } return nil } diff --git a/tui/internal/views/layoutTool.go b/tui/internal/views/layoutTool.go index 05695ef..9e187c1 100644 --- a/tui/internal/views/layoutTool.go +++ b/tui/internal/views/layoutTool.go @@ -1,6 +1,7 @@ package views import ( + "esdi/cdashdisplay" "esdi/tui/internal/dom" "esdi/tui/internal/events" "esdi/tui/internal/ui" @@ -17,7 +18,8 @@ const ( ) type windowReference struct { - ID int16 + ID int16 + Form *dom.UINode } func getWindowRefFromNode(node *tview.TreeNode) *windowReference { @@ -54,16 +56,21 @@ func FindNodeByID( return nil } -func appendWindow(bus *events.Bus, tree *tview.TreeView, idx int16, title string) { +func appendWindow(bus *events.Bus, doc *dom.DOM, tree *tview.TreeView, idx int16, + win *cdashdisplay.UIWindow) { root := tree.GetRoot() if root == nil { bus.Emit(ui.LogEv{Log: "unable to get root of tree view"}) return } - fmtTitle := fmt.Sprintf("%s [%2d]", title, idx) + // Create the update tool + updateForm := windowInfoForm(bus, doc, idx, win) + + fmtTitle := fmt.Sprintf("%s [%2d]", win.Title.String(), idx) ref := windowReference{ - ID: idx, + ID: idx, + Form: updateForm, } newWindow := tview.NewTreeNode(fmtTitle).SetReference(&ref) root.AddChild(newWindow) @@ -79,7 +86,7 @@ func BindWindowEvents( bus.On(ui.WindowCreatedEv{}, func(e any) { go func() { - win := e.(ui.WindowCreatedEv) + ev := e.(ui.WindowCreatedEv) bus.Emit(ui.LogEv{Log: "Received a window created event\n"}) if tree == nil { @@ -87,7 +94,7 @@ func BindWindowEvents( return } - appendWindow(bus, tree, win.ID, win.Title) + appendWindow(bus, doc, tree, ev.ID, &ev.Win) }() }) @@ -116,7 +123,7 @@ func BindWindowEvents( layout := e.(ui.RegisterLoadedLayout) for idx, w := range layout.Layout.Windows { - appendWindow(bus, tree, idx, w.Title.String()) + appendWindow(bus, doc, tree, idx, w) } // bus.Emit(ui.ForceRedraw{}) @@ -216,12 +223,42 @@ func layoutToolUIOnSelect(bus *events.Bus, doc *dom.DOM) { } } - AddAndShowPage(bus, doc, apiToolPages, layoutToolUINode) + AddAndShowPage(bus, doc, apiToolPages, layoutToolUINode, true) } -func layoutToolTreeViewOnChange() func(node *tview.TreeNode) { +func layoutToolTreeViewOnChange(bus *events.Bus, doc *dom.DOM) func(node *tview.TreeNode) { return func(node *tview.TreeNode) { // Here we want to change the current existing form on the action pages + nodeRef := node.GetReference() + if nodeRef == nil { + // its probably root I guess, thats what I'll believe + return + } + + nodeWinRef := nodeRef.(*windowReference) + + bus.Emit(ui.LogEv{ + Log: fmt.Sprintf("changing to -> %d | %s\n", nodeWinRef.ID, nodeWinRef.Form.ID), + }) + + pages := doc.GetElemByID(layoutToolActionPagesID) + AddAndShowPage(bus, doc, pages.(*tview.Pages), nodeWinRef.Form, false) + } +} + +func layoutToolTreeViewOnSelect(bus *events.Bus) func(node *tview.TreeNode) { + return func(node *tview.TreeNode) { + // Get the window reference which will have the ID for the form + bus.Emit(ui.LogEv{Log: "PRESSED ENTER\n"}) + + ref := node.GetReference() + if ref == nil { + bus.Emit(ui.LogEv{Log: "Couldn't find reference for node\n"}) + return + } + + nodeWinRef := ref.(*windowReference) + bus.Emit(ui.ChangeFocusEv{Target: nodeWinRef.Form.Self}) } } @@ -231,7 +268,8 @@ func buildLayoutTreeComponent(bus *events.Bus, doc *dom.DOM) (*dom.UINode, error layoutTree.SetBorder(true).SetTitle("Layout Tree"). SetInputCapture(layoutToolTreeViewEvCapture(bus, doc, layoutTree)) - layoutTree.SetChangedFunc(layoutToolTreeViewOnChange()) + layoutTree.SetChangedFunc(layoutToolTreeViewOnChange(bus, doc)) + layoutTree.SetSelectedFunc(layoutToolTreeViewOnSelect(bus)) layoutTreeUINode, err := doc.NewUINode(layoutToolTreeID, doc.GetElemByID(rightFlexID), layoutTree) diff --git a/tui/internal/views/layoutTool_NewWindow.go b/tui/internal/views/layoutTool_NewWindow.go index ec837a0..781af0b 100644 --- a/tui/internal/views/layoutTool_NewWindow.go +++ b/tui/internal/views/layoutTool_NewWindow.go @@ -4,6 +4,7 @@ import ( "fmt" "strconv" + "esdi/cdashdisplay" "esdi/tui/internal/dom" "esdi/tui/internal/events" "esdi/tui/internal/models" @@ -104,5 +105,79 @@ func createNewWindowForm(bus *events.Bus, doc *dom.DOM) { } AddAndShowPage(bus, doc, doc.GetElemByID(layoutToolActionPagesID).(*tview.Pages), - formNode) + formNode, true) +} + +func windowInfoPageID(idx int16) string { + return fmt.Sprintf("layout-tool-win-info-%d", idx) +} + +func windowInfoForm(bus *events.Bus, doc *dom.DOM, idx int16, + win *cdashdisplay.UIWindow) *dom.UINode { + var err error + + x0 := tview.NewInputField().SetLabel("x").SetText(fmt.Sprintf("%d", win.Dims.X0)) + y0 := tview.NewInputField().SetLabel("y").SetText(fmt.Sprintf("%d", win.Dims.Y0)) + width := tview.NewInputField().SetLabel("width").SetText(fmt.Sprintf("%d", win.Dims.Width)) + height := tview.NewInputField().SetLabel("height").SetText(fmt.Sprintf("%d", win.Dims.Height)) + title := tview.NewInputField().SetLabel("title").SetText(win.Title.String()) + winType := tview.NewDropDown().SetLabel("type"). + SetOptions([]string{"string", "bar"}, func(s string, id int) { + // Here we have to add extra options for the configuration of default + // values and so on + }). + SetCurrentOption(0) + + form := tview.NewForm(). + AddFormItem(x0). + AddFormItem(y0). + AddFormItem(width). + AddFormItem(height). + AddFormItem(title). + AddFormItem(winType). + AddButton("Update", func() { + bus.Emit(ui.LogEv{Log: "update event was created\n"}) + // Validate the inputs + window, err := validateFormInputs( + x0.GetText(), + y0.GetText(), + width.GetText(), + height.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.LogEv{Log: "sending update window ev\n"}) + bus.Emit(ui.UpdateWindowEv{ID: idx, Window: window}) + }) + + form.SetBorder(true). + SetTitle(fmt.Sprintf("Info - %s [%2d]", win.Title.String(), idx)). + SetTitleAlign(tview.AlignLeft). + SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { + switch ev.Key() { + case tcell.KeyEscape: + bus.Emit(ui.ChangeFocusEv{Target: doc.GetElemByID(layoutToolTreeID)}) + } + + return ev + }) + + var formNode *dom.UINode + elemId := windowInfoPageID(idx) + formNode = doc.GetNodeByID(elemId) + layoutToolActionPagesElem := doc.GetElemByID(layoutToolActionPagesID) + if formNode == nil { + formNode, err = doc.NewUINode(elemId, layoutToolActionPagesElem, form) + if err != nil { + panic("failed to create UI node for the new window form: " + err.Error()) + } + } + + // AddAndShowPage(bus, doc, layoutToolActionPagesElem.(*tview.Pages), formNode) + return formNode } diff --git a/tui/internal/views/layoutTool_WindowManipulation.go b/tui/internal/views/layoutTool_WindowManipulation.go index 57ac543..79ce896 100644 --- a/tui/internal/views/layoutTool_WindowManipulation.go +++ b/tui/internal/views/layoutTool_WindowManipulation.go @@ -168,5 +168,5 @@ func windowManipulationTool(bus *events.Bus, doc *dom.DOM, idx int16) { } box.SetInputCapture(windowManipulationEvCapture(bus, doc, idx, &state)) - AddAndShowPage(bus, doc, actionPages, boxNode) + AddAndShowPage(bus, doc, actionPages, boxNode, true) }