diff --git a/dropdown.go b/dropdown.go index 470a315..6f1bc3f 100644 --- a/dropdown.go +++ b/dropdown.go @@ -9,7 +9,6 @@ import ( "fmt" "strings" - "github.com/awesome-gocui/gocui" log "go.wit.com/log" "go.wit.com/toolkits/tree" "go.wit.com/widget" @@ -133,98 +132,3 @@ func dropdownUnclicked(w, h int) { // log.Log(GOCUI, "dropdownUnclicked()", d.node.Strings(), "end. now try to enable me.dropdownV") } */ - -func (tk *guiWidget) forceSizes(r *rectType) { - tk.gocuiSize.w0 = r.w0 - tk.gocuiSize.w1 = r.w1 - tk.gocuiSize.h0 = r.h0 - tk.gocuiSize.h1 = r.h1 - - tk.full.w0 = r.w0 - tk.full.w1 = r.w1 - tk.full.h0 = r.h0 - tk.full.h1 = r.h1 - - tk.force.w0 = r.w0 - tk.force.w1 = r.w1 - tk.force.h0 = r.h0 - tk.force.h1 = r.h1 -} - -func (callertk *guiWidget) showTextbox() { - if me.textbox.tk == nil { - // should only happen once - me.textbox.tk = makeNewFlagWidget(me.textbox.wId) - me.textbox.tk.dumpWidget("init() textbox") - } - if me.textbox.tk == nil { - log.Log(GOCUI, "showTextbox() Is Broken") - return - } - - tk := me.textbox.tk - r := new(rectType) - // startW, startH := tk.Position() - r.w0 = callertk.gocuiSize.w0 + 4 - r.h0 = callertk.gocuiSize.h0 + 3 - r.w1 = r.w0 + 24 - r.h1 = r.h0 + 2 - me.textbox.tk.forceSizes(r) - me.textbox.tk.dumpWidget("after sizes") - - me.textbox.tk.Show() // actually makes the gocui view. TODO: redo this - - if me.textbox.tk.v == nil { - log.Info("wtf went wrong") - return - } - - me.textbox.tk.setColorModal() - - me.textbox.tk.v.Editable = true - me.textbox.tk.v.Wrap = true - - me.baseGui.SetView(me.textbox.tk.cuiName, r.w0, r.h0, r.w1, r.h1, 0) - me.baseGui.SetCurrentView(me.textbox.tk.v.Name()) - - // bind the enter key to a function so we can close the textbox - me.baseGui.SetKeybinding(me.textbox.tk.v.Name(), gocui.KeyEnter, gocui.ModNone, theCloseTheTextbox) - - me.textbox.active = true - me.textbox.callerTK = callertk - - tk.dumpWidget("showTextbox()") -} - -func theCloseTheTextbox(g *gocui.Gui, v *gocui.View) error { - textboxClosed() - return nil -} - -// updates the text and sends an event back to the application -func textboxClosed() { - // get the text the user entered - newtext := "testing" - if me.textbox.tk.v == nil { - newtext = "" - } else { - newtext = me.textbox.tk.v.ViewBuffer() - } - newtext = strings.TrimSpace(newtext) - me.textbox.active = false - me.textbox.tk.Hide() - log.Info("textbox closed", newtext) - - if me.clock.tk.v != nil { - me.baseGui.SetCurrentView("help") - } else { - me.baseGui.SetCurrentView("msg") - } - - // change the text of the caller widget - me.textbox.callerTK.SetText(newtext) - me.textbox.callerTK.node.SetCurrentS(newtext) - - // send an event from the plugin with the new string - me.myTree.SendUserEvent(me.textbox.callerTK.node) -} diff --git a/eventMouse.go b/eventMouse.go index 088f2e0..e84612c 100644 --- a/eventMouse.go +++ b/eventMouse.go @@ -4,6 +4,7 @@ package main import ( + "fmt" "time" "github.com/awesome-gocui/gocui" @@ -51,6 +52,25 @@ func mouseDown(g *gocui.Gui, v *gocui.View) error { w, h := g.MousePosition() me.mouse.downW = w me.mouse.downH = h + + win := findWindowUnderMouse() + if win != nil { + w, h := g.MousePosition() + s := fmt.Sprintf("mouse(%d,%d) ", w, h) + offW := win.gocuiSize.w1 - w + offH := win.gocuiSize.h1 - h + s += fmt.Sprintf("corner(%d,%d)", offW, offH) + if (offW < 3) && (offH < 3) { + // log.Info("mouse down resize on ", s) + me.mouse.resize = true + // store the stdout corner for computing the drag size + me.stdout.lastW = me.stdout.tk.gocuiSize.w0 + me.stdout.lastH = me.stdout.tk.gocuiSize.h0 + } else { + // log.Info("mouse down resize off", s) + me.mouse.resize = false + } + } return nil } diff --git a/eventMouseClick.go b/eventMouseClick.go index dcda9fd..88e37a3 100644 --- a/eventMouseClick.go +++ b/eventMouseClick.go @@ -130,37 +130,47 @@ func doMouseClick(w int, h int) { return } - // priority widgets. send the click here first - for _, tk := range findByXY(w, h) { - switch tk.node.WidgetType { - case widget.Checkbox: - if tk.node.State.Checked { - log.Log(WARN, "checkbox is being set to false") - tk.node.State.Checked = false - tk.setCheckbox() - } else { - log.Log(WARN, "checkbox is being set to true") - tk.node.State.Checked = true - tk.setCheckbox() + win := findWindowUnderMouse() + if win != nil { + // look in this window for widgets + // widgets have priority. send the click here first + for _, tk := range win.findByXYreal(w, h) { + switch tk.node.WidgetType { + case widget.Checkbox: + if tk.node.State.Checked { + log.Log(WARN, "checkbox is being set to false") + tk.node.State.Checked = false + tk.setCheckbox() + } else { + log.Log(WARN, "checkbox is being set to true") + tk.node.State.Checked = true + tk.setCheckbox() + } + me.myTree.SendUserEvent(tk.node) + return + case widget.Button: + tk.dumpWidget("click()") // enable this to debug widget clicks + me.myTree.SendFromUser(tk.node) + return + case widget.Combobox: + tk.showDropdown() + return + case widget.Dropdown: + tk.showDropdown() + return + case widget.Textbox: + tk.showTextbox() + return + default: + // TODO: enable the GUI debugger in gocui + // tk.dumpWidget("undef click()") // enable this to debug widget clicks } - me.myTree.SendUserEvent(tk.node) - case widget.Button: - tk.dumpWidget("click()") // enable this to debug widget clicks - me.myTree.SendFromUser(tk.node) - return - case widget.Combobox: - tk.showDropdown() - return - case widget.Dropdown: - tk.showDropdown() - return - case widget.Textbox: - tk.showTextbox() - return - default: - // TODO: enable the GUI debugger in gocui - // tk.dumpWidget("undef click()") // enable this to debug widget clicks } + log.Info("you clicked on a window, but not any widgets", win.cuiName) + win.redrawWindow(win.gocuiSize.w0, win.gocuiSize.h0) + me.stdout.outputOnTop = false + setThingsOnTop() + return } var found bool diff --git a/eventMouseDrag.go b/eventMouseDrag.go index 4e2312d..ce66257 100644 --- a/eventMouseDrag.go +++ b/eventMouseDrag.go @@ -168,7 +168,7 @@ func (tk *guiWidget) moveNew() { newH := h - me.stdout.lastH me.stdout.w = newW me.stdout.h = newH - log.Info("Resize true", w, h, newW, newH) + // log.Info("Resize true", w, h, newW, newH) // me.stdout.lastW = w - me.stdout.mouseOffsetW // me.stdout.lastH = h - me.stdout.mouseOffsetH tk.relocateStdout(me.stdout.lastW, me.stdout.lastH) @@ -178,6 +178,7 @@ func (tk *guiWidget) moveNew() { newW := tk.lastW + w - me.mouse.downW newH := tk.lastH + h - me.mouse.downH tk.relocateStdout(newW, newH) + // log.Info("Resize false", w, h, newW, newH) } } // always place the help menu on top diff --git a/find.go b/find.go index 189d84b..7ab3a4e 100644 --- a/find.go +++ b/find.go @@ -132,6 +132,7 @@ func findNextWindow() *guiWidget { return me.allwin[0] } +// find the window under the mouse and only the window under the mouse func findWindowUnderMouse() *guiWidget { w, h := me.baseGui.MousePosition() @@ -194,68 +195,8 @@ func findWindowUnderMouse() *guiWidget { return nil } -// returns the "highest priority widget under the mouse -func findUnderMouse() *guiWidget { - w, h := me.baseGui.MousePosition() - - widgets := findByXY(w, h) - - // search through all the widgets that were below the mouse click - var found *guiWidget - for _, w := range widgets { - // prioritize window buttons. This means if some code covers - // up the window widgets, then it will ignore everything else - // and allow the user (hopefully) to redraw or switch windows - // TODO: display the window widgets on top - if w.node.WidgetType == widget.Window { - return w - } - } - - // return anything else that is interactive - for _, w := range widgets { - if w.node.WidgetType == widget.Button { - return w - } - if w.node.WidgetType == widget.Combobox { - return w - } - if w.node.WidgetType == widget.Checkbox { - return w - } - w.dumpWidget("findUnderMouse() found something unknown") - found = w - } - // maybe something else was found - return found -} - -// panics. todo: fix ctrl-mouse click? -// find the widget under the mouse click +// todo: use this? func ctrlDown(g *gocui.Gui, v *gocui.View) error { - var found *guiWidget - // var widgets []*node - // var f func (n *node) - found = findUnderMouse() - if me.ctrlDown == nil { - setupCtrlDownWidget() - - var tk *guiWidget - tk = me.ctrlDown.TK.(*guiWidget) - tk.labelN = found.String() - tk.cuiName = "ctrlDown" - // me.ctrlDown.parent = me.rootNode - } - var tk *guiWidget - tk = me.ctrlDown.TK.(*guiWidget) - if found == nil { - found = me.treeRoot.TK.(*guiWidget) - } - tk.labelN = found.String() - newR := found.realGocuiSize() - tk.gocuiSize.w0 = newR.w0 - tk.gocuiSize.h0 = newR.h0 - tk.gocuiSize.w1 = newR.w1 - tk.gocuiSize.h1 = newR.h1 + log.Info("todo: clicked with ctrlDown") return nil } diff --git a/init.go b/init.go index e290c8a..8b2a7be 100644 --- a/init.go +++ b/init.go @@ -52,8 +52,8 @@ func init() { me.clock.wId = -5 me.mouse.mouseUp = true - me.mouse.clicktime = time.Millisecond * 100 - me.mouse.doubletime = time.Millisecond * 300 + me.mouse.clicktime = time.Millisecond * 200 + me.mouse.doubletime = time.Millisecond * 400 me.myTree = tree.New() me.myTree.PluginName = "gocui" diff --git a/structs.go b/structs.go index 565ce28..e33b7dc 100644 --- a/structs.go +++ b/structs.go @@ -156,9 +156,9 @@ type window struct { active bool // means this window is the active one isBG bool // means this is the background widget. There is only one of these order int // what level the window is on - resize bool // only set the title once - collapsed bool // only show the window title bar - dense bool // true if the window is huge + // resize bool // only set the title once + collapsed bool // only show the window title bar + dense bool // true if the window is huge } type colorT struct { diff --git a/textbox.go b/textbox.go new file mode 100644 index 0000000..66ba092 --- /dev/null +++ b/textbox.go @@ -0,0 +1,108 @@ +// Copyright 2017-2025 WIT.COM Inc. All rights reserved. +// Use of this source code is governed by the GPL 3.0 + +package main + +// simulates a dropdown menu in gocui + +import ( + "strings" + + "github.com/awesome-gocui/gocui" + log "go.wit.com/log" +) + +func (tk *guiWidget) forceSizes(r *rectType) { + tk.gocuiSize.w0 = r.w0 + tk.gocuiSize.w1 = r.w1 + tk.gocuiSize.h0 = r.h0 + tk.gocuiSize.h1 = r.h1 + + tk.full.w0 = r.w0 + tk.full.w1 = r.w1 + tk.full.h0 = r.h0 + tk.full.h1 = r.h1 + + tk.force.w0 = r.w0 + tk.force.w1 = r.w1 + tk.force.h0 = r.h0 + tk.force.h1 = r.h1 +} + +func (callertk *guiWidget) showTextbox() { + if me.textbox.tk == nil { + // should only happen once + me.textbox.tk = makeNewFlagWidget(me.textbox.wId) + me.textbox.tk.dumpWidget("init() textbox") + } + if me.textbox.tk == nil { + log.Log(GOCUI, "showTextbox() Is Broken") + return + } + + tk := me.textbox.tk + r := new(rectType) + // startW, startH := tk.Position() + r.w0 = callertk.gocuiSize.w0 + 4 + r.h0 = callertk.gocuiSize.h0 + 3 + r.w1 = r.w0 + 24 + r.h1 = r.h0 + 2 + me.textbox.tk.forceSizes(r) + me.textbox.tk.dumpWidget("after sizes") + + me.textbox.tk.Show() // actually makes the gocui view. TODO: redo this + + if me.textbox.tk.v == nil { + log.Info("wtf went wrong") + return + } + + me.textbox.tk.setColorModal() + + me.textbox.tk.v.Editable = true + me.textbox.tk.v.Wrap = true + + me.baseGui.SetView(me.textbox.tk.cuiName, r.w0, r.h0, r.w1, r.h1, 0) + me.baseGui.SetCurrentView(me.textbox.tk.v.Name()) + + // bind the enter key to a function so we can close the textbox + me.baseGui.SetKeybinding(me.textbox.tk.v.Name(), gocui.KeyEnter, gocui.ModNone, theCloseTheTextbox) + + me.textbox.active = true + me.textbox.callerTK = callertk + + tk.dumpWidget("showTextbox()") +} + +func theCloseTheTextbox(g *gocui.Gui, v *gocui.View) error { + textboxClosed() + return nil +} + +// updates the text and sends an event back to the application +func textboxClosed() { + // get the text the user entered + newtext := "testing" + if me.textbox.tk.v == nil { + newtext = "" + } else { + newtext = me.textbox.tk.v.ViewBuffer() + } + newtext = strings.TrimSpace(newtext) + me.textbox.active = false + me.textbox.tk.Hide() + log.Info("textbox closed", newtext) + + if me.clock.tk.v != nil { + me.baseGui.SetCurrentView("help") + } else { + me.baseGui.SetCurrentView("msg") + } + + // change the text of the caller widget + me.textbox.callerTK.SetText(newtext) + me.textbox.callerTK.node.SetCurrentS(newtext) + + // send an event from the plugin with the new string + me.myTree.SendUserEvent(me.textbox.callerTK.node) +} diff --git a/treeDraw.go b/treeDraw.go index 3061f4f..f1e9b95 100644 --- a/treeDraw.go +++ b/treeDraw.go @@ -102,20 +102,6 @@ func (w *guiWidget) simpleDrawAt(offsetW, offsetH int) { w.dumpWidget("simpleDrawAt()") } -/* -var toggle bool = true - -func (w *guiWidget) toggleTree() { - if toggle { - w.drawTree(toggle) - toggle = false - } else { - w.hideWidgets() - toggle = true - } -} -*/ - // display the widgets in the binary tree func (w *guiWidget) drawTree(draw bool) { if w == nil {