gocui: callbacks work via a channel

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-04-06 18:00:18 -05:00
parent 90e45a4a3e
commit bddce3d5a3
10 changed files with 86 additions and 7 deletions

View File

@ -131,13 +131,13 @@ Creates a window helpful for debugging this package
`func InitPlugins(names []string)`
### func [LoadToolkit](/plugin.go#L46)
### func [LoadToolkit](/plugin.go#L50)
`func LoadToolkit(name string) bool`
loads and initializes a toolkit (andlabs/ui, gocui, etc)
### func [Main](/main.go#L127)
### func [Main](/main.go#L143)
`func Main(f func())`
@ -159,7 +159,7 @@ This should not pass a function
`func ShowDebugValues()`
### func [StandardExit](/main.go#L179)
### func [StandardExit](/main.go#L204)
`func StandardExit()`
@ -193,7 +193,7 @@ This struct can be used with the go-arg package
var Config GuiConfig
```
### type [Node](/structs.go#L58)
### type [Node](/structs.go#L60)
`type Node struct { ... }`
@ -252,7 +252,7 @@ You get a window
`func Start() *Node`
#### func [StartS](/main.go#L113)
#### func [StartS](/main.go#L129)
`func StartS(name string) *Node`

View File

@ -64,6 +64,7 @@ func (n *Node) DebugGoChannels(makeWindow bool) {
debugWG.Done()
})
g.NewButton("close chan", func () {
log("close() on", debugNumberChan)
close(debugNumberChan)
})
g.NewButton("print", func () {

25
main.go
View File

@ -104,6 +104,22 @@ func Start() *Node {
return Config.rootNode
}
func doSomething() {
log(logNow, "doSomething()")
}
func watchCallback() {
log(logNow, "makeCallback() START")
for {
log(logNow, "makeCallback() for loop")
select {
case a := <-Config.guiChan:
log(logNow, "makeCallback() SELECT widget id =", a.WidgetId, a.Name)
sleep(.5) // TODO: remove this. added while under development
}
}
}
func (n *Node) LoadPlugin(name string) bool {
StartS(name)
Redraw(name)
@ -129,6 +145,11 @@ func Main(f func()) {
InitPlugins([]string{"andlabs", "gocui"})
if (Config.guiChan == nil) {
Config.guiChan = make(chan toolkit.Action)
go watchCallback()
}
for _, aplug := range allPlugins {
log(debugGui, "gui.Node.NewButton() toolkit plugin =", aplug.name)
if (aplug.MainOk) {
@ -140,8 +161,12 @@ func Main(f func()) {
continue
}
aplug.MainOk = true
if (aplug.Callback != nil) {
aplug.Callback(Config.guiChan)
}
aplug.Main(f)
}
}
/*

View File

@ -33,6 +33,10 @@ type aplug struct {
Quit func()
// NewWindow func(*toolkit.Widget)
// sets the chan for the plugin to call back too
Callback func(chan toolkit.Action)
// NewWindow func(*toolkit.Widget)
// simplifies passing to the plugin
// Send func(*toolkit.Widget, *toolkit.Widget)
@ -83,6 +87,8 @@ func LoadToolkit(name string) bool {
// Sends a widget (button, checkbox, etc) and it's parent widget
newPlug.Action = loadFuncA(&newPlug, "Action")
newPlug.Callback = loadCallback(&newPlug, "Callback")
allPlugins = append(allPlugins, &newPlug)
log(debugPlugin, "gui.LoadToolkit() END", newPlug.name, filename)
@ -112,6 +118,25 @@ func loadFuncE(p *aplug, funcName string) func() {
return newfunc
}
func loadCallback(p *aplug, funcName string) func(chan toolkit.Action) {
var newfunc func(chan toolkit.Action)
var ok bool
var test plugin.Symbol
test, err = p.plug.Lookup(funcName)
if err != nil {
log(debugGui, "DID NOT FIND: name =", test, "err =", err)
return nil
}
newfunc, ok = test.(func(chan toolkit.Action))
if !ok {
log(debugGui, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
return nil
}
return newfunc
}
func loadFunc2(p *aplug, funcName string) func(*toolkit.Widget, *toolkit.Widget) {
var newfunc func(*toolkit.Widget, *toolkit.Widget)
var ok bool

View File

@ -51,6 +51,8 @@ type GuiConfig struct {
ActionCh1 chan int
ActionCh2 chan int
guiChan chan toolkit.Action
}
// The Node is a binary tree. This is how all GUI elements are stored

View File

@ -34,6 +34,7 @@ func (w *cuiWidget) doWidgetClick() {
} else {
w.setCheckbox(true)
}
w.doUserEvent()
case toolkit.Grid:
me.rootNode.hideWidgets()
w.placeGrid()
@ -47,10 +48,28 @@ func (w *cuiWidget) doWidgetClick() {
}
w.placeWidgets()
w.toggleTree()
case toolkit.Button:
w.doUserEvent()
default:
}
}
// this passes the user event back from the plugin
func (w *cuiWidget) doUserEvent() {
if (me.callback == nil) {
log(logError, "doUserEvent() no callback channel was configured")
return
}
var a toolkit.Action
a.WidgetId = w.id
a.Name = w.name
a.Text = w.text
a.B = w.b
a.ActionType = toolkit.User
me.callback <- a
log(logNow, "END: sent a button click callback()")
}
var toggle bool = true
func (w *cuiWidget) toggleTree() {
if (toggle) {

View File

@ -6,6 +6,7 @@ package main
import (
"os"
"git.wit.org/wit/gui/toolkit"
)
func Init() {
@ -27,6 +28,11 @@ func Init() {
me.padH = 3
}
// this sets the channel to send user events back from the plugin
func Callback(guiCallback chan toolkit.Action) {
me.callback = guiCallback
}
func Exit() {
// TODO: exit correctly
me.baseGui.Close()

View File

@ -23,7 +23,7 @@ type config struct {
rootNode *cuiWidget // the base of the binary tree. it should have id == 0
ctrlDown *cuiWidget // shown if you click the mouse when the ctrl key is pressed
callback func(int)
callback chan toolkit.Action
helpLabel *gocui.View
defaultBehavior bool

View File

@ -110,6 +110,7 @@ const (
const (
Add ActionType = iota
User // the user did something (mouse, keyboard, etc)
Delete
Get
Set

View File

@ -15,7 +15,7 @@ var watchtime time.Duration = 100 // in tenths of seconds
func Watchdog() {
var i = 1
for {
log(debugGui, "watchdog timer is alive. give me something to do.", i)
log(logInfo, "watchdog timer is alive. give me something to do.", i)
i += 1
time.Sleep(watchtime * time.Second / 10)
}