lots cleaner code between the plugin

Queue() around SetText is helping userspace crashing
    merge forceDump(bool) into Dump()
    debugging output configuration is pretty clean
    keep cutting down duplicate things
    --gui-verbose flag works
    make label "standard" code
    add debug.FreeOSMemory()
    move the GO language internals to display in the GUI
    update push to do tags and go to github.com/wit-go/
    remove the other license file
        it might be confusing golang.org and github
    proper WidgetType
    added a Quit() button

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-03-01 11:35:36 -06:00
parent 053ea69885
commit 6196739d82
48 changed files with 1344 additions and 927 deletions

View File

@ -1,8 +0,0 @@
GNU Lesser General Public License (LGPL)
I don't want it to be possible to make closed source forks of this.
If you need to use this in a proprietary GO application, then
compile this as a plugin. The BSD license is bad for core GO libraries.
(GO now supports plugins as of version 1.8)
https://medium.com/@henvic/opensource-and-go-what-license-f6b36c201854

View File

@ -19,11 +19,12 @@ deb:
-wit mirrors -wit mirrors
examples: \ examples: \
all \
cmds-buttonplugin \ cmds-buttonplugin \
cmds-console-ui-helloworld \ cmds-console-ui-helloworld \
cmds-helloworld \ cmds-helloworld \
cmds-debug \ cmds-textbox \
cmds-textbox cmds-debug
cmds-buttonplugin: cmds-buttonplugin:
make -C cmds/buttonplugin make -C cmds/buttonplugin
@ -35,20 +36,21 @@ cmds-helloworld:
make -C cmds/helloworld make -C cmds/helloworld
cmds-debug: cmds-debug:
make -C cmds/debug -make -C cmds/debug
cmds-textbox: cmds-textbox:
make -C cmds/textbox make -C cmds/textbox
# sync repo to the github backup # sync repo to the github backup
# git remote add github git@github.com:witorg/gui.git # git remote add github git@github.com:witorg/gui.git
# git remote add github2 git@github.com:wit-go/gui.git
github: github:
git push origin master git push origin master
git push github2 master
git push github2 --tags
git push github master git push github master
git push github devel
git push github jcarr
@echo @echo
@echo check https://github.com/witorg/gui @echo check https://github.com/wit-go/gui
@echo @echo
doc: doc:

View File

@ -145,41 +145,41 @@ var WARN bool
## Functions ## Functions
### func [DebugWidgetWindow](/debug_widget.go#L7)
`func DebugWidgetWindow(w *Node)`
### func [DebugWindow](/debug_window.go#L9) ### func [DebugWindow](/debug_window.go#L9)
`func DebugWindow()` `func DebugWindow()`
Creates a window helpful for debugging this package Creates a window helpful for debugging this package
### func [GetDebug](/debug.go#L20) ### func [Delete](/common.go#L66)
`func GetDebug() bool` `func Delete(c *Node)`
### func [GolangDebugWindow](/example_window_golang_debug.go#L10) ### func [Indent](/debug.go#L123)
`func GolangDebugWindow()`
### func [Indent](/debug.go#L120)
`func Indent(a ...interface{})` `func Indent(a ...interface{})`
### func [InitPlugins](/main.go#L35) ### func [InitPlugins](/main.go#L46)
`func InitPlugins(names []string)` `func InitPlugins(names []string)`
### func [LoadToolkit](/plugin.go#L53) ### func [LoadToolkit](/plugin.go#L56)
`func LoadToolkit(name string) bool` `func LoadToolkit(name string) bool`
loads and initializes a toolkit (andlabs/ui, gocui, etc) loads and initializes a toolkit (andlabs/ui, gocui, etc)
### func [Main](/main.go#L76) ### func [Main](/main.go#L87)
`func Main(f func())` `func Main(f func())`
This should not pass a function This should not pass a function
### func [Queue](/main.go#L106) ### func [Queue](/main.go#L117)
`func Queue(f func())` `func Queue(f func())`
@ -194,31 +194,25 @@ For example: gui.Queue(NewWindow())
`func SetDebug(s bool)` `func SetDebug(s bool)`
### func [SetDebugChange](/debug.go#L52) ### func [SetDebugChange](/debug.go#L58)
`func SetDebugChange(s bool)` `func SetDebugChange(s bool)`
This passes the debugChange flag to the toolkit plugin This passes the debugChange flag to the toolkit plugin
### func [SetDebugToolkit](/debug.go#L37) ### func [SetDebugToolkit](/debug.go#L43)
`func SetDebugToolkit(s bool)` `func SetDebugToolkit(s bool)`
This passes the debugToolkit flag to the toolkit plugin This passes the debugToolkit flag to the toolkit plugin
### func [ShowDebugValues](/debug.go#L66) ### func [ShowDebugValues](/debug.go#L72)
`func ShowDebugValues()` `func ShowDebugValues()`
### func [StandardClose](/main.go#L119) ### func [StandardExit](/main.go#L136)
`func StandardClose(n *Node)` `func StandardExit()`
The window is destroyed but the application does not quit
### func [StandardExit](/main.go#L125)
`func StandardExit(n *Node)`
The window is destroyed but the application does not quit The window is destroyed but the application does not quit
@ -239,7 +233,7 @@ This goroutine can be used like a watchdog timer
This struct can be used with the go-arg package This struct can be used with the go-arg package
### type [GuiConfig](/structs.go#L30) ### type [GuiConfig](/structs.go#L33)
`type GuiConfig struct { ... }` `type GuiConfig struct { ... }`
@ -249,14 +243,14 @@ This struct can be used with the go-arg package
var Config GuiConfig var Config GuiConfig
``` ```
### type [Node](/structs.go#L48) ### type [Node](/structs.go#L54)
`type Node struct { ... }` `type Node struct { ... }`
The Node is a binary tree. This is how all GUI elements are stored 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 simply the name and the size of whatever GUI element exists
#### func [NewWindow](/window.go#L14) #### func [NewWindow](/window.go#L15)
`func NewWindow() *Node` `func NewWindow() *Node`

View File

@ -1,25 +1,9 @@
package gui package gui
import "git.wit.org/wit/gui/toolkit"
func (n *Node) NewButton(name string, custom func()) *Node { func (n *Node) NewButton(name string, custom func()) *Node {
newNode := n.New(name, "Button") newNode := n.New(name, toolkit.Button, custom)
send(n, newNode)
newNode.Widget.Custom = func() {
log(debugGui, "even newer clicker() name", newNode.Widget)
if (custom != nil) {
custom()
} else {
log(debugGui, "wit/gui No callback function is defined for button name =", name)
}
}
for _, aplug := range allPlugins {
log(debugGui, "gui.NewButton() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewButton == nil) {
log(debugGui, "\tgui.NewButton() aplug.NewButton = nil", aplug.name)
continue
}
aplug.NewButton(&n.Widget, &newNode.Widget)
}
return newNode return newNode
} }

View File

@ -1,55 +1,20 @@
package gui package gui
import "git.wit.org/wit/gui/toolkit"
func (n *Node) Checked() bool { func (n *Node) Checked() bool {
n.Dump() n.Dump()
return n.checked return n.widget.B
} }
/*
This was the old code
newt.Custom = func () {
println("AM IN CALLBACK. SETTING NODE.checked START")
if newt.Checked() {
println("is checked")
c.checked = true
} else {
println("is not checked")
c.checked = false
}
commonCallback(c)
println("AM IN CALLBACK. SETTING NODE.checked END")
}
*/
func (n *Node) NewCheckbox(name string) *Node { func (n *Node) NewCheckbox(name string) *Node {
newNode := n.New(name, "Checkbox") newNode := n.New(name, toolkit.Checkbox, nil)
newNode.custom = n.custom send(n, newNode)
return newNode
newNode.Widget.Custom = func() { }
log(debugChange, "wit go gui checkbox", newNode.Widget)
if (n.custom != nil) { func (n *Node) NewThing(name string) *Node {
log(debugChange, "trying parent.custom() callback() name =", name) newNode := n.New(name, toolkit.Button, nil)
n.custom() send(n, newNode)
} else {
log(debugChange, "wit/gui No parent.custom() function is defined for button name =", name)
}
if (newNode.custom != nil) {
log(debugChange, "trying newNode.custom() callback name =", name)
newNode.custom()
} else {
log(debugChange, "wit/gui No newNode.custom() function is defined for button name =", name)
}
}
for _, aplug := range allPlugins {
log(debugGui, "gui.NewCheckbox() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewCheckbox == nil) {
log(debugGui, "\tgui.NewCheckbox() aplug.NewCheckbox = nil", aplug.name)
continue
}
aplug.NewCheckbox(&n.Widget, &newNode.Widget)
}
return newNode return newNode
} }

View File

@ -7,8 +7,8 @@
# #
run: build run: build
./buttonplugin >/tmp/buttonplugin.log 2>&1 # ./buttonplugin >/tmp/buttonplugin.log 2>&1
# ./buttonplugin ./buttonplugin
build-release: build-release:
go get -v -u -x . go get -v -u -x .

View File

@ -42,7 +42,7 @@ func main() {
log.Println("Main() END") log.Println("Main() END")
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
gui.Watchdog() gui.Watchdog()
gui.StandardExit(nil) gui.StandardExit()
} }
var counter int = 5 var counter int = 5
@ -82,7 +82,9 @@ func buttonWindow() {
}) })
g.NewButton("gui.GolangDebugWindow()", func () { g.NewButton("gui.GolangDebugWindow()", func () {
gui.GolangDebugWindow() // make a seperate window out of this
// w.GolangDebugWindow(false)
w.GolangDebugWindow(true)
}) })
g.NewButton("LoadToolkit(andlabs)", func () { g.NewButton("LoadToolkit(andlabs)", func () {

View File

@ -11,8 +11,6 @@ import (
type LogOptions struct { type LogOptions struct {
LogFile string LogFile string
Verbose bool Verbose bool
// GuiDebug bool `help:"open up the wit/gui Debugging Window"`
// GuiDemo bool `help:"open the wit/gui Demo Window"`
User string `arg:"env:USER"` User string `arg:"env:USER"`
} }
@ -45,11 +43,15 @@ func main() {
func initGUI() { func initGUI() {
var w *gui.Node var w *gui.Node
gui.Config.Title = "Hello World" gui.Config.Title = "Hello World"
gui.Config.Width = 640 gui.Config.Width = 642
gui.Config.Height = 480 gui.Config.Height = 481
gui.Config.Exit = myDefaultExit gui.Config.Exit = myDefaultExit
w = gui.NewWindow() w = gui.NewWindow()
w.Custom = func () {
log.Println("myDefaultExit(w)")
myDefaultExit(w)
}
w.Dump() w.Dump()
addDemoTab(w, "A Simple Tab Demo") addDemoTab(w, "A Simple Tab Demo")
addDemoTab(w, "A Second Tab") addDemoTab(w, "A Second Tab")
@ -57,6 +59,9 @@ func initGUI() {
if (args.GuiDebug) { if (args.GuiDebug) {
gui.DebugWindow() gui.DebugWindow()
} }
if (args.GuiVerbose) {
gui.SetDebug(true)
}
} }
func addDemoTab(window *gui.Node, title string) { func addDemoTab(window *gui.Node, title string) {
@ -71,18 +76,19 @@ func addDemoTab(window *gui.Node, title string) {
dd.AddDropdownName("more 1") dd.AddDropdownName("more 1")
dd.AddDropdownName("more 2") dd.AddDropdownName("more 2")
dd.AddDropdownName("more 3") dd.AddDropdownName("more 3")
dd.OnChanged = func(*gui.Node) {
s := dd.GetText()
tb.SetText("hello world " + args.User + "\n" + s)
}
g2 = newNode.NewGroup("group 2") g2 = newNode.NewGroup("group 2")
tb = g2.NewTextbox("tb") tb = g2.NewTextbox("tb")
log.Println("tb =", tb.GetText()) log.Println("tb =", tb.GetText())
tb.OnChanged = func(*gui.Node) { tb.Custom = func() {
s := tb.GetText() s := tb.GetText()
log.Println("text =", s) log.Println("text =", s)
} }
dd.Custom = func() {
s := dd.GetText()
log.Println("hello world " + args.User + "\n" + s + "\n")
tb.SetText("hello world " + args.User + "\n" + s + "\n")
}
} }
func myDefaultExit(n *gui.Node) { func myDefaultExit(n *gui.Node) {

View File

@ -1,17 +1,32 @@
package gui package gui
// import "errors" import (
import "regexp" "regexp"
// "errors"
// "git.wit.org/wit/gui/toolkit"
)
// functions for handling text related GUI elements // functions for handling text related GUI elements
func (n *Node) SetText(str string) bool { func (n *Node) SetText(str string) bool {
log(debugChange, "gui.SetText() value = FIXME. NOT DOING ANYTHING", str) log(debugChange, "gui.SetText() value =", str)
n.widget.Action = "Set"
n.widget.S = str
send(n.parent, n)
return true
}
func (n *Node) AppendText(str string) bool {
n.widget.Action = "Set"
tmp := n.widget.S + str
log(debugChange, "gui.AppendText() value =", tmp)
n.widget.S = tmp
send(n.parent, n)
return true return true
} }
func (n *Node) GetText() string { func (n *Node) GetText() string {
return "TODO: GetText() = {}" return n.widget.S
} }
/* /*
@ -48,19 +63,18 @@ func normalizeInt(s string) string {
return clean return clean
} }
func Delete(c *Node) {
c.widget.Action = "Delete"
send(c.parent, c)
}
func commonCallback(n *Node) { func commonCallback(n *Node) {
// TODO: make all of this common code to all the widgets // TODO: make all of this common code to all the widgets
if (n.OnChanged == nil) { // This might be common everywhere finally (2023/03/01)
log(debugChange, "Not Running n.OnChanged(n) == nil") if (n.Custom == nil) {
log(debugChange, "Not Running n.Custom(n) == nil")
} else { } else {
log(debugChange, "Running n.OnChanged(n)") log(debugChange, "Running n.Custom(n)")
n.OnChanged(n) n.Custom()
}
if (n.custom == nil) {
log(debugChange, "Not Running n.custom(n) == nil")
} else {
log(debugChange, "Running n.custom()")
n.custom()
} }
} }

View File

@ -4,8 +4,8 @@ package gui
// A function dump out the binary tree // A function dump out the binary tree
import ( import (
// "fmt" "strconv"
"reflect" "git.wit.org/wit/gui/toolkit"
) )
// various debugging flags // various debugging flags
@ -17,14 +17,20 @@ var debugChange bool = false // shows user events like mouse and keyboard
var debugPlugin bool = false var debugPlugin bool = false
var debugToolkit bool = false var debugToolkit bool = false
func GetDebug () bool { // func GetDebug () bool {
return debugGui // return debugGui
} // }
func SetDebug (s bool) { func SetDebug (s bool) {
debugGui = s debugGui = s
// debugDump = s debugChange = s
// debugNode = s debugDump = s
debugTabs = s
debugPlugin = s
debugNode = s
debugToolkit = s
SetDebugChange(s)
SetDebugToolkit(s)
} }
/* /*
@ -64,12 +70,14 @@ func SetDebugChange (s bool) {
} }
func ShowDebugValues() { func ShowDebugValues() {
// The order here should match the order in the GUI
// TODO: get the order from the node binary tree
log(true, "Debug =", debugGui) log(true, "Debug =", debugGui)
log(true, "DebugChange =", debugChange)
log(true, "DebugDump =", debugDump) log(true, "DebugDump =", debugDump)
log(true, "DebugNode =", debugNode)
log(true, "DebugTabs =", debugTabs) log(true, "DebugTabs =", debugTabs)
log(true, "DebugPlugin =", debugPlugin) log(true, "DebugPlugin =", debugPlugin)
log(true, "DebugChange =", debugChange) log(true, "DebugNode =", debugNode)
log(true, "DebugToolkit =", debugToolkit) log(true, "DebugToolkit =", debugToolkit)
// dump out the debugging flags for the plugins // dump out the debugging flags for the plugins
@ -102,14 +110,9 @@ func (n *Node) Dump() {
if (n.children != nil) { if (n.children != nil) {
Indent("children = ", n.children) Indent("children = ", n.children)
} }
if (n.custom != nil) { if (n.Custom != nil) {
Indent("custom = ", n.custom) Indent("Custom = ", n.Custom)
} }
Indent("checked = ", n.checked)
if (n.OnChanged != nil) {
Indent("OnChanged = ", n.OnChanged)
}
Indent("text = ", reflect.ValueOf(n.text).Kind(), n.text)
Indent("NODE DUMP END") Indent("NODE DUMP END")
} }
@ -124,15 +127,15 @@ func Indent(a ...interface{}) {
func (n *Node) dumpWidget() { func (n *Node) dumpWidget() {
var info string var info string
if (n.Widget.Type == "") { info = n.widget.Type.String()
n.Widget.Type = "UNDEF"
}
info = n.Widget.Type
info += ", " + n.Widget.Name info += ", " + n.widget.Name
if (n.Name != n.Widget.Name) { if (n.Name != n.widget.Name) {
info += " NAME MISMATCH" info += " NAME MISMATCH"
} }
if (n.widget.Type == toolkit.Checkbox) {
info += " = " + strconv.FormatBool(n.widget.B)
}
logindent(listChildrenDepth, defaultPadding, n.id, info) logindent(listChildrenDepth, defaultPadding, n.id, info)
} }

84
debug_flags.go Normal file
View File

@ -0,0 +1,84 @@
package gui
// Let's you toggle on and off the various types of debugging output
// These checkboxes should be in the same order as the are printed
func (n *Node) debugFlags(makeWindow bool) {
var w, g *Node
// Either:
// make a new window
// make a new tab in the existing window
if (makeWindow) {
Config.Title = "Debug Flags"
Config.Width = 300
Config.Height = 400
w = NewWindow()
w.Custom = w.StandardClose
} else {
w = n.NewTab("Debug Flags")
}
w.Dump()
g = w.NewGroup("Debug Flags")
g.NewButton("Turn on all Debug Flags", func () {
SetDebug(true)
})
g.NewButton("Turn off all Debug Flags", func () {
SetDebug(false)
})
// generally useful debugging
cb1 := g.NewCheckbox("debugGui")
cb1.Custom = func() {
debugGui = cb1.widget.B
log(debugGui, "Custom() n.widget =", cb1.widget.Name, cb1.widget.B)
}
// debugging that will show you things like mouse clicks, user inputing text, etc
// also set toolkit.DebugChange
cb2 := g.NewCheckbox("debugChange")
cb2.Custom = func() {
debugChange = cb2.widget.B
SetDebugChange(cb2.widget.B)
log(debugGui, "Custom() n.widget =", cb2.widget.Name, cb2.widget.B)
}
// supposed to tell if you are going to dump full variable output
cb3 := g.NewCheckbox("debugDump")
cb3.Custom = func() {
debugDump = cb3.widget.B
log(debugGui, "Custom() n.widget =", cb3.widget.Name, cb3.widget.B)
}
cb4 := g.NewCheckbox("debugTabs")
cb4.Custom = func() {
debugTabs = cb4.widget.B
log(debugGui, "Custom() n.widget =", cb4.widget.Name, cb4.widget.B)
}
// should show you when things go into or come back from the plugin
cb5 := g.NewCheckbox("debugPlugin")
cb5.Custom = func() {
debugPlugin = cb5.widget.B
log(debugGui, "Custom() n.widget =", cb5.widget.Name, cb5.widget.B)
}
cb6 := g.NewCheckbox("debugNode")
cb6.Custom = func() {
debugNode = cb6.widget.B
log(debugGui, "Custom() n.widget =", cb6.widget.Name, cb6.widget.B)
}
// turns on debugging inside the plugin toolkit
cb7 := g.NewCheckbox("debugToolkit")
cb7.Custom = func() {
SetDebugToolkit(cb7.widget.B)
log(debugGui, "Custom() n.widget =", cb7.widget.Name, cb7.widget.B)
}
g.NewButton("Dump Debug Flags", func () {
ShowDebugValues()
})
}

168
debug_golang.go Normal file
View File

@ -0,0 +1,168 @@
package gui
import (
"fmt"
"bytes"
// "os"
"runtime"
"runtime/debug"
"runtime/pprof"
)
func (n *Node) GolangDebugWindow(makeWindow bool) {
var w, g, og, outputTextbox *Node
// Either:
// make a new window
// make a new tab in the existing window
if (makeWindow) {
Config.Title = "GO"
Config.Width = 300
Config.Height = 400
w = NewWindow()
w.Custom = w.StandardClose
} else {
w = n.NewTab("GO")
}
w.Dump()
g = w.NewGroup("Language Internals")
g.NewButton("ReadModuleInfo()", func () {
tmp, _ := debug.ReadBuildInfo()
outputTextbox.SetText(tmp.String())
})
g.NewButton("debug.PrintStack()", func () {
outputTextbox.SetText(string(debug.Stack()))
})
g.NewButton("pprof.Lookup(goroutine)", func () {
buf := new(bytes.Buffer)
pprof.Lookup("goroutine").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("pprof.Lookup(heap)", func () {
buf := new(bytes.Buffer)
pprof.Lookup("heap").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("pprof.Lookup(block)", func () {
buf := new(bytes.Buffer)
pprof.Lookup("block").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("pprof.Lookup threadcreate", func () {
buf := new(bytes.Buffer)
pprof.Lookup("threadcreate").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("runtime.ReadMemStats()", func () {
outputTextbox.SetText(runtimeReadMemStats())
})
g.NewButton("debug.FreeOSMemory()", func () {
var out string = "Before debug.FreeOSMemory():\n\n"
out += runtimeReadMemStats()
debug.FreeOSMemory()
out += "\n\nAfter debug.FreeOSMemory():\n\n"
out += runtimeReadMemStats()
outputTextbox.SetText(out)
})
g.NewButton("debug.ReadGCStats()", func () {
var tmp debug.GCStats
var out string
debug.ReadGCStats(&tmp)
log(tmp)
out += fmt.Sprintln("LastGC:", tmp.LastGC, "// time.Time time of last collection")
out += fmt.Sprintln("NumGC:", tmp.NumGC, "// number of garbage collections")
out += fmt.Sprintln("PauseTotal:", tmp.PauseTotal, "// total pause for all collections")
out += fmt.Sprintln("Pause:", tmp.Pause, "// []time.Duration pause history, most recent first")
out += fmt.Sprintln("PauseEnd:", tmp.Pause, "// []time.Time pause history, most recent first")
out += fmt.Sprintln("PauseQuantiles:", tmp.PauseQuantiles, "// []time.Duration")
outputTextbox.SetText(out)
})
g.NewButton("debug.SetTraceback('all')", func () {
debug.SetTraceback("all")
})
g.NewButton("panic()", func () {
panic("test")
})
g.NewLabel("TODO:")
g.NewButton("debug.SetMemoryLimit(int)", func () {
// TODO:
//debug.SetMemoryLimit(1024 * 1024 * 100)
})
g.NewButton("debug.SetMaxStack(int bytes)", func () {
// default is apparently 1GB
})
g.NewButton("debug.SetMaxThreads(int)", func () {
// default is apparently 10,000
})
g.NewButton("debug.SetTraceback('all')", func () {
debug.SetTraceback("all")
})
// deprecated (probably) by String() implementation within golang
g.NewButton("dumpModuleInfo() (deprecate)", func () {
outputTextbox.SetText(dumpModuleInfo())
})
og = w.NewGroup("output")
outputTextbox = og.NewTextbox("outputBox")
outputTextbox.Custom = func () {
log("custom TextBox() for golang output a =", outputTextbox.widget.S, outputTextbox.id)
}
}
func runtimeReadMemStats() string {
var s runtime.MemStats
var out string
runtime.ReadMemStats(&s)
out += fmt.Sprintln("alloc:", s.Alloc, "bytes")
out += fmt.Sprintln("total-alloc:", s.TotalAlloc, "bytes")
out += fmt.Sprintln("sys:", s.Sys, "bytes")
out += fmt.Sprintln("lookups:", s.Lookups)
out += fmt.Sprintln("mallocs:", s.Mallocs)
out += fmt.Sprintln("frees:", s.Frees)
out += fmt.Sprintln("heap-alloc:", s.HeapAlloc, "bytes")
out += fmt.Sprintln("heap-sys:", s.HeapSys, "bytes")
out += fmt.Sprintln("heap-idle:", s.HeapIdle,"bytes")
out += fmt.Sprintln("heap-in-use:", s.HeapInuse, "bytes")
out += fmt.Sprintln("heap-released:", s.HeapReleased, "bytes")
out += fmt.Sprintln("heap-objects:", s.HeapObjects)
out += fmt.Sprintln("stack-in-use:", s.StackInuse, "bytes")
out += fmt.Sprintln("stack-sys", s.StackSys, "bytes")
out += fmt.Sprintln("next-gc: when heap-alloc >=", s.NextGC, "bytes")
out += fmt.Sprintln("last-gc:", s.LastGC, "ns")
out += fmt.Sprintln("gc-pause:", s.PauseTotalNs, "ns")
out += fmt.Sprintln("num-gc:", s.NumGC)
out += fmt.Sprintln("enable-gc:", s.EnableGC)
out += fmt.Sprintln("debug-gc:", s.DebugGC)
return out
}
func dumpModuleInfo() string {
var out string
tmp, _ := debug.ReadBuildInfo()
if tmp == nil {
out += fmt.Sprintln("This wasn't compiled with go module support")
return ""
}
out += fmt.Sprintln("mod.Path = ", tmp.Path)
out += fmt.Sprintln("mod.Main.Path = ", tmp.Main.Path)
out += fmt.Sprintln("mod.Main.Version = ", tmp.Main.Version)
out += fmt.Sprintln("mod.Main.Sum = ", tmp.Main.Sum)
for _, value := range tmp.Deps {
out += fmt.Sprintln("\tmod.Path = ", value.Path)
out += fmt.Sprintln("\tmod.Version = ", value.Version)
}
return out
}

115
debug_widget.go Normal file
View File

@ -0,0 +1,115 @@
package gui
import (
"strconv"
)
func DebugWidgetWindow(w *Node) {
var win, g *Node
title := "ID =" + strconv.Itoa(w.id) + " " + w.widget.Name
Config.Title = title
Config.Width = 300
Config.Height = 400
win = NewWindow()
win.Custom = w.StandardClose
g = win.NewGroup("Actions")
g.NewLabel(title)
g.NewButton("Dump()", func () {
w.Dump()
})
g.NewButton("Disable()", func () {
w.widget.Action = "Disable"
send(w.parent, w)
})
g.NewButton("Enable()", func () {
w.widget.Action = "Enable"
send(w.parent, w)
})
g.NewButton("Show()", func () {
w.widget.Action = "Show"
send(w.parent, w)
})
g.NewButton("Hide()", func () {
w.widget.Action = "Hide"
send(w.parent, w)
})
g.NewButton("Value()", func () {
log("w.B =", w.widget.B)
log("w.I =", w.widget.I)
log("w.S =", w.widget.S)
})
g.NewButton("Set Value(20)", func () {
w.widget.Action = "Set"
w.widget.B = true
w.widget.I = 20
w.widget.S = "Set Value(20)"
send(w.parent, w)
})
g.NewButton("Delete()", func () {
Delete(w)
})
}
func (n *Node) debugWidgets(makeWindow bool) {
var w, gList, gShow *Node
// Either:
// make a new window
// make a new tab in the existing window
if (makeWindow) {
Config.Title = "Widgets"
Config.Width = 300
Config.Height = 400
w = NewWindow()
w.Custom = w.StandardClose
} else {
w = n.NewTab("Widgets")
}
w.Dump()
gList = w.NewGroup("Pick a widget to debug")
gShow = w.NewGroup("Added Widgets go here")
gList.NewButton("Button", func () {
a := gShow.NewButton("myButton", func () {
log("this code is more better")
})
DebugWidgetWindow(a)
})
gList.NewButton("Checkbox", func () {
a := gShow.NewCheckbox("myCheckbox")
a.Custom = func () {
log("custom checkox func a =", a.widget.B, a.id)
}
DebugWidgetWindow(a)
})
gList.NewButton("Label", func () {
a := gShow.NewLabel("mylabel")
DebugWidgetWindow(a)
})
gList.NewButton("Textbox", func () {
a := gShow.NewTextbox("mytext")
a.Custom = func () {
log("custom TextBox() a =", a.widget.S, a.id)
}
DebugWidgetWindow(a)
})
gList.NewButton("Slider", func () {
a := gShow.NewSlider("tmp slider", 10, 55)
a.Custom = func () {
log("custom slider() a =", a.widget.S, a.id)
}
DebugWidgetWindow(a)
})
gList.NewButton("Spinner", func () {
a := gShow.NewSpinner("tmp spinner", 6, 32)
a.Custom = func () {
log("custom spinner() a =", a.widget.S, a.id)
}
DebugWidgetWindow(a)
})
}

View File

@ -10,88 +10,16 @@ func DebugWindow() {
Config.Title = "go.wit.org/gui debug window" Config.Title = "go.wit.org/gui debug window"
Config.Width = 300 Config.Width = 300
Config.Height = 200 Config.Height = 200
Config.Exit = StandardClose
bugWin = NewWindow() bugWin = NewWindow()
bugWin.Custom = bugWin.StandardClose
bugWin.DebugTab("Debug Tab") bugWin.DebugTab("Debug Tab")
} }
var checkd, checkdn, checkdt, checkdtk *Node var checkd, checkdn, checkdt, checkdtk, lb1, lb2 *Node
var myButton *Node
//////////////////////// debug flags //////////////////////////////////
func debugFlags(n *Node) {
var df, checkdn, checkdd, changeCheckbox *Node
df = n.NewGroup("Debug Flags")
df.NewLabel("flags to control debugging output")
cb := df.NewCheckbox("debugGui")
cb.custom = func() {
log(true, "custom ran correctly for =", n.Name)
debugGui = true
}
checkdd = df.NewCheckbox("debugDump")
checkdd.custom = func() {
log(true, "debugDump() custom ran correctly for =", n.Name)
debugDump = true
}
checkdn = df.NewCheckbox("debugNode")
checkdn.custom = func() {
log(true, "debugNode() custom ran correctly for =", n.Name)
debugNode = true
}
cb = df.NewCheckbox("debugChange")
cb.custom = func() {
log(true, "checkbox: custom() ran correctly for =", cb.Name)
log(true, "START debugChange =", debugChange)
if (debugChange) {
debugChange = false
SetDebugChange(false)
log(true, "debugToolkitChange turned off node.Name =", cb.Name)
} else {
debugChange = true
SetDebugChange(true)
log(true, "debugToolkitChange turned on Name =", cb.Name)
}
log(true, "END debugChange =", debugChange)
}
cb = df.NewCheckbox("debugTabs")
cb.custom = func() {
log(true, "debugTabs() custom ran correctly for =", n.Name)
debugTabs = true
}
cb = df.NewCheckbox("debugPlugin")
cb.custom = func() {
log(true, "debugPlugin() custom ran correctly for =", n.Name)
debugPlugin = true
}
changeCheckbox = df.NewCheckbox("debugToolkit")
changeCheckbox.custom = func() {
SetDebugToolkit(true)
}
df.NewButton("Debug Toolkit", func() {
if (debugToolkit) {
SetDebugToolkit(false)
log(true, "debugToolkit turned off node.Name =", n.Name)
} else {
SetDebugToolkit(true)
log(true, "debugToolkit turned on Name =", n.Name)
}
})
df.NewButton("Dump Debug Flags", func () {
ShowDebugValues()
})
}
func (n *Node) DebugTab(title string) *Node { func (n *Node) DebugTab(title string) *Node {
var newN, gog, g1, g2, g3, dd *Node var newN, gog, g1, g2, g3, dd, junk, newThing *Node
// time.Sleep(1 * time.Second) // time.Sleep(1 * time.Second)
newN = n.NewTab(title) newN = n.NewTab(title)
@ -101,7 +29,13 @@ func (n *Node) DebugTab(title string) *Node {
gog = newN.NewGroup("GOLANG") gog = newN.NewGroup("GOLANG")
gog.NewLabel("go language") gog.NewLabel("go language")
gog.NewButton("GO Language Debug", func () { gog.NewButton("GO Language Debug", func () {
GolangDebugWindow() newN.GolangDebugWindow(false)
})
gog.NewButton("Debug Flags", func () {
newN.debugFlags(false)
})
gog.NewButton("Debug Widgets", func () {
newN.debugWidgets(false)
}) })
gog.NewLabel("wit/gui package") gog.NewLabel("wit/gui package")
@ -109,11 +43,21 @@ func (n *Node) DebugTab(title string) *Node {
// DemoToolkitWindow() // DemoToolkitWindow()
}) })
debugFlags(newN) junk = gog.NewButton("junk", func () {
log("click junk, get junk")
})
gog.NewLabel("tmp label")
//////////////////////// window debugging things ////////////////////////////////// //////////////////////// window debugging things //////////////////////////////////
g1 = newN.NewGroup("Current Windows") g1 = newN.NewGroup("Current Windows")
dd = g1.NewDropdown("Window Dropdown") dd = g1.NewDropdown("Window Dropdown")
dd.Custom = func() {
name := dd.widget.S
bugWin = mapWindows[name]
log("The Window was set to", name)
}
log(debugGui, "dd =", dd) log(debugGui, "dd =", dd)
// initialize the windows map if it hasn't been // initialize the windows map if it hasn't been
@ -122,6 +66,7 @@ func (n *Node) DebugTab(title string) *Node {
} }
var dump = false var dump = false
var last = ""
for _, child := range Config.master.children { for _, child := range Config.master.children {
log(debugGui, "\t\t", child.id, child.Width, child.Height, child.Name) log(debugGui, "\t\t", child.id, child.Width, child.Height, child.Name)
if (child.parent != nil) { if (child.parent != nil) {
@ -134,16 +79,44 @@ func (n *Node) DebugTab(title string) *Node {
child.Dump() child.Dump()
} }
dd.AddDropdownName(child.Name) dd.AddDropdownName(child.Name)
last = child.Name
mapWindows[child.Name] = child mapWindows[child.Name] = child
} }
dd.SetDropdownName(last)
dd.SetDropdown(0) dd.NewButton("Delete(junk)", func () {
Delete(junk)
})
dd.NewButton("myButton", func () {
gog.NewButton("myButton", func () {
log("this code is better")
})
})
dd.NewButton("add Hope", func () {
var i int = 1
log("add hope?", i)
gog.NewButton("hope", func () {
i += 1
log("write better code", i)
})
})
dd.NewButton("add newThing", func () {
var i, j int = 1, 1
newThing = gog.NewThing("NewThing")
newThing.Custom = func() {
f := i + j
log("newThing!!! n.widget =", newThing.widget.Name, newThing.widget.B, f)
j = i
i = f
}
log("newThing!!! n.widget")
})
g2 = newN.NewGroup("Debug Window") g2 = newN.NewGroup("Debug Window")
g2.NewButton("SetMargined(tab)", func () { g2.NewButton("SetMargined(tab)", func () {
log(debugChange, "START SetMargined(tab)", g2.Name) log(debugChange, "START SetMargined(tab)", g2.Name)
// name := dd.GetText() // name := dd.GetText()
name := dd.Widget.S name := dd.widget.S
log(true, "name =", name)
log(debugChange, "name =", name) log(debugChange, "name =", name)
log(debugChange, "mapWindows[name] =", mapWindows[name]) log(debugChange, "mapWindows[name] =", mapWindows[name])
/* /*
@ -154,7 +127,7 @@ func (n *Node) DebugTab(title string) *Node {
} }
*/ */
bugWin = mapWindows[name] bugWin = mapWindows[name]
log(debugChange, "END dd.Widget.S =", dd.Widget.S) log(debugChange, "END dd.widget.S =", dd.widget.S)
// gw.UiTab.SetMargined(*gw.TabNumber, true) // gw.UiTab.SetMargined(*gw.TabNumber, true)
}) })
g2.NewButton("Hide(tab)", func () { g2.NewButton("Hide(tab)", func () {
@ -170,6 +143,9 @@ func (n *Node) DebugTab(title string) *Node {
g2.NewButton("change Title", func () { g2.NewButton("change Title", func () {
// mainWindow.SetText("hello world") // mainWindow.SetText("hello world")
}) })
g2.NewButton("Quit", func () {
exit()
})
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
g3 = newN.NewGroup("Node Debug") g3 = newN.NewGroup("Node Debug")

View File

@ -1,53 +1,46 @@
package gui package gui
import (
"git.wit.org/wit/gui/toolkit"
)
// add a new entry to the dropdown name
func (n *Node) AddDropdownName(name string) { func (n *Node) AddDropdownName(name string) {
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(debugGui, "gui.AddDropdownName() aplug =", aplug.name, "name =", name) log(debugPlugin, "AddDropdownName() aplug =", aplug.name, "name =", name)
if (aplug.AddDropdownName == nil) { if (aplug.AddDropdownName == nil) {
log(debugGui, "\tgui.AddDropdownName() aplug.NewDropdown = nil", aplug.name) log(debugPlugin, "\taplug.AddDropdownName() = nil")
continue continue
} }
aplug.AddDropdownName(&n.Widget, name) aplug.AddDropdownName(&n.widget, name)
} }
if (n.Widget.Custom == nil) {
n.SetDropdownChange( func() {
log(debugChange, "gui.Dropdown change() REAL Custom() name =", name)
log(debugChange, "gui.Dropdown change() REAL n.Widget.S =", n.Widget.S)
})
}
// TODO, this makes functions over and over for each dropdown menu
/*
n.Widget.Custom = func() {
log(debugChange, "gui.Dropdown change() START Custom() name =", name)
log(debugChange, "gui.Dropdown change() START n.Widget.S =", n.Widget.S)
}
*/
} }
func (n *Node) SetDropdown(s any) { // Set the dropdown menu to 'name'
log(debugGui, "gui.SetDropdown() TODO: make this work. s =", s) func (n *Node) SetDropdownName(name string) {
} log(debugGui, "SetDropdownName() work. name =", name)
for _, aplug := range allPlugins {
func (n *Node) SetDropdownChange(f func()) { log(debugPlugin, "SetDropdownName() aplug =", aplug.name, "name =", name)
n.Widget.Custom = f if (aplug.SetDropdownName == nil) {
log(true, "\taplug.SetDropdownName() aplug = nil")
continue
}
aplug.SetDropdownName(&n.widget, name)
}
} }
func (n *Node) NewDropdown(name string) *Node { func (n *Node) NewDropdown(name string) *Node {
newNode := n.New(name, "Dropdown") newNode := n.New(name, toolkit.Dropdown, nil)
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(debugGui, "gui.NewDropdown() aplug =", aplug.name, "name =", newNode.Widget.Name) log(debugGui, "gui.NewDropdown() aplug =", aplug.name, "name =", newNode.widget.Name)
if (aplug.NewDropdown == nil) { if (aplug.NewDropdown == nil) {
log(debugGui, "\tgui.NewDropdown() aplug.NewDropdown = nil", aplug.name) log(debugGui, "\tgui.NewDropdown() aplug.NewDropdown = nil", aplug.name)
continue continue
} }
aplug.NewDropdown(&n.Widget, &newNode.Widget) aplug.NewDropdown(&n.widget, &newNode.widget)
} }
// TODO, this doesn't work for some reason (over-written by plugin?) // TODO, this doesn't work for some reason (over-written by plugin?)
newNode.Widget.Custom = func() {
log(true, "gui.NewDropdown() START Custom()")
}
return newNode return newNode
} }

View File

@ -1,104 +0,0 @@
package gui
import (
"os"
"runtime"
"runtime/debug"
"runtime/pprof"
)
func GolangDebugWindow() {
var w, t *Node
Config.Title = "Go Language Debug Window"
Config.Width = 400
Config.Height = 400
Config.Exit = StandardClose
w = NewWindow()
t = w.NewTab("Debug Tab")
log("debugWindow() START")
/////////////////////////////// Column DEBUG GOLANG //////////////////////
g := t.NewGroup("GO Language")
g.NewButton("runtime.Stack()", func () {
log("\tSTART")
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
log("\t %s", buf)
log("\tEND")
})
g.NewButton("dumpModuleInfo()", func () {
log("\tSTART")
dumpModuleInfo()
log("\tEND")
})
g.NewButton("debug.PrintStack()", func () {
log("\tSTART")
debug.PrintStack()
log("\tEND")
})
g.NewButton("pprof.Lookup(goroutine)", func () {
log("\tSTART")
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
log("\tEND")
})
g.NewButton("pprof.Lookup(heap)", func () {
log("\tSTART")
pprof.Lookup("heap").WriteTo(os.Stdout, 1)
log("\tEND")
})
g.NewButton("pprof.Lookup(block)", func () {
log("\tSTART")
pprof.Lookup("block").WriteTo(os.Stdout, 1)
log("\tEND")
})
g.NewButton("pprof.Lookup threadcreate", func () {
log("\tSTART")
pprof.Lookup("threadcreate").WriteTo(os.Stdout, 1)
log("\tEND")
})
g.NewButton("runtime.ReadMemStats", func () {
var s runtime.MemStats
runtime.ReadMemStats(&s)
log("alloc: %v bytes\n", s.Alloc)
log("total-alloc: %v bytes\n", s.TotalAlloc)
log("sys: %v bytes\n", s.Sys)
log("lookups: %v\n", s.Lookups)
log("mallocs: %v\n", s.Mallocs)
log("frees: %v\n", s.Frees)
log("heap-alloc: %v bytes\n", s.HeapAlloc)
log("heap-sys: %v bytes\n", s.HeapSys)
log("heap-idle: %v bytes\n", s.HeapIdle)
log("heap-in-use: %v bytes\n", s.HeapInuse)
log("heap-released: %v bytes\n", s.HeapReleased)
log("heap-objects: %v\n", s.HeapObjects)
log("stack-in-use: %v bytes\n", s.StackInuse)
log("stack-sys: %v bytes\n", s.StackSys)
log("next-gc: when heap-alloc >= %v bytes\n", s.NextGC)
log("last-gc: %v ns\n", s.LastGC)
log("gc-pause: %v ns\n", s.PauseTotalNs)
log("num-gc: %v\n", s.NumGC)
log("enable-gc: %v\n", s.EnableGC)
log("debug-gc: %v\n", s.DebugGC)
})
}
func dumpModuleInfo() {
tmp, _ := debug.ReadBuildInfo()
if tmp == nil {
log("This wasn't compiled with go module support")
return
}
log("mod.Path = ", tmp.Path)
log("mod.Main.Path = ", tmp.Main.Path)
log("mod.Main.Version = ", tmp.Main.Version)
log("mod.Main.Sum = ", tmp.Main.Sum)
for _, value := range tmp.Deps {
log("\tmod.Path = ", value.Path)
log("\tmod.Version = ", value.Version)
}
}

View File

@ -1,22 +1,14 @@
package gui package gui
import (
"git.wit.org/wit/gui/toolkit"
)
// TODO: which name is better. AddGroup or NewGroup ? // TODO: which name is better. AddGroup or NewGroup ?
// first reaction is NewGroup // first reaction is NewGroup
func (n *Node) NewGroup(name string) *Node { func (n *Node) NewGroup(name string) *Node {
var newNode *Node var newNode *Node
newNode = n.New(name, "Group") newNode = n.New(name, toolkit.Group, nil)
send(n, newNode)
log(debugGui, "toolkit.NewGroup() START", name)
log(debugGui, "gui.Node.NewGroup()", name)
for _, aplug := range allPlugins {
log(debugGui, "gui.Node.NewGroup() toolkit plugin =", aplug.name)
if (aplug.NewGroup == nil) {
continue
}
aplug.NewGroup(&n.Widget, &newNode.Widget)
}
return newNode return newNode
} }

View File

@ -1,19 +1,14 @@
package gui package gui
// import "errors" import (
// import "regexp" "git.wit.org/wit/gui/toolkit"
)
func (n *Node) NewLabel(text string) *Node { func (n *Node) NewLabel(text string) *Node {
newNode := n.New(text, "Label") newNode := n.New(text, toolkit.Label, func() {
log(debugChange, "TextBox changed", text)
for _, aplug := range allPlugins { })
log(debugGui, "gui.NewLabel() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewLabel == nil) {
log(debugGui, "\tgui.NewLabel() aplug.NewLabel = nil", aplug.name)
continue
}
aplug.NewLabel(&n.Widget, &newNode.Widget)
}
send(n, newNode)
return newNode return newNode
} }

5
log.go
View File

@ -98,8 +98,9 @@ func log(a ...any) {
if (a == nil) { if (a == nil) {
return return
} }
var blah bool
if (reflect.TypeOf(a[0]) == reflect.TypeOf(blah)) { var tbool bool
if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) {
// golog.Println("\t a[0] = bool") // golog.Println("\t a[0] = bool")
if (a[0] == false) { if (a[0] == false) {
return return

43
main.go
View File

@ -16,20 +16,31 @@ const Yaxis = 1 // stack things vertically
var res embed.FS var res embed.FS
func init() { func init() {
debugGui = true log("init() has been run")
log(debugGui, "gui.init() has been run")
Config.counter = 0 Config.counter = 0
Config.prefix = "wit" Config.prefix = "wit"
Config.Width = 640
title := "guiBinaryTree" Config.Height = 480
w := 640
h := 480
// Populates the top of the binary tree // Populates the top of the binary tree
Config.master = addNode(title, w, h) Config.master = addNode("guiBinaryTree")
// Config.master.Dump()
debugGui = false go doGuiChan()
}
func doGuiChan() {
for {
select {
case <-Config.ActionCh1:
log(true, "CHANNEL ACTION 1 !!!!!")
return
case <-Config.ActionCh2:
log(true, "CHANNEL ACTION 2 !!!!!")
return
default:
}
}
} }
func InitPlugins(names []string) { func InitPlugins(names []string) {
@ -116,21 +127,21 @@ func Queue(f func()) {
} }
// The window is destroyed but the application does not quit // The window is destroyed but the application does not quit
func StandardClose(n *Node) { func (n *Node) StandardClose() {
log(debugGui, "wit/gui Standard Window Close. name =", n.Name) log(debugGui, "wit/gui Standard Window Close. name =", n.Name)
log(debugGui, "wit/gui Standard Window Close. n.custom exit =", n.custom) log(debugGui, "wit/gui Standard Window Close. n.Custom exit =", n.Custom)
} }
// The window is destroyed but the application does not quit // The window is destroyed but the application does not quit
func StandardExit(n *Node) { func StandardExit() {
log(debugGui, "wit/gui Standard Window Exit. running os.Exit()") log("wit/gui Standard Window Exit. running os.Exit()")
log(debugGui, "gui.Node.StandardExit() attempt to exit each toolkit plugin") log("gui.Node.StandardExit() attempt to exit each toolkit plugin")
for i, aplug := range allPlugins { for i, aplug := range allPlugins {
log(debugGui, "gui.Node.NewButton()", i, aplug) log("gui.Node.NewButton()", i, aplug)
if (aplug.Quit != nil) { if (aplug.Quit != nil) {
aplug.Quit() aplug.Quit()
} }
} }
exit("StandardExit") exit(0)
} }

37
node.go
View File

@ -1,15 +1,30 @@
package gui package gui
// import "git.wit.org/wit/gui/toolkit" import "git.wit.org/wit/gui/toolkit"
/* /*
generic function to create a new node on the binary tree generic function to create a new node on the binary tree
*/ */
func (n *Node) New(title string, t string) *Node { func (n *Node) New(title string, t toolkit.WidgetType, custom func()) *Node {
var newN *Node var newN *Node
newN = addNode(title, n.Width, n.Height) newN = addNode(title)
newN.Widget.Type = t newN.widget.Type = t
newN.widget.Action = "New"
newN.Custom = custom
// TODO: This should not be defined for each widget. This has to be stupid
// or wait a second, is this where I send something to a channel?
newN.widget.Custom = func() {
if (newN.Custom == nil) {
log(debugChange, "newT.Custom() == nil. Not doing anything. SEND SOMETHING TO THE CHANNEL")
return
}
log(debugChange, "newT.Custom() START SEND SOMETHING TO THE CHANNEL widget.Name =", newN.widget.Name)
// send something to the channel here????
newN.Custom()
log(debugChange, "newT.Custom() END SEND SOMETHING TO THE CHANNEL widget.Name =", newN.widget.Name)
}
n.Append(newN) n.Append(newN)
newN.parent = n newN.parent = n
@ -19,20 +34,10 @@ func (n *Node) New(title string, t string) *Node {
/* /*
raw create function for a new node struct raw create function for a new node struct
*/ */
func addNode(title string, width int, height int) *Node { func addNode(title string) *Node {
n := new(Node) n := new(Node)
n.Name = title n.Name = title
n.Width = width n.widget.Name = title
n.Height = height
n.Widget.Name = title
n.Widget.Width = width
n.Widget.Height = height
// no longer a string
// id := Config.prefix + strconv.Itoa(Config.counter)
// n.id = id
n.id = Config.counter n.id = Config.counter
Config.counter += 1 Config.counter += 1

View File

@ -26,21 +26,24 @@ type aplug struct {
MainOk bool MainOk bool
Init func() Init func()
Main func(func ()) // TODO: make Main() main() and never allow the user to call it
Queue func(func ()) // run plugin.Main() when the plugin is loaded
Main func(func ()) // this never returns. Each plugin must have it's own goroutine
Queue func(func ()) // Should this return right away? Should it wait (can it wait?)
Quit func() Quit func()
NewWindow func(*toolkit.Widget) // NewWindow func(*toolkit.Widget)
// simplifies passing to the plugin
Send func(*toolkit.Widget, *toolkit.Widget)
NewButton func(*toolkit.Widget, *toolkit.Widget) NewButton func(*toolkit.Widget, *toolkit.Widget)
NewGroup func(*toolkit.Widget, *toolkit.Widget) NewGroup func(*toolkit.Widget, *toolkit.Widget)
NewCheckbox func(*toolkit.Widget, *toolkit.Widget) NewCheckbox func(*toolkit.Widget, *toolkit.Widget)
NewTab 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) NewDropdown func(*toolkit.Widget, *toolkit.Widget)
AddDropdownName func(*toolkit.Widget, string) AddDropdownName func(*toolkit.Widget, string)
SetDropdownName func(*toolkit.Widget, string)
SetDebugToolkit func(bool) SetDebugToolkit func(bool)
SetDebugChange func(bool) SetDebugChange func(bool)
@ -73,27 +76,27 @@ func LoadToolkit(name string) bool {
// newPlug.Ok = true // newPlug.Ok = true
newPlug.name = name newPlug.name = name
// map all the functions // deprecate Init(?)
newPlug.Init = loadFuncE(&newPlug, "Init") newPlug.Init = loadFuncE(&newPlug, "Init")
newPlug.Quit = loadFuncE(&newPlug, "Quit")
// this should be laodFuncE() // 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") newPlug.Queue = loadFuncF(&newPlug, "Queue")
newPlug.NewWindow = loadFunc1(&newPlug, "NewWindow") // unload the plugin and restore state
newPlug.Quit = loadFuncE(&newPlug, "Quit")
newPlug.NewButton = loadFunc2(&newPlug, "NewButton") // Sends a widget (button, checkbox, etc) and it's parent widget
newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup") // This includes instructions like "Add", "Delete", "Disable", etc
newPlug.NewCheckbox = loadFunc2(&newPlug, "NewCheckbox") newPlug.Send = loadFunc2(&newPlug, "Send")
newPlug.NewTab = loadFunc2(&newPlug, "NewTab")
newPlug.NewLabel = loadFunc2(&newPlug, "NewLabel") // newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup")
newPlug.NewTextbox = loadFunc2(&newPlug, "NewTextbox")
newPlug.NewSlider = loadFunc2(&newPlug, "NewSlider")
newPlug.NewSpinner = loadFunc2(&newPlug, "NewSpinner")
newPlug.NewDropdown = loadFunc2(&newPlug, "NewDropdown") newPlug.NewDropdown = loadFunc2(&newPlug, "NewDropdown")
newPlug.AddDropdownName = loadFuncS(&newPlug, "AddDropdownName") newPlug.AddDropdownName = loadFuncS(&newPlug, "AddDropdownName")
newPlug.SetDropdownName = loadFuncS(&newPlug, "SetDropdownName")
newPlug.SetDebugToolkit = loadFuncB(&newPlug, "SetDebugToolkit") newPlug.SetDebugToolkit = loadFuncB(&newPlug, "SetDebugToolkit")
newPlug.SetDebugChange = loadFuncB(&newPlug, "SetDebugChange") newPlug.SetDebugChange = loadFuncB(&newPlug, "SetDebugChange")
@ -275,3 +278,16 @@ func loadfile(filename string) *plugin.Plugin {
log(debugGui, "plugin WORKED =", filename) log(debugGui, "plugin WORKED =", filename)
return plug return plug
} }
// Sends a widget and what to do with it to the plugin
// parent = n, child = c
func send(p *Node, c *Node) {
for _, aplug := range allPlugins {
log(debugPlugin, "Send() aplug =", aplug.name, "name =", c.widget.Name)
if (aplug.Send == nil) {
log(debugPlugin, "\tSend() failed (aplug.Selete = nil) for", aplug.name)
continue
}
aplug.Send(&c.parent.widget, &c.widget)
}
}

View File

@ -1,22 +1,16 @@
package gui package gui
import (
"git.wit.org/wit/gui/toolkit"
)
func (n *Node) NewSlider(name string, x int, y int) *Node { func (n *Node) NewSlider(name string, x int, y int) *Node {
newNode := n.New(name, "Slider") newNode := n.New(name, toolkit.Slider, func() {
newNode.Widget.X = x log(debugGui, "even newer clicker() name in NewSlider name =", name)
newNode.Widget.Y = y })
newNode.widget.X = x
newNode.Widget.Custom = func() { newNode.widget.Y = y
log(debugGui, "even newer clicker() name in NewSlider", newNode.Widget)
}
for _, aplug := range allPlugins {
log(debugGui, "gui.NewSlider() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewSlider == nil) {
log(debugGui, "\tgui.NewSlider() aplug.NewSlider = nil", aplug.name)
continue
}
aplug.NewSlider(&n.Widget, &newNode.Widget)
}
send(n, newNode)
return newNode return newNode
} }

View File

@ -1,22 +1,16 @@
package gui package gui
import (
"git.wit.org/wit/gui/toolkit"
)
func (n *Node) NewSpinner(name string, x int, y int) *Node { func (n *Node) NewSpinner(name string, x int, y int) *Node {
newNode := n.New(name, "Spinner") newNode := n.New(name, toolkit.Spinner, func() {
newNode.Widget.X = x log(debugGui, "even newer clicker() name in NewSpinner name =", name)
newNode.Widget.Y = y })
newNode.widget.X = x
newNode.Widget.Custom = func() { newNode.widget.Y = y
log(debugGui, "even newer clicker() name in NewSpinner", newNode.Widget)
}
for _, aplug := range allPlugins {
log(debugGui, "gui.NewSpinner() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewSpinner == nil) {
log(debugGui, "\tgui.NewSpinner() aplug.NewSpinner = nil", aplug.name)
continue
}
aplug.NewSpinner(&n.Widget, &newNode.Widget)
}
send(n, newNode)
return newNode return newNode
} }

View File

@ -25,8 +25,11 @@ var Config GuiConfig
type GuiArgs struct { type GuiArgs struct {
Toolkit []string `arg:"--toolkit" help:"The order to attempt loading plugins [gocui,andlabs,gtk,qt]"` Toolkit []string `arg:"--toolkit" help:"The order to attempt loading plugins [gocui,andlabs,gtk,qt]"`
GuiDebug bool `arg:"--gui-debug" help:"debug the GUI"` GuiDebug bool `arg:"--gui-debug" help:"debug the GUI"`
GuiVerbose bool `arg:"--gui-verbose" help:"enable all GUI flags"`
} }
// var verbose GuiArgs.GuiDebug
type GuiConfig struct { type GuiConfig struct {
// This is the master node. The Binary Tree starts here // This is the master node. The Binary Tree starts here
master *Node master *Node
@ -41,6 +44,9 @@ type GuiConfig struct {
depth int depth int
counter int // used to make unique ID's counter int // used to make unique ID's
prefix string prefix string
ActionCh1 chan int
ActionCh2 chan int
} }
// The Node is a binary tree. This is how all GUI elements are stored // The Node is a binary tree. This is how all GUI elements are stored
@ -48,7 +54,7 @@ type GuiConfig struct {
type Node struct { type Node struct {
id int id int
Widget toolkit.Widget widget toolkit.Widget
// deprecate these and use toolkit.Widget // deprecate these and use toolkit.Widget
Name string Name string
@ -56,16 +62,15 @@ type Node struct {
Height int Height int
// this function is run when there are mouse or keyboard events // this function is run when there are mouse or keyboard events
OnChanged func(*Node) Custom func()
parent *Node parent *Node
children []*Node children []*Node
// is keeping // is keeping
// deprecate these things if they don't really need to exist // deprecate these things if they don't really need to exist
custom func() // checked bool
checked bool // text string
text string
} }
func (n *Node) Parent() *Node { func (n *Node) Parent() *Node {

13
tab.go
View File

@ -1,22 +1,15 @@
package gui package gui
import ( import (
"git.wit.org/wit/gui/toolkit"
) )
// This function should make a new node with the parent and // This function should make a new node with the parent and
// the 'tab' as a child // the 'tab' as a child
func (n *Node) NewTab(text string) *Node { func (n *Node) NewTab(text string) *Node {
newNode := n.New(text, "Tab") newNode := n.New(text, toolkit.Tab, nil)
for _, aplug := range allPlugins {
log(debugGui, "gui.NewTab() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewTab == nil) {
log(debugGui, "\tgui.NewTab() aplug.NewTab = nil", aplug.name)
continue
}
aplug.NewTab(&n.Widget, &newNode.Widget)
}
send(n, newNode)
return newNode return newNode
} }

View File

@ -1,20 +1,14 @@
package gui package gui
import (
"git.wit.org/wit/gui/toolkit"
)
func (n *Node) NewTextbox(name string) *Node { func (n *Node) NewTextbox(name string) *Node {
newNode := n.New(name, "Textbox") newNode := n.New(name, toolkit.Textbox, func() {
log(debugGui, "wit/gui clicker()NewTextBox BUT IS EMPTY. FIXME name =", name)
newNode.Widget.Custom = func() { })
log(debugGui, "wit/gui clicker()NewTextBox BUT IS EMPTY. FIXME", newNode.Widget)
}
for _, aplug := range allPlugins {
log(debugGui, "gui.NewTextbox() aplug =", aplug.name, "name =", newNode.Widget.Name)
if (aplug.NewTextbox == nil) {
log(debugGui, "\tgui.NewTextbox() aplug.NewTextbox = nil", aplug.name)
continue
}
aplug.NewTextbox(&n.Widget, &newNode.Widget)
}
send(n, newNode)
return newNode return newNode
} }

View File

@ -11,7 +11,7 @@ func (t *andlabsT) GetBox() *ui.Box {
// create a new box // create a new box
func (t *andlabsT) NewBox() *andlabsT { func (t *andlabsT) NewBox() *andlabsT {
log(debugToolkit, "gui.Toolbox.NewBox() START create default") log(debugToolkit, "gui.Toolbox.NewBox() START create default")
t.Dump() t.Dump(debugToolkit)
if (t.uiGroup != nil) { if (t.uiGroup != nil) {
log(debugToolkit, "\tgui.Toolbox.NewBox() is a Group") log(debugToolkit, "\tgui.Toolbox.NewBox() is a Group")
var newTK andlabsT var newTK andlabsT
@ -49,6 +49,6 @@ func (t *andlabsT) NewBox() *andlabsT {
return &newT return &newT
} }
log(debugToolkit, "\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box") log(debugToolkit, "\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box")
t.Dump() t.Dump(debugToolkit)
return nil return nil
} }

View File

@ -7,7 +7,7 @@ import (
"git.wit.org/wit/gui/toolkit" "git.wit.org/wit/gui/toolkit"
) )
func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) { func newButton(parentW *toolkit.Widget, w *toolkit.Widget) {
var t, newt *andlabsT var t, newt *andlabsT
var b *ui.Button var b *ui.Button
log(debugToolkit, "gui.andlabs.NewButton()", w.Name) log(debugToolkit, "gui.andlabs.NewButton()", w.Name)
@ -25,19 +25,11 @@ func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) {
b = ui.NewButton(w.Name) b = ui.NewButton(w.Name)
newt.uiButton = b newt.uiButton = b
newt.tw = w
newt.parent = t
b.OnClicked(func(*ui.Button) { b.OnClicked(func(*ui.Button) {
log(debugChange, "TODO: SHOULD LEAVE Button click HERE VIA channels. button name =", w.Name) newt.commonChange(newt.tw)
log(debugChange, "FOUND WIDGET =", w)
if (w.Custom == nil) {
log(debugChange, "WIDGET DOES NOT have Custom()")
log(debugChange, "TODO: NOTHING TO DO button name =", w.Name)
return
}
// t.Dump()
// newt.Dump()
log(debugChange, "Running w.Custom()")
w.Custom()
}) })
log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box parent t:", w.Name) log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box parent t:", w.Name)
@ -55,3 +47,41 @@ func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) {
mapWidgetsToolkits(w, newt) mapWidgetsToolkits(w, newt)
} }
func doButton(p *toolkit.Widget, c *toolkit.Widget) {
if broken(c) {
return
}
if (c.Action == "New") {
newButton(p, c)
return
}
ct := mapToolkits[c]
if (ct == nil) {
log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c)
return
}
if ct.broken() {
log(true, "Button() ct.broken", ct)
return
}
if (ct.uiButton == nil) {
log(true, "Button() uiButton == nil", ct)
return
}
log(true, "Going to attempt:", c.Action)
switch c.Action {
case "Enable":
ct.uiButton.Enable()
case "Disable":
ct.uiButton.Disable()
case "Show":
ct.uiButton.Show()
case "Hide":
ct.uiButton.Hide()
case "Set":
ct.uiButton.SetText(c.S)
default:
log(true, "Can't do", c.Action, "to a Button")
}
}

View File

@ -1,36 +1,29 @@
package main package main
import "git.wit.org/wit/gui/toolkit" import (
"git.wit.org/wit/gui/toolkit"
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
)
import "github.com/andlabs/ui" func (t andlabsT) NewCheckbox(w *toolkit.Widget) *andlabsT {
import _ "github.com/andlabs/ui/winmanifest" log(debugToolkit, "NewCheckbox()", w.Name, w.Type)
func (t andlabsT) NewCheckbox(name string, f func()) *andlabsT {
log(debugToolkit, "gui.Toolkit.NewCheckbox()", name)
var newt andlabsT var newt andlabsT
newt.tw = w
if t.broken() { if t.broken() {
return nil return nil
} }
c := ui.NewCheckbox(name) c := ui.NewCheckbox(w.Name)
newt.uiCheckbox = c newt.uiCheckbox = c
newt.uiBox = t.uiBox newt.uiBox = t.uiBox
t.uiBox.Append(c, stretchy) t.uiBox.Append(c, stretchy)
// newt.Custom = f
c.OnToggled(func(spin *ui.Checkbox) { c.OnToggled(func(spin *ui.Checkbox) {
// log(debugToolkit, "gui.Toolkit.NewCheckbox() clicked", name) newt.tw.B = newt.Checked()
newt.commonChange("Checkbox") log(debugChange, "val =", newt.tw.B)
/* newt.commonChange(newt.tw)
if (f != nil) {
log(debugToolkit, "Run custom() here", f)
log(SPEW, f)
f()
} else {
log(debugToolkit, "No custom() function here")
}
*/
}) })
return &newt return &newt
@ -45,25 +38,52 @@ func (t andlabsT) Checked() bool {
} }
func NewCheckbox(parentW *toolkit.Widget, w *toolkit.Widget) { func NewCheckbox(parentW *toolkit.Widget, w *toolkit.Widget) {
log(debugToolkit, "gui.andlabs.NewCheckbox()", w.Name) log(debugToolkit, "NewCheckbox()", w.Name)
t := mapToolkits[parentW] t := mapToolkits[parentW]
if (t == nil) { if (t == nil) {
listMap() listMap(debugError)
return
} }
newt := t.NewCheckbox(w.Name, w.Custom) newt := t.NewCheckbox(w)
newt.Custom = w.Custom
/*
if (w.Custom != nil) {
log(true, "go.andlabs.NewCheckbox() toolkit struct == nil. name=", parentW.Name, w.Name)
log(true, "Run custom() START here", w.Custom)
w.Custom()
log(true, "Run custom() END")
// exit("ran it here")
} else {
log(true, "No custom() function here")
// exit("nothing here")
}
*/
mapWidgetsToolkits(w, newt) mapWidgetsToolkits(w, newt)
} }
func doCheckbox(p *toolkit.Widget, c *toolkit.Widget) {
if broken(c) {
return
}
if (c.Action == "New") {
NewCheckbox(p, c)
return
}
ct := mapToolkits[c]
if (ct == nil) {
log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c)
return
}
if ct.broken() {
log(true, "checkbox() ct.broken", ct)
return
}
if (ct.uiCheckbox == nil) {
log(true, "checkbox() uiCheckbox == nil", ct)
return
}
log(true, "Going to attempt:", c.Action)
switch c.Action {
case "Enable":
ct.uiCheckbox.Enable()
case "Disable":
ct.uiCheckbox.Disable()
case "Show":
ct.uiCheckbox.Show()
case "Hide":
ct.uiCheckbox.Hide()
case "Set":
ct.uiCheckbox.SetText(c.S)
ct.uiCheckbox.SetChecked(c.B)
default:
log(true, "Can't do", c.Action, "to a checkbox")
}
}

View File

@ -1,5 +1,9 @@
package main package main
import (
"git.wit.org/wit/gui/toolkit"
)
// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc // This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
func init() { func init() {
// Can you pass values to a plugin init() ? Otherwise, there is no way to safely print // Can you pass values to a plugin init() ? Otherwise, there is no way to safely print
@ -7,79 +11,52 @@ func init() {
setDefaultBehavior(true) setDefaultBehavior(true)
} }
func (t andlabsT) commonChange(widget string) { func (t andlabsT) commonChange(tw *toolkit.Widget) {
s := t.String() log(debugChange, "commonChange() START widget =", t.Name, t.Type)
log(debugChange, "commonChange() START widget =", widget) if (tw == nil) {
log(debugChange, "commonChange() t.String =", s) log(true, "commonChange() What the fuck. there is no widget t.tw == nil")
if (t.OnChanged != nil) {
// log(debugChange, "commonChange() toolkit.OnChanged() START")
// t.OnChanged(&t)
exit("OnChanged is not implemented. TODO: FIX THIS")
return return
} }
if (t.Custom != nil) { if (tw.Custom == nil) {
log(debugChange, "commonChange() START toolkit.Custom()") log(debugChange, "commonChange() END Widget.Custom() = nil", t.tw.Name, t.tw.Type)
t.Custom()
log(debugChange, "commonChange() END toolkit.Custom()")
return return
} }
if (widget == "Checkbox") { tw.Custom()
log(debugChange, "commonChange() END Need to read the Checkbox value") log(debugChange, "commonChange() END Widget.Custom()", t.tw.Name, t.tw.Type)
return
}
if (widget == "Dropdown") {
t.getDropdown()
if (t.tw == nil) {
log(debugChange, "commonChange() END tw.Custom == nil")
}
if (t.tw.Custom == nil) {
log(debugChange, "commonChange() END Dropdown (no custom())")
}
t.tw.Custom()
log(debugChange, "commonChange() END Dropdown")
return
}
log(debugChange, "commonChange() t.String =", s)
log(debugChange, "commonChange() ENDED without finding any callback")
}
func (t *andlabsT) getDropdown() {
log(debugChange, "commonChange() Need to read the dropdown menu")
if (t.uiCombobox == nil) {
log(debugChange, "commonChange() END BAD NEWS. t.uiCombobox == nil")
return
}
i := t.uiCombobox.Selected()
log(debugChange, "commonChange() t.uiCombobox = ", i)
if (t.tw == nil) {
log(debugChange, "commonChange() END tw = nil")
return
}
t.tw.S = t.String()
log(debugChange, "commonChange() END tw = ", t.tw)
return
} }
// does some sanity checks on the internal structs of the binary tree // does some sanity checks on the internal structs of the binary tree
// TODO: probably this should not panic unless it's running in devel mode (?) // TODO: probably this should not panic unless it's running in devel mode (?)
// TODO: redo this now that WidgetType is used and send() is used to package plugins
func (t *andlabsT) broken() bool { func (t *andlabsT) broken() bool {
if (t.parent != nil) {
return false
}
if (t.uiBox == nil) { if (t.uiBox == nil) {
if (t.uiWindow != nil) { if (t.uiWindow != nil) {
log(debugToolkit, "gui.Toolkit.UiBox == nil. This is an empty window. Try to add a box") log(debugToolkit, "UiBox == nil. This is an empty window. Try to add a box")
t.NewBox() t.NewBox()
return false return false
} }
log(debugToolkit, "gui.Toolkit.UiBox == nil. I can't add a widget without a place to put it") log(true, "UiBox == nil. I can't add a widget without a place to put it")
// log(debugToolkit, "probably could just make a box here?") // log(debugToolkit, "probably could just make a box here?")
// corruption or something horrible? // corruption or something horrible?
t.Dump(true)
panic("wit/gui toolkit/andlabs func broken() invalid goroutine access into this toolkit?") panic("wit/gui toolkit/andlabs func broken() invalid goroutine access into this toolkit?")
panic("wit/gui toolkit/andlabs func broken() this probably should not cause the app to panic here (?)") panic("wit/gui toolkit/andlabs func broken() this probably should not cause the app to panic here (?)")
return true return true
} }
if (t.uiWindow == nil) { if (t.uiWindow == nil) {
log(debugToolkit, "gui.Toolkit.UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)") log(debugToolkit, "UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)")
forceDump(t) t.Dump(debugToolkit)
return false return false
} }
return false return false
} }
func broken(w *toolkit.Widget) bool {
if (w == nil) {
log(true, "widget == nil. I can't do anything widget")
return true
}
return false
}

View File

@ -1,6 +1,6 @@
package main package main
// import "git.wit.org/wit/gui/toolkit" import "git.wit.org/wit/gui/toolkit"
import "github.com/davecgh/go-spew/spew" import "github.com/davecgh/go-spew/spew"
@ -15,6 +15,8 @@ var margin bool // add space around the frames of windows
var debugToolkit bool var debugToolkit bool
var debugChange bool var debugChange bool
var debugPlugin bool
var debugError bool = true
// var DebugToolkit bool // var DebugToolkit bool
// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc // This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
@ -59,42 +61,35 @@ func (t *andlabsT) String() string {
return t.GetText() return t.GetText()
} }
func forceDump(t *andlabsT) {
tmp := debugToolkit
debugToolkit = true
t.Dump()
debugToolkit = tmp
}
func (t *andlabsT) GetText() string { func (t *andlabsT) GetText() string {
log(debugToolkit, "gui.Toolkit.GetText() Enter debugToolkit=", debugToolkit) log(debugToolkit, "GetText() Enter debugToolkit=", debugToolkit)
if (t.uiEntry != nil) { if (t.uiEntry != nil) {
log(debugToolkit, "gui.Toolkit.uiEntry.Text() =", t.uiEntry.Text()) log(debugToolkit, "uiEntry.Text() =", t.uiEntry.Text())
return t.uiEntry.Text() return t.uiEntry.Text()
} }
if (t.uiMultilineEntry != nil) { if (t.uiMultilineEntry != nil) {
log(debugToolkit, "gui.Toolkit.uiMultilineEntry.Text() =", t.uiMultilineEntry.Text()) log(debugToolkit, "uiMultilineEntry.Text() =", t.uiMultilineEntry.Text())
text := t.uiMultilineEntry.Text() text := t.uiMultilineEntry.Text()
log(debugToolkit, "gui.Toolkit.uiMultilineEntry.Text() =", text) log(debugToolkit, "uiMultilineEntry.Text() =", text)
t.text = text t.text = text
return text return text
} }
if (t.uiCombobox != nil) { if (t.uiCombobox != nil) {
log(debugToolkit, "gui.Toolkit.uiCombobox() =", t.text) log(debugToolkit, "uiCombobox() =", t.text)
return t.text return t.text
} }
return "" return ""
} }
func (t *andlabsT) SetText(s string) bool { func (t *andlabsT) SetText(s string) bool {
log(debugToolkit, "gui.Toolkit.Text() SetText() Enter") log(debugToolkit, "Text() SetText() Enter")
if (t.uiEntry != nil) { if (t.uiEntry != nil) {
log(debugToolkit, "gui.Toolkit.Value() =", t.uiEntry.Text) log(debugToolkit, "Value() =", t.uiEntry.Text)
t.uiEntry.SetText(s) t.uiEntry.SetText(s)
return true return true
} }
if (t.uiMultilineEntry != nil) { if (t.uiMultilineEntry != nil) {
log(debugToolkit, "gui.Toolkit.Value() =", t.uiMultilineEntry.Text) log(debugToolkit, "Value() =", t.uiMultilineEntry.Text)
t.uiMultilineEntry.SetText(s) t.uiMultilineEntry.SetText(s)
return true return true
} }
@ -103,91 +98,101 @@ func (t *andlabsT) SetText(s string) bool {
func sanity(t *andlabsT) bool { func sanity(t *andlabsT) bool {
if (debugToolkit) { if (debugToolkit) {
log(debugToolkit, "gui.Toolkit.Value() Enter") log(debugToolkit, "Value() Enter")
scs := spew.ConfigState{MaxDepth: 1} scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(t) scs.Dump(t)
} }
if (t.uiEntry == nil) { if (t.uiEntry == nil) {
log(debugToolkit, "gui.Toolkit.Value() =", t.uiEntry.Text) log(debugToolkit, "Value() =", t.uiEntry.Text)
return false return false
} }
return true return true
} }
func (t *andlabsT) SetValue(i int) bool { func (t *andlabsT) SetValue(i int) bool {
log(debugToolkit, "gui.Toolkit.SetValue() START") log(debugToolkit, "SetValue() START")
if (sanity(t)) { if (sanity(t)) {
return false return false
} }
t.Dump() t.Dump(debugToolkit)
// panic("got to toolkit.SetValue") // panic("got to toolkit.SetValue")
return true return true
} }
func (t *andlabsT) Value() int { func (t *andlabsT) Value() int {
if (debugToolkit) { if (debugToolkit) {
log(debugToolkit, "gui.Toolkit.Value() Enter") log(debugToolkit, "Value() Enter")
scs := spew.ConfigState{MaxDepth: 1} scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(t) scs.Dump(t)
} }
if (t == nil) { if (t == nil) {
log(debugToolkit, "gui.Toolkit.Value() can not get value t == nil") log(debugToolkit, "Value() can not get value t == nil")
return 0 return 0
} }
if (t.uiSlider != nil) { if (t.uiSlider != nil) {
log(debugToolkit, "gui.Toolkit.Value() =", t.uiSlider.Value) log(debugToolkit, "Value() =", t.uiSlider.Value)
return t.uiSlider.Value() return t.uiSlider.Value()
} }
if (t.uiSpinbox != nil) { if (t.uiSpinbox != nil) {
log(debugToolkit, "gui.Toolkit.Value() =", t.uiSpinbox.Value) log(debugToolkit, "Value() =", t.uiSpinbox.Value)
return t.uiSpinbox.Value() return t.uiSpinbox.Value()
} }
log(debugToolkit, "gui.Toolkit.Value() Could not find a ui element to get a value from") log(debugToolkit, "Value() Could not find a ui element to get a value from")
return 0 return 0
} }
func (t *andlabsT) Dump() { func (t *andlabsT) Dump(b bool) {
if ! debugToolkit { if ! b {
return return
} }
log(debugToolkit, "gui.Toolkit.Dump() Name = ", t.Name, t.Width, t.Height) log(b, "Name = ", t.Name, t.Width, t.Height)
if (t.uiBox != nil) { if (t.uiBox != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiBox =", t.uiBox) log(b, "uiBox =", t.uiBox)
} }
if (t.uiButton != nil) { if (t.uiButton != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiButton =", t.uiButton) log(b, "uiButton =", t.uiButton)
} }
if (t.uiCombobox != nil) { if (t.uiCombobox != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiCombobox =", t.uiCombobox) log(b, "uiCombobox =", t.uiCombobox)
} }
if (t.uiWindow != nil) { if (t.uiWindow != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiWindow =", t.uiWindow) log(b, "uiWindow =", t.uiWindow)
} }
if (t.uiTab != nil) { if (t.uiTab != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiTab =", t.uiTab) log(b, "uiTab =", t.uiTab)
} }
if (t.uiGroup != nil) { if (t.uiGroup != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiGroup =", t.uiGroup) log(b, "uiGroup =", t.uiGroup)
} }
if (t.uiEntry != nil) { if (t.uiEntry != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiEntry =", t.uiEntry) log(b, "uiEntry =", t.uiEntry)
} }
if (t.uiMultilineEntry != nil) { if (t.uiMultilineEntry != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiMultilineEntry =", t.uiMultilineEntry) log(b, "uiMultilineEntry =", t.uiMultilineEntry)
} }
if (t.uiSlider != nil) { if (t.uiSlider != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiSlider =", t.uiSlider) log(b, "uiSlider =", t.uiSlider)
} }
if (t.uiCheckbox != nil) { if (t.uiCheckbox != nil) {
log(debugToolkit, "gui.Toolkit.Dump() uiCheckbox =", t.uiCheckbox) log(b, "uiCheckbox =", t.uiCheckbox)
} }
if (t.OnExit != nil) { widgetDump(b, t.tw)
log(debugToolkit, "gui.Toolkit.Dump() OnExit =", t.OnExit) }
}
if (t.Custom != nil) { func widgetDump(b bool, w *toolkit.Widget) {
log(debugToolkit, "gui.Toolkit.Dump() Custom =", t.Custom) if (w == nil) {
} log(b, "widget = nil")
log(debugToolkit, "gui.Toolkit.Dump() c =", t.c) return
log(debugToolkit, "gui.Toolkit.Dump() val =", t.val) }
log(debugToolkit, "gui.Toolkit.Dump() text =", t.text)
log(b, "widget.Name =", w.Name)
log(b, "widget.Action =", w.Action)
log(b, "widget.Type =", w.Type)
log(b, "widget.Custom =", w.Custom)
log(b, "widget.B =", w.B)
log(b, "widget.I =", w.I)
log(b, "widget.Width =", w.Width)
log(b, "widget.Height =", w.Height)
log(b, "widget.X =", w.X)
log(b, "widget.Y =", w.Y)
} }

View File

@ -1,20 +1,20 @@
package main package main
import "github.com/andlabs/ui" import (
import _ "github.com/andlabs/ui/winmanifest" "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
"git.wit.org/wit/gui/toolkit"
)
import "git.wit.org/wit/gui/toolkit" func (t *andlabsT) NewDropdown(w *toolkit.Widget) *andlabsT {
func (t *andlabsT) NewDropdown(title string) *andlabsT {
// make new node here
var newt andlabsT var newt andlabsT
log(debugToolkit, "gui.Toolbox.NewDropdown() START", w.Name)
log(debugToolkit, "gui.Toolbox.NewDropdownCombobox()", title)
if t.broken() { if t.broken() {
return nil return nil
} }
newt.tw = w
s := ui.NewCombobox() s := ui.NewCombobox()
newt.uiCombobox = s newt.uiCombobox = s
newt.uiBox = t.uiBox newt.uiBox = t.uiBox
@ -27,11 +27,11 @@ func (t *andlabsT) NewDropdown(title string) *andlabsT {
s.OnSelected(func(spin *ui.Combobox) { s.OnSelected(func(spin *ui.Combobox) {
i := spin.Selected() i := spin.Selected()
if (newt.val == nil) { if (newt.val == nil) {
log(debugToolkit, "make map didn't work") log(debugChange, "make map didn't work")
newt.text = "error" newt.text = "error"
} }
newt.text = newt.val[i] newt.tw.S = newt.val[i]
newt.commonChange("Dropdown") newt.commonChange(newt.tw)
}) })
return &newt return &newt
@ -44,6 +44,12 @@ func (t *andlabsT) AddDropdownName(title string) {
return return
} }
t.val[t.c] = title t.val[t.c] = title
// If this is the first menu added, set the dropdown to it
if (t.c == 0) {
log(debugChange, "THIS IS THE FIRST Dropdown", title)
t.uiCombobox.SetSelected(1)
}
t.c = t.c + 1 t.c = t.c + 1
} }
@ -57,11 +63,10 @@ func NewDropdown(parentW *toolkit.Widget, w *toolkit.Widget) {
t := mapToolkits[parentW] t := mapToolkits[parentW]
if (t == nil) { if (t == nil) {
log(debugToolkit, "go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) log(debugToolkit, "go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name)
listMap() listMap(debugToolkit)
return
} }
newt := t.NewDropdown(w.Name) newt := t.NewDropdown(w)
newt.Custom = w.Custom
newt.tw = w
mapWidgetsToolkits(w, newt) mapWidgetsToolkits(w, newt)
} }
@ -71,18 +76,21 @@ func AddDropdownName(w *toolkit.Widget, s string) {
t := mapToolkits[w] t := mapToolkits[w]
if (t == nil) { if (t == nil) {
log(debugToolkit, "go.andlabs.AddDropdownName() toolkit struct == nil. name=", w.Name, s) log(debugToolkit, "go.andlabs.AddDropdownName() toolkit struct == nil. name=", w.Name, s)
listMap() listMap(debugToolkit)
return
} }
t.AddDropdownName(s) t.AddDropdownName(s)
} }
func SetDropdown(w *toolkit.Widget, i int) { func SetDropdownName(w *toolkit.Widget, s string) {
log(debugToolkit, "gui.andlabs.SetDropdown()", i) log(debugChange, "gui.andlabs.SetDropdown()", w.Name, ",", s)
t := mapToolkits[w] t := mapToolkits[w]
if (t == nil) { if (t == nil) {
log(debugToolkit, "go.andlabs.SetDropdown() toolkit struct == nil. name=", w.Name, i) log(debugError, "ERROR: SetDropdown() FAILED mapToolkits[w] == nil. name=", w.Name, s)
listMap() listMap(debugError)
return
} }
t.SetDropdown(i) t.SetDropdown(1)
t.tw.S = s
} }

View File

@ -7,13 +7,13 @@ import (
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
) )
func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) { func newGroup(parentW *toolkit.Widget, w *toolkit.Widget) {
log(debugToolkit, "gui.andlabs.NewGroup()", w.Name) log(debugToolkit, "gui.andlabs.NewGroup()", w.Name)
t := mapToolkits[parentW] t := mapToolkits[parentW]
if (t == nil) { if (t == nil) {
log(debugToolkit, "go.andlabs.NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name) log(debugToolkit, "go.andlabs.NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name)
listMap() listMap(debugToolkit)
} }
newt := t.NewGroup(w.Name) newt := t.NewGroup(w.Name)
mapWidgetsToolkits(w, newt) mapWidgetsToolkits(w, newt)
@ -23,18 +23,23 @@ func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) {
func (t andlabsT) NewGroup(title string) *andlabsT { func (t andlabsT) NewGroup(title string) *andlabsT {
var newt andlabsT var newt andlabsT
log(debugToolkit, "gui.Toolbox.NewGroup() create", title) log(debugToolkit, "NewGroup() create", title)
g := ui.NewGroup(title) g := ui.NewGroup(title)
g.SetMargined(margin) g.SetMargined(margin)
if (t.uiBox != nil) { if (t.uiBox != nil) {
// TODO: temporary hack to make the output textbox 'fullscreen'
if (title == "output") {
t.uiBox.Append(g, true)
} else {
t.uiBox.Append(g, stretchy) t.uiBox.Append(g, stretchy)
}
} else if (t.uiWindow != nil) { } else if (t.uiWindow != nil) {
t.uiWindow.SetChild(g) t.uiWindow.SetChild(g)
} else { } else {
log(debugToolkit, "gui.ToolboxNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it") log(debugError, "NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
log(debugToolkit, "probably could just make a box here?") log(debugError, "probably could just make a box here?")
exit("internal wit/gui error") exit("internal wit/gui error")
} }
@ -47,8 +52,5 @@ func (t andlabsT) NewGroup(title string) *andlabsT {
newt.uiWindow = t.uiWindow newt.uiWindow = t.uiWindow
newt.Name = title newt.Name = title
t.Dump()
newt.Dump()
// panic("toolkit.NewGroup")
return &newt return &newt
} }

View File

@ -7,66 +7,74 @@ import (
"git.wit.org/wit/gui/toolkit" "git.wit.org/wit/gui/toolkit"
) )
var pwLabel *toolkit.Widget func newLabel(parentW *toolkit.Widget, w *toolkit.Widget) {
var wLabel *toolkit.Widget var newt *andlabsT
var tmpNewt *andlabsT log(debugToolkit, "NewLabel()", w.Name)
func NewLabel(parentW *toolkit.Widget, w *toolkit.Widget) {
pwLabel = parentW
wLabel = w
tmpNewt = new(andlabsT)
tmpNewt.Width = 10
log(debugToolkit, "mapWidgets in ui.QueueMain() START newt =", tmpNewt.Width, tmpNewt)
if (tmpNewt == nil) {
log(debugToolkit, "mapWidgets WHY THE HELL IS THIS NIL?", tmpNewt.Width, tmpNewt)
}
ui.QueueMain(newLabel)
log(true, "sleep(.2) HACK. TODO: wrap spinlock around andlabs.ui goroutine")
// log(true, "sleep(.2) HACK. TODO: verify newLabel() is running inside andlabs/ui goroutine") // verified that worked
sleep(.2)
log(debugToolkit, "mapWidgets parentW/wLabel =", pwLabel)
log(debugToolkit, "mapWidgets new/newt =", tmpNewt)
mapWidgetsToolkits(w, tmpNewt)
/*
t := mapToolkits[parentW] t := mapToolkits[parentW]
if (t == nil) { if (t == nil) {
log(debugToolkit, "go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) listMap(debugError)
listMap() log(debugError, "ERROR newLabel() listMap()")
} log(debugError, "ERROR FFFFFFFFFFFF listMap()")
newt := t.NewDropdown(w.Name) log(debugError, "ERROR FFFFFFFFFFFF listMap()")
mapWidgetsToolkits(w, newt)
*/
}
func newLabel() {
var t, newt *andlabsT
log(debugToolkit, "gui.andlabs.NewButton()", wLabel.Name)
t = mapToolkits[pwLabel]
if (t == nil) {
log(debugToolkit, "go.andlabs.NewButton() toolkit struct == nil. name=", pwLabel.Name, wLabel.Name)
return return
} }
log(debugToolkit, "NewLabel()", w.Name)
if t.broken() { if t.broken() {
return return
} }
newt = tmpNewt
newt.uiLabel = ui.NewLabel(wLabel.Name) newt = new(andlabsT)
c := ui.NewLabel(w.Name + " FIX")
newt.uiLabel = c
newt.uiBox = t.uiBox newt.uiBox = t.uiBox
newt.tw = w
if (defaultBehavior) {
t.uiBox.Append(c, stretchy)
}
log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box parent t:", wLabel.Name) mapWidgetsToolkits(w, newt)
t.Dump() }
log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box new t:", wLabel.Name)
newt.Dump()
if (t.uiBox != nil) {
t.uiBox.Append(newt.uiLabel, false) func doLabel(p *toolkit.Widget, c *toolkit.Widget) {
} else { if broken(c) {
log(debugToolkit, "ERROR: wit/gui andlabs couldn't place this label in a box")
return return
} }
if (c.Action == "New") {
newLabel(p, c)
return
}
ct := mapToolkits[c]
if (ct == nil) {
log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c)
return
}
if ct.broken() {
log(true, "Label() ct.broken", ct)
return
}
if (ct.uiLabel == nil) {
log(true, "Label() uiLabel == nil", ct)
return
}
log(true, "Going to attempt:", c.Action)
switch c.Action {
case "Enable":
ct.uiLabel.Enable()
case "Disable":
ct.uiLabel.Disable()
case "Show":
ct.uiLabel.Show()
case "Hide":
ct.uiLabel.Hide()
case "Set":
ct.uiLabel.SetText(c.S)
default:
log(true, "Can't do", c.Action, "to a Label")
}
} }

View File

@ -98,9 +98,8 @@ func log(a ...any) {
if (a == nil) { if (a == nil) {
return return
} }
var blah bool var tbool bool
if (reflect.TypeOf(a[0]) == reflect.TypeOf(blah)) { if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) {
// golog.Println("\t a[0] = bool")
if (a[0] == false) { if (a[0] == false) {
return return
} }
@ -111,7 +110,9 @@ func log(a ...any) {
// a = a[1:] // a = a[1:]
a[0] = "WIT/GUI/Toolkit" a[0] = "WIT/GUI/Toolkit"
if (debugToolkit) { if (debugToolkit) {
spew.Dump(a) scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(a)
// spew.Dump(a)
} }
return return
} }

View File

@ -32,20 +32,19 @@ func Main(f func()) {
// For example: Queue(NewWindow()) // For example: Queue(NewWindow())
// //
func Queue(f func()) { func Queue(f func()) {
log(debugToolkit, "Sending function to ui.QueueMain() (using gtk via andlabs/ui)") log(debugToolkit, "Sending function to ui.QueueMain()")
log("THIS MIGHT BREAK") log(true, "THIS DOES BREAK. TODO: wrap this")
ui.QueueMain(f) ui.QueueMain(f)
// f() // f()
} }
func Init() { func Init() {
log(debugToolkit, "should Init() here") log(debugToolkit, "Init()")
mapWidgets = make(map[*andlabsT]*toolkit.Widget) mapWidgets = make(map[*andlabsT]*toolkit.Widget)
mapToolkits = make(map[*toolkit.Widget]*andlabsT) mapToolkits = make(map[*toolkit.Widget]*andlabsT)
} }
func Quit() { func Quit() {
log(debugToolkit, "should Quit() here") log(debugToolkit, "Quit() TODO: close the toolkit cleanly")
// myExit(nil)
} }

View File

@ -1,49 +1,104 @@
package main package main
import ( // if you include more than just this import
"git.wit.org/wit/gui/toolkit" // then your plugin might be doing something un-ideal (just a guess from 2023/02/27)
) import "git.wit.org/wit/gui/toolkit"
// This is a map between the widgets in wit/gui and the internal structures of gocui // import "github.com/andlabs/ui"
// import _ "github.com/andlabs/ui/winmanifest"
var mapWidgets map[*andlabsT]*toolkit.Widget //
var mapToolkits map[*toolkit.Widget]*andlabsT // This should be called ?
// Pass() ?
// This lists out the know mappings // This handles all interaction between the wit/gui package (what golang knows about)
func listMap() { // and this plugin that talks to the OS and does scary and crazy things to make
log(debugToolkit, "listMap() HERE") // a GUI on whatever OS or whatever GUI toolkit you might have (GTK, QT, WASM, libcurses)
log(debugToolkit, "listMap() HERE") //
log(debugToolkit, "listMap() HERE mapWidgets()") // Once you are here, you should be in a protected goroutine created by the golang wit/gui package
for t, w := range mapWidgets { //
log(debugToolkit, "andlabs =", t.Name, "widget =", w.Name) // TODO: make sure you can't escape this goroutine
//
func Send(p *toolkit.Widget, c *toolkit.Widget) {
if (p == nil) {
log(debugPlugin, "Send() parent = nil")
} else {
log(debugPlugin, "Send() parent =", p.Name, ",", p.Type)
} }
log(debugToolkit, "listMap() HERE mapToolkits()") log(debugPlugin, "Send() child =", c.Name, ",", c.Action, ",", c.Type)
for w, t := range mapToolkits {
log(debugToolkit, "andlabs =", t, "widget =", w.Name) switch c.Type {
forceDump(t) case toolkit.Window:
newWindow(c)
case toolkit.Tab:
newTab(p, c)
case toolkit.Group:
newGroup(p, c)
case toolkit.Button:
doButton(p, c)
case toolkit.Checkbox:
doCheckbox(p, c)
case toolkit.Label:
newLabel(p, c)
case toolkit.Textbox:
doTextbox(p, c)
case toolkit.Slider:
newSlider(p, c)
case toolkit.Spinner:
newSpinner(p, c)
default:
log(true, "unknown parent =", p.Name, p.Type)
log(true, "unknown child =", c.Name, c.Type)
log(true, "Don't know how to do", c.Type, "yet")
} }
} }
func mapWidgetsToolkits(w *toolkit.Widget, t *andlabsT) { // delete the child widget from the parent
if (mapToolkits[w] == nil) { // p = parent, c = child
mapToolkits[w] = t func destroy(p *toolkit.Widget, c *toolkit.Widget) {
} else { log(true, "delete()", c.Name, c.Type)
log(debugToolkit, "WTF: mapToolkits was sent nil. this should not happen w =", w)
log(debugToolkit, "WTF: mapToolkits was sent nil. this should not happen t =", t.Width) pt := mapToolkits[p]
log(debugToolkit, "WTF: mapToolkits map already set to ", mapToolkits[w]) ct := mapToolkits[c]
panic("WTF mapWidgetsToolkits() w == nil") if (ct == nil) {
log(true, "delete FAILED (ct = mapToolkit[c] == nil) for c", c.Name, c.Type)
// this pukes out a whole universe of shit
// listMap()
return
} }
if (mapWidgets[t] == nil) { switch ct.Type {
mapWidgets[t] = w case toolkit.Button:
log(true, "Should delete Button here:", c.Name)
log(true, "Parent:")
pt.Dump(true)
log(true, "Child:")
ct.Dump(true)
if (pt.uiBox == nil) {
log(true, "Don't know how to destroy this")
} else { } else {
log(debugToolkit, "WTF: mapWidgets already installed. w =", w) log(true, "Fuck it, destroy the whole box", pt.Name)
log(debugToolkit, "WTF: mapWidgets already installed. t =", t.Width, t) // pt.uiBox.Destroy() // You have a bug: You cannot destroy a uiControl while it still has a parent.
log(SPEW, &t) pt.uiBox.SetPadded(false)
log(SPEW, t) pt.uiBox.Delete(4)
log(SPEW, *t) ct.uiButton.Disable()
log(debugToolkit, "WTF: mapWidgets already mapped to", mapWidgets[t]) // ct.uiButton.Hide()
log(SPEW, mapWidgets[t]) ct.uiButton.Destroy()
panic("WTF. mapWidget andlabs toolkit already mapped to gui toolkit") }
case toolkit.Window:
log(true, "Should delete Window here:", c.Name)
default:
log(true, "Don't know how to delete c =", c.Type, c.Name)
log(true, "Don't know how to delete pt =", pt.Type, pt.Name, pt.uiButton)
log(true, "Don't know how to delete ct =", ct.Type, ct.Name, ct.uiButton)
log(true, "Parent:")
pt.Dump(true)
log(true, "Child:")
ct.Dump(true)
log(true, "Fuckit, let's destroy a button", c.Name, c.Type)
if (ct.uiButton != nil) {
pt.uiBox.Delete(4)
ct.uiButton.Destroy()
}
} }
} }

View File

@ -7,31 +7,32 @@ import (
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
) )
func (t andlabsT) NewSlider(title string, x int, y int) *andlabsT { func (t andlabsT) newSlider(w *toolkit.Widget) *andlabsT {
// make new node here // make new node here
log(debugToolkit, "gui.Toolkit.NewSpinbox()", x, y) log(debugToolkit, w.Name, w.Type, w.X, w.Y)
var newt andlabsT var newt andlabsT
if (t.uiBox == nil) { if (t.uiBox == nil) {
log(debugToolkit, "gui.ToolkitNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it") log(debugToolkit, "node.UiBox == nil. I can't add a range UI element without a place to put it")
log(debugToolkit, "probably could just make a box here?") log(debugToolkit, "probably could just make a box here?")
exit("internal golang wit/gui/toolkit error") exit("internal golang wit/gui/toolkit error")
return nil return nil
} }
s := ui.NewSlider(x, y) s := ui.NewSlider(w.X, w.Y)
newt.uiSlider = s newt.uiSlider = s
newt.uiBox = t.uiBox newt.uiBox = t.uiBox
newt.tw = w
t.uiBox.Append(s, stretchy) t.uiBox.Append(s, stretchy)
s.OnChanged(func(spin *ui.Slider) { s.OnChanged(func(spin *ui.Slider) {
newt.commonChange("Slider") newt.commonChange(newt.tw)
}) })
return &newt return &newt
} }
func NewSlider(parentW *toolkit.Widget, w *toolkit.Widget) { func newSlider(parentW *toolkit.Widget, w *toolkit.Widget) {
var newt *andlabsT var newt *andlabsT
log(debugToolkit, "gui.andlabs.NewTab()", w.Name) log(debugToolkit, "gui.andlabs.NewTab()", w.Name)
@ -40,6 +41,6 @@ func NewSlider(parentW *toolkit.Widget, w *toolkit.Widget) {
log(debugToolkit, "go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name) log(debugToolkit, "go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name)
return return
} }
newt = t.NewSlider(w.Name, w.X, w.Y) newt = t.newSlider(w)
mapWidgetsToolkits(w, newt) mapWidgetsToolkits(w, newt)
} }

View File

@ -1,27 +1,43 @@
package main package main
import "github.com/andlabs/ui" import (
import _ "github.com/andlabs/ui/winmanifest" "git.wit.org/wit/gui/toolkit"
func (t andlabsT) NewSpinner(title string, x int, y int) *andlabsT { "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
)
func (t andlabsT) newSpinner(w *toolkit.Widget) *andlabsT {
// make new node here // make new node here
log(debugToolkit, "gui.Toolkit.NewSpinner()", x, y) log(debugToolkit, "newSpinner()", w.X, w.Y)
var newt andlabsT var newt andlabsT
if (t.uiBox == nil) { if (t.uiBox == nil) {
log(debugToolkit, "gui.ToolkitNode.NewSpinner() node.UiBox == nil. I can't add a range UI element without a place to put it") log(debugToolkit, "newSpinner() node.UiBox == nil. I can't add a range UI element without a place to put it")
exit("internal golang wit/gui error")
return nil return nil
} }
s := ui.NewSpinbox(x, y) s := ui.NewSpinbox(w.X, w.Y)
newt.uiSpinbox = s newt.uiSpinbox = s
newt.uiBox = t.uiBox newt.uiBox = t.uiBox
newt.tw = w
t.uiBox.Append(s, stretchy) t.uiBox.Append(s, stretchy)
s.OnChanged(func(s *ui.Spinbox) { s.OnChanged(func(s *ui.Spinbox) {
newt.commonChange("Spinner") newt.commonChange(newt.tw)
}) })
return &newt return &newt
} }
func newSpinner(parentW *toolkit.Widget, w *toolkit.Widget) {
var newt *andlabsT
t := mapToolkits[parentW]
if (t == nil) {
log(debugToolkit, "go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name)
return
}
newt = t.newSpinner(w)
mapWidgetsToolkits(w, newt)
}

View File

@ -10,31 +10,27 @@ type andlabsT struct {
id string id string
Name string Name string
Type toolkit.WidgetType
Width int Width int
Height int Height int
tw *toolkit.Widget tw *toolkit.Widget
parent *andlabsT
OnChanged func(*andlabsT)
OnExit func(*andlabsT)
Custom func()
uiBox *ui.Box uiBox *ui.Box
uiBox2 *ui.Box // temporary hack while implementing tabs
uiButton *ui.Button uiButton *ui.Button
uiControl *ui.Control uiControl *ui.Control
uiCombobox *ui.Combobox uiCombobox *ui.Combobox
uiCheckbox *ui.Checkbox uiCheckbox *ui.Checkbox
uiEntry *ui.Entry uiEntry *ui.Entry
uiMultilineEntry *ui.MultilineEntry
uiGroup *ui.Group uiGroup *ui.Group
uiLabel *ui.Label uiLabel *ui.Label
uiSlider *ui.Slider uiSlider *ui.Slider
uiSpinbox *ui.Spinbox uiSpinbox *ui.Spinbox
uiTab *ui.Tab uiTab *ui.Tab
uiText *ui.EditableCombobox
uiWindow *ui.Window uiWindow *ui.Window
UiWindowBad *ui.Window // UiWindowBad *ui.Window // erase this
uiMultilineEntry *ui.MultilineEntry
uiEditableCombobox *ui.EditableCombobox
// used as a counter to work around limitations of widgets like combobox // used as a counter to work around limitations of widgets like combobox
// this is probably fucked up and in many ways wrong because of unsafe goroutine threading // this is probably fucked up and in many ways wrong because of unsafe goroutine threading

View File

@ -33,7 +33,7 @@ func (t *andlabsT) newTab(name string) *andlabsT {
if (t.uiTab == nil) { if (t.uiTab == nil) {
// this means you have to make a new tab // this means you have to make a new tab
log(debugToolkit, "gui.toolkit.NewTab() GOOD. This should be the first tab:", name) log(debugToolkit, "gui.toolkit.NewTab() GOOD. This should be the first tab:", name)
newt = newTab(t.uiWindow, name) newt = rawTab(t.uiWindow, name)
t.uiTab = newt.uiTab t.uiTab = newt.uiTab
} else { } else {
// this means you have to append a tab // this means you have to append a tab
@ -44,9 +44,9 @@ func (t *andlabsT) newTab(name string) *andlabsT {
newt.Name = name newt.Name = name
log(debugToolkit, "t:") log(debugToolkit, "t:")
t.Dump() t.Dump(debugToolkit)
log(debugToolkit, "newt:") log(debugToolkit, "newt:")
newt.Dump() newt.Dump(debugToolkit)
return newt return newt
} }
@ -62,7 +62,7 @@ func tabSetMargined(tab *ui.Tab) {
} }
} }
func newTab(w *ui.Window, name string) *andlabsT { func rawTab(w *ui.Window, name string) *andlabsT {
var t andlabsT var t andlabsT
log(debugToolkit, "gui.toolkit.NewTab() ADD", name) log(debugToolkit, "gui.toolkit.NewTab() ADD", name)
@ -118,7 +118,7 @@ func (t *andlabsT) appendTab(name string) *andlabsT {
return &newT return &newT
} }
func NewTab(parentW *toolkit.Widget, w *toolkit.Widget) { func newTab(parentW *toolkit.Widget, w *toolkit.Widget) {
var newt *andlabsT var newt *andlabsT
log(debugToolkit, "gui.andlabs.NewTab()", w.Name) log(debugToolkit, "gui.andlabs.NewTab()", w.Name)

View File

@ -5,19 +5,32 @@ import "git.wit.org/wit/gui/toolkit"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
func (t andlabsT) NewTextbox(name string) *andlabsT { func newTextbox(parentW *toolkit.Widget, w *toolkit.Widget) {
var newt andlabsT log(debugToolkit, "NewTexbox()", w.Name)
log(debugToolkit, "gui.Toolkit.NewTextbox()", name) t := mapToolkits[parentW]
if (t == nil) {
listMap(debugError)
log(debugError, "newTextbox() listMap()")
log(debugError, "FFFFFFFFFFFF listMap()")
log(debugError, "FFFFFFFFFFFF listMap()")
}
// t.NewTextbox(w)
// func (t andlabsT) NewTextbox(w *toolkit.Widget) *andlabsT {
var newt *andlabsT
newt = new(andlabsT)
log(debugToolkit, "gui.Toolkit.NewTextbox()", w.Name)
if t.broken() { if t.broken() {
return nil return
} }
c := ui.NewNonWrappingMultilineEntry() c := ui.NewNonWrappingMultilineEntry()
newt.uiMultilineEntry = c newt.uiMultilineEntry = c
newt.uiBox = t.uiBox newt.uiBox = t.uiBox
newt.Name = name newt.Name = w.Name
newt.tw = w
if (defaultBehavior) { if (defaultBehavior) {
t.uiBox.Append(c, true) t.uiBox.Append(c, true)
} else { } else {
@ -25,41 +38,59 @@ func (t andlabsT) NewTextbox(name string) *andlabsT {
} }
c.OnChanged(func(spin *ui.MultilineEntry) { c.OnChanged(func(spin *ui.MultilineEntry) {
newt.commonChange("Textbox") w.S = newt.uiMultilineEntry.Text()
// this is still dangerous
// newt.commonChange(newt.tw)
log(debugChange, "Not yet safe to trigger on change for ui.MultilineEntry")
}) })
return &newt
}
func NewTextbox(parentW *toolkit.Widget, w *toolkit.Widget) {
var t, newt *andlabsT
log(debugToolkit, "gui.andlabs.NewTextbox()", w.Name)
t = mapToolkits[parentW]
if (t == nil) {
log(debugToolkit, "go.andlabs.NewTextbox() toolkit struct == nil. name=", parentW.Name, w.Name)
return
}
if t.broken() {
return
}
newt = new(andlabsT)
newt.uiLabel = ui.NewLabel(w.Name)
newt.uiBox = t.uiBox
log(debugToolkit, "gui.Toolbox.NewTextbox() about to append to Box parent t:", w.Name)
t.Dump()
log(debugToolkit, "gui.Toolbox.NewTextbox() about to append to Box new t:", w.Name)
newt.Dump()
if (t.uiBox != nil) {
t.uiBox.Append(newt.uiLabel, false)
} else {
log(debugToolkit, "ERROR: wit/gui andlabs couldn't place this Textbox in a box")
return
}
mapWidgetsToolkits(w, newt) mapWidgetsToolkits(w, newt)
} }
func doTextbox(p *toolkit.Widget, c *toolkit.Widget) {
if broken(c) {
return
}
if (c.Action == "New") {
newTextbox(p, c)
return
}
ct := mapToolkits[c]
if (ct == nil) {
log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c)
return
}
if ct.broken() {
log(true, "Textbox() ct.broken", ct)
return
}
if (ct.uiMultilineEntry == nil) {
log(debugError, "Textbox() uiMultilineEntry == nil", ct)
return
}
// the dns control panel isn't crashing anymore (?)
Queue(ct.doSimpleAction)
}
func (t *andlabsT) doSimpleAction() {
if (t.tw == nil) {
log(true, "doSimpleAction() got an empty widget")
log(true, "THIS SHOULD NEVER HAPPEN")
panic("crap. panic. widget == nil")
}
log(debugChange, "Going to attempt:", t.tw.Action)
switch t.tw.Action {
case "Enable":
t.uiMultilineEntry.Enable()
case "Disable":
t.uiMultilineEntry.Disable()
case "Show":
t.uiMultilineEntry.Show()
case "Hide":
t.uiMultilineEntry.Hide()
case "Set":
t.uiMultilineEntry.SetText(t.tw.S)
default:
log(debugError, "Can't do", t.tw.Action, "to a Textbox")
}
}

67
toolkit/andlabs/widget.go Normal file
View File

@ -0,0 +1,67 @@
package main
import (
"git.wit.org/wit/gui/toolkit"
)
// This is a map between the widgets in wit/gui and the internal structures of gocui
var mapWidgets map[*andlabsT]*toolkit.Widget
var mapToolkits map[*toolkit.Widget]*andlabsT
// This lists out the know mappings
func listMap(b bool) {
log(b, "listMap() HERE")
log(b, "listMap() HERE")
for t, w := range mapWidgets {
log(b, "andlabs =", t.Name, "widget =", w.Name)
}
log(debugToolkit, "listMap() HERE mapToolkits()")
for w, t := range mapToolkits {
log(b, "andlabs =", t, "widget =", w.Name)
t.Dump(b)
}
log(b, "listMap() HERE mapWidgets()")
log(b, "listMap() HERE FIXME. output too big")
}
func mapWidgetsToolkits(w *toolkit.Widget, t *andlabsT) {
if ((mapToolkits[w] == nil) && (mapWidgets[t] == nil)) {
log(debugToolkit, "map a new widget", w, t)
mapToolkits[w] = t
mapWidgets[t] = w
return
}
if (mapToolkits[w] != nil) {
tw := mapToolkits[w]
if (tw == nil) {
// logic corruption somewhere? Have you been deleting things recently?
log(true, "mapToolkits[w] is set, but mapWidgets[t] is nil")
panic("WTF mapWidgets[t] == nil")
}
log(true, "mapToolkits[w] is", tw)
if (tw == nil) {
log(true, "BAD map? mapWidgets[w] tw == nil")
} else {
log(true, "BAD map? mapWidgets[w] is", tw)
tw.Dump(true)
}
}
if (mapWidgets[t] != nil) {
wt := mapWidgets[t]
if (mapToolkits[w] == nil) {
// logic corruption somewhere? Have you been deleting things recently?
log(true, "mapWidgets[t] is set, but mapToolkits[w] is nil")
panic("WTF mapToolkits[w] == nil")
}
if (wt == nil) {
log(true, "BAD map? mapWidgets[t] wt == nil")
} else {
log(true, "BAD map? mapWidgets[t] is", wt)
widgetDump(true, wt)
}
}
log(debugToolkit, "map of widget worked", w.Type, ",", w.Name, ",", w.Action)
}

View File

@ -15,8 +15,8 @@ func (t *andlabsT) ErrorWindow(msg1 string, msg2 string) {
ui.MsgBoxError(t.uiWindow, msg1, msg2) ui.MsgBoxError(t.uiWindow, msg1, msg2)
} }
func NewWindow(w *toolkit.Widget) { func newWindow(w *toolkit.Widget) {
var t *andlabsT var newt *andlabsT
log(debugToolkit, "toolkit NewWindow", w.Name, w.Width, w.Height) log(debugToolkit, "toolkit NewWindow", w.Name, w.Width, w.Height)
@ -24,34 +24,23 @@ func NewWindow(w *toolkit.Widget) {
log(debugToolkit, "wit/gui plugin error. widget == nil") log(debugToolkit, "wit/gui plugin error. widget == nil")
return return
} }
t = new(andlabsT) newt = new(andlabsT)
// t = NewWindow2(w.Name, w.Width, w.Height) newt.tw = w
// func NewWindow2(title string, x int, y int) *andlabsT {
// menubar bool is if the OS defined border on the window should be used // menubar bool is if the OS defined border on the window should be used
win := ui.NewWindow(w.Name, w.Width, w.Height, menubar) win := ui.NewWindow(w.Name, w.Width, w.Height, menubar)
win.SetBorderless(canvas) win.SetBorderless(canvas)
win.SetMargined(margin) win.SetMargined(margin)
win.OnClosing(func(*ui.Window) bool { win.OnClosing(func(*ui.Window) bool {
log(debugToolkit, "ui.Window().OnExit() SHOULD ATTEMPT CALLBACK here") newt.commonChange(newt.tw)
t.Dump()
if (w.Custom != nil) {
w.Custom()
return true return true
}
// if (w.Event != nil) {
// w.Event(w)
// return true
// }
log(debugToolkit, "andlabs.ui.Window().OnClosing() was not defined")
return false
}) })
win.Show() win.Show()
t.uiWindow = win newt.uiWindow = win
t.UiWindowBad = win // deprecate this as soon as possible // newt.UiWindowBad = win // deprecate this as soon as possible
t.Name = w.Name newt.Name = w.Name
mapWidgetsToolkits(w, t) mapWidgetsToolkits(w, newt)
return return
} }

View File

@ -11,8 +11,19 @@ package toolkit
// Event() seems like a good name. // Event() seems like a good name.
// Could a protobuf be used here? (Can functions be passed?) // Could a protobuf be used here? (Can functions be passed?)
type Widget struct { type Widget struct {
Name string Name string // "New", "Delete", "Set", aka something to do
Type string // after lots of back and forth, a simple string Action string // "New", "Delete", "Set", aka something to do
// Type string // after lots of back and forth, a simple string
Type WidgetType
// This is how the values are passed back and forth
// values from things like checkboxes & dropdown's
// The string is also used to set the button name
B bool
I int
// maybe safe if there is correctly working Custom() between goroutines
// (still probably not, almost certainly not)
S string // not safe to have 'S'
// This GUI is intended for simple things // This GUI is intended for simple things
// We are not laying out PDF's here // We are not laying out PDF's here
@ -22,49 +33,61 @@ type Widget struct {
X int X int
Y int Y int
// latest attempt // Put space around elements to improve look & feel
Margin bool
// Make widgets fill up the space available
Expand bool
// latest attempt. seems to work so far (2023/02/28)
// Hopefully this will be the barrier between the goroutines
Custom func() Custom func()
// This might be useful to simplify retrieving
// values from things like checkboxes & dropdown's
B bool
I int
S string
// other things I've tried
// Event func(*Widget) *Widget
// OnChanged func(*Widget)
// Custom func(*Widget)
// OnExit func(*Widget)
} }
/* type WidgetType int
type Widget int
// https://ieftimov.com/post/golang-datastructures-trees/ // https://ieftimov.com/post/golang-datastructures-trees/
const ( const (
Unknown Widget = iota Unknown WidgetType = iota
Window Window
Tab Tab
Group
Frame Frame
Dropbox Button
Spinner Checkbox
Dropdown
Label Label
Textbox
Slider
Spinner
) )
func (s Widget) String() string { func (s WidgetType) String() string {
switch s { switch s {
case Window: case Window:
return "Window" return "Window"
case Tab: case Tab:
return "Tab" return "Tab"
case Group:
return "Group"
case Frame: case Frame:
return "Frame" return "Frame"
case Button:
return "Button"
case Checkbox:
return "Checkbox"
case Dropdown:
return "Dropdown"
case Label: case Label:
return "Label" return "Label"
case Dropbox: case Textbox:
return "Dropbox" return "Textbox"
case Slider:
return "Slider"
case Spinner:
return "Spinner"
case Unknown:
return "Unknown"
} }
return "unknown" return "GuiToolkitTUndefinedType"
} }
*/

View File

@ -1,6 +1,7 @@
package gui package gui
import ( import (
"git.wit.org/wit/gui/toolkit"
) )
//import toolkit "git.wit.org/wit/gui/toolkit/andlabs" //import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
@ -13,39 +14,33 @@ import (
// my guess). // my guess).
func NewWindow() *Node { func NewWindow() *Node {
var newNode *Node var newNode *Node
var custom func()
title := Config.Title // If the user didn't set a custom Exit() use the standard exit() function
// Windows are created off of the master node of the Binary Tree // This makes sure the GUI properly closes everything (GTK, QT, console ui, etc exit)
newNode = Config.master.New(title, "Window")
newNode.Widget.Width = Config.Width
newNode.Widget.Height = Config.Height
if (Config.Exit != nil) { if (Config.Exit != nil) {
log("setting a custom exit") log(debugGui, "setting a custom exit")
newNode.custom = func() { custom = func() {
log(debugChange, "Running a custom exit()", Config.Exit)
log(debugChange, "Running a custom exit() Config.Title =", Config.Title)
log(debugChange, "Running a custom exit() Config.Width =", Config.Width)
Config.Exit(newNode) Config.Exit(newNode)
} }
} else { } else {
log("not setting a custom exit") log(debugGui, "setting the standard exit")
custom = func () {
log(debugChange, "Running StandardExit()")
StandardExit()
} }
if (newNode.custom == nil) {
newNode.custom = func () {StandardExit(newNode)}
} }
// Windows are created off of the master node of the Binary Tree
newNode = Config.master.New(Config.Title, toolkit.Window, custom)
newNode.Widget.Custom = newNode.custom newNode.widget.Width = Config.Width
newNode.widget.Height = Config.Height
log(debugGui, "gui.Node.Window()", title) log(debugGui, "Window()", Config.Title)
for _, aplug := range allPlugins {
log(debugGui, "gui.Node.NewWindow() toolkit plugin =", aplug.name)
if (aplug.NewWindow == nil) {
log(debugGui, "gui.Node.NewWindow() is nil")
continue
}
aplug.NewWindow(&newNode.Widget)
}
send(nil, newNode)
return newNode return newNode
} }