better toolkit init options

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-04-12 13:00:29 -05:00
parent a235371d1a
commit ca708db97e
12 changed files with 97 additions and 85 deletions

View File

@ -123,20 +123,17 @@ Creates a window helpful for debugging this package
`func ExampleCatcher(f func())`
### func [FindPlugin](/plugin.go#L64)
`func FindPlugin(name string) *aplug`
loads and initializes a toolkit (andlabs/ui, gocui, etc)
attempts to locate the .so file
### func [Indent](/debug.go#L120)
`func Indent(b bool, a ...interface{})`
### func [LoadPlugin](/main.go#L114)
`func LoadPlugin(name string) bool`
### func [LoadToolkit](/plugin.go#L68)
`func LoadToolkit(name string) *aplug`
loads and initializes a toolkit (andlabs/ui, gocui, etc)
### func [SetDebug](/debug.go#L28)
`func SetDebug(s bool)`
@ -149,7 +146,7 @@ loads and initializes a toolkit (andlabs/ui, gocui, etc)
`func ShowDebugValues()`
### func [StandardExit](/main.go#L155)
### func [StandardExit](/main.go#L153)
`func StandardExit()`
@ -190,7 +187,7 @@ var Config GuiConfig
The Node is a binary tree. This is how all GUI elements are stored
simply the name and the size of whatever GUI element exists
#### func [New](/main.go#L132)
#### func [New](/main.go#L126)
`func New() *Node`

View File

@ -18,7 +18,7 @@ func main() {
// This will turn on all debugging
// gui.SetDebug(true)
myGui = gui.New()
myGui = gui.New().LoadToolkit("gocui")
buttonWindow()
// This is just a optional goroutine to watch that things are alive
@ -55,11 +55,11 @@ func buttonWindow() {
g.NewButton("Load 'gocui'", func () {
// this set the xterm and mate-terminal window title. maybe works generally?
fmt.Println("\033]0;" + title + "blah \007")
gui.LoadPlugin("gocui")
myGui.LoadToolkit("gocui")
})
g.NewButton("Load 'andlabs'", func () {
gui.LoadPlugin("andlabs")
myGui.LoadToolkit("andlabs")
})
g.NewButton("NewButton(more)", func () {

View File

@ -90,8 +90,8 @@ func (n *Node) DebugTab(title string) *Node {
}
})
g2.NewButton("load plugin 'gocui'", func () {
LoadPlugin("gocui")
g2.NewButton("load toolkit 'gocui'", func () {
Config.rootNode.LoadToolkit("gocui")
})
return newN

31
main.go
View File

@ -40,7 +40,7 @@ func init() {
Config.flag = Config.rootNode.newNode("flag", 0, nil)
Config.flag.WidgetType = toolkit.Flag
Config.guiChan = make(chan toolkit.Action)
Config.guiChan = make(chan toolkit.Action, 1)
go watchCallback()
}
@ -111,18 +111,12 @@ func (n *Node) doUserEvent(a toolkit.Action) {
}
}
func LoadPlugin(name string) bool {
func (n *Node) LoadToolkit(name string) *Node {
log(logInfo, "Start() Main(f) for name =", name)
newPlugin := LoadToolkit(name)
if (newPlugin == nil) {
return false
if (FindPlugin(name) == nil) {
return n
}
sleep(1) // temp hack until chan communication is setup
// TODO: find a new way to do this that is locking, safe and accurate
Config.rootNode.redraw(newPlugin)
return true
return n
}
// There should only be one of these per application
@ -130,18 +124,22 @@ func LoadPlugin(name string) bool {
// some toolkit's on some operating systems don't support more than one
// Keep things simple. Do the default expected thing whenever possible
func New() *Node {
if (LoadPlugin("gocui")) {
return Config.rootNode
}
func (n *Node) Default() *Node {
if (FindPlugin("gocui") == nil) {
log(logError, "New() failed to load gocui")
}
// if DISPLAY isn't set, return since gtk can't load
// TODO: figure out how to check what to do in macos and mswindows
if (os.Getenv("DISPLAY") == "") {
return Config.rootNode
return n
}
if (LoadPlugin("andlabs")) {
if (FindPlugin("andlabs") == nil) {
log(logError, "New() failed to load andlabs")
}
return Config.rootNode
return n
}
// The window is destroyed but the application does not quit
@ -157,9 +155,6 @@ func StandardExit() {
log("StandardExit() attempt to exit each toolkit plugin")
for i, aplug := range allPlugins {
log("NewButton()", i, aplug)
if (aplug.Quit != nil) {
aplug.Quit()
}
}
exit(0)
}

View File

@ -21,10 +21,11 @@ type aplug struct {
filename string
plug *plugin.Plugin
sym *plugin.Symbol
LoadOk bool
// LoadOk bool
InitOk bool
MainOk bool
// MainOk bool
// startup whatever might need to be setup in the plugin
Init func()
// This passes the go channel to the plugin
@ -47,35 +48,30 @@ type aplug struct {
// each toolkit has it's own goroutine and each one is sent this
// add button request
pluginChan chan toolkit.Action
PluginChannel func() chan toolkit.Action
// deprecate all this
// TODO: make Main() main() and never allow the user to call it
// run plugin.Main() when the plugin is loaded
Main func(func ()) // this never returns. Each plugin must have it's own goroutine
Quit func()
// simplifies passing to the plugin
// Send func(*toolkit.Widget, *toolkit.Widget)
// should replace Send()
// Action func(*toolkit.Action)
// Main func(func ()) // this never returns. Each plugin must have it's own goroutine
// Quit func()
}
var allPlugins []*aplug
// loads and initializes a toolkit (andlabs/ui, gocui, etc)
func LoadToolkit(name string) *aplug {
// attempts to locate the .so file
func FindPlugin(name string) *aplug {
var newPlug *aplug
newPlug = new(aplug)
log(logInfo, "LoadToolkit() START")
newPlug.LoadOk = false
log(logInfo, "FindPlugin() START")
newPlug.InitOk = false
for _, aplug := range allPlugins {
log(debugGui, "LoadToolkit() already loaded toolkit plugin =", aplug.name)
log(debugGui, "FindPlugin() already loaded toolkit plugin =", aplug.name)
if (aplug.name == name) {
log(debugError, "LoadToolkit() SKIPPING", name, "as you can't load it twice")
log(debugError, "FindPlugin() SKIPPING", name, "as you can't load it twice")
return aplug
}
}
@ -94,13 +90,13 @@ func LoadToolkit(name string) *aplug {
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
@ -116,14 +112,20 @@ func LoadToolkit(name string) *aplug {
allPlugins = append(allPlugins, newPlug)
log(debugPlugin, "LoadToolkit() END", newPlug.name, filename)
log(debugPlugin, "FindPlugin() END", newPlug.name, filename)
newPlug.Init()
// set the communication to the plugins
newPlug.pluginChan = newPlug.PluginChannel()
newPlug.Callback(Config.guiChan)
newPlug.LoadOk = true
newPlug.InitOk = true
sleep(1) // temp hack until chan communication is setup
// TODO: find a new way to do this that is locking, safe and accurate
Config.rootNode.redraw(newPlug)
return newPlug
}

View File

@ -15,21 +15,21 @@ func actionDump(b bool, a *toolkit.Action) {
log(b, "actionDump() ParentId =", a.ParentId)
}
func add(a *toolkit.Action) {
func add(a toolkit.Action) {
if (andlabs[a.WidgetId] != nil) {
log(debugError, "add() error. can't make a widget that already exists. id =", a.WidgetId)
actionDump(debugError, a)
actionDump(debugError, &a)
return
}
if (a.WidgetId == 0) {
log(debugError, "add() error. w.WidgetId == 0")
actionDump(debugError, a)
actionDump(debugError, &a)
return
}
// for now, window gets handled without checking where == nil)
if (a.WidgetType == toolkit.Window) {
newWindow(*a)
newWindow(a)
return
}
@ -44,49 +44,49 @@ func add(a *toolkit.Action) {
switch a.WidgetType {
case toolkit.Window:
newWindow(*a)
newWindow(a)
return
case toolkit.Tab:
log(debugError, "add() CAME AT THIS FROM add() =", a.Name)
log(debugError, "add() CAME AT THIS FROM add() =", a.Name)
log(debugError, "add() CAME AT THIS FROM add() =", a.Name)
newTab(*a)
newTab(a)
return
case toolkit.Label:
newLabel(a)
newLabel(&a)
return
case toolkit.Button:
newButton(a)
newButton(&a)
return
case toolkit.Grid:
newGrid(a)
newGrid(&a)
return
case toolkit.Checkbox:
newCheckbox(a)
newCheckbox(&a)
return
case toolkit.Spinner:
newSpinner(a)
newSpinner(&a)
return
case toolkit.Slider:
newSlider(a)
newSlider(&a)
return
case toolkit.Dropdown:
newDropdown(a)
newDropdown(&a)
return
case toolkit.Combobox:
newCombobox(a)
newCombobox(&a)
return
case toolkit.Textbox:
newTextbox(a)
newTextbox(&a)
return
case toolkit.Group:
newGroup(a)
newGroup(&a)
return
case toolkit.Box:
newBox(a)
newBox(&a)
return
case toolkit.Image:
newImage(a)
newImage(&a)
return
default:
log(debugError, "add() error TODO: ", a.WidgetType, a.Name)
@ -122,13 +122,14 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool {
// add the structure to the array
if (andlabs[a.WidgetId] == nil) {
log(logInfo, "newTab() MAPPED", a.WidgetId, a.ParentId)
log(logInfo, "place() MAPPED", a.WidgetId, a.ParentId)
andlabs[a.WidgetId] = newt
newt.WidgetType = a.WidgetType
} else {
log(debugError, "newTab() DO WHAT?", a.WidgetId, a.ParentId)
log(debugError, "THIS IS BAD")
log(debugError, "place() DO WHAT?", a.WidgetId, a.ParentId)
log(debugError, "place() THIS IS BAD")
}
log(logInfo, "place() DONE MAPPED", a.WidgetId, a.ParentId)
if (newt.uiControl == nil) {
log(debugError, "place() ERROR uiControl == nil", a.ParentId)
@ -141,12 +142,13 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool {
return false
}
log(logInfo, "place() switch", where.WidgetType)
switch where.WidgetType {
case toolkit.Grid:
log(debugGrid, "add() Grid try at Parent X,Y =", a.X, a.Y)
log(debugGrid, "place() Grid try at Parent X,Y =", a.X, a.Y)
newt.gridX = a.X
newt.gridY = a.Y
log(debugGrid, "add() Grid try at gridX,gridY", newt.gridX, newt.gridY)
log(debugGrid, "place() Grid try at gridX,gridY", newt.gridX, newt.gridY)
// at the very end, subtract 1 from X & Y since andlabs/ui starts counting at zero
t.uiGrid.Append(newt.uiControl,
newt.gridY - 1, newt.gridX - 1, 1, 1,
@ -155,7 +157,7 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool {
case toolkit.Group:
if (t.uiBox == nil) {
t.uiGroup.SetChild(newt.uiControl)
log(debugGrid, "add() hack Group to use this as the box?", a.Name, a.WidgetType)
log(debugGrid, "place() hack Group to use this as the box?", a.Name, a.WidgetType)
t.uiBox = newt.uiBox
} else {
t.uiBox.Append(newt.uiControl, stretchy)
@ -166,6 +168,8 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool {
t.boxC += 1
return true
case toolkit.Box:
log(logInfo, "place() uiBox =", t.uiBox)
log(logInfo, "place() uiControl =", newt.uiControl)
t.uiBox.Append(newt.uiControl, stretchy)
t.boxC += 1
return true
@ -173,7 +177,7 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool {
t.uiWindow.SetChild(newt.uiControl)
return true
default:
log(debugError, "add() how?", a.ParentId)
log(debugError, "place() how?", a.ParentId)
}
return false
}

View File

@ -24,7 +24,6 @@ func newButton(a *toolkit.Action) {
newt.uiButton = b
newt.uiControl = b
newt.wId = a.WidgetId
// newt.tw = a.Widget
newt.WidgetType = a.WidgetType
newt.parent = t

View File

@ -1,6 +1,7 @@
package main
import (
"sync"
"embed"
"git.wit.org/wit/gui/toolkit"
@ -16,14 +17,20 @@ var res embed.FS
var pluginChan chan toolkit.Action
var uiMainUndef bool = true
var uiMain sync.Once
var muAction sync.Mutex
func catchActionChannel() {
log(logNow, "catchActionChannel() START")
for {
log(logNow, "catchActionChannel() for loop")
uiMain.Do(func() {
go ui.Main(demoUI)
})
select {
case a := <-pluginChan:
log(logNow, "catchActionChannel() SELECT widget id =", a.WidgetId, a.Name)
/*
// go Action(a)
if (uiMainUndef) {
log(logError,"catchActionChannel() main() was not run yet")
@ -34,7 +41,7 @@ func catchActionChannel() {
log(logError,"catchActionChannel() ui.Main() START")
log(logError,"catchActionChannel() ui.Main() START")
sleep(1)
go ui.Main(demoUI)
// go ui.Main(demoUI)
// go ui.Main( func() {
// rawAction(a)
// })
@ -46,6 +53,12 @@ func catchActionChannel() {
rawAction(a)
log(logNow, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
}
*/
log(logNow, "catchActionChannel() STUFF", a.WidgetId, a.ActionType, a.WidgetType)
muAction.Lock()
rawAction(a)
muAction.Unlock()
log(logNow, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
}
}
}
@ -90,7 +103,7 @@ func Init() {
setDefaultBehavior(true)
andlabs = make(map[int]*andlabsT)
pluginChan = make(chan toolkit.Action)
pluginChan = make(chan toolkit.Action, 1)
log(logNow, "Init() start channel reciever")
go catchActionChannel()

View File

@ -55,7 +55,7 @@ func rawAction(a toolkit.Action) {
switch a.ActionType {
case toolkit.Add:
add(&a)
add(a)
case toolkit.Show:
a.B = true
show(&a)

View File

@ -22,6 +22,7 @@ type andlabsT struct {
// tw *toolkit.Widget
parent *andlabsT
a toolkit.Action
uiControl ui.Control

View File

@ -127,6 +127,7 @@ const (
Append
Move
Dump
Quit
)
func (s WidgetType) String() string {

View File

@ -24,10 +24,10 @@ func Watchdog() {
}
}
if (i == 2) {
LoadPlugin("gocui")
Config.rootNode.LoadToolkit("gocui")
}
// if (i == 3) {
// LoadPlugin("andlabs")
// Config.rootNode.LoadToolkit("andlabs")
// }
i += 1
time.Sleep(watchtime * time.Second / 10)