move and resize commands working
This commit is contained in:
+17
-5
@@ -249,11 +249,11 @@ func (d *CDashDisplay) updateWindowDimensions(win *UIWindow, packet UpdateDimsPa
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *CDashDisplay) MoveWindow(wID int16, delta helper.Vector) (UIDimensions, error) {
|
||||
func (d *CDashDisplay) MoveWindow(wID int16, delta *helper.Vector) error {
|
||||
// Get the window from the layout
|
||||
window, ok := d.State.Layout.Windows[wID]
|
||||
if !ok {
|
||||
return UIDimensions{}, fmt.Errorf("window with ID '%d' doesn't exist", wID)
|
||||
return fmt.Errorf("window with ID '%d' doesn't exist", wID)
|
||||
}
|
||||
|
||||
// Now we will create new dimensions
|
||||
@@ -267,10 +267,16 @@ func (d *CDashDisplay) MoveWindow(wID int16, delta helper.Vector) (UIDimensions,
|
||||
Dims: newDimensions,
|
||||
}
|
||||
|
||||
return newDimensions, d.updateWindowDimensions(window, packet)
|
||||
err := d.updateWindowDimensions(window, packet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
window.Dims = newDimensions
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *CDashDisplay) ResizeWindow(wID int16, delta helper.Vector) error {
|
||||
func (d *CDashDisplay) ResizeWindow(wID int16, delta *helper.Vector) error {
|
||||
// Get the window from the layout
|
||||
window, ok := d.State.Layout.Windows[wID]
|
||||
if !ok {
|
||||
@@ -299,7 +305,13 @@ func (d *CDashDisplay) ResizeWindow(wID int16, delta helper.Vector) error {
|
||||
Dims: newDimensions,
|
||||
}
|
||||
|
||||
return d.updateWindowDimensions(window, packet)
|
||||
err := d.updateWindowDimensions(window, packet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
window.Dims = newDimensions
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *CDashDisplay) SaveLayout(outputPath string) error {
|
||||
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
Windows:
|
||||
1:
|
||||
Dims:
|
||||
X0: 234
|
||||
Y0: 124
|
||||
X0: 252
|
||||
Y0: 122
|
||||
Width: 117
|
||||
Height: 72
|
||||
Decor:
|
||||
@@ -21,10 +21,10 @@ Windows:
|
||||
Title: SPEEDO
|
||||
2:
|
||||
Dims:
|
||||
X0: 401
|
||||
X0: 399
|
||||
Y0: 120
|
||||
Width: 176
|
||||
Height: 76
|
||||
Width: 155
|
||||
Height: 70
|
||||
Decor:
|
||||
BGColour: 4161
|
||||
FGColour: 65535
|
||||
|
||||
@@ -19,6 +19,7 @@ type LayoutController struct {
|
||||
LayoutToolView *views.LayoutToolView
|
||||
Messages chan string
|
||||
DevService *services.CDashService
|
||||
MoveToolState *windowManipState
|
||||
}
|
||||
|
||||
func NewLayoutController(base *Controller, service *services.CDashService) *LayoutController {
|
||||
@@ -27,6 +28,7 @@ func NewLayoutController(base *Controller, service *services.CDashService) *Layo
|
||||
LayoutToolView: views.NewLayoutToolView(),
|
||||
Messages: make(chan string, 10),
|
||||
DevService: service,
|
||||
MoveToolState: &windowManipState{Mode: moveMode},
|
||||
}
|
||||
|
||||
lc.registerHooks()
|
||||
@@ -53,14 +55,7 @@ func (lc *LayoutController) registerHooks() {
|
||||
lc.deleteWindow()
|
||||
case 'm':
|
||||
lc.Messages <- "calling window manipulation tool\n"
|
||||
// Go into move mode
|
||||
// bus.Emit(ui.LogEv{Log: })
|
||||
// wRef, err := getCurNodeRef(tree)
|
||||
// if err != nil {
|
||||
// bus.Emit(ui.LogEv{Log: " -> " + err.Error()})
|
||||
// break
|
||||
// }
|
||||
// windowManipulationTool(bus, doc, wRef.ID)
|
||||
lc.moveWindow()
|
||||
case 's':
|
||||
// Save the current layout
|
||||
lc.Messages <- "calling save layout\n"
|
||||
@@ -88,9 +83,9 @@ func (lc *LayoutController) registerHooks() {
|
||||
}
|
||||
|
||||
nodeWinRef := nodeRef.(*models.UIWindow)
|
||||
lc.Messages <- fmt.Sprintf("changing to -> %d\n", nodeWinRef.WID)
|
||||
lc.Messages <- fmt.Sprintf("changing to -> %d\n", nodeWinRef.IDX)
|
||||
|
||||
lc.LayoutToolView.ShowWindowFormByID(nodeWinRef.WID)
|
||||
lc.LayoutToolView.ShowWindowFormByID(nodeWinRef.IDX)
|
||||
})
|
||||
|
||||
lc.LayoutToolView.LayoutTree.Tree.SetSelectedFunc(func(node *tview.TreeNode) {
|
||||
@@ -103,7 +98,7 @@ func (lc *LayoutController) registerHooks() {
|
||||
|
||||
nodeWinRef := nodeRef.(*models.UIWindow)
|
||||
|
||||
lc.App.SetFocus(lc.LayoutToolView.FormQuickAccess[nodeWinRef.WID].Form.Form)
|
||||
lc.App.SetFocus(lc.LayoutToolView.FormQuickAccess[nodeWinRef.IDX].Form.Form)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -189,8 +184,8 @@ func (lc *LayoutController) createWindow() {
|
||||
|
||||
err = lc.updateFormView(
|
||||
&models.UIWindow{
|
||||
WID: wID,
|
||||
Data: *window,
|
||||
IDX: wID,
|
||||
Window: *window,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -209,7 +204,7 @@ func (lc *LayoutController) updateFormView(win *models.UIWindow) error {
|
||||
}
|
||||
|
||||
// Set the update window button behaviour
|
||||
formView := lc.LayoutToolView.FormQuickAccess[win.WID]
|
||||
formView := lc.LayoutToolView.FormQuickAccess[win.IDX]
|
||||
err = SetFormButtonCallback(formView.Form.Form, "Update", func() {
|
||||
lc.Messages <- "pressed update form button\n"
|
||||
window, err := lc.parseWindowFormData(*formView.Form)
|
||||
@@ -225,8 +220,8 @@ func (lc *LayoutController) updateFormView(win *models.UIWindow) error {
|
||||
}
|
||||
|
||||
lc.updateWindowAction(&models.UIWindow{
|
||||
WID: win.WID,
|
||||
Data: *window,
|
||||
IDX: win.IDX,
|
||||
Window: *window,
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
@@ -284,7 +279,7 @@ func (lc *LayoutController) newWindowAction() {
|
||||
}
|
||||
|
||||
func (lc *LayoutController) updateWindowAction(win *models.UIWindow) {
|
||||
err := lc.DevService.UpdateWindow(win.WID, &win.Data)
|
||||
err := lc.DevService.UpdateWindow(win.IDX, &win.Window)
|
||||
|
||||
lc.Messages <- fmt.Sprintf("Window: %v\n", win)
|
||||
|
||||
@@ -297,13 +292,29 @@ func (lc *LayoutController) updateWindowAction(win *models.UIWindow) {
|
||||
func (lc *LayoutController) displayLoadedLayouts() {
|
||||
for idx, w := range lc.DevService.CDash.State.Layout.Windows {
|
||||
|
||||
err := lc.updateFormView(&models.UIWindow{WID: idx, Data: *w})
|
||||
err := lc.updateFormView(&models.UIWindow{IDX: idx, Window: *w})
|
||||
if err != nil {
|
||||
lc.Messages <- "failed to add window to list"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (lc *LayoutController) getCurrentTreeNodeModel() (*tview.TreeNode, *models.UIWindow, error) {
|
||||
// Grab the form for the currently selected window
|
||||
node := lc.LayoutToolView.LayoutTree.Tree.GetCurrentNode()
|
||||
if node == nil {
|
||||
return nil, nil, fmt.Errorf("failed to grab current tree node")
|
||||
}
|
||||
|
||||
// From this node get its references
|
||||
ref, ok := node.GetReference().(*models.UIWindow)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("failed to get data on currently selected window")
|
||||
}
|
||||
|
||||
return node, ref, nil
|
||||
}
|
||||
|
||||
func (lc *LayoutController) loadLayout() {
|
||||
// We would get the layout path from somewhere but for nots its layout.yaml
|
||||
err := lc.DevService.LoadLayout("layout.yaml")
|
||||
@@ -337,7 +348,7 @@ func (lc *LayoutController) deleteWindow() {
|
||||
win := curNode.GetReference().(*models.UIWindow)
|
||||
|
||||
// Delete it
|
||||
err := lc.DevService.DeleteWindow(win.WID)
|
||||
err := lc.DevService.DeleteWindow(win.IDX)
|
||||
if err != nil {
|
||||
lc.Messages <- "failed to delete window: " + err.Error() + "\n"
|
||||
return
|
||||
@@ -346,3 +357,48 @@ func (lc *LayoutController) deleteWindow() {
|
||||
// Reflect the deletion in the view
|
||||
lc.LayoutToolView.DeleteWindowByNode(curNode)
|
||||
}
|
||||
|
||||
// moveWindow is a utility to interactively move the windows on the display
|
||||
func (lc *LayoutController) moveWindow() {
|
||||
lc.Messages <- "Entering move mode (ESC to exit)\n"
|
||||
|
||||
_, win, err := lc.getCurrentTreeNodeModel()
|
||||
if err != nil {
|
||||
lc.Messages <- "failed to enter move mode: " + err.Error() + "\n"
|
||||
return
|
||||
}
|
||||
|
||||
formView := lc.LayoutToolView.FormQuickAccess[win.IDX].Form
|
||||
oldCapture := formView.Form.GetInputCapture()
|
||||
|
||||
formView.Form.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey {
|
||||
lc.Messages <- "Captured event??\n"
|
||||
switch ev.Key() {
|
||||
case tcell.KeyESC:
|
||||
formView.Form.SetInputCapture(oldCapture)
|
||||
lc.App.SetFocus(lc.LayoutToolView.LayoutTree.Tree)
|
||||
}
|
||||
|
||||
// Mode switching
|
||||
switch ev.Rune() {
|
||||
case 'r':
|
||||
lc.MoveToolState.Mode = resizeMode
|
||||
lc.Messages <- "Switching to resizeMode"
|
||||
return nil
|
||||
case 'm':
|
||||
lc.MoveToolState.Mode = moveMode
|
||||
lc.Messages <- "Switching to moveMode"
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delegate the current handler input
|
||||
handler := lc.MoveToolState.CurrentHandler(lc, win)
|
||||
if handler != nil {
|
||||
return handler(ev)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
lc.App.SetFocus(formView.Form)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
helper "esdi/helpers"
|
||||
"esdi/tui/internal/models"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
type ManipMode int
|
||||
|
||||
const (
|
||||
moveMode ManipMode = iota
|
||||
resizeMode
|
||||
)
|
||||
|
||||
type modeHandler func(*tcell.EventKey) *tcell.EventKey
|
||||
|
||||
type windowManipState struct {
|
||||
Mode ManipMode
|
||||
}
|
||||
|
||||
func keyToVector(r rune) (helper.Vector, bool) {
|
||||
var mult uint16 = 1
|
||||
|
||||
// Is uppercase? For fast movement
|
||||
if r >= 'A' && r <= 'Z' {
|
||||
mult = 10
|
||||
r += 'a' - 'A'
|
||||
}
|
||||
|
||||
switch r {
|
||||
case 'h':
|
||||
return helper.Vector{DX: -mult, DY: 0}, true
|
||||
case 'j':
|
||||
return helper.Vector{DX: 0, DY: mult}, true
|
||||
case 'k':
|
||||
return helper.Vector{DX: 0, DY: -mult}, true
|
||||
case 'l':
|
||||
return helper.Vector{DX: mult, DY: 0}, true
|
||||
}
|
||||
|
||||
return helper.Vector{}, false
|
||||
}
|
||||
|
||||
func (lc *LayoutController) handleMovementCapture(win *models.UIWindow,
|
||||
ev *tcell.EventKey) *tcell.EventKey {
|
||||
vec, ok := keyToVector(ev.Rune())
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := lc.DevService.MoveWindow(win, &vec)
|
||||
if err != nil {
|
||||
lc.Messages <- "failed to move window: " + err.Error() + "\n"
|
||||
return nil
|
||||
}
|
||||
|
||||
// Success - update the form
|
||||
lc.LayoutToolView.UpdateFormView(win)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lc *LayoutController) handleResizeCapture(win *models.UIWindow,
|
||||
ev *tcell.EventKey) *tcell.EventKey {
|
||||
vec, ok := keyToVector(ev.Rune())
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := lc.DevService.ResizeWindow(win, &vec)
|
||||
if err != nil {
|
||||
lc.Messages <- "failed to resize window: " + err.Error() + "\n"
|
||||
return nil
|
||||
}
|
||||
|
||||
// Success - update the form
|
||||
lc.LayoutToolView.UpdateFormView(win)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *windowManipState) CurrentHandler(lc *LayoutController, w *models.UIWindow) modeHandler {
|
||||
switch s.Mode {
|
||||
case moveMode:
|
||||
return func(ev *tcell.EventKey) *tcell.EventKey {
|
||||
return lc.handleMovementCapture(w, ev)
|
||||
}
|
||||
case resizeMode:
|
||||
return func(ev *tcell.EventKey) *tcell.EventKey {
|
||||
return lc.handleResizeCapture(w, ev)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -17,6 +17,6 @@ type WindowForm struct {
|
||||
}
|
||||
|
||||
type UIWindow struct {
|
||||
WID int16
|
||||
Data cdashdisplay.UIWindow
|
||||
IDX int16
|
||||
Window cdashdisplay.UIWindow
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package services
|
||||
|
||||
import (
|
||||
"esdi/cdashdisplay"
|
||||
helper "esdi/helpers"
|
||||
"esdi/peripheral"
|
||||
"esdi/tui/internal/models"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
@@ -64,3 +66,27 @@ func (cds *CDashService) UpdateWindow(idx int16, win *cdashdisplay.UIWindow) err
|
||||
func (cds *CDashService) DeleteWindow(idx int16) error {
|
||||
return cds.CDash.DestroyWindow(idx)
|
||||
}
|
||||
|
||||
func (cds *CDashService) ResizeWindow(win *models.UIWindow, vec *helper.Vector) error {
|
||||
err := cds.CDash.ResizeWindow(win.IDX, vec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the UI window data
|
||||
win.Window = *cds.CDash.State.Layout.Windows[win.IDX]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cds *CDashService) MoveWindow(win *models.UIWindow, vec *helper.Vector) error {
|
||||
err := cds.CDash.MoveWindow(win.IDX, vec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the UI window data
|
||||
win.Window = *cds.CDash.State.Layout.Windows[win.IDX]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ func (lt *LayoutTreeView) AddWindow(win *models.UIWindow) error {
|
||||
|
||||
// Create this new node
|
||||
newWindow := tview.NewTreeNode(
|
||||
windowInfoPageTitle(win.WID, win.Data.Title.String()),
|
||||
windowInfoPageTitle(win.IDX, win.Window.Title.String()),
|
||||
).SetReference(win)
|
||||
|
||||
root.AddChild(newWindow)
|
||||
@@ -214,13 +214,13 @@ func NewLayoutToolView() *LayoutToolView {
|
||||
}
|
||||
|
||||
func (ltv *LayoutToolView) WindowCreatedSuccessfuly(win *models.UIWindow) error {
|
||||
updateWindowForm := NewWindowFormView(&win.Data)
|
||||
updateWindowForm := NewWindowFormView(win)
|
||||
|
||||
// Update the pages ID
|
||||
ltv.LayoutActions.Pages.RemovePage(LayoutToolNewWindowID)
|
||||
AddAndShowPage(
|
||||
ltv.LayoutActions.Pages,
|
||||
windowInfoPageID(win.WID),
|
||||
windowInfoPageID(win.IDX),
|
||||
updateWindowForm.Form.Form,
|
||||
)
|
||||
|
||||
@@ -228,7 +228,7 @@ func (ltv *LayoutToolView) WindowCreatedSuccessfuly(win *models.UIWindow) error
|
||||
ltv.LayoutActions.CreateWindowView = nil
|
||||
|
||||
// Add this form thing to the quick access map
|
||||
ltv.FormQuickAccess[win.WID] = updateWindowForm
|
||||
ltv.FormQuickAccess[win.IDX] = updateWindowForm
|
||||
|
||||
// Add it to the tree view
|
||||
return ltv.LayoutTree.AddWindow(win)
|
||||
@@ -261,6 +261,10 @@ func (ltv *LayoutToolView) DeleteWindowByNode(node *tview.TreeNode) {
|
||||
|
||||
// We have to delete it from the map
|
||||
// This isn't very safe now is it?
|
||||
delete(ltv.FormQuickAccess, node.GetReference().(*models.UIWindow).WID)
|
||||
delete(ltv.FormQuickAccess, node.GetReference().(*models.UIWindow).IDX)
|
||||
// Did we delete everything ???
|
||||
}
|
||||
|
||||
func (ltv *LayoutToolView) UpdateFormView(win *models.UIWindow) {
|
||||
ltv.FormQuickAccess[win.IDX].SetValues(win)
|
||||
}
|
||||
|
||||
+17
-33
@@ -3,7 +3,7 @@ package views
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"esdi/cdashdisplay"
|
||||
"esdi/tui/internal/models"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
@@ -90,7 +90,7 @@ type WindowFormView struct {
|
||||
UpdateBtn *tview.Button
|
||||
}
|
||||
|
||||
func NewWindowFormView(win *cdashdisplay.UIWindow) *WindowFormView {
|
||||
func NewWindowFormView(win *models.UIWindow) *WindowFormView {
|
||||
view := &WindowFormView{
|
||||
Form: NewCDashDisplayWindowFormView(),
|
||||
}
|
||||
@@ -98,43 +98,27 @@ func NewWindowFormView(win *cdashdisplay.UIWindow) *WindowFormView {
|
||||
view.UpdateBtn = tview.NewButton("Update")
|
||||
// Need to inject the button functionality later
|
||||
|
||||
// In case the window is moved we need to update this form
|
||||
// bus.On(ui.WindowMovedEv{}, func(e any) {
|
||||
// data := e.(ui.WindowMovedEv)
|
||||
// // Only update the fields if the event is for this thing
|
||||
// if data.ID != idx {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // Get the current window-info-page
|
||||
// elem := doc.GetElemByID(windowInfoPageID(data.ID))
|
||||
// if elem == nil {
|
||||
// bus.Emit(ui.LogEv{Log: "could't get hold of info page"})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// x0.SetText(fmt.Sprintf("%d", data.Dims.X0))
|
||||
// x0.SetText(fmt.Sprintf("%d", data.Dims.Y0))
|
||||
// width.SetText(fmt.Sprintf("%d", data.Dims.Width))
|
||||
// height.SetText(fmt.Sprintf("%d", data.Dims.Height))
|
||||
// })
|
||||
|
||||
// Set the fields data
|
||||
view.Form.X.SetText(fmt.Sprintf("%d", win.Dims.X0))
|
||||
view.Form.Y.SetText(fmt.Sprintf("%d", win.Dims.Y0))
|
||||
view.Form.Width.SetText(fmt.Sprintf("%d", win.Dims.Width))
|
||||
view.Form.Height.SetText(fmt.Sprintf("%d", win.Dims.Height))
|
||||
view.Form.Title.SetText(win.Title.String())
|
||||
view.Form.PreviewValue.SetText(win.Opts.PreviewValue.String())
|
||||
view.Form.ShowID.SetChecked(win.Opts.ShowID == 1)
|
||||
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.SetValues(win)
|
||||
|
||||
view.Form.Form.AddButton("Update", func() {})
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
func (fv *WindowFormView) SetValues(win *models.UIWindow) {
|
||||
fv.Form.X.SetText(fmt.Sprintf("%d", win.Window.Dims.X0))
|
||||
fv.Form.Y.SetText(fmt.Sprintf("%d", win.Window.Dims.Y0))
|
||||
fv.Form.Width.SetText(fmt.Sprintf("%d", win.Window.Dims.Width))
|
||||
fv.Form.Height.SetText(fmt.Sprintf("%d", win.Window.Dims.Height))
|
||||
fv.Form.Title.SetText(win.Window.Title.String())
|
||||
fv.Form.PreviewValue.SetText(win.Window.Opts.PreviewValue.String())
|
||||
fv.Form.ShowID.SetChecked(win.Window.Opts.ShowID == 1)
|
||||
fv.Form.WinType.SetCurrentOption(0) // NOTE: this needs to set the correct option
|
||||
fv.Form.TitleSize.SetCurrentOption(int(win.Window.Decor.TitleSize))
|
||||
fv.Form.TextSize.SetCurrentOption(int(win.Window.Decor.TextSize))
|
||||
}
|
||||
|
||||
func windowInfoPageID(idx int16) string {
|
||||
return fmt.Sprintf("layout-tool-win-info-%d", idx)
|
||||
}
|
||||
Reference in New Issue
Block a user