194 lines
4.2 KiB
Go
194 lines
4.2 KiB
Go
package main
|
|
|
|
/*
|
|
These code should be common to all gui plugins
|
|
|
|
There are some helper functions that are probably going to be
|
|
the same everywhere. Mostly due to handling the binary tree structure
|
|
and the channel communication
|
|
|
|
For now, it's just a symlink to the 'master' version in
|
|
./toolkit/nocui/common.go
|
|
*/
|
|
|
|
import (
|
|
"reflect"
|
|
"strconv"
|
|
|
|
"go.wit.com/log"
|
|
"go.wit.com/gui/widget"
|
|
)
|
|
|
|
// this is the channel we send user events like
|
|
// mouse clicks or keyboard events back to the program
|
|
var callback chan widget.Action
|
|
|
|
// this is the channel we get requests to make widgets
|
|
var pluginChan chan widget.Action
|
|
|
|
type node struct {
|
|
parent *node
|
|
children []*node
|
|
|
|
WidgetId int // widget ID
|
|
WidgetType widget.WidgetType
|
|
ParentId int // parent ID
|
|
|
|
// a reference name for programming and debuggign. Must be unique
|
|
progname string
|
|
|
|
// the text used for button labesl, window titles, checkbox names, etc
|
|
label string
|
|
|
|
// horizontal means layout widgets like books on a bookshelf
|
|
// vertical means layout widgets like books in a stack
|
|
direction widget.Orientation
|
|
|
|
// This is how the values are passed back and forth
|
|
// values from things like checkboxes & dropdown's
|
|
value any
|
|
|
|
// This is used for things like a slider(0,100)
|
|
X int
|
|
Y int
|
|
|
|
// This is for the grid size & widget position
|
|
W int
|
|
H int
|
|
AtW int
|
|
AtH int
|
|
|
|
vals []string // dropdown menu items
|
|
|
|
// horizontal bool `default:false`
|
|
|
|
hasTabs bool // does the window have tabs?
|
|
currentTab bool // the visible tab
|
|
|
|
// the internal plugin toolkit structure
|
|
// in the gtk plugin, it has gtk things like margin & border settings
|
|
// in the text console one, it has text console things like colors for menus & buttons
|
|
tk *guiWidget
|
|
}
|
|
|
|
// searches the binary tree for a WidgetId
|
|
func (n *node) findWidgetId(id int) *node {
|
|
if (n == nil) {
|
|
return nil
|
|
}
|
|
|
|
if n.WidgetId == id {
|
|
return n
|
|
}
|
|
|
|
for _, child := range n.children {
|
|
newN := child.findWidgetId(id)
|
|
if (newN != nil) {
|
|
return newN
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (n *node) doUserEvent() {
|
|
if (callback == nil) {
|
|
log.Log(ERROR, "doUserEvent() callback == nil", n.WidgetId)
|
|
return
|
|
}
|
|
var a widget.Action
|
|
a.WidgetId = n.WidgetId
|
|
a.Value = n.value
|
|
a.ActionType = widget.User
|
|
log.Log(INFO, "doUserEvent() START: send a user event to the callback channel")
|
|
callback <- a
|
|
log.Log(INFO, "doUserEvent() END: sent a user event to the callback channel")
|
|
return
|
|
}
|
|
|
|
func addNode(a *widget.Action) *node {
|
|
n := new(node)
|
|
n.WidgetType = a.WidgetType
|
|
n.WidgetId = a.WidgetId
|
|
n.ParentId = a.ParentId
|
|
|
|
// copy the data from the action message
|
|
n.progname = a.ProgName
|
|
n.value = a.Value
|
|
n.direction = a.Direction
|
|
|
|
n.X = a.X
|
|
n.Y = a.Y
|
|
|
|
n.W = a.W
|
|
n.H = a.H
|
|
n.AtW = a.AtW
|
|
n.AtH = a.AtH
|
|
|
|
// store the internal toolkit information
|
|
n.tk = initWidget(n)
|
|
// n.tk = new(guiWidget)
|
|
|
|
if (a.WidgetType == widget.Root) {
|
|
log.Log(INFO, "addNode() Root")
|
|
return n
|
|
}
|
|
|
|
if (me.rootNode.findWidgetId(a.WidgetId) != nil) {
|
|
log.Log(ERROR, "addNode() WidgetId already exists", a.WidgetId)
|
|
return me.rootNode.findWidgetId(a.WidgetId)
|
|
}
|
|
|
|
// add this new widget on the binary tree
|
|
n.parent = me.rootNode.findWidgetId(a.ParentId)
|
|
if n.parent != nil {
|
|
n.parent.children = append(n.parent.children, n)
|
|
//w := n.tk
|
|
//w.parent = n.parent.tk
|
|
//w.parent.children = append(w.parent.children, w)
|
|
}
|
|
return n
|
|
}
|
|
|
|
// Other goroutines must use this to access the GUI
|
|
//
|
|
// You can not acess / process the GUI thread directly from
|
|
// other goroutines. This is due to the nature of how
|
|
// Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
|
|
//
|
|
// this sets the channel to send user events back from the plugin
|
|
func Callback(guiCallback chan widget.Action) {
|
|
callback = guiCallback
|
|
}
|
|
|
|
func PluginChannel() chan widget.Action {
|
|
return pluginChan
|
|
}
|
|
|
|
func getString(A any) string {
|
|
if A == nil {
|
|
log.Warn("getString() got nil")
|
|
return ""
|
|
}
|
|
var k reflect.Kind
|
|
k = reflect.TypeOf(A).Kind()
|
|
|
|
switch k {
|
|
case reflect.Int:
|
|
var i int
|
|
i = A.(int)
|
|
return strconv.Itoa(i)
|
|
case reflect.String:
|
|
return A.(string)
|
|
case reflect.Bool:
|
|
if A.(bool) == true {
|
|
return "true"
|
|
} else {
|
|
return "false"
|
|
}
|
|
default:
|
|
log.Warn("getString uknown kind", k, "value =", A)
|
|
return ""
|
|
}
|
|
return ""
|
|
}
|