summaryrefslogtreecommitdiff
path: root/plugin.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin.go')
-rw-r--r--plugin.go265
1 files changed, 195 insertions, 70 deletions
diff --git a/plugin.go b/plugin.go
index 58e6dbe..e13f751 100644
--- a/plugin.go
+++ b/plugin.go
@@ -8,109 +8,234 @@ package gui
import (
"log"
"os"
-
"plugin"
- "github.com/davecgh/go-spew/spew"
+
+ "git.wit.org/wit/gui/toolkit"
)
-// TODO: could a protobuf work here?
-type Greeter interface {
- Greet()
- JcarrButton()
- AddButton(string)
+var err error
+type Symbol any
+
+type aplug struct {
+ // Ok bool
+ name string
+ filename string
+ plug *plugin.Plugin
+ sym *plugin.Symbol
+ LoadOk bool
+ InitOk bool
+ MainOk bool
+
+ Init func()
+ Main func(func ())
+ Queue func(func ())
+ Quit func()
+ NewWindow func(*toolkit.Widget)
+ NewButton func(*toolkit.Widget, *toolkit.Widget)
+ NewGroup func(*toolkit.Widget, *toolkit.Widget)
+ NewCheckbox func(*toolkit.Widget, *toolkit.Widget)
+ NewTab func(*toolkit.Widget, *toolkit.Widget)
+ NewLabel func(*toolkit.Widget, *toolkit.Widget)
+ NewTextbox func(*toolkit.Widget, *toolkit.Widget)
+ NewSlider func(*toolkit.Widget, *toolkit.Widget)
+ NewSpinner func(*toolkit.Widget, *toolkit.Widget)
+
+ NewDropdown func(*toolkit.Widget, *toolkit.Widget)
+ AddDropdownName func(*toolkit.Widget, string)
}
-var PlugGocli *plugin.Plugin
-var PlugGocliOk bool
-var PlugHello *plugin.Plugin
+var allPlugins []*aplug
+
+// loads and initializes a toolkit (andlabs/ui, gocui, etc)
+func LoadToolkit(name string) bool {
+ var newPlug aplug
+
+ log.Println("gui.LoadToolkit() START")
+ newPlug.LoadOk = false
+
+ for _, aplug := range allPlugins {
+ log.Println("gui.LoadToolkit() already loaded toolkit plugin =", aplug.name)
+ if (aplug.name == name) {
+ log.Println("gui.LoadToolkit() SKIPPING")
+ return true
+ }
+ }
+
+ // locate the shared library file
+ filename := name + ".so"
+ loadPlugin(&newPlug, filename)
+ if (newPlug.plug == nil) {
+ return false
+ }
+ // newPlug.Ok = true
+ newPlug.name = name
+
+ // map all the functions
+ newPlug.Init = loadFuncE(&newPlug, "Init")
+ newPlug.Quit = loadFuncE(&newPlug, "Quit")
+
+ // this should be laodFuncE()
+ newPlug.Main = loadFuncF(&newPlug, "Main")
+ newPlug.Queue = loadFuncF(&newPlug, "Queue")
+
+ newPlug.NewWindow = loadFunc1(&newPlug, "NewWindow")
+
+ newPlug.NewButton = loadFunc2(&newPlug, "NewButton")
+ newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup")
+ newPlug.NewCheckbox = loadFunc2(&newPlug, "NewCheckbox")
+ newPlug.NewTab = loadFunc2(&newPlug, "NewTab")
+ newPlug.NewLabel = loadFunc2(&newPlug, "NewLabel")
+ newPlug.NewTextbox = loadFunc2(&newPlug, "NewTextbox")
+ newPlug.NewSlider = loadFunc2(&newPlug, "NewSlider")
+ newPlug.NewSpinner = loadFunc2(&newPlug, "NewSpinner")
+
+ newPlug.NewDropdown = loadFunc2(&newPlug, "NewDropdown")
+ newPlug.AddDropdownName = loadFuncS(&newPlug, "AddDropdownName")
-// var gBut plugin.Symbol
-var jcarrBut plugin.Symbol
-var symGreeter plugin.Symbol
-var greeter Greeter
-var ok bool
+ allPlugins = append(allPlugins, &newPlug)
-var typeToolkit plugin.Symbol
-var typeToolkitCast Greeter
+ log.Println("gui.LoadToolkit() END", newPlug.name, filename)
+ newPlug.LoadOk = true
+ return true
+}
-func LoadPlugin(name string) *plugin.Plugin {
- scs := spew.ConfigState{MaxDepth: 1}
+func loadFuncE(p *aplug, funcName string) func() {
+ var newfunc func()
+ var ok bool
+ var test plugin.Symbol
- // load module
- // 1. open the so file to load the symbols
- plug, err := plugin.Open(name)
- log.Println("plug =")
- log.Println(scs.Sdump(plug))
+ test, err = p.plug.Lookup(funcName)
if err != nil {
- log.Println(err)
+ log.Println("DID NOT FIND: name =", test, "err =", err)
return nil
}
- // 2. look up a symbol (an exported function or variable)
- // in this case, variable Greeter
- typeToolkit, err = plug.Lookup("Toolkit")
- log.Println("plugin.Toolkit", typeToolkit)
- log.Println(scs.Sdump(typeToolkit))
- if err != nil {
- log.Println(err)
- os.Exit(1)
+ newfunc, ok = test.(func())
+ if !ok {
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
+ return newfunc
+}
+
+func loadFunc1(p *aplug, funcName string) func(*toolkit.Widget) {
+ var newfunc func(*toolkit.Widget)
+ var ok bool
+ var test plugin.Symbol
- symGreeter, err = plug.Lookup("Greeter")
- log.Println("symGreater", symGreeter)
- log.Println(scs.Sdump(symGreeter))
+ test, err = p.plug.Lookup(funcName)
if err != nil {
- log.Println(err)
- os.Exit(1)
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
}
- // 3. Assert that loaded symbol is of a desired type
- // in this case interface type Greeter (defined above)
- // var greeter Greeter
- greeter, ok = symGreeter.(Greeter)
- log.Println("greeter", symGreeter)
- log.Println(scs.Sdump(greeter))
+ newfunc, ok = test.(func(*toolkit.Widget))
if !ok {
- log.Println("unexpected type from module symbol")
- os.Exit(1)
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
+ return newfunc
+}
- /*
- typeToolkitCast, ok = typeToolkit.(Greeter)
+func loadFuncS(p *aplug, funcName string) func(*toolkit.Widget, string) {
+ var newfunc func(*toolkit.Widget, string)
+ var ok bool
+ var test plugin.Symbol
+
+ test, err = p.plug.Lookup(funcName)
+ if err != nil {
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
+ }
+
+ newfunc, ok = test.(func(*toolkit.Widget, string))
if !ok {
- log.Println("unexpected cast of Toolkit to Greeter")
- os.Exit(1)
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
- */
- return plug
+ return newfunc
}
-func RunGreet() {
- log.Println("gui.RunGreet() START")
- if (greeter == nil) {
- log.Println("wit/gui gocui plugin didn't load")
- return
+func loadFunc2(p *aplug, funcName string) func(*toolkit.Widget, *toolkit.Widget) {
+ var newfunc func(*toolkit.Widget, *toolkit.Widget)
+ var ok bool
+ var test plugin.Symbol
+
+ test, err = p.plug.Lookup(funcName)
+ if err != nil {
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
+ }
+
+ newfunc, ok = test.(func(*toolkit.Widget, *toolkit.Widget))
+ if !ok {
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
- PlugGocliOk = true
- greeter.Greet()
+ return newfunc
}
-func LookupJcarrButton() {
- log.Println("lookupJcarrButton() START")
+// This is probably dangerous and should never be done
+// executing arbitrary functions will cause them to run inside the goroutine that
+// the GUI toolkit itself is running in. TODO: move to channels here
+func loadFuncF(p *aplug, funcName string) func(func ()) {
+ var newfunc func(func ())
+ var ok bool
+ var test plugin.Symbol
- if (greeter == nil) {
- log.Println("wit/gui gocui plugin didn't load")
- return
+ test, err = p.plug.Lookup(funcName)
+ if err != nil {
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
}
- greeter.JcarrButton()
+
+ newfunc, ok = test.(func(func ()))
+ if !ok {
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
+ }
+ return newfunc
}
-func GocuiAddButton(name string) {
- log.Println("GocuiAddButton() START", name)
+func loadPlugin(p *aplug, name string) {
+ var filename string
+
+ // attempt to write out the file from the internal resource
+ internalName := "toolkit/" + name
+ soFile, err := res.ReadFile(internalName)
+ if (err != nil) {
+ log.Println(err)
+ } else {
+ err = os.WriteFile("/tmp/wit/" + name, soFile, 0644)
+ if (err != nil) {
+ log.Println(err)
+ }
+ }
+
+ filename = "/tmp/wit/" + name
+ p.plug = loadfile(filename)
+ if (p.plug != nil) {
+ p.filename = filename
+ return
+ }
- if (greeter == nil) {
- log.Println("wit/gui gocui plugin didn't load")
+ filename = "/usr/share/wit/gui/" + name
+ p.plug = loadfile(filename)
+ if (p.plug != nil) {
+ p.filename = filename
return
}
- greeter.AddButton(name)
+ return
+}
+
+// load module
+// 1. open the shared object file to load the symbols
+func loadfile(filename string) *plugin.Plugin {
+ plug, err := plugin.Open(filename)
+ log.Println("plug =", plug)
+ if err != nil {
+ log.Println(err)
+ return nil
+ }
+ return plug
}