summaryrefslogtreecommitdiff
path: root/eventMouseDrag.go
blob: c2625e153fc4626e0470d2f95a76adaa2c9805aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// 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

	// this runs while the user moves the mouse. this highlights text
	// toggle off all highlight views except for whatever is under the mouse
	for _, view := range g.Views() {
		view.Highlight = false
	}
	w, h := g.MousePosition()
	if v, err := g.ViewByPosition(w, h); err == nil {
		// todo: identify and highlight grid rows here
		if me.dropdown.active || me.textbox.active {
			if me.dropdown.tk != nil && me.dropdown.tk.v == v {
				v.Highlight = true
			}
			if me.textbox.tk != nil && me.textbox.tk.v == v {
				v.Highlight = true
			}
		} else {
			v.Highlight = true
		}
	}

	// 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

	// 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
	}

	// drag whatever was set to drag
	if me.mouse.currentDrag != nil {
		// me.mouse.currentDrag.dumpWidget(fmt.Sprintf("MM (%3d,%3d)", w, h))
		me.mouse.currentDrag.moveNew()
		return
	}
	log.Info(fmt.Sprintf("gui toolkit error. nothing to drag at (%d,%d)", w, h))
	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
	/*
		// 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
			}
			found = true
		}
	*/
}

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)
			// log.Info("Resize false", w, h, newW, newH)
		}
	}
	// always place the help menu on top
	setThingsOnTop() // sets help, Stdout, etc on the top after windows have been redrawn
}