diff --git a/cdashdisplay/display.go b/cdashdisplay/display.go index 7dd794c..797bb4d 100644 --- a/cdashdisplay/display.go +++ b/cdashdisplay/display.go @@ -302,40 +302,45 @@ func (d *CDashDisplay) ResizeWindow(wID int16, delta helper.Vector) error { return d.updateWindowDimensions(window, packet) } -func (d *CDashDisplay) SaveLayout() { - file, err := os.OpenFile(path.Join(layoutsDir, "layout.yaml"), +func (d *CDashDisplay) SaveLayout(outputPath string) error { + file, err := os.OpenFile(path.Join(layoutsDir, outputPath), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755) if err != nil { - panic("failed to open logging file: " + err.Error()) + return err } data, err := yaml.Marshal(d.State.Layout) if err != nil { - panic("failed to marshal layout data") + return err } _, err = file.Write(data) if err != nil { - panic("failed to write data to file") + return err } + + return nil } -func (d *CDashDisplay) LoadLayout() { - data, err := os.ReadFile(path.Join(layoutsDir, "layout.yaml")) +func (d *CDashDisplay) LoadLayout(layoutName string) error { + data, err := os.ReadFile(path.Join(layoutsDir, layoutName)) if err != nil { - panic(err.Error()) + return err } layout := NewLayoutTree() err = yaml.Unmarshal(data, layout) if err != nil { - panic(err.Error()) + return err } for _, w := range layout.Windows { _, err = d.CreateWindow(*w) if err != nil { - pLogger.Debug(fmt.Sprintf("Failed to create window: %v", w)) + // NOTE: Add a way to handle multiple errors ? + return err } } + + return nil } diff --git a/cdashdisplay/transportPackets.go b/cdashdisplay/transportPackets.go index 6dcaaaa..df9071a 100644 --- a/cdashdisplay/transportPackets.go +++ b/cdashdisplay/transportPackets.go @@ -8,6 +8,10 @@ const ( ShowIDTrue uint8 = 1 ) +const ( + WinTypeString uint8 = 0 +) + type UIDimensions struct { X0 uint16 `yaml:"X0"` Y0 uint16 `yaml:"Y0"` diff --git a/helpers/helper.go b/helpers/helper.go index 2f2a2e4..ab9f902 100644 --- a/helpers/helper.go +++ b/helpers/helper.go @@ -11,6 +11,10 @@ type Vector struct { DY uint16 } +type MultiError struct { + Errors []error +} + func B32(s string) [32]byte { var b [32]byte copy(b[:], s) diff --git a/layouts/layout.yaml b/layouts/layout.yaml index d38e5f4..9c70f97 100755 --- a/layouts/layout.yaml +++ b/layouts/layout.yaml @@ -38,7 +38,7 @@ Windows: ShowID: 0 WinType: 0 PreviewValue: "7456" - Title: TACH + Title: TACHO 3: Dims: X0: 340 diff --git a/tui/internal/controllers/controllers.go b/tui/internal/controllers/controllers.go index 9cbc10b..c5b270f 100644 --- a/tui/internal/controllers/controllers.go +++ b/tui/internal/controllers/controllers.go @@ -4,6 +4,7 @@ package controllers import ( "esdi/tui/internal/dom" "esdi/tui/internal/events" + "fmt" "log/slog" "github.com/rivo/tview" @@ -15,3 +16,30 @@ type Controller struct { App *tview.Application Dom *dom.DOM } + +func ListFormButtonLabels(form *tview.Form) []string { + list := make([]string, form.GetButtonCount()) + for idx := range form.GetButtonCount() { + btn := form.GetButton(idx) + list = append(list, btn.GetLabel()) + } + + return list +} + +func SetFormButtonCallback(form *tview.Form, btnLabel string, fn func()) error { + btnIndex := form.GetButtonIndex(btnLabel) + if btnIndex == -1 { + availableButtons := ListFormButtonLabels(form) + return fmt.Errorf("no button with label: `%s` : [%v]", availableButtons) + } + + button := form.GetButton(btnIndex) + if button == nil { + return fmt.Errorf("not button with ID %d in form", btnIndex) + } + + button.SetSelectedFunc(fn) + + return nil +} diff --git a/tui/internal/controllers/deviceController.go b/tui/internal/controllers/deviceController.go index 0a60caa..c320da7 100644 --- a/tui/internal/controllers/deviceController.go +++ b/tui/internal/controllers/deviceController.go @@ -21,7 +21,7 @@ type DeviceController struct { func NewDeviceController(base *Controller, devService *serv.CDashService) *DeviceController { mc := &DeviceController{ Controller: base, - LayoutCtrl: NewLayoutController(base), + LayoutCtrl: NewLayoutController(base, devService), DevService: devService, StreamStrl: NewStreamingCtrl(), } @@ -122,11 +122,6 @@ func NewDeviceController(base *Controller, devService *serv.CDashService) *Devic // mc.CDash.SaveLayout() // }) - // mc.Bus.On(ui.LoadLayoutEv{}, func(e any) { - // mc.CDash.LoadLayout() - // mc.Bus.Emit(ui.RegisterLoadedLayout{*mc.CDash.State.Layout}) - // }) - // mc.Bus.On(ui.ForceRedraw{}, func(e any) { // // mc.App.QueueUpdateDraw(func() {}) // mc.App.Draw() diff --git a/tui/internal/controllers/layoutController.go b/tui/internal/controllers/layoutController.go index 0ad2e25..9c5a5b7 100644 --- a/tui/internal/controllers/layoutController.go +++ b/tui/internal/controllers/layoutController.go @@ -2,9 +2,15 @@ package controllers import ( "esdi/cdashdisplay" + helper "esdi/helpers" + "esdi/tui/internal/models" + "esdi/tui/internal/services" "esdi/tui/internal/views" + "fmt" + "strconv" "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" ) type LayoutController struct { @@ -12,13 +18,15 @@ type LayoutController struct { OnExit func() LayoutToolView *views.LayoutToolView Messages chan string + DevService *services.CDashService } -func NewLayoutController(base *Controller) *LayoutController { +func NewLayoutController(base *Controller, service *services.CDashService) *LayoutController { lc := &LayoutController{ Controller: base, LayoutToolView: views.NewLayoutToolView(), Messages: make(chan string, 10), + DevService: service, } lc.registerHooks() @@ -27,6 +35,7 @@ func NewLayoutController(base *Controller) *LayoutController { } func (lc *LayoutController) registerHooks() { + // Set the input capture behaviour lc.LayoutToolView.LayoutTree.Tree.SetInputCapture( func(ev *tcell.EventKey) *tcell.EventKey { switch ev.Key() { @@ -63,10 +72,12 @@ func (lc *LayoutController) registerHooks() { // Go into edit mode case 's': // Save the current layout - // bus.Emit(ui.SaveLayoutEv{}) + lc.Messages <- "calling save layout\n" + lc.saveLayout() case 'l': // Load the layout - // bus.Emit(ui.LoadLayoutEv{}) + lc.Messages <- "calling load layout\n" + lc.loadLayout() case 'g': // Go -> launches the current set up source // streamingWindow(bus, doc) @@ -75,87 +86,173 @@ func (lc *LayoutController) registerHooks() { return ev }, ) + + // Set the tree input actions + lc.LayoutToolView.LayoutTree.Tree.SetChangedFunc(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.(*models.UIWindow) + lc.Messages <- fmt.Sprintf("changing to -> %d\n", nodeWinRef.WID) + + lc.LayoutToolView.ShowWindowFormByID(nodeWinRef.WID) + }) + + lc.LayoutToolView.LayoutTree.Tree.SetSelectedFunc(func(node *tview.TreeNode) { + // Change focus to the selected window + nodeRef := node.GetReference() + if nodeRef == nil { + // its probably root I guess, thats what I'll believe + return + } + + nodeWinRef := nodeRef.(*models.UIWindow) + + lc.App.SetFocus(lc.LayoutToolView.FormQuickAccess[nodeWinRef.WID].Form.Form) + }) } -func (lc *LayoutController) parseCreateWindowInput() (*cdashdisplay.UIWindow, error) { - form := lc.LayoutToolView.LayoutActions.CreateWindowView +func (lc *LayoutController) parseWindowFormData( + form views.CDashDisplayWindowFormView, +) (*cdashdisplay.UIWindow, error) { - lc.Messages <- form.Form.X.GetText() + xValue, err := strconv.ParseUint(form.X.GetText(), 10, 64) + if err != nil { + return nil, err + } + yValue, err := strconv.ParseUint(form.Y.GetText(), 10, 64) + if err != nil { + return nil, err + } + widthValue, err := strconv.ParseUint(form.Width.GetText(), 10, 64) + if err != nil { + return nil, err + } + heightValue, err := strconv.ParseUint(form.Height.GetText(), 10, 64) + if err != nil { + return nil, err + } - // 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 - // } - // titleSizeValue, err := strconv.ParseUint(titleSize, 10, 64) - // if err != nil { - // return models.Window{}, err - // } - // textSizeValue, err := strconv.ParseUint(textSize, 10, 64) - // if err != nil { - // return models.Window{}, err - // } - // - // showIDValue := cdashdisplay.ShowIDFalse - // if showID { - // showIDValue = cdashdisplay.ShowIDTrue - // } + titleSizeInputID, titleSizeInput := form.TitleSize.GetCurrentOption() + if titleSizeInputID == -1 { + return nil, fmt.Errorf("no option selected for title size") + } + titleSizeValue, err := strconv.ParseUint(titleSizeInput, 10, 64) + if err != nil { + return nil, err + } - // win := e.(ui.CreateWindowEv).Window - // - // winDecor := cdashdisplay.DefaultDecorations - // winDecor.TextSize = win.TextSize - // winDecor.TitleSize = win.TitleSize - // - // uiWindow := cdashdisplay.UIWindow{ - // Dims: cdashdisplay.UIDimensions{ - // X0: win.X, - // Y0: win.Y, - // Width: win.Width, - // Height: win.Height, - // }, - // Opts: cdashdisplay.UIWindowOpts{ - // WinType: win.Type, // NOTE: values aren't implemented yet - // ShowID: win.ShowID, - // PreviewValue: helper.B32(win.PreviewValue), - // }, - // Decor: winDecor, - // Title: helper.B32(win.Title), - // } - // - // wID, err := mc.CDash.CreateWindow(uiWindow) - // if err != nil { - // mc.Bus.Emit(ui.PrintLogEv{Log: "failed to create window\n"}) - // return - // } - // - // mc.Bus.Emit(ui.WindowCreatedEv{ID: wID, Win: uiWindow}) - // mc.Bus.Emit(ui.PrintLogEv{Log: "Window created!\n"}) + textSizeInputID, textSizeInput := form.TextSize.GetCurrentOption() + if textSizeInputID == -1 { + return nil, fmt.Errorf("no option selected for text size") + } + textSizeValue, err := strconv.ParseUint(textSizeInput, 10, 64) + if err != nil { + return nil, err + } - // return models.Window{ - // X: uint16(xValue), - // Y: uint16(yValue), - // Width: uint16(widthValue), - // Height: uint16(heightValue), - // ShowID: showIDValue, - // TitleSize: uint8(titleSizeValue), - // TextSize: uint8(textSizeValue), - // PreviewValue: prev, - // Title: title, - // }, nil + showIDValue := cdashdisplay.ShowIDFalse + if form.ShowID.IsChecked() { + showIDValue = cdashdisplay.ShowIDTrue + } - return nil, nil + winDecor := cdashdisplay.DefaultDecorations + winDecor.TextSize = uint8(textSizeValue - 1) + winDecor.TitleSize = uint8(titleSizeValue - 1) + + uiWindow := &cdashdisplay.UIWindow{ + Dims: cdashdisplay.UIDimensions{ + X0: uint16(xValue), + Y0: uint16(yValue), + Width: uint16(widthValue), + Height: uint16(heightValue), + }, + Opts: cdashdisplay.UIWindowOpts{ + WinType: cdashdisplay.WinTypeString, // NOTE: values aren't implemented yet + ShowID: showIDValue, + PreviewValue: helper.B32(form.PreviewValue.GetText()), + }, + Decor: winDecor, + Title: helper.B32(form.Title.GetText()), + } + + return uiWindow, nil +} + +func (lc *LayoutController) createWindow() { + window, err := lc.parseWindowFormData(*lc.LayoutToolView.LayoutActions.CreateWindowView.Form) + if err != nil { + lc.Messages <- "failed to parse form inputs: " + err.Error() + return + } + + wID, err := lc.DevService.CreateWindow(window) + if err != nil { + lc.Messages <- "failed to create window\n" + return + } + + err = lc.updateFormView( + &models.UIWindow{ + WID: wID, + Data: *window, + }, + ) + if err != nil { + + // NOTE: if we fail to append the window to the views we must delete it + // altogether given we won't be able to manipulate it any further + lc.Messages <- "failed to append window to views " + err.Error() + } +} + +func (lc *LayoutController) updateFormView(win *models.UIWindow) error { + // OnSuccess we update our form to be an existing window form + err := lc.LayoutToolView.WindowCreatedSuccessfuly(win) + if err != nil { + return err + } + + // Set the update window button behaviour + formView := lc.LayoutToolView.FormQuickAccess[win.WID] + err = SetFormButtonCallback(formView.Form.Form, "Update", func() { + lc.Messages <- "pressed update form button\n" + window, err := lc.parseWindowFormData(*formView.Form) + if err != nil { + lc.Messages <- "failed to parse window form data " + err.Error() + "\n" + return + } + lc.Messages <- fmt.Sprintf("window data in form: %v\n", window) + + if err != nil { + lc.Messages <- "failed to parse form: " + err.Error() + "\n" + return + } + + lc.updateWindowAction(&models.UIWindow{ + WID: win.WID, + Data: *window, + }) + }) + if err != nil { + lc.Messages <- "failed to set callback for update button\n" + return err + } + + formView.Form.Form.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { + switch ev.Key() { + case tcell.KeyEscape: + lc.App.SetFocus(lc.LayoutToolView.LayoutTree.Tree) + } + + return ev + }) + + return nil } func (lc *LayoutController) newWindowAction() { @@ -167,8 +264,8 @@ func (lc *LayoutController) newWindowAction() { } // Get the new window form view - newWindowForm := views.NewCreateWindowFormView() - lc.LayoutToolView.LayoutActions.CreateWindowView = newWindowForm + lc.LayoutToolView.LayoutActions.CreateWindowView = views.NewCreateWindowFormView() + newWindowForm := lc.LayoutToolView.LayoutActions.CreateWindowView // Set the event capture for this form newWindowForm.Form.Form.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { @@ -181,40 +278,56 @@ func (lc *LayoutController) newWindowAction() { }) // Set the behaviour for when we press the create button - newWindowForm.CreateBtn.SetSelectedFunc(func() { - lc.Messages <- "am I here???" - lc.parseCreateWindowInput() - // _, titleSizeTxt := titleSize.GetCurrentOption() - // _, textSizeTxt := textSize.GetCurrentOption() - // // Validate the inputs - // window, err := validateFormInputs( - // x0.GetText(), - // y0.GetText(), - // width.GetText(), - // height.GetText(), - // title.GetText(), - // previewValue.GetText(), - // titleSizeTxt, - // textSizeTxt, - // showID.IsChecked(), - // ) - - // if err != nil { - // // bus.Emit(ui.LogEv{Log: fmt.Sprintf("failed to parse form: %s\n", err.Error())}) - // return - // } - - // bus.Emit(ui.LogEv{Log: fmt.Sprintf("showID: %d\n", window.ShowID)}) - // bus.Emit(ui.CreateWindowEv{Window: window}) + err := SetFormButtonCallback(newWindowForm.Form.Form, "Create", func() { + lc.createWindow() }) + if err != nil { + lc.Messages <- "Failed to set the callback for the create window button" + } // Set this on the action page and change to it - views.AddAndShowPage( - lc.LayoutToolView.LayoutActions.Pages, - "new-window-action-form", - newWindowForm.Form.Form, - ) + lc.LayoutToolView.ShowCreateWindowForm() // Set its focus lc.App.SetFocus(newWindowForm.Form.Form) } + +func (lc *LayoutController) updateWindowAction(win *models.UIWindow) { + err := lc.DevService.UpdateWindow(win.WID, &win.Data) + + lc.Messages <- fmt.Sprintf("Window: %v\n", win) + + if err != nil { + lc.Messages <- "failed to update window due to " + err.Error() + "\n" + return + } +} + +func (lc *LayoutController) displayLoadedLayouts() { + for idx, w := range lc.DevService.CDash.State.Layout.Windows { + + err := lc.updateFormView(&models.UIWindow{WID: idx, Data: *w}) + if err != nil { + lc.Messages <- "failed to add window to list" + } + } +} + +func (lc *LayoutController) loadLayout() { + // We would get the layout path from somewhere but for nots its layout.yaml + err := lc.DevService.LoadLayout("layout.yaml") + if err != nil { + lc.Messages <- "failed to load layout: " + err.Error() + return + } + + lc.displayLoadedLayouts() +} + +func (lc *LayoutController) saveLayout() { + err := lc.DevService.SaveLayout("layout.yaml") + if err != nil { + lc.Messages <- "failed to save layout: " + err.Error() + return + } +} diff --git a/tui/internal/models/window.go b/tui/internal/models/window.go index e338a65..bc34508 100644 --- a/tui/internal/models/window.go +++ b/tui/internal/models/window.go @@ -1,7 +1,9 @@ // Package models package models -type Window struct { +import "esdi/cdashdisplay" + +type WindowForm struct { X uint16 Y uint16 Width uint16 @@ -13,3 +15,8 @@ type Window struct { ShowID uint8 PreviewValue string } + +type UIWindow struct { + WID int16 + Data cdashdisplay.UIWindow +} diff --git a/tui/internal/services/device.go b/tui/internal/services/device.go index 248f1a2..3761075 100644 --- a/tui/internal/services/device.go +++ b/tui/internal/services/device.go @@ -39,3 +39,24 @@ func (cds *CDashService) FindDevice() { cds.Logger.Info("found cdashdisplay on: " + display.WT.Cfg.Name) cds.Messages <- "found cdashdisplay on: " + display.WT.Cfg.Name + "\n" } + +func (cds *CDashService) CreateWindow(win *cdashdisplay.UIWindow) (int16, error) { + wID, err := cds.CDash.CreateWindow(*win) + if err != nil { + return -1, err + } + + return wID, nil +} + +func (cds *CDashService) LoadLayout(layoutPath string) error { + return cds.CDash.LoadLayout(layoutPath) +} + +func (cds *CDashService) SaveLayout(layoutPath string) error { + return cds.CDash.SaveLayout(layoutPath) +} + +func (cds *CDashService) UpdateWindow(idx int16, win *cdashdisplay.UIWindow) error { + return cds.CDash.UpdateWindow(idx, win) +} diff --git a/tui/internal/ui/events.go b/tui/internal/ui/events.go index 3049ca8..4ffeb56 100644 --- a/tui/internal/ui/events.go +++ b/tui/internal/ui/events.go @@ -47,11 +47,11 @@ type RegisterLoadedLayout struct { type UpdateWindowEv struct { ID int16 - Window models.Window + Window models.WindowForm } type CreateWindowEv struct { - Window models.Window + Window models.WindowForm } type DestroyWindowEv struct { @@ -59,7 +59,7 @@ type DestroyWindowEv struct { } type LayoutRegisterWindowEv struct { - Window models.Window + Window models.WindowForm } type MoveWindowEv struct { diff --git a/tui/internal/views/layoutTool.go b/tui/internal/views/layoutTool.go index 18245c6..e45a5e5 100644 --- a/tui/internal/views/layoutTool.go +++ b/tui/internal/views/layoutTool.go @@ -1,9 +1,9 @@ package views import ( - "esdi/cdashdisplay" "esdi/tui/internal/dom" "esdi/tui/internal/events" + "esdi/tui/internal/models" "esdi/tui/internal/ui" "fmt" @@ -15,6 +15,7 @@ const ( LayoutToolFlexID = "layout-tool-flex" LayoutToolTreeID = "layout-tool-tree" LayoutToolActionPagesID = "layout-tool-action-pages" + LayoutToolNewWindowID = "new-window-action-form" ) type windowReference struct { @@ -56,46 +57,11 @@ func FindNodeByID( return nil } -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 - // } - // - // // Create the update tool - // updateForm := windowInfoForm(bus, doc, idx, win) - // - // fmtTitle := fmt.Sprintf("%s [%2d]", win.Title.String(), idx) - // ref := windowReference{ - // ID: idx, - // Form: updateForm, - // } - // newWindow := tview.NewTreeNode(fmtTitle).SetReference(&ref) - // root.AddChild(newWindow) -} - func BindWindowEvents( bus *events.Bus, doc *dom.DOM, tree *tview.TreeView, ) { - // 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 - - bus.On(ui.WindowCreatedEv{}, func(e any) { - ev := e.(ui.WindowCreatedEv) - - bus.Emit(ui.LogEv{Log: "Received a window created event\n"}) - if tree == nil { - bus.Emit(ui.LogEv{Log: "tree view is nil"}) - return - } - - appendWindow(bus, doc, tree, ev.ID, &ev.Win) - }) - bus.On(ui.WindowDestroyedEv{}, func(e any) { root := tree.GetRoot() if root == nil { @@ -111,20 +77,6 @@ func BindWindowEvents( bus.Emit(ui.ForceRedraw{}) }) - bus.On(ui.RegisterLoadedLayout{}, func(e any) { - root := tree.GetRoot() - if root == nil { - return - } - - layout := e.(ui.RegisterLoadedLayout) - for idx, w := range layout.Layout.Windows { - appendWindow(bus, doc, tree, idx, w) - } - - // bus.Emit(ui.ForceRedraw{}) - }) - bus.On(ui.ErrorCreateWindowEv{}, func(e any) { go func() { bus.Emit(ui.LogEv{ @@ -150,31 +102,6 @@ func getCurNodeRef(tree *tview.TreeView) (*windowReference, error) { return winRef, nil } -func layoutToolTreeViewOnChange(bus *events.Bus, doc *dom.DOM) func(node *tview.TreeNode) { - // Set focus to our new tool - // if changeFocus { - // bus.Emit(ui.ChangeFocusEv{Target: page.Self}) - // } - - 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(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 @@ -194,29 +121,23 @@ func layoutToolTreeViewOnSelect(bus *events.Bus) func(node *tview.TreeNode) { type LayoutTreeView struct { Tree *tview.TreeView InputCapture func(*tcell.EventKey) *tcell.EventKey - OnChange func(node *tview.TreeNode) - OnSelect func(node *tview.TreeNode) + // OnChange func(node *tview.TreeNode) + // OnSelect func(node *tview.TreeNode) } func NewLayoutTreeView() *LayoutTreeView { view := &LayoutTreeView{ InputCapture: blankInputCapture, - OnChange: blankTreeViewOnChange, - OnSelect: blankTreeViewOnChange, + // OnChange: blankTreeViewOnChange, + // OnSelect: blankTreeViewOnChange, } view.Tree = tview.NewTreeView() view.Tree.SetBorder(true).SetTitle("Layout Tree") view.Tree.SetInputCapture(view.InputCapture) - view.Tree.SetChangedFunc(view.OnChange) - view.Tree.SetSelectedFunc(view.OnSelect) - - // view.Tree.SetChangedFunc(layoutToolTreeViewOnChange(bus, doc)) - // view.Tree.SetSelectedFunc(layoutToolTreeViewOnSelect(bus)) - - // Bind the events for the treeview - // BindWindowEvents(bus, doc, layoutTreeUINode.Self.(*tview.TreeView)) + // Inject ChangedFunc + // Inject SelectedFunc // Create a root element rootElem := tview.NewTreeNode(".") @@ -225,6 +146,22 @@ func NewLayoutTreeView() *LayoutTreeView { return view } +func (lt *LayoutTreeView) AddWindow(win *models.UIWindow) error { + root := lt.Tree.GetRoot() + if root == nil { + return fmt.Errorf("unable to get root of treeview") + } + + // Create this new node + newWindow := tview.NewTreeNode( + windowInfoPageTitle(win.WID, win.Data.Title.String()), + ).SetReference(win) + + root.AddChild(newWindow) + + return nil +} + type LayoutToolActionView struct { Pages *tview.Pages CreateWindowView *CreateWindowFormView @@ -249,13 +186,16 @@ func NewLayoutToolActionView() *LayoutToolActionView { } type LayoutToolView struct { - Flex *tview.Flex - LayoutTree *LayoutTreeView - LayoutActions *LayoutToolActionView + Flex *tview.Flex + FormQuickAccess map[int16]*WindowFormView + LayoutTree *LayoutTreeView + LayoutActions *LayoutToolActionView } func NewLayoutToolView() *LayoutToolView { - view := &LayoutToolView{} + view := &LayoutToolView{ + FormQuickAccess: make(map[int16]*WindowFormView), + } // Want a TreeView at the top view.LayoutTree = NewLayoutTreeView() @@ -273,5 +213,39 @@ func NewLayoutToolView() *LayoutToolView { return view } -func (ltv *LayoutToolView) AddWindow() { +func (ltv *LayoutToolView) WindowCreatedSuccessfuly(win *models.UIWindow) error { + updateWindowForm := NewWindowFormView(&win.Data) + + // Update the pages ID + ltv.LayoutActions.Pages.RemovePage(LayoutToolNewWindowID) + AddAndShowPage( + ltv.LayoutActions.Pages, + windowInfoPageID(win.WID), + updateWindowForm.Form.Form, + ) + + // Then set the CreateWindowView pointer to nil + ltv.LayoutActions.CreateWindowView = nil + + // Add this form thing to the quick access map + ltv.FormQuickAccess[win.WID] = updateWindowForm + + // Add it to the tree view + return ltv.LayoutTree.AddWindow(win) +} + +func (ltv *LayoutToolView) ShowCreateWindowForm() { + AddAndShowPage( + ltv.LayoutActions.Pages, + LayoutToolNewWindowID, + ltv.LayoutActions.CreateWindowView.Form.Form, + ) +} + +func (ltv *LayoutToolView) ShowWindowFormByID(idx int16) { + AddAndShowPage( + ltv.LayoutActions.Pages, + windowInfoPageID(idx), + nil, + ) } diff --git a/tui/internal/views/layoutTool_NewWindow.go b/tui/internal/views/layoutTool_NewWindow.go index ea4b59f..af0be0c 100644 --- a/tui/internal/views/layoutTool_NewWindow.go +++ b/tui/internal/views/layoutTool_NewWindow.go @@ -45,7 +45,7 @@ func NewCDashDisplayWindowFormView() *CDashDisplayWindowFormView { for k := range 20 { view.TextSize.AddOption(fmt.Sprintf("%d", k+1), blankDropdownOptionCallback) } - view.TitleSize.SetCurrentOption(0) + view.TextSize.SetCurrentOption(0) view.Form = tview.NewForm(). AddFormItem(view.X). @@ -97,33 +97,6 @@ func NewWindowFormView(win *cdashdisplay.UIWindow) *WindowFormView { view.UpdateBtn = tview.NewButton("Update") // Need to inject the button functionality later - // AddButton("Update", func() { - // bus.Emit(ui.LogEv{Log: "update event was created\n"}) - // - // _, titleSizeTxt := titleSize.GetCurrentOption() - // _, textSizeTxt := textSize.GetCurrentOption() - // // Validate the inputs - // window, err := validateFormInputs( - // x0.GetText(), - // y0.GetText(), - // width.GetText(), - // height.GetText(), - // title.GetText(), - // previewValue.GetText(), - // titleSizeTxt, - // textSizeTxt, - // showID.IsChecked(), - // ) - // - // if err != nil { - // bus.Emit(ui.LogEv{Log: fmt.Sprintf("failed to parse form: %s\n", err.Error())}) - // return - // } - // - // bus.Emit(ui.LogEv{Log: fmt.Sprintf("showID: %d\n", window.ShowID)}) - // bus.Emit(ui.LogEv{Log: "sending update window ev\n"}) - // bus.Emit(ui.UpdateWindowEv{ID: idx, Window: window}) - // }) // In case the window is moved we need to update this form // bus.On(ui.WindowMovedEv{}, func(e any) { @@ -157,10 +130,15 @@ func NewWindowFormView(win *cdashdisplay.UIWindow) *WindowFormView { view.Form.WinType.SetCurrentOption(0) // NOTE: this needs to set the correct option view.Form.TitleSize.SetCurrentOption(int(win.Decor.TitleSize)) view.Form.TextSize.SetCurrentOption(int(win.Decor.TextSize)) + view.Form.Form.AddButton("Update", func() {}) return view } -func WindowInfoPageID(idx int16) string { +func windowInfoPageID(idx int16) string { return fmt.Sprintf("layout-tool-win-info-%d", idx) } + +func windowInfoPageTitle(idx int16, title string) string { + return fmt.Sprintf("%s [%02d]", title, idx) +}