open gocui when DISPLAY=""

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-04-07 09:18:03 -05:00
parent 5ba335ddee
commit 8f6e971948
9 changed files with 96 additions and 60 deletions

View File

@ -127,13 +127,16 @@ Creates a window helpful for debugging this package
`func Indent(b bool, a ...interface{})`
### func [InitPlugins](/main.go#L58)
### func [InitPlugins](/main.go#L61)
`func InitPlugins(names []string)`
`func InitPlugins(names []string) []string`
TODO: add logic to just load the 1st 'most common' gui toolkit
and allow the 'go-arg' command line args to override the defaults
### func [LoadToolkit](/plugin.go#L50)
`func LoadToolkit(name string) bool`
`func LoadToolkit(name string) *aplug`
loads and initializes a toolkit (andlabs/ui, gocui, etc)
@ -159,7 +162,7 @@ This should not pass a function
`func ShowDebugValues()`
### func [StandardExit](/main.go#L255)
### func [StandardExit](/main.go#L262)
`func StandardExit()`
@ -248,11 +251,11 @@ func main() {
You get a window
```
#### func [Start](/main.go#L98)
#### func [Start](/main.go#L97)
`func Start() *Node`
#### func [StartS](/main.go#L180)
#### func [StartS](/main.go#L178)
`func StartS(name string) *Node`

View File

@ -11,6 +11,7 @@ import (
var title string = "Demo Plugin Window"
var outfile string = "/tmp/guilogfile"
var myGui *gui.Node
var buttonCounter int = 5
@ -27,25 +28,13 @@ func main() {
// gui.Init()
// buttonWindow()
go gui.Main(func () {
log.Println("START Main f()")
myGui = gui.Start()
time.Sleep(1 * time.Second)
buttonWindow()
/*
log.Println("END NewWindow()")
log.Println("START NewGroup()")
g := w.NewGroup("new Group 22")
log.Println("END NewGroup()")
g.NewButton("asdjkl", func () {
log.Println("world")
})
*/
log.Println("END Main f()")
// gui.StandardExit(nil)
})
log.Println("Main() END")
time.Sleep(1 * time.Second)
gui.StartS("gocui")
gui.Redraw("gocui")
// gui.StartS("gocui")
// gui.Redraw("gocui")
gui.Watchdog()
gui.StandardExit()
}
@ -84,6 +73,10 @@ func buttonWindow() {
gui.Redraw("gocui")
})
g.NewButton("Load 'andlabs'", func () {
gui.StartS("andlabs")
})
g.NewButton("NewButton(more)", func () {
log.Println("new foobar 2. Adding button 'foobar 3'")
name := "foobar " + strconv.Itoa(buttonCounter)

45
main.go
View File

@ -1,6 +1,7 @@
package gui
import (
"os"
// "embed"
"git.wit.org/wit/gui/toolkit"
)
@ -55,44 +56,42 @@ func doGuiChan() {
}
}
func InitPlugins(names []string) {
// TODO: add logic to just load the 1st 'most common' gui toolkit
// and allow the 'go-arg' command line args to override the defaults
func InitPlugins(names []string) []string {
log(debugGui, "Starting gui.Init()")
for _, aplug := range allPlugins {
log(debugGui, "LoadToolkit() already loaded toolkit plugin =", aplug.name)
for _, name := range names {
if (name == aplug.name) {
return
return []string{name}
}
}
}
// try to load each plugin in the order passed to this function
for _, name := range names {
if (LoadToolkit(name)) {
// aplug.InitOk = true
// aplug.Init()
return
aPlug := LoadToolkit(name)
if (aPlug != nil) {
// exit because it worked!
return []string{name}
}
}
// the program didn't specify a plugin. Try to load one
// TODO: detect the OS & user preferences to load the best one
// TODO: commented out Init() on 02/26/2023 because I'm not sure how to run it correctly
if (LoadToolkit("andlabs")) {
// aplug.InitOk = true
// aplug.Init()
return
andlabsPlug := LoadToolkit("andlabs")
if (andlabsPlug != nil) {
return []string{}
}
if (LoadToolkit("gocui")) {
// aplug.InitOk = true
// aplug.Init()
return
gocuiPlug := LoadToolkit("andlabs")
if (gocuiPlug != nil) {
return []string{}
}
// Should die here? TODO: need a Node to call StandardExit
// StandardExit("golang wit/gui could not load a plugin TODO: do something to STDOUT (?)")
return []string{}
}
func Start() *Node {
@ -173,13 +172,13 @@ func (n *Node) doUserEvent(a toolkit.Action) {
func (n *Node) LoadPlugin(name string) bool {
StartS(name)
Redraw(name)
return true
}
func StartS(name string) *Node {
log(logInfo, "Start() Main(f) for name =", name)
if (LoadToolkit(name) == false) {
aplug := LoadToolkit(name)
if (aplug == nil) {
return Config.rootNode
}
// will this really work on mswindows & macos?
@ -187,6 +186,7 @@ func StartS(name string) *Node {
}
go Main(f)
sleep(1) // temp hack until chan communication is setup
Config.rootNode.Redraw(aplug)
return Config.rootNode
}
@ -194,7 +194,14 @@ func StartS(name string) *Node {
func Main(f func()) {
log(debugGui, "Starting gui.Main() (using gtk via andlabs/ui)")
// TODO: this is linux only
// TODO: detect if this was run from the command line (parent == bash?)
// if DISPLAY is not set, don't even bother with loading andlabs
if (os.Getenv("DISPLAY") == "") {
InitPlugins([]string{"gocui"})
} else {
InitPlugins([]string{"andlabs", "gocui"})
}
if (Config.guiChan == nil) {
Config.guiChan = make(chan toolkit.Action)

View File

@ -47,8 +47,9 @@ type aplug struct {
var allPlugins []*aplug
// loads and initializes a toolkit (andlabs/ui, gocui, etc)
func LoadToolkit(name string) bool {
var newPlug aplug
func LoadToolkit(name string) *aplug {
var newPlug *aplug
newPlug = new(aplug)
log(debugGui, "gui.LoadToolkit() START")
newPlug.LoadOk = false
@ -57,44 +58,45 @@ func LoadToolkit(name string) bool {
log(debugGui, "gui.LoadToolkit() already loaded toolkit plugin =", aplug.name)
if (aplug.name == name) {
log(debugGui, "gui.LoadToolkit() SKIPPING")
return true
return aplug
}
}
// locate the shared library file
filename := name + ".so"
loadPlugin(&newPlug, filename)
loadPlugin(newPlug, filename)
if (newPlug.plug == nil) {
log(true, "attempt to find plugin", filename, "failed")
return false
return nil
}
// newPlug.Ok = true
newPlug.name = name
// deprecate Init(?)
newPlug.Init = loadFuncE(&newPlug, "Init")
newPlug.Init = loadFuncE(newPlug, "Init")
// should make a goroutine that never exits
newPlug.Main = loadFuncF(&newPlug, "Main")
newPlug.Main = loadFuncF(newPlug, "Main")
// should send things to the goroutine above
// newPlug.Queue = loadFuncF(&newPlug, "Queue")
// unload the plugin and restore state
newPlug.Quit = loadFuncE(&newPlug, "Quit")
newPlug.Quit = loadFuncE(newPlug, "Quit")
// Sends instructions like "Add", "Delete", "Disable", etc
// Sends a widget (button, checkbox, etc) and it's parent widget
newPlug.Action = loadFuncA(&newPlug, "Action")
newPlug.Action = loadFuncA(newPlug, "Action")
newPlug.Callback = loadCallback(&newPlug, "Callback")
newPlug.Callback = loadCallback(newPlug, "Callback")
allPlugins = append(allPlugins, &newPlug)
allPlugins = append(allPlugins, newPlug)
log(debugPlugin, "gui.LoadToolkit() END", newPlug.name, filename)
newPlug.Init()
Config.rootNode.Redraw(newPlug)
newPlug.LoadOk = true
return true
return newPlug
}
// TODO: All these functions need to be done a smarter way

View File

@ -38,9 +38,10 @@ func helplayout(g *gocui.Gui) error {
fmt.Fprintln(help, "d: show/hide debugging")
fmt.Fprintln(help, "h: hide widgets")
fmt.Fprintln(help, "s: show all widgets")
fmt.Fprintln(help, "q: quit()")
fmt.Fprintln(help, "p: panic()")
fmt.Fprintln(help, "STDOUT: /tmp/witgui.log")
fmt.Fprintln(help, "Ctrl-C or Q: Exit")
// fmt.Fprintln(help, "Ctrl-C: Exit") // TODO: fix ctrl-c handling
if _, err := g.SetCurrentView("help"); err != nil {
return err
}

View File

@ -70,9 +70,24 @@ func addDebugKeys(g *gocui.Gui) {
return nil
})
// exit
g.SetKeybinding("", 'q', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
me.baseGui.Close()
exit("forced exit() from within gocui")
return nil
})
g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
me.baseGui.Close()
exit("forced exit() from within gocui")
return nil
})
// panic
g.SetKeybinding("", 'p', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
me.baseGui.Close()
panic("forced panic in gocui")
return nil
})

View File

@ -34,7 +34,7 @@ func Callback(guiCallback chan toolkit.Action) {
}
func Exit() {
// TODO: exit correctly
// TODO: send exit to the plugin
me.baseGui.Close()
}
@ -51,4 +51,5 @@ func Main(f func()) {
log("This is a test log entry")
MouseMain()
me.baseGui.Close()
}

View File

@ -15,8 +15,15 @@ func Action(a *toolkit.Action) {
w := findWidget(a.WidgetId, me.rootNode)
switch a.ActionType {
case toolkit.Add:
if (w == nil) {
w = makeWidget(a)
w.addWidget()
} else {
// this is done to protect the plugin being 'refreshed' with the
// widget binary tree. TODO: find a way to keep them in sync
log(logError, "Action() Add ignored for already defined widget",
a.WidgetId, a.ActionType, a.WidgetType, a.Name)
}
case toolkit.Show:
if (a.B) {
w.drawView()

View File

@ -15,7 +15,14 @@ var watchtime time.Duration = 100 // in tenths of seconds
func Watchdog() {
var i = 1
for {
log(logInfo, "watchdog timer is alive. give me something to do.", i)
log(logNow, "watchdog timer is alive. give me something to do.", i)
if (Config.rootNode == nil) {
log(logInfo, "Config.rootNode == nil", i)
} else {
if (logVerbose) {
Config.rootNode.ListChildren(true)
}
}
i += 1
time.Sleep(watchtime * time.Second / 10)
}