summaryrefslogtreecommitdiff
path: root/action.go
blob: 1580bf72818df5c41403fb1f9fc54a098762f11b (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
package gui

/*
	This is where the communication to the toolkit plugin happens.

	We copy the current values from the widget node of the binary tree
	and send an "action" to the toolkit over a channel.

	TODO: use protobuf
*/

import (
	"errors"

	"go.wit.com/log"
	"go.wit.com/widget"
)

func (n *Node) SetVisable(b bool) {
	n.visable = b
}

// returns true if the window is not visable to the user
// in which case events are not sent to the toolkit
func (n *Node) WindowVisable() bool {
	if n == nil {
		return true
	}
	if n.WidgetType == widget.Window {
		return n.visable
	}
	if n.parent == nil {
		return true
	} else {
		return n.parent.WindowVisable()
	}
	return true
}

// 2024/01/11 finally moving to type any. simplify to just 'value'
// 2023/05/09 pretty clean
// 2023/04/06 Queue() is also being used and channels are being used.
func sendAction(n *Node, atype widget.ActionType) {
	if n == nil {
		log.Error(errors.New("Sending Action on n = nil"))
		log.Warn("Sending Action on n = nil")
		return
	}
	n.mu.Lock()
	defer n.mu.Unlock()
	// log.Warn("SENDING ACTION STRINGS n.Strings", n.strings, n.id, n.WidgetType, n.GetProgName())

	// if the widget is hidden, don't send actions to the plugin
	/*
		if n.hidden {
			if atype == widget.Hide {
				// well, unless this is a Hide action, then inform the toolkit
				log.Warn("SENDING HIDDEN ACTION. IS THIS A WINDOW?", n.GetProgName(), atype)
			} else {
				log.Warn("NOT SENDING HIDDEN ACTION", n.GetProgName(), atype)
				// return
			}
		}
	*/

	// this checks to see if the window is show in the toolkit. If it is not,
	// then don't send any events. Unless it is a window widget, then send events
	if n.WidgetType != widget.Window {
		if !n.WindowVisable() {
			log.Warn("NOT SENDING ACTION. Window is not visable", n.id, n.WidgetType, n.GetProgName())
			return
		}
	}

	var a widget.Action
	a.ActionType = atype

	// These should be "stable" at this point (2024/01/13)
	a.WidgetId = n.id

	// set state
	a.State.ProgName = n.progname
	a.State.Label = n.label
	a.State.Value = n.value

	a.State.Checked = n.checked
	a.State.Visable = n.visable
	a.State.Pad = n.pad
	a.State.Expand = n.expand
	a.State.Borderless = n.borderless
	a.State.Direction = n.direction

	for s, _ := range n.strings {
		a.State.Strings = append(a.State.Strings, s)
	}
	// log.Warn("SENDING ACTION STRINGS a.Strings", a.Strings)
	// log.Warn("SENDING ACTION a.State.Value", a.State.Value)
	a.State.Range.Low = n.X
	a.State.Range.High = n.Y

	a.ProgName = n.progname
	a.Value = n.value
	a.Direction = n.direction

	// These should be improved/deprecated based on the gui/widget docs
	a.X = n.X
	a.Y = n.Y

	a.State.GridOffset.X = n.AtW
	a.State.GridOffset.Y = n.AtH

	if n.parent != nil {
		a.ParentId = n.parent.id
	}
	a.WidgetType = n.WidgetType
	sendActionToPlugin(&a)
}

// sends the action/event to each toolkit via a golang plugin channel
func sendActionToPlugin(a *widget.Action) {
	for _, aplug := range allPlugins {
		log.Warn("send to toolkit =", aplug.name, "Action type=", a.ActionType, a.WidgetId)
		if aplug.pluginChan == nil {
			log.Warn("Action() retrieving the aplug.PluginChannel()", aplug.name)
			aplug.pluginChan = aplug.PluginChannel()
			log.Warn("Action() retrieved", aplug.pluginChan)
		}
		log.Verbose("Action() SEND to pluginChan", aplug.name, a.ActionType, a.WidgetType, a.WidgetId, a.ProgName)
		aplug.pluginChan <- *a
		// added during debugging. might be a good idea in general for a tactile experience
		// start playing with this
		if a.ActionType == widget.Hide {
			// log.Sleep(.001) // this delay makes it so SetText() works on initial widget creation
		} else {
			// 2024/12/16 still leaving this as I'm not sure binary tree access is actually
			// safe (thread safe, correct locking, etc). I think it is. Things seem stable
			// sync.Mutex() locks don't appear to work somehow in a way I don't understand
			// it's probably due to []string use. use map[] instead
			log.Sleep(.000001) // this delay makes it so SetText() works on initial widget creation
			// log.Sleep(.002) // this delay makes it so SetText() works on initial widget creation
		}
	}
}