From 75a5c7bf728d02bcf5accd1360c99a9c6edc0b91 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Fri, 31 Jan 2025 08:50:00 -0600 Subject: wrapping my head around this code again --- Makefile | 2 +- dropdown.go | 17 ++++- eventsHandler.go | 89 ++++++++++++++++++++++ gocui.go | 9 ++- help.go | 4 +- junk1.go | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++ keybindings.go | 222 ------------------------------------------------------- mouse.go | 27 ++++++- structs.go | 4 + 9 files changed, 351 insertions(+), 233 deletions(-) create mode 100644 eventsHandler.go create mode 100644 junk1.go delete mode 100644 keybindings.go diff --git a/Makefile b/Makefile index 12be8c6..bf73fc0 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ BUILDTIME = $(shell date +%Y.%m.%d) all: clean gocui.so @#ldd gocui.so -gocui.so: view.pb.go goimports +gocui.so: goimports GO111MODULE=off go build -v -work -buildmode=plugin -o gocui.so \ -ldflags "-X main.VERSION=${VERSION} -X main.BUILDTIME=${BUILDTIME} -X gui.GUIVERSION=${VERSION}" diff --git a/dropdown.go b/dropdown.go index 24fb4c6..3674e1e 100644 --- a/dropdown.go +++ b/dropdown.go @@ -10,6 +10,17 @@ import ( "go.wit.com/widget" ) +// dropdowns don't exist so this is an attempt to pretend they exist +// by having a fake window view in gocui that appears with the dropdown +// items. by detecting where the user clicks, we should be +// able to set the text of the button to that value (and +// rezise it. + +// the thing is this is so damned complicated because it +// is very hard to debug this. thanks to the floating on +// screen debugging output I might be able to figure it +// it out now. maybe. notsure. + func makeDropdownView(ddItems string) *guiWidget { newNode := addDropdown() tk := newNode.TK.(*guiWidget) @@ -145,12 +156,12 @@ func (w *guiWidget) dropdownClicked(mouseW, mouseH int) string { } func dropdownUnclicked(mouseX, mouseH int) { + log.Log(GOCUI, "dropdownUnclicked() mouseup: got inside me.dropdown handler? wxh =", mouseX, mouseH) if me.dropdownV == nil { log.Log(GOCUI, "mouseUp() dropdownV = nil", mouseX, mouseH) return } tk := me.dropdownV - log.Log(GOCUI, "mouseUp() view msgMouseDown (check here for dropdown menu click) (w,h) =", mouseX, mouseH) - log.Log(GOCUI, "mouseUp() ddview is the thing that was clicked", mouseX, mouseH) - log.Log(GOCUI, "mouseUp() find out what the string is here", mouseX, mouseH, tk.gocuiSize.h1) + log.Log(GOCUI, fmt.Sprintf("dropdownUnclicked at apparently (w=%d h=%d)", mouseX, mouseH)) + log.Log(GOCUI, "dropdownUnclicked() find out what the string is here", mouseX, mouseH, tk.gocuiSize.h1) } diff --git a/eventsHandler.go b/eventsHandler.go new file mode 100644 index 0000000..a443431 --- /dev/null +++ b/eventsHandler.go @@ -0,0 +1,89 @@ +// WIT.COM Inc. 2017-2025 GPL 3.0 + +package main + +import ( + "github.com/awesome-gocui/gocui" +) + +// tells 'gocui' what to call based on what key was pressed +func registerHandlers(g *gocui.Gui) { + g.SetKeybinding("", '?', gocui.ModNone, theHelp) // 'h' toggles on and off the help menu + g.SetKeybinding("", 'r', gocui.ModNone, widgetRefresh) // screen refresh + g.SetKeybinding("", 'w', gocui.ModNone, doWindow) // close all windows + g.SetKeybinding("", 'q', gocui.ModNone, doExit) // exit + g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, doExit) // exit + g.SetKeybinding("", gocui.KeyCtrlV, gocui.ModNone, doPanic) // forced panic + + // debugging + g.SetKeybinding("", 'd', gocui.ModNone, theLetterD) // 'd' toggles on and off debugging buttons + g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone, openDebuggger) // open the debugger + g.SetKeybinding("", 'L', gocui.ModNone, dumpWidgets) // list all widgets + g.SetKeybinding("", 'M', gocui.ModNone, dumpWidgetPlacement) // list all widgets with positions + +} + +func doExit(g *gocui.Gui, v *gocui.View) error { + return nil +} + +func doPanic(g *gocui.Gui, v *gocui.View) error { + return nil +} + +func dumpWidgets(g *gocui.Gui, v *gocui.View) error { + return nil +} + +func dumpWidgetPlacement(g *gocui.Gui, v *gocui.View) error { + return nil +} + +func openDebuggger(g *gocui.Gui, v *gocui.View) error { + return nil +} + +// is run whenever anyone hits 'd' (in an open space) +func theLetterD(g *gocui.Gui, v *gocui.View) error { + // widgets that don't have physical existance in + // a display toolkit are hidden. In the case + // of gocui, they are set as not 'visible' and put offscreen + // or have the size set to zero + // (hopefully anyway) lots of things with the toolkit + // still don't work + + fakeStartWidth = me.FakeW + fakeStartHeight = me.TabH + me.FramePadH + if showDebug { + showFake() + showDebug = false + } else { + hideFake() + showDebug = true + } + return nil +} + +func theHelp(g *gocui.Gui, v *gocui.View) error { + if showHelp { + helplayout() + showHelp = false + if me.dropdownV == nil { + me.dropdownV = makeDropdownView("addWidget() ddview") + } + me.dropdownV.Show() + } else { + me.baseGui.DeleteView("help") + showHelp = true + me.dropdownV.Hide() + } + return nil +} + +func widgetRefresh(g *gocui.Gui, v *gocui.View) error { + return nil +} + +func doWindow(g *gocui.Gui, v *gocui.View) error { + return nil +} diff --git a/gocui.go b/gocui.go index 13c3b78..c7f4011 100644 --- a/gocui.go +++ b/gocui.go @@ -1,3 +1,6 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is (now) governed by the GPL 3.0 + // Copyright 2014 The gocui Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -13,8 +16,6 @@ import ( "go.wit.com/log" ) -var ecount int = 3 - // Thanks to the gocui developers -- your package kicks ass // This function is called on every event. It is a callback function from the gocui package // which has an excellent implementation. While gocui handles things like text highlighting @@ -22,7 +23,7 @@ var ecount int = 3 // complicated console handling, it sends events here in a clean way. // This is equivalent to the linux command xev (apt install x11-utils) func gocuiEvent(g *gocui.Gui) error { - ecount += 1 + me.ecount += 1 maxX, maxY := g.Size() mx, my := g.MousePosition() log.Verbose("handleEvent() START", maxX, maxY, mx, my, msgMouseDown) @@ -36,7 +37,7 @@ func gocuiEvent(g *gocui.Gui) error { // setOutput(me.logStdout) // me.logStdout.Write("test out") w := me.logStdout.TK.(*guiWidget) - msg := fmt.Sprintf("test out gocuiEvent() %d\n", ecount) + msg := fmt.Sprintf("test out gocuiEvent() %d\n", me.ecount) w.Write([]byte(msg)) // log.CaptureMode(w) log.Log(NOW, "logStdout test out") diff --git a/help.go b/help.go index d96ff9a..8131b19 100644 --- a/help.go +++ b/help.go @@ -20,7 +20,9 @@ var helpText []string = []string{"KEYBINDINGS", "s/h: show/hide all widgets", "L: list all widgets", "M: list all widgets positions", - "\x1b[0;32m  \x1b[0m", + + "\x1b[0;32m  \x1b[0m", // this was a test to see what might be + // possible with gocui. it doesn't seem to work for me "q: quit()", "p: panic()", "o: show Stdout", diff --git a/junk1.go b/junk1.go new file mode 100644 index 0000000..de8c104 --- /dev/null +++ b/junk1.go @@ -0,0 +1,210 @@ +// Copyright 2014 The gocui Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "syscall" + + "github.com/awesome-gocui/gocui" + + "go.wit.com/log" +) + +// handle ctrl+z +func handle_ctrl_z(g *gocui.Gui, v *gocui.View) error { + gocui.Suspend() + log.Info("got ctrl+z") + syscall.Kill(syscall.Getpid(), syscall.SIGSTOP) + log.Info("got ctrl+z syscall() done") + gocui.Resume() + return nil +} + +func defaultKeybindings(g *gocui.Gui) error { + if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { + return err + } + // setup ctrl+z + keyForced, modForced := gocui.MustParse("ctrl+z") + if err := g.SetKeybinding("", keyForced, modForced, handle_ctrl_z); err != nil { + log.Error(err) + } + for _, n := range []string{"but1", "but2", "help", "but3"} { + if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil { + return err + } + } + if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil { + return err + } + // mouseDown() runs whenever you click on an unknown view (?) + if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, mouseDown); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown); err != nil { + return err + } + // if err := g.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click); err != nil { + // return err + // } + /* + if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil { + return err + } + */ + if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil { + return err + } + addDebugKeys(g) + return nil +} + +func addDebugKeys(g *gocui.Gui) { + // show debugging buttons + g.SetKeybinding("", 'd', gocui.ModNone, theLetterD) + + // display the help menu + g.SetKeybinding("", '?', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + if showHelp { + helplayout() + showHelp = false + if me.dropdownV == nil { + me.dropdownV = makeDropdownView("addWidget() ddview") + } + me.dropdownV.Show() + } else { + me.baseGui.DeleteView("help") + showHelp = true + me.dropdownV.Hide() + } + return nil + }) + + // redraw all the widgets + g.SetKeybinding("", 'r', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + var w *guiWidget + w = me.treeRoot.TK.(*guiWidget) + if redoWidgets { + wRoot := me.treeRoot.TK.(*guiWidget) + wRoot.redoWindows(0, 0) + redoWidgets = false + } else { + w.hideWidgets() + redoWidgets = true + } + return nil + }) + + // hide all widgets + g.SetKeybinding("", 'h', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + var w *guiWidget + w = me.treeRoot.TK.(*guiWidget) + w.hideWidgets() + return nil + }) + + // show all widgets + g.SetKeybinding("", 's', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + var w *guiWidget + w = me.treeRoot.TK.(*guiWidget) + w.showWidgets() + return nil + }) + + // list all widgets + g.SetKeybinding("", 'L', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + me.treeRoot.ListWidgets() + + tk := me.logStdout.TK.(*guiWidget) + // msg := fmt.Sprintf("test out kb %d\n", ecount) + // tk.Write([]byte(msg)) + if tk == nil { + log.Log(ERROR, "tk = nil") + } + if tk.v == nil { + log.Log(ERROR, "tk.v = nil") + } else { + log.Log(ERROR, "setting log.CaptureMode(tk.v)") + log.Log(ERROR, "setting log.CaptureMode(tk.v)") + log.CaptureMode(tk) + } + return nil + }) + + // list all widgets with positions + g.SetKeybinding("", 'M', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + w := me.treeRoot.TK.(*guiWidget) + w.dumpTree("M") + return nil + }) + + // redo windows + g.SetKeybinding("", 'w', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + wRoot := me.treeRoot.TK.(*guiWidget) + wRoot.redoWindows(0, 0) + return nil + }) + + // log to output window + g.SetKeybinding("", 'o', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + log.Log(ERROR, "TODO: trying re-implement this") + tk := me.logStdout.TK.(*guiWidget) + if tk == nil { + log.Log(ERROR, "tk = nil") + } + if tk.v == nil { + log.Log(ERROR, "tk.v = nil") + } + if tk.Visible() { + log.Log(ERROR, "setting visible to false") + tk.SetVisible(false) + // setOutput(os.Stdout) + } else { + log.Log(ERROR, "setting visible to true") + tk.SetVisible(true) + // setOutput(me.logStdout.tk) + } + return nil + }) + + // exit + g.SetKeybinding("", 'q', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + standardExit() + return nil + }) + g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + standardExit() + return nil + }) + g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + if showDebug { + me.myTree.SendEnableDebugger() + } + return nil + }) + g.SetKeybinding("", gocui.KeyCtrlV, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return nil + }) + + // panic + g.SetKeybinding("", 'p', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + standardClose() + panic("forced panic in gocui") + return nil + }) +} diff --git a/keybindings.go b/keybindings.go deleted file mode 100644 index d4752b7..0000000 --- a/keybindings.go +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "syscall" - - "github.com/awesome-gocui/gocui" - - "go.wit.com/log" -) - -// handle ctrl+z -func handle_ctrl_z(g *gocui.Gui, v *gocui.View) error { - gocui.Suspend() - log.Info("got ctrl+z") - syscall.Kill(syscall.Getpid(), syscall.SIGSTOP) - log.Info("got ctrl+z syscall() done") - gocui.Resume() - return nil -} - -func defaultKeybindings(g *gocui.Gui) error { - if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { - return err - } - // setup ctrl+z - keyForced, modForced := gocui.MustParse("ctrl+z") - if err := g.SetKeybinding("", keyForced, modForced, handle_ctrl_z); err != nil { - log.Error(err) - } - for _, n := range []string{"but1", "but2", "help", "but3"} { - if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil { - return err - } - } - if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil { - return err - } - // mouseDown() runs whenever you click on an unknown view (?) - if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, mouseDown); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown); err != nil { - return err - } - // if err := g.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click); err != nil { - // return err - // } - /* - if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil { - return err - } - */ - if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil { - return err - } - addDebugKeys(g) - return nil -} - -func addDebugKeys(g *gocui.Gui) { - // show debugging buttons - g.SetKeybinding("", 'd', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - fakeStartWidth = me.FakeW - fakeStartHeight = me.TabH + me.FramePadH - if showDebug { - showFake() - showDebug = false - } else { - hideFake() - showDebug = true - } - return nil - }) - - // display the help menu - g.SetKeybinding("", '?', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - if showHelp { - helplayout() - showHelp = false - if me.dropdownV == nil { - me.dropdownV = makeDropdownView("addWidget() ddview") - } - me.dropdownV.Show() - } else { - me.baseGui.DeleteView("help") - showHelp = true - me.dropdownV.Hide() - } - return nil - }) - - // redraw all the widgets - g.SetKeybinding("", 'r', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - var w *guiWidget - w = me.treeRoot.TK.(*guiWidget) - if redoWidgets { - wRoot := me.treeRoot.TK.(*guiWidget) - wRoot.redoWindows(0, 0) - redoWidgets = false - } else { - w.hideWidgets() - redoWidgets = true - } - return nil - }) - - // hide all widgets - g.SetKeybinding("", 'h', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - var w *guiWidget - w = me.treeRoot.TK.(*guiWidget) - w.hideWidgets() - return nil - }) - - // show all widgets - g.SetKeybinding("", 's', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - var w *guiWidget - w = me.treeRoot.TK.(*guiWidget) - w.showWidgets() - return nil - }) - - // list all widgets - g.SetKeybinding("", 'L', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - me.treeRoot.ListWidgets() - - tk := me.logStdout.TK.(*guiWidget) - // msg := fmt.Sprintf("test out kb %d\n", ecount) - // tk.Write([]byte(msg)) - if tk == nil { - log.Log(ERROR, "tk = nil") - } - if tk.v == nil { - log.Log(ERROR, "tk.v = nil") - } else { - log.Log(ERROR, "setting log.CaptureMode(tk.v)") - log.Log(ERROR, "setting log.CaptureMode(tk.v)") - log.CaptureMode(tk) - } - return nil - }) - - // list all widgets with positions - g.SetKeybinding("", 'M', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - w := me.treeRoot.TK.(*guiWidget) - w.dumpTree("M") - return nil - }) - - // redo windows - g.SetKeybinding("", 'w', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - wRoot := me.treeRoot.TK.(*guiWidget) - wRoot.redoWindows(0, 0) - return nil - }) - - // log to output window - g.SetKeybinding("", 'o', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - log.Log(ERROR, "TODO: trying re-implement this") - tk := me.logStdout.TK.(*guiWidget) - if tk == nil { - log.Log(ERROR, "tk = nil") - } - if tk.v == nil { - log.Log(ERROR, "tk.v = nil") - } - if tk.Visible() { - log.Log(ERROR, "setting visible to false") - tk.SetVisible(false) - // setOutput(os.Stdout) - } else { - log.Log(ERROR, "setting visible to true") - tk.SetVisible(true) - // setOutput(me.logStdout.tk) - } - return nil - }) - - // exit - g.SetKeybinding("", 'q', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - standardExit() - return nil - }) - g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - standardExit() - return nil - }) - g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - if showDebug { - me.myTree.SendEnableDebugger() - } - return nil - }) - g.SetKeybinding("", gocui.KeyCtrlV, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return nil - }) - - // panic - g.SetKeybinding("", 'p', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - standardClose() - panic("forced panic in gocui") - return nil - }) -} diff --git a/mouse.go b/mouse.go index 08e2e5d..4078d70 100644 --- a/mouse.go +++ b/mouse.go @@ -2,6 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// note by jcarr@wit.com in 2025: this is one of the coolest +// things ever what this does. I've tried to improve +// it while I've been working on making a gocui +// GO plugin so it can be generalized as a useful +// console interface. Well done everyone that has +// contributed to this gocui project !!! + package main import ( @@ -27,8 +34,13 @@ func mouseMove(g *gocui.Gui) { func msgDown(g *gocui.Gui, v *gocui.View) error { initialMouseX, initialMouseY = g.MousePosition() + + // debugging output log.Log(GOCUI, "msgDown() X,Y", initialMouseX, initialMouseY) - if vx, vy, _, _, err := g.ViewPosition("msg"); err == nil { + + // + vx, vy, _, _, err := g.ViewPosition("msg") + if err == nil { xOffset = initialMouseX - vx yOffset = initialMouseY - vy msgMouseDown = true @@ -40,6 +52,7 @@ func mouseUp(g *gocui.Gui, v *gocui.View) error { w, h := g.MousePosition() dropdownUnclicked(w, h) + if msgMouseDown { msgMouseDown = false if movingMsg { @@ -55,16 +68,26 @@ func mouseUp(g *gocui.Gui, v *gocui.View) error { return nil } +// func isMouseInMsg + +// this is where you have to figure out what +// widget was underneath so you can active +// the right response for the toolkit user's app func mouseDown(g *gocui.Gui, v *gocui.View) error { mx, my := g.MousePosition() - if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil { + + vx0, vy0, vx1, vy1, err := g.ViewPosition("msg") + if err == nil { if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 { return msgDown(g, v) } } globalMouseDown = true + maxX, _ := g.Size() + findUnderMouse() + msg := fmt.Sprintf("mouseDown() Mouse really down at: %d,%d", mx, my) // dropdownClicked(mx, my) x := mx - len(msg)/2 diff --git a/structs.go b/structs.go index c69971b..c9d6122 100644 --- a/structs.go +++ b/structs.go @@ -102,6 +102,10 @@ type config struct { // used to attempt to write to the stdout window fakefile *FakeFile + + // just a counter for curiosity. + // counts how many mouse and keyboard events have occurred + ecount int } // deprecate these -- cgit v1.2.3