// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 // 2025 note by jcarr: // this is one of the coolest things ever worked with. // Personally, I've been working on making a gocui GO plugin // so I can use it as a generalized console GUI toolkit. // // Well done everyone that has contributed to this gocui project !!! // I am in your debt. Happy hacking & peace. package main import ( "fmt" "time" "github.com/awesome-gocui/gocui" log "go.wit.com/log" "go.wit.com/widget" ) // this function uses the mouse position to highlight & unhighlight things // this is run every time the user moves the mouse over the terminal window func mouseMove(g *gocui.Gui) { me.ok = true // this tells init() it's okay to work with gocui // very useful for debugging in the past. also, just fun if me.supermouse { w, h := g.MousePosition() for _, tk := range findByXY(w, h) { s := fmt.Sprintf("SM (%3d,%3d)", w, h) tk.dumpWidget(s) } } if time.Since(me.mouse.down) < me.mouse.clicktime { // log.Info("not yet") return } if me.dropdown.active || me.textbox.active { // can't drag or do anything when dropdown or textbox are visible return } // okay, the mouse is down and it has been long enough // the user is trying to drag something. let's figure out what w, h := g.MousePosition() // toggle off all highlight vies except for whatever is under the mouse for _, view := range g.Views() { view.Highlight = false } if v, err := g.ViewByPosition(w, h); err == nil { v.Highlight = true } // create the 'msg' view if it does not yet exist // TODO: put this somewhere more correct if widgetView, _ := g.View("msg"); widgetView == nil { if createStdout(g) { return } return } /* if me.mouse.globalMouseDown && (me.dropdown.active || me.textbox.active) { log.Info("can't drag while dropdown or textbox are active", w, h) return } */ if me.mouse.mouseUp { return } // if me.mouse.globalMouseDown { // log.Info("msgMouseDown == true") // plugin will segfault if you don't keep this inside a check for msgMouseDown // don't move this code out of here var found bool = false if me.mouse.currentDrag != nil { // me.mouse.currentDrag.dumpWidget(fmt.Sprintf("MM (%3d,%3d)", w, h)) me.mouse.currentDrag.moveNew() return } // new function that is smarter if tk := findWindowUnderMouse(); tk != nil { tk.setAsDragging() return } // first look for windows for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Window { tk.setAsDragging() return } } // now look for the STDOUT window for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Flag { tk.setAsDragging() return } } for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Stdout { tk.setAsDragging() // tk.moveNew() return } /* if tk.node.WidgetType == widget.Label { me.mouse.currentDrag = tk // tk.moveNew() return } */ found = true } if !found { log.Info(fmt.Sprintf("findByXY() empty. nothing to move at (%d,%d)", w, h)) } } func (tk *guiWidget) setAsDragging() { me.mouse.currentDrag = tk tk.lastW = tk.gocuiSize.w0 tk.lastH = tk.gocuiSize.h0 } // this is how the window gets dragged around func (tk *guiWidget) moveNew() { w, h := me.baseGui.MousePosition() if tk.node.WidgetType == widget.Window { tk.window.wasDragged = true // compute the new location based off how far the mouse has moved // since the mouse button was pressed down newW := tk.lastW + w - me.mouse.downW newH := tk.lastH + h - me.mouse.downH tk.redrawWindow(newW, newH) setThingsOnTop() // sets help, Stdout, etc on the top after windows have been redrawn return } if tk.node.WidgetType == widget.Flag { me.baseGui.SetView(tk.cuiName, w-3, h-3, w+20, h+20, 0) // tk.verifyRect() s := fmt.Sprintf("move(%dx%d) %s ###", w, h, tk.cuiName) tk.dumpWidget(s) return } if tk.node.WidgetType == widget.Stdout { if me.mouse.resize { newW := w - me.stdout.lastW newH := h - me.stdout.lastH me.stdout.w = newW me.stdout.h = 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) } else { // compute the new location based off how far the mouse has moved // since the mouse button was pressed down newW := tk.lastW + w - me.mouse.downW newH := tk.lastH + h - me.mouse.downH tk.relocateStdout(newW, newH) } } // always place the help menu on top setThingsOnTop() // sets help, Stdout, etc on the top after windows have been redrawn }