diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 63f8dce..0000000 --- a/LICENSE.md +++ /dev/null @@ -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 diff --git a/Makefile b/Makefile index 95b9d29..d262786 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,12 @@ deb: -wit mirrors examples: \ + all \ cmds-buttonplugin \ cmds-console-ui-helloworld \ cmds-helloworld \ - cmds-debug \ - cmds-textbox + cmds-textbox \ + cmds-debug cmds-buttonplugin: make -C cmds/buttonplugin @@ -35,20 +36,21 @@ cmds-helloworld: make -C cmds/helloworld cmds-debug: - make -C cmds/debug + -make -C cmds/debug cmds-textbox: make -C cmds/textbox # sync repo to the github backup # git remote add github git@github.com:witorg/gui.git +# git remote add github2 git@github.com:wit-go/gui.git github: git push origin master + git push github2 master + git push github2 --tags git push github master - git push github devel - git push github jcarr @echo - @echo check https://github.com/witorg/gui + @echo check https://github.com/wit-go/gui @echo doc: diff --git a/README-goreadme.md b/README-goreadme.md index f21e4fe..a051b8a 100644 --- a/README-goreadme.md +++ b/README-goreadme.md @@ -145,41 +145,41 @@ var WARN bool ## Functions +### func [DebugWidgetWindow](/debug_widget.go#L7) + +`func DebugWidgetWindow(w *Node)` + ### func [DebugWindow](/debug_window.go#L9) `func DebugWindow()` 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 GolangDebugWindow()` - -### func [Indent](/debug.go#L120) +### func [Indent](/debug.go#L123) `func Indent(a ...interface{})` -### func [InitPlugins](/main.go#L35) +### func [InitPlugins](/main.go#L46) `func InitPlugins(names []string)` -### func [LoadToolkit](/plugin.go#L53) +### func [LoadToolkit](/plugin.go#L56) `func LoadToolkit(name string) bool` loads and initializes a toolkit (andlabs/ui, gocui, etc) -### func [Main](/main.go#L76) +### func [Main](/main.go#L87) `func Main(f func())` This should not pass a function -### func [Queue](/main.go#L106) +### func [Queue](/main.go#L117) `func Queue(f func())` @@ -194,31 +194,25 @@ For example: gui.Queue(NewWindow()) `func SetDebug(s bool)` -### func [SetDebugChange](/debug.go#L52) +### func [SetDebugChange](/debug.go#L58) `func SetDebugChange(s bool)` This passes the debugChange flag to the toolkit plugin -### func [SetDebugToolkit](/debug.go#L37) +### func [SetDebugToolkit](/debug.go#L43) `func SetDebugToolkit(s bool)` This passes the debugToolkit flag to the toolkit plugin -### func [ShowDebugValues](/debug.go#L66) +### func [ShowDebugValues](/debug.go#L72) `func ShowDebugValues()` -### func [StandardClose](/main.go#L119) +### func [StandardExit](/main.go#L136) -`func StandardClose(n *Node)` - -The window is destroyed but the application does not quit - -### func [StandardExit](/main.go#L125) - -`func StandardExit(n *Node)` +`func StandardExit()` 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 -### type [GuiConfig](/structs.go#L30) +### type [GuiConfig](/structs.go#L33) `type GuiConfig struct { ... }` @@ -249,14 +243,14 @@ This struct can be used with the go-arg package var Config GuiConfig ``` -### type [Node](/structs.go#L48) +### type [Node](/structs.go#L54) `type Node struct { ... }` The Node is a binary tree. This is how all GUI elements are stored simply the name and the size of whatever GUI element exists -#### func [NewWindow](/window.go#L14) +#### func [NewWindow](/window.go#L15) `func NewWindow() *Node` diff --git a/button.go b/button.go index dd93721..35e252d 100644 --- a/button.go +++ b/button.go @@ -1,25 +1,9 @@ package gui +import "git.wit.org/wit/gui/toolkit" + func (n *Node) NewButton(name string, custom func()) *Node { - newNode := n.New(name, "Button") - - 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) - } - + newNode := n.New(name, toolkit.Button, custom) + send(n, newNode) return newNode } diff --git a/checkbox.go b/checkbox.go index 0372a50..068be7b 100644 --- a/checkbox.go +++ b/checkbox.go @@ -1,55 +1,20 @@ package gui +import "git.wit.org/wit/gui/toolkit" + func (n *Node) Checked() bool { 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 { - newNode := n.New(name, "Checkbox") - newNode.custom = n.custom - - newNode.Widget.Custom = func() { - log(debugChange, "wit go gui checkbox", newNode.Widget) - if (n.custom != nil) { - log(debugChange, "trying parent.custom() callback() name =", name) - n.custom() - } 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) - } - + newNode := n.New(name, toolkit.Checkbox, nil) + send(n, newNode) + return newNode +} + +func (n *Node) NewThing(name string) *Node { + newNode := n.New(name, toolkit.Button, nil) + send(n, newNode) return newNode } diff --git a/cmds/buttonplugin/Makefile b/cmds/buttonplugin/Makefile index faa8882..49d190c 100644 --- a/cmds/buttonplugin/Makefile +++ b/cmds/buttonplugin/Makefile @@ -7,8 +7,8 @@ # run: build - ./buttonplugin >/tmp/buttonplugin.log 2>&1 - # ./buttonplugin + # ./buttonplugin >/tmp/buttonplugin.log 2>&1 + ./buttonplugin build-release: go get -v -u -x . diff --git a/cmds/buttonplugin/main.go b/cmds/buttonplugin/main.go index 6132ed6..9ed47fa 100644 --- a/cmds/buttonplugin/main.go +++ b/cmds/buttonplugin/main.go @@ -42,7 +42,7 @@ func main() { log.Println("Main() END") time.Sleep(1 * time.Second) gui.Watchdog() - gui.StandardExit(nil) + gui.StandardExit() } var counter int = 5 @@ -82,7 +82,9 @@ func buttonWindow() { }) 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 () { diff --git a/cmds/textbox/main.go b/cmds/textbox/main.go index b260681..44431b7 100644 --- a/cmds/textbox/main.go +++ b/cmds/textbox/main.go @@ -11,8 +11,6 @@ import ( type LogOptions struct { LogFile string 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"` } @@ -45,11 +43,15 @@ func main() { func initGUI() { var w *gui.Node gui.Config.Title = "Hello World" - gui.Config.Width = 640 - gui.Config.Height = 480 + gui.Config.Width = 642 + gui.Config.Height = 481 gui.Config.Exit = myDefaultExit w = gui.NewWindow() + w.Custom = func () { + log.Println("myDefaultExit(w)") + myDefaultExit(w) + } w.Dump() addDemoTab(w, "A Simple Tab Demo") addDemoTab(w, "A Second Tab") @@ -57,6 +59,9 @@ func initGUI() { if (args.GuiDebug) { gui.DebugWindow() } + if (args.GuiVerbose) { + gui.SetDebug(true) + } } 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 2") 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") tb = g2.NewTextbox("tb") log.Println("tb =", tb.GetText()) - tb.OnChanged = func(*gui.Node) { + tb.Custom = func() { s := tb.GetText() 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) { diff --git a/common.go b/common.go index 5dc098d..22e4319 100644 --- a/common.go +++ b/common.go @@ -1,17 +1,32 @@ package gui -// import "errors" -import "regexp" +import ( + "regexp" + // "errors" + // "git.wit.org/wit/gui/toolkit" +) // functions for handling text related GUI elements 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 } func (n *Node) GetText() string { - return "TODO: GetText() = {}" + return n.widget.S } /* @@ -48,19 +63,18 @@ func normalizeInt(s string) string { return clean } +func Delete(c *Node) { + c.widget.Action = "Delete" + send(c.parent, c) +} + func commonCallback(n *Node) { // TODO: make all of this common code to all the widgets - if (n.OnChanged == nil) { - log(debugChange, "Not Running n.OnChanged(n) == nil") + // This might be common everywhere finally (2023/03/01) + if (n.Custom == nil) { + log(debugChange, "Not Running n.Custom(n) == nil") } else { - log(debugChange, "Running n.OnChanged(n)") - n.OnChanged(n) - } - - if (n.custom == nil) { - log(debugChange, "Not Running n.custom(n) == nil") - } else { - log(debugChange, "Running n.custom()") - n.custom() + log(debugChange, "Running n.Custom(n)") + n.Custom() } } diff --git a/debug.go b/debug.go index f2be829..7fe9a6a 100644 --- a/debug.go +++ b/debug.go @@ -4,8 +4,8 @@ package gui // A function dump out the binary tree import ( - // "fmt" - "reflect" + "strconv" + "git.wit.org/wit/gui/toolkit" ) // various debugging flags @@ -17,14 +17,20 @@ var debugChange bool = false // shows user events like mouse and keyboard var debugPlugin bool = false var debugToolkit bool = false -func GetDebug () bool { - return debugGui -} +// func GetDebug () bool { +// return debugGui +// } func SetDebug (s bool) { - debugGui = s - // debugDump = s - // debugNode = s + debugGui = s + debugChange = 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() { - log(true, "Debug =", debugGui) - log(true, "DebugDump =", debugDump) - log(true, "DebugNode =", debugNode) - log(true, "DebugTabs =", debugTabs) - log(true, "DebugPlugin =", debugPlugin) - log(true, "DebugChange =", debugChange) + // 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, "DebugChange =", debugChange) + log(true, "DebugDump =", debugDump) + log(true, "DebugTabs =", debugTabs) + log(true, "DebugPlugin =", debugPlugin) + log(true, "DebugNode =", debugNode) log(true, "DebugToolkit =", debugToolkit) // dump out the debugging flags for the plugins @@ -102,14 +110,9 @@ func (n *Node) Dump() { if (n.children != nil) { Indent("children = ", n.children) } - if (n.custom != nil) { - Indent("custom = ", n.custom) + if (n.Custom != nil) { + 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") } @@ -124,15 +127,15 @@ func Indent(a ...interface{}) { func (n *Node) dumpWidget() { var info string - if (n.Widget.Type == "") { - n.Widget.Type = "UNDEF" - } - info = n.Widget.Type + info = n.widget.Type.String() - info += ", " + n.Widget.Name - if (n.Name != n.Widget.Name) { + info += ", " + n.widget.Name + if (n.Name != n.widget.Name) { info += " NAME MISMATCH" } + if (n.widget.Type == toolkit.Checkbox) { + info += " = " + strconv.FormatBool(n.widget.B) + } logindent(listChildrenDepth, defaultPadding, n.id, info) } diff --git a/debug_flags.go b/debug_flags.go new file mode 100644 index 0000000..ea535c4 --- /dev/null +++ b/debug_flags.go @@ -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() + }) +} diff --git a/debug_golang.go b/debug_golang.go new file mode 100644 index 0000000..87ccdb5 --- /dev/null +++ b/debug_golang.go @@ -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 +} diff --git a/debug_widget.go b/debug_widget.go new file mode 100644 index 0000000..da15706 --- /dev/null +++ b/debug_widget.go @@ -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) + }) +} diff --git a/debug_window.go b/debug_window.go index 82d7557..0ee2271 100644 --- a/debug_window.go +++ b/debug_window.go @@ -10,88 +10,16 @@ func DebugWindow() { Config.Title = "go.wit.org/gui debug window" Config.Width = 300 Config.Height = 200 - Config.Exit = StandardClose bugWin = NewWindow() + bugWin.Custom = bugWin.StandardClose bugWin.DebugTab("Debug Tab") } -var checkd, checkdn, checkdt, checkdtk *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() - }) -} +var checkd, checkdn, checkdt, checkdtk, lb1, lb2 *Node +var myButton *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) newN = n.NewTab(title) @@ -101,7 +29,13 @@ func (n *Node) DebugTab(title string) *Node { gog = newN.NewGroup("GOLANG") gog.NewLabel("go language") 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") @@ -109,11 +43,21 @@ func (n *Node) DebugTab(title string) *Node { // DemoToolkitWindow() }) - debugFlags(newN) + junk = gog.NewButton("junk", func () { + log("click junk, get junk") + }) + + gog.NewLabel("tmp label") + //////////////////////// window debugging things ////////////////////////////////// g1 = newN.NewGroup("Current Windows") 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) // initialize the windows map if it hasn't been @@ -122,6 +66,7 @@ func (n *Node) DebugTab(title string) *Node { } var dump = false + var last = "" for _, child := range Config.master.children { log(debugGui, "\t\t", child.id, child.Width, child.Height, child.Name) if (child.parent != nil) { @@ -134,16 +79,44 @@ func (n *Node) DebugTab(title string) *Node { child.Dump() } dd.AddDropdownName(child.Name) + last = child.Name mapWindows[child.Name] = child } - - dd.SetDropdown(0) + dd.SetDropdownName(last) + 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.NewButton("SetMargined(tab)", func () { log(debugChange, "START SetMargined(tab)", g2.Name) // name := dd.GetText() - name := dd.Widget.S + name := dd.widget.S + log(true, "name =", name) log(debugChange, "name =", name) log(debugChange, "mapWindows[name] =", mapWindows[name]) /* @@ -154,7 +127,7 @@ func (n *Node) DebugTab(title string) *Node { } */ 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) }) g2.NewButton("Hide(tab)", func () { @@ -170,6 +143,9 @@ func (n *Node) DebugTab(title string) *Node { g2.NewButton("change Title", func () { // mainWindow.SetText("hello world") }) + g2.NewButton("Quit", func () { + exit() + }) ///////////////////////////////////////////////////// g3 = newN.NewGroup("Node Debug") diff --git a/andlabs.go b/direct.go similarity index 100% rename from andlabs.go rename to direct.go diff --git a/dropdown.go b/dropdown.go index e999f7e..214cc5a 100644 --- a/dropdown.go +++ b/dropdown.go @@ -1,53 +1,46 @@ package gui +import ( + "git.wit.org/wit/gui/toolkit" +) + +// add a new entry to the dropdown name func (n *Node) AddDropdownName(name string) { 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) { - log(debugGui, "\tgui.AddDropdownName() aplug.NewDropdown = nil", aplug.name) + log(debugPlugin, "\taplug.AddDropdownName() = nil") 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) { - log(debugGui, "gui.SetDropdown() TODO: make this work. s =", s) -} - -func (n *Node) SetDropdownChange(f func()) { - n.Widget.Custom = f +// Set the dropdown menu to 'name' +func (n *Node) SetDropdownName(name string) { + log(debugGui, "SetDropdownName() work. name =", name) + for _, aplug := range allPlugins { + log(debugPlugin, "SetDropdownName() aplug =", aplug.name, "name =", name) + if (aplug.SetDropdownName == nil) { + log(true, "\taplug.SetDropdownName() aplug = nil") + continue + } + aplug.SetDropdownName(&n.widget, name) + } } func (n *Node) NewDropdown(name string) *Node { - newNode := n.New(name, "Dropdown") + newNode := n.New(name, toolkit.Dropdown, nil) 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) { log(debugGui, "\tgui.NewDropdown() aplug.NewDropdown = nil", aplug.name) 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?) - newNode.Widget.Custom = func() { - log(true, "gui.NewDropdown() START Custom()") - } return newNode } diff --git a/example_window_golang_debug.go b/example_window_golang_debug.go deleted file mode 100644 index 466654a..0000000 --- a/example_window_golang_debug.go +++ /dev/null @@ -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) - } -} - diff --git a/group.go b/group.go index 2037861..fb7ee47 100644 --- a/group.go +++ b/group.go @@ -1,22 +1,14 @@ package gui +import ( + "git.wit.org/wit/gui/toolkit" +) + // TODO: which name is better. AddGroup or NewGroup ? // first reaction is NewGroup func (n *Node) NewGroup(name string) *Node { var newNode *Node - newNode = n.New(name, "Group") - - 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) - } - + newNode = n.New(name, toolkit.Group, nil) + send(n, newNode) return newNode } diff --git a/label.go b/label.go index f51ce66..1e40fcd 100644 --- a/label.go +++ b/label.go @@ -1,19 +1,14 @@ package gui -// import "errors" -// import "regexp" +import ( + "git.wit.org/wit/gui/toolkit" +) func (n *Node) NewLabel(text string) *Node { - newNode := n.New(text, "Label") - - 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) - } + newNode := n.New(text, toolkit.Label, func() { + log(debugChange, "TextBox changed", text) + }) + send(n, newNode) return newNode } diff --git a/log.go b/log.go index 71e22f6..e808944 100644 --- a/log.go +++ b/log.go @@ -98,8 +98,9 @@ func log(a ...any) { if (a == nil) { 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") if (a[0] == false) { return diff --git a/main.go b/main.go index 01e15b6..d05f334 100644 --- a/main.go +++ b/main.go @@ -16,20 +16,31 @@ const Yaxis = 1 // stack things vertically var res embed.FS func init() { - debugGui = true - log(debugGui, "gui.init() has been run") + log("init() has been run") Config.counter = 0 Config.prefix = "wit" - - title := "guiBinaryTree" - w := 640 - h := 480 + Config.Width = 640 + Config.Height = 480 // Populates the top of the binary tree - Config.master = addNode(title, w, h) - // Config.master.Dump() - debugGui = false + Config.master = addNode("guiBinaryTree") + + 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) { @@ -116,21 +127,21 @@ func Queue(f func()) { } // 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. 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 -func StandardExit(n *Node) { - log(debugGui, "wit/gui Standard Window Exit. running os.Exit()") - log(debugGui, "gui.Node.StandardExit() attempt to exit each toolkit plugin") +func StandardExit() { + log("wit/gui Standard Window Exit. running os.Exit()") + log("gui.Node.StandardExit() attempt to exit each toolkit plugin") for i, aplug := range allPlugins { - log(debugGui, "gui.Node.NewButton()", i, aplug) + log("gui.Node.NewButton()", i, aplug) if (aplug.Quit != nil) { aplug.Quit() } } - exit("StandardExit") + exit(0) } diff --git a/node.go b/node.go index f143771..b237c78 100644 --- a/node.go +++ b/node.go @@ -1,15 +1,30 @@ 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 */ -func (n *Node) New(title string, t string) *Node { +func (n *Node) New(title string, t toolkit.WidgetType, custom func()) *Node { var newN *Node - newN = addNode(title, n.Width, n.Height) - newN.Widget.Type = t + newN = addNode(title) + 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) newN.parent = n @@ -19,20 +34,10 @@ func (n *Node) New(title string, t string) *Node { /* 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.Name = title - n.Width = width - 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.widget.Name = title n.id = Config.counter Config.counter += 1 diff --git a/plugin.go b/plugin.go index a4e007a..3b558f5 100644 --- a/plugin.go +++ b/plugin.go @@ -26,21 +26,24 @@ type aplug struct { MainOk bool Init func() - Main func(func ()) - Queue func(func ()) + // TODO: make Main() main() and never allow the user to call it + // run plugin.Main() when the plugin is loaded + Main func(func ()) // this never returns. Each plugin must have it's own goroutine + Queue func(func ()) // Should this return right away? Should it wait (can it wait?) 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) NewGroup func(*toolkit.Widget, *toolkit.Widget) NewCheckbox func(*toolkit.Widget, *toolkit.Widget) NewTab func(*toolkit.Widget, *toolkit.Widget) - NewLabel func(*toolkit.Widget, *toolkit.Widget) - NewTextbox func(*toolkit.Widget, *toolkit.Widget) - NewSlider func(*toolkit.Widget, *toolkit.Widget) - NewSpinner func(*toolkit.Widget, *toolkit.Widget) NewDropdown func(*toolkit.Widget, *toolkit.Widget) AddDropdownName func(*toolkit.Widget, string) + SetDropdownName func(*toolkit.Widget, string) SetDebugToolkit func(bool) SetDebugChange func(bool) @@ -73,27 +76,27 @@ func LoadToolkit(name string) bool { // newPlug.Ok = true newPlug.name = name - // map all the functions + // deprecate 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") + + // should send things to the goroutine above 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") - newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup") - newPlug.NewCheckbox = loadFunc2(&newPlug, "NewCheckbox") - newPlug.NewTab = loadFunc2(&newPlug, "NewTab") - newPlug.NewLabel = loadFunc2(&newPlug, "NewLabel") - newPlug.NewTextbox = loadFunc2(&newPlug, "NewTextbox") - newPlug.NewSlider = loadFunc2(&newPlug, "NewSlider") - newPlug.NewSpinner = loadFunc2(&newPlug, "NewSpinner") + // Sends a widget (button, checkbox, etc) and it's parent widget + // This includes instructions like "Add", "Delete", "Disable", etc + newPlug.Send = loadFunc2(&newPlug, "Send") + + // newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup") newPlug.NewDropdown = loadFunc2(&newPlug, "NewDropdown") newPlug.AddDropdownName = loadFuncS(&newPlug, "AddDropdownName") + newPlug.SetDropdownName = loadFuncS(&newPlug, "SetDropdownName") newPlug.SetDebugToolkit = loadFuncB(&newPlug, "SetDebugToolkit") newPlug.SetDebugChange = loadFuncB(&newPlug, "SetDebugChange") @@ -275,3 +278,16 @@ func loadfile(filename string) *plugin.Plugin { log(debugGui, "plugin WORKED =", filename) 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) + } +} diff --git a/slider.go b/slider.go index 35867a3..300fc8f 100644 --- a/slider.go +++ b/slider.go @@ -1,22 +1,16 @@ package gui +import ( + "git.wit.org/wit/gui/toolkit" +) + func (n *Node) NewSlider(name string, x int, y int) *Node { - newNode := n.New(name, "Slider") - newNode.Widget.X = x - newNode.Widget.Y = y - - newNode.Widget.Custom = func() { - 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) - } + newNode := n.New(name, toolkit.Slider, func() { + log(debugGui, "even newer clicker() name in NewSlider name =", name) + }) + newNode.widget.X = x + newNode.widget.Y = y + send(n, newNode) return newNode } diff --git a/spinner.go b/spinner.go index c554701..169894d 100644 --- a/spinner.go +++ b/spinner.go @@ -1,22 +1,16 @@ package gui +import ( + "git.wit.org/wit/gui/toolkit" +) + func (n *Node) NewSpinner(name string, x int, y int) *Node { - newNode := n.New(name, "Spinner") - newNode.Widget.X = x - newNode.Widget.Y = y - - newNode.Widget.Custom = func() { - 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) - } + newNode := n.New(name, toolkit.Spinner, func() { + log(debugGui, "even newer clicker() name in NewSpinner name =", name) + }) + newNode.widget.X = x + newNode.widget.Y = y + send(n, newNode) return newNode } diff --git a/structs.go b/structs.go index 271bc0b..b3589af 100644 --- a/structs.go +++ b/structs.go @@ -25,8 +25,11 @@ var Config GuiConfig type GuiArgs struct { Toolkit []string `arg:"--toolkit" help:"The order to attempt loading plugins [gocui,andlabs,gtk,qt]"` 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 { // This is the master node. The Binary Tree starts here master *Node @@ -41,6 +44,9 @@ type GuiConfig struct { depth int counter int // used to make unique ID's prefix string + + ActionCh1 chan int + ActionCh2 chan int } // The Node is a binary tree. This is how all GUI elements are stored @@ -48,7 +54,7 @@ type GuiConfig struct { type Node struct { id int - Widget toolkit.Widget + widget toolkit.Widget // deprecate these and use toolkit.Widget Name string @@ -56,16 +62,15 @@ type Node struct { Height int // this function is run when there are mouse or keyboard events - OnChanged func(*Node) + Custom func() parent *Node children []*Node // is keeping // deprecate these things if they don't really need to exist - custom func() - checked bool - text string + // checked bool + // text string } func (n *Node) Parent() *Node { diff --git a/tab.go b/tab.go index 6e2e47e..ce840b5 100644 --- a/tab.go +++ b/tab.go @@ -1,22 +1,15 @@ package gui import ( + "git.wit.org/wit/gui/toolkit" ) // This function should make a new node with the parent and // the 'tab' as a child func (n *Node) NewTab(text string) *Node { - newNode := n.New(text, "Tab") - - 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) - } + newNode := n.New(text, toolkit.Tab, nil) + send(n, newNode) return newNode } diff --git a/textbox.go b/textbox.go index 376b75d..123244c 100644 --- a/textbox.go +++ b/textbox.go @@ -1,20 +1,14 @@ package gui +import ( + "git.wit.org/wit/gui/toolkit" +) + func (n *Node) NewTextbox(name string) *Node { - newNode := n.New(name, "Textbox") - - 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) - } + newNode := n.New(name, toolkit.Textbox, func() { + log(debugGui, "wit/gui clicker()NewTextBox BUT IS EMPTY. FIXME name =", name) + }) + send(n, newNode) return newNode } diff --git a/toolkit/andlabs/box.go b/toolkit/andlabs/box.go index 463b89a..430e78e 100644 --- a/toolkit/andlabs/box.go +++ b/toolkit/andlabs/box.go @@ -11,7 +11,7 @@ func (t *andlabsT) GetBox() *ui.Box { // create a new box func (t *andlabsT) NewBox() *andlabsT { log(debugToolkit, "gui.Toolbox.NewBox() START create default") - t.Dump() + t.Dump(debugToolkit) if (t.uiGroup != nil) { log(debugToolkit, "\tgui.Toolbox.NewBox() is a Group") var newTK andlabsT @@ -49,6 +49,6 @@ func (t *andlabsT) NewBox() *andlabsT { return &newT } log(debugToolkit, "\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box") - t.Dump() + t.Dump(debugToolkit) return nil } diff --git a/toolkit/andlabs/button.go b/toolkit/andlabs/button.go index 9933e1f..deb34fa 100644 --- a/toolkit/andlabs/button.go +++ b/toolkit/andlabs/button.go @@ -7,7 +7,7 @@ import ( "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 b *ui.Button log(debugToolkit, "gui.andlabs.NewButton()", w.Name) @@ -25,19 +25,11 @@ func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) { b = ui.NewButton(w.Name) newt.uiButton = b + newt.tw = w + newt.parent = t b.OnClicked(func(*ui.Button) { - log(debugChange, "TODO: SHOULD LEAVE Button click HERE VIA channels. button name =", w.Name) - 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() + newt.commonChange(newt.tw) }) 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) } + +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") + } +} diff --git a/toolkit/andlabs/checkbox.go b/toolkit/andlabs/checkbox.go index 5466d17..29a8e4d 100644 --- a/toolkit/andlabs/checkbox.go +++ b/toolkit/andlabs/checkbox.go @@ -1,36 +1,29 @@ 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" -import _ "github.com/andlabs/ui/winmanifest" - -func (t andlabsT) NewCheckbox(name string, f func()) *andlabsT { - log(debugToolkit, "gui.Toolkit.NewCheckbox()", name) +func (t andlabsT) NewCheckbox(w *toolkit.Widget) *andlabsT { + log(debugToolkit, "NewCheckbox()", w.Name, w.Type) var newt andlabsT + newt.tw = w if t.broken() { return nil } - c := ui.NewCheckbox(name) + c := ui.NewCheckbox(w.Name) newt.uiCheckbox = c newt.uiBox = t.uiBox t.uiBox.Append(c, stretchy) - // newt.Custom = f c.OnToggled(func(spin *ui.Checkbox) { - // log(debugToolkit, "gui.Toolkit.NewCheckbox() clicked", name) - newt.commonChange("Checkbox") - /* - if (f != nil) { - log(debugToolkit, "Run custom() here", f) - log(SPEW, f) - f() - } else { - log(debugToolkit, "No custom() function here") - } - */ + newt.tw.B = newt.Checked() + log(debugChange, "val =", newt.tw.B) + newt.commonChange(newt.tw) }) return &newt @@ -45,25 +38,52 @@ func (t andlabsT) Checked() bool { } func NewCheckbox(parentW *toolkit.Widget, w *toolkit.Widget) { - log(debugToolkit, "gui.andlabs.NewCheckbox()", w.Name) + log(debugToolkit, "NewCheckbox()", w.Name) t := mapToolkits[parentW] if (t == nil) { - listMap() + listMap(debugError) + return } - newt := t.NewCheckbox(w.Name, w.Custom) - 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") - } - */ + newt := t.NewCheckbox(w) 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") + } +} diff --git a/toolkit/andlabs/common.go b/toolkit/andlabs/common.go index 94e19e1..31b73e6 100644 --- a/toolkit/andlabs/common.go +++ b/toolkit/andlabs/common.go @@ -1,5 +1,9 @@ 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 func init() { // Can you pass values to a plugin init() ? Otherwise, there is no way to safely print @@ -7,79 +11,52 @@ func init() { setDefaultBehavior(true) } -func (t andlabsT) commonChange(widget string) { - s := t.String() - log(debugChange, "commonChange() START widget =", widget) - log(debugChange, "commonChange() t.String =", s) - if (t.OnChanged != nil) { - // log(debugChange, "commonChange() toolkit.OnChanged() START") - // t.OnChanged(&t) - exit("OnChanged is not implemented. TODO: FIX THIS") +func (t andlabsT) commonChange(tw *toolkit.Widget) { + log(debugChange, "commonChange() START widget =", t.Name, t.Type) + if (tw == nil) { + log(true, "commonChange() What the fuck. there is no widget t.tw == nil") return } - if (t.Custom != nil) { - log(debugChange, "commonChange() START toolkit.Custom()") - t.Custom() - log(debugChange, "commonChange() END toolkit.Custom()") + if (tw.Custom == nil) { + log(debugChange, "commonChange() END Widget.Custom() = nil", t.tw.Name, t.tw.Type) return } - if (widget == "Checkbox") { - log(debugChange, "commonChange() END Need to read the Checkbox value") - 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 + tw.Custom() + log(debugChange, "commonChange() END Widget.Custom()", t.tw.Name, t.tw.Type) } // 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: redo this now that WidgetType is used and send() is used to package plugins func (t *andlabsT) broken() bool { + if (t.parent != nil) { + return false + } if (t.uiBox == 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() 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?") // 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() this probably should not cause the app to panic here (?)") return true } 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)") - forceDump(t) + log(debugToolkit, "UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)") + t.Dump(debugToolkit) 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 +} diff --git a/toolkit/andlabs/debug.go b/toolkit/andlabs/debug.go index 9b7e160..befbaa0 100644 --- a/toolkit/andlabs/debug.go +++ b/toolkit/andlabs/debug.go @@ -1,6 +1,6 @@ package main -// import "git.wit.org/wit/gui/toolkit" +import "git.wit.org/wit/gui/toolkit" 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 debugChange bool +var debugPlugin bool +var debugError bool = true // var DebugToolkit bool // 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() } -func forceDump(t *andlabsT) { - tmp := debugToolkit - debugToolkit = true - t.Dump() - debugToolkit = tmp -} - func (t *andlabsT) GetText() string { - log(debugToolkit, "gui.Toolkit.GetText() Enter debugToolkit=", debugToolkit) + log(debugToolkit, "GetText() Enter debugToolkit=", debugToolkit) if (t.uiEntry != nil) { - log(debugToolkit, "gui.Toolkit.uiEntry.Text() =", t.uiEntry.Text()) + log(debugToolkit, "uiEntry.Text() =", t.uiEntry.Text()) return t.uiEntry.Text() } if (t.uiMultilineEntry != nil) { - log(debugToolkit, "gui.Toolkit.uiMultilineEntry.Text() =", t.uiMultilineEntry.Text()) + log(debugToolkit, "uiMultilineEntry.Text() =", t.uiMultilineEntry.Text()) text := t.uiMultilineEntry.Text() - log(debugToolkit, "gui.Toolkit.uiMultilineEntry.Text() =", text) + log(debugToolkit, "uiMultilineEntry.Text() =", text) t.text = text return text } if (t.uiCombobox != nil) { - log(debugToolkit, "gui.Toolkit.uiCombobox() =", t.text) + log(debugToolkit, "uiCombobox() =", t.text) return t.text } return "" } func (t *andlabsT) SetText(s string) bool { - log(debugToolkit, "gui.Toolkit.Text() SetText() Enter") + log(debugToolkit, "Text() SetText() Enter") if (t.uiEntry != nil) { - log(debugToolkit, "gui.Toolkit.Value() =", t.uiEntry.Text) + log(debugToolkit, "Value() =", t.uiEntry.Text) t.uiEntry.SetText(s) return true } if (t.uiMultilineEntry != nil) { - log(debugToolkit, "gui.Toolkit.Value() =", t.uiMultilineEntry.Text) + log(debugToolkit, "Value() =", t.uiMultilineEntry.Text) t.uiMultilineEntry.SetText(s) return true } @@ -103,91 +98,101 @@ func (t *andlabsT) SetText(s string) bool { func sanity(t *andlabsT) bool { if (debugToolkit) { - log(debugToolkit, "gui.Toolkit.Value() Enter") + log(debugToolkit, "Value() Enter") scs := spew.ConfigState{MaxDepth: 1} scs.Dump(t) } if (t.uiEntry == nil) { - log(debugToolkit, "gui.Toolkit.Value() =", t.uiEntry.Text) + log(debugToolkit, "Value() =", t.uiEntry.Text) return false } return true } func (t *andlabsT) SetValue(i int) bool { - log(debugToolkit, "gui.Toolkit.SetValue() START") + log(debugToolkit, "SetValue() START") if (sanity(t)) { return false } - t.Dump() + t.Dump(debugToolkit) // panic("got to toolkit.SetValue") return true } func (t *andlabsT) Value() int { if (debugToolkit) { - log(debugToolkit, "gui.Toolkit.Value() Enter") + log(debugToolkit, "Value() Enter") scs := spew.ConfigState{MaxDepth: 1} scs.Dump(t) } 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 } if (t.uiSlider != nil) { - log(debugToolkit, "gui.Toolkit.Value() =", t.uiSlider.Value) + log(debugToolkit, "Value() =", t.uiSlider.Value) return t.uiSlider.Value() } if (t.uiSpinbox != nil) { - log(debugToolkit, "gui.Toolkit.Value() =", t.uiSpinbox.Value) + log(debugToolkit, "Value() =", 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 } -func (t *andlabsT) Dump() { - if ! debugToolkit { +func (t *andlabsT) Dump(b bool) { + if ! b { 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) { - log(debugToolkit, "gui.Toolkit.Dump() uiBox =", t.uiBox) + log(b, "uiBox =", t.uiBox) } if (t.uiButton != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiButton =", t.uiButton) + log(b, "uiButton =", t.uiButton) } if (t.uiCombobox != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiCombobox =", t.uiCombobox) + log(b, "uiCombobox =", t.uiCombobox) } if (t.uiWindow != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiWindow =", t.uiWindow) + log(b, "uiWindow =", t.uiWindow) } if (t.uiTab != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiTab =", t.uiTab) + log(b, "uiTab =", t.uiTab) } if (t.uiGroup != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiGroup =", t.uiGroup) + log(b, "uiGroup =", t.uiGroup) } if (t.uiEntry != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiEntry =", t.uiEntry) + log(b, "uiEntry =", t.uiEntry) } if (t.uiMultilineEntry != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiMultilineEntry =", t.uiMultilineEntry) + log(b, "uiMultilineEntry =", t.uiMultilineEntry) } if (t.uiSlider != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiSlider =", t.uiSlider) + log(b, "uiSlider =", t.uiSlider) } if (t.uiCheckbox != nil) { - log(debugToolkit, "gui.Toolkit.Dump() uiCheckbox =", t.uiCheckbox) + log(b, "uiCheckbox =", t.uiCheckbox) } - if (t.OnExit != nil) { - log(debugToolkit, "gui.Toolkit.Dump() OnExit =", t.OnExit) - } - if (t.Custom != nil) { - log(debugToolkit, "gui.Toolkit.Dump() Custom =", t.Custom) - } - log(debugToolkit, "gui.Toolkit.Dump() c =", t.c) - log(debugToolkit, "gui.Toolkit.Dump() val =", t.val) - log(debugToolkit, "gui.Toolkit.Dump() text =", t.text) + widgetDump(b, t.tw) +} + +func widgetDump(b bool, w *toolkit.Widget) { + if (w == nil) { + log(b, "widget = nil") + return + } + + 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) } diff --git a/toolkit/andlabs/dropdown.go b/toolkit/andlabs/dropdown.go index 2691a62..935741c 100644 --- a/toolkit/andlabs/dropdown.go +++ b/toolkit/andlabs/dropdown.go @@ -1,20 +1,20 @@ package main -import "github.com/andlabs/ui" -import _ "github.com/andlabs/ui/winmanifest" +import ( + "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(title string) *andlabsT { - // make new node here +func (t *andlabsT) NewDropdown(w *toolkit.Widget) *andlabsT { var newt andlabsT - - log(debugToolkit, "gui.Toolbox.NewDropdownCombobox()", title) + log(debugToolkit, "gui.Toolbox.NewDropdown() START", w.Name) if t.broken() { return nil } + newt.tw = w s := ui.NewCombobox() newt.uiCombobox = s newt.uiBox = t.uiBox @@ -27,11 +27,11 @@ func (t *andlabsT) NewDropdown(title string) *andlabsT { s.OnSelected(func(spin *ui.Combobox) { i := spin.Selected() if (newt.val == nil) { - log(debugToolkit, "make map didn't work") + log(debugChange, "make map didn't work") newt.text = "error" } - newt.text = newt.val[i] - newt.commonChange("Dropdown") + newt.tw.S = newt.val[i] + newt.commonChange(newt.tw) }) return &newt @@ -44,6 +44,12 @@ func (t *andlabsT) AddDropdownName(title string) { return } 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 } @@ -57,11 +63,10 @@ func NewDropdown(parentW *toolkit.Widget, w *toolkit.Widget) { t := mapToolkits[parentW] if (t == nil) { log(debugToolkit, "go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) - listMap() + listMap(debugToolkit) + return } - newt := t.NewDropdown(w.Name) - newt.Custom = w.Custom - newt.tw = w + newt := t.NewDropdown(w) mapWidgetsToolkits(w, newt) } @@ -71,18 +76,21 @@ func AddDropdownName(w *toolkit.Widget, s string) { t := mapToolkits[w] if (t == nil) { log(debugToolkit, "go.andlabs.AddDropdownName() toolkit struct == nil. name=", w.Name, s) - listMap() + listMap(debugToolkit) + return } t.AddDropdownName(s) } -func SetDropdown(w *toolkit.Widget, i int) { - log(debugToolkit, "gui.andlabs.SetDropdown()", i) +func SetDropdownName(w *toolkit.Widget, s string) { + log(debugChange, "gui.andlabs.SetDropdown()", w.Name, ",", s) t := mapToolkits[w] if (t == nil) { - log(debugToolkit, "go.andlabs.SetDropdown() toolkit struct == nil. name=", w.Name, i) - listMap() + log(debugError, "ERROR: SetDropdown() FAILED mapToolkits[w] == nil. name=", w.Name, s) + listMap(debugError) + return } - t.SetDropdown(i) + t.SetDropdown(1) + t.tw.S = s } diff --git a/toolkit/andlabs/group.go b/toolkit/andlabs/group.go index 1762b7f..613efb6 100644 --- a/toolkit/andlabs/group.go +++ b/toolkit/andlabs/group.go @@ -7,13 +7,13 @@ import ( _ "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) t := mapToolkits[parentW] if (t == nil) { log(debugToolkit, "go.andlabs.NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name) - listMap() + listMap(debugToolkit) } newt := t.NewGroup(w.Name) mapWidgetsToolkits(w, newt) @@ -23,18 +23,23 @@ func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) { func (t andlabsT) NewGroup(title string) *andlabsT { var newt andlabsT - log(debugToolkit, "gui.Toolbox.NewGroup() create", title) + log(debugToolkit, "NewGroup() create", title) g := ui.NewGroup(title) g.SetMargined(margin) if (t.uiBox != nil) { - t.uiBox.Append(g, stretchy) + // TODO: temporary hack to make the output textbox 'fullscreen' + if (title == "output") { + t.uiBox.Append(g, true) + } else { + t.uiBox.Append(g, stretchy) + } } else if (t.uiWindow != nil) { t.uiWindow.SetChild(g) } else { - log(debugToolkit, "gui.ToolboxNode.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, "NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it") + log(debugError, "probably could just make a box here?") exit("internal wit/gui error") } @@ -47,8 +52,5 @@ func (t andlabsT) NewGroup(title string) *andlabsT { newt.uiWindow = t.uiWindow newt.Name = title - t.Dump() - newt.Dump() - // panic("toolkit.NewGroup") return &newt } diff --git a/toolkit/andlabs/label.go b/toolkit/andlabs/label.go index e990b42..6bdd9b2 100644 --- a/toolkit/andlabs/label.go +++ b/toolkit/andlabs/label.go @@ -7,66 +7,74 @@ import ( "git.wit.org/wit/gui/toolkit" ) -var pwLabel *toolkit.Widget -var wLabel *toolkit.Widget -var tmpNewt *andlabsT +func newLabel(parentW *toolkit.Widget, w *toolkit.Widget) { + var newt *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] if (t == nil) { - log(debugToolkit, "go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) - listMap() - } - newt := t.NewDropdown(w.Name) - 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) + listMap(debugError) + log(debugError, "ERROR newLabel() listMap()") + log(debugError, "ERROR FFFFFFFFFFFF listMap()") + log(debugError, "ERROR FFFFFFFFFFFF listMap()") return } + log(debugToolkit, "NewLabel()", w.Name) if t.broken() { 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.tw = w + if (defaultBehavior) { + t.uiBox.Append(c, stretchy) + } - log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box parent t:", wLabel.Name) - t.Dump() - log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box new t:", wLabel.Name) - newt.Dump() + mapWidgetsToolkits(w, newt) +} - if (t.uiBox != nil) { - t.uiBox.Append(newt.uiLabel, false) - } else { - log(debugToolkit, "ERROR: wit/gui andlabs couldn't place this label in a box") + +func doLabel(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { 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") + } } diff --git a/toolkit/andlabs/log.go b/toolkit/andlabs/log.go index fff5ba8..98b4e54 100644 --- a/toolkit/andlabs/log.go +++ b/toolkit/andlabs/log.go @@ -98,9 +98,8 @@ func log(a ...any) { if (a == nil) { return } - var blah bool - if (reflect.TypeOf(a[0]) == reflect.TypeOf(blah)) { - // golog.Println("\t a[0] = bool") + var tbool bool + if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) { if (a[0] == false) { return } @@ -111,7 +110,9 @@ func log(a ...any) { // a = a[1:] a[0] = "WIT/GUI/Toolkit" if (debugToolkit) { - spew.Dump(a) + scs := spew.ConfigState{MaxDepth: 1} + scs.Dump(a) + // spew.Dump(a) } return } diff --git a/toolkit/andlabs/main.go b/toolkit/andlabs/main.go index 73aaad5..a72821a 100644 --- a/toolkit/andlabs/main.go +++ b/toolkit/andlabs/main.go @@ -32,20 +32,19 @@ func Main(f func()) { // For example: Queue(NewWindow()) // func Queue(f func()) { - log(debugToolkit, "Sending function to ui.QueueMain() (using gtk via andlabs/ui)") - log("THIS MIGHT BREAK") + log(debugToolkit, "Sending function to ui.QueueMain()") + log(true, "THIS DOES BREAK. TODO: wrap this") ui.QueueMain(f) // f() } func Init() { - log(debugToolkit, "should Init() here") + log(debugToolkit, "Init()") mapWidgets = make(map[*andlabsT]*toolkit.Widget) mapToolkits = make(map[*toolkit.Widget]*andlabsT) } func Quit() { - log(debugToolkit, "should Quit() here") - // myExit(nil) + log(debugToolkit, "Quit() TODO: close the toolkit cleanly") } diff --git a/toolkit/andlabs/plugin.go b/toolkit/andlabs/plugin.go index 5165178..5bc40a0 100644 --- a/toolkit/andlabs/plugin.go +++ b/toolkit/andlabs/plugin.go @@ -1,49 +1,104 @@ package main -import ( - "git.wit.org/wit/gui/toolkit" -) +// if you include more than just this import +// 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 lists out the know mappings -func listMap() { - log(debugToolkit, "listMap() HERE") - log(debugToolkit, "listMap() HERE") - log(debugToolkit, "listMap() HERE mapWidgets()") - for t, w := range mapWidgets { - log(debugToolkit, "andlabs =", t.Name, "widget =", w.Name) +// +// This should be called ? +// Pass() ? +// This handles all interaction between the wit/gui package (what golang knows about) +// and this plugin that talks to the OS and does scary and crazy things to make +// a GUI on whatever OS or whatever GUI toolkit you might have (GTK, QT, WASM, libcurses) +// +// Once you are here, you should be in a protected goroutine created by the golang wit/gui package +// +// 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()") - for w, t := range mapToolkits { - log(debugToolkit, "andlabs =", t, "widget =", w.Name) - forceDump(t) + log(debugPlugin, "Send() child =", c.Name, ",", c.Action, ",", c.Type) + + switch c.Type { + 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) { - if (mapToolkits[w] == nil) { - mapToolkits[w] = t - } else { - 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) - log(debugToolkit, "WTF: mapToolkits map already set to ", mapToolkits[w]) - panic("WTF mapWidgetsToolkits() w == nil") +// delete the child widget from the parent +// p = parent, c = child +func destroy(p *toolkit.Widget, c *toolkit.Widget) { + log(true, "delete()", c.Name, c.Type) + + pt := mapToolkits[p] + ct := mapToolkits[c] + 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) { - mapWidgets[t] = w - } else { - log(debugToolkit, "WTF: mapWidgets already installed. w =", w) - log(debugToolkit, "WTF: mapWidgets already installed. t =", t.Width, t) - log(SPEW, &t) - log(SPEW, t) - log(SPEW, *t) - log(debugToolkit, "WTF: mapWidgets already mapped to", mapWidgets[t]) - log(SPEW, mapWidgets[t]) - panic("WTF. mapWidget andlabs toolkit already mapped to gui toolkit") + switch ct.Type { + 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 { + log(true, "Fuck it, destroy the whole box", pt.Name) + // pt.uiBox.Destroy() // You have a bug: You cannot destroy a uiControl while it still has a parent. + pt.uiBox.SetPadded(false) + pt.uiBox.Delete(4) + ct.uiButton.Disable() + // ct.uiButton.Hide() + ct.uiButton.Destroy() + } + + 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() + } } } diff --git a/toolkit/andlabs/slider.go b/toolkit/andlabs/slider.go index 4857935..87639ca 100644 --- a/toolkit/andlabs/slider.go +++ b/toolkit/andlabs/slider.go @@ -7,31 +7,32 @@ import ( _ "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 - log(debugToolkit, "gui.Toolkit.NewSpinbox()", x, y) + log(debugToolkit, w.Name, w.Type, w.X, w.Y) var newt andlabsT 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?") exit("internal golang wit/gui/toolkit error") return nil } - s := ui.NewSlider(x, y) + s := ui.NewSlider(w.X, w.Y) newt.uiSlider = s newt.uiBox = t.uiBox + newt.tw = w t.uiBox.Append(s, stretchy) s.OnChanged(func(spin *ui.Slider) { - newt.commonChange("Slider") + newt.commonChange(newt.tw) }) return &newt } -func NewSlider(parentW *toolkit.Widget, w *toolkit.Widget) { +func newSlider(parentW *toolkit.Widget, w *toolkit.Widget) { var newt *andlabsT 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) return } - newt = t.NewSlider(w.Name, w.X, w.Y) + newt = t.newSlider(w) mapWidgetsToolkits(w, newt) } diff --git a/toolkit/andlabs/spinner.go b/toolkit/andlabs/spinner.go index b98fb0c..1a7430e 100644 --- a/toolkit/andlabs/spinner.go +++ b/toolkit/andlabs/spinner.go @@ -1,27 +1,43 @@ package main -import "github.com/andlabs/ui" -import _ "github.com/andlabs/ui/winmanifest" +import ( + "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 - log(debugToolkit, "gui.Toolkit.NewSpinner()", x, y) + log(debugToolkit, "newSpinner()", w.X, w.Y) var newt andlabsT 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") - exit("internal golang wit/gui error") + log(debugToolkit, "newSpinner() node.UiBox == nil. I can't add a range UI element without a place to put it") return nil } - s := ui.NewSpinbox(x, y) + s := ui.NewSpinbox(w.X, w.Y) newt.uiSpinbox = s newt.uiBox = t.uiBox + newt.tw = w t.uiBox.Append(s, stretchy) s.OnChanged(func(s *ui.Spinbox) { - newt.commonChange("Spinner") + newt.commonChange(newt.tw) }) 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) +} diff --git a/toolkit/andlabs/structs.go b/toolkit/andlabs/structs.go index cf3afaf..45b6d1d 100644 --- a/toolkit/andlabs/structs.go +++ b/toolkit/andlabs/structs.go @@ -10,31 +10,27 @@ type andlabsT struct { id string Name string + Type toolkit.WidgetType Width int Height int tw *toolkit.Widget - - OnChanged func(*andlabsT) - OnExit func(*andlabsT) - - Custom func() + parent *andlabsT uiBox *ui.Box - uiBox2 *ui.Box // temporary hack while implementing tabs uiButton *ui.Button uiControl *ui.Control uiCombobox *ui.Combobox uiCheckbox *ui.Checkbox uiEntry *ui.Entry - uiMultilineEntry *ui.MultilineEntry uiGroup *ui.Group uiLabel *ui.Label uiSlider *ui.Slider uiSpinbox *ui.Spinbox uiTab *ui.Tab - uiText *ui.EditableCombobox 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 // this is probably fucked up and in many ways wrong because of unsafe goroutine threading diff --git a/toolkit/andlabs/tab.go b/toolkit/andlabs/tab.go index f9085b4..995bbbd 100644 --- a/toolkit/andlabs/tab.go +++ b/toolkit/andlabs/tab.go @@ -33,7 +33,7 @@ func (t *andlabsT) newTab(name string) *andlabsT { if (t.uiTab == nil) { // this means you have to make a new tab 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 } else { // this means you have to append a tab @@ -44,9 +44,9 @@ func (t *andlabsT) newTab(name string) *andlabsT { newt.Name = name log(debugToolkit, "t:") - t.Dump() + t.Dump(debugToolkit) log(debugToolkit, "newt:") - newt.Dump() + newt.Dump(debugToolkit) 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 log(debugToolkit, "gui.toolkit.NewTab() ADD", name) @@ -118,7 +118,7 @@ func (t *andlabsT) appendTab(name string) *andlabsT { return &newT } -func NewTab(parentW *toolkit.Widget, w *toolkit.Widget) { +func newTab(parentW *toolkit.Widget, w *toolkit.Widget) { var newt *andlabsT log(debugToolkit, "gui.andlabs.NewTab()", w.Name) diff --git a/toolkit/andlabs/textbox.go b/toolkit/andlabs/textbox.go index cb6075d..e916fd9 100644 --- a/toolkit/andlabs/textbox.go +++ b/toolkit/andlabs/textbox.go @@ -5,19 +5,32 @@ import "git.wit.org/wit/gui/toolkit" import "github.com/andlabs/ui" import _ "github.com/andlabs/ui/winmanifest" -func (t andlabsT) NewTextbox(name string) *andlabsT { - var newt andlabsT +func newTextbox(parentW *toolkit.Widget, w *toolkit.Widget) { + 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() { - return nil + return } c := ui.NewNonWrappingMultilineEntry() newt.uiMultilineEntry = c newt.uiBox = t.uiBox - newt.Name = name + newt.Name = w.Name + newt.tw = w if (defaultBehavior) { t.uiBox.Append(c, true) } else { @@ -25,41 +38,59 @@ func (t andlabsT) NewTextbox(name string) *andlabsT { } 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) } + + +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") + } +} diff --git a/toolkit/andlabs/widget.go b/toolkit/andlabs/widget.go new file mode 100644 index 0000000..58f8514 --- /dev/null +++ b/toolkit/andlabs/widget.go @@ -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) +} diff --git a/toolkit/andlabs/window.go b/toolkit/andlabs/window.go index 7527ac5..40cd410 100644 --- a/toolkit/andlabs/window.go +++ b/toolkit/andlabs/window.go @@ -15,8 +15,8 @@ func (t *andlabsT) ErrorWindow(msg1 string, msg2 string) { ui.MsgBoxError(t.uiWindow, msg1, msg2) } -func NewWindow(w *toolkit.Widget) { - var t *andlabsT +func newWindow(w *toolkit.Widget) { + var newt *andlabsT 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") return } - t = new(andlabsT) - // t = NewWindow2(w.Name, w.Width, w.Height) + newt = new(andlabsT) + 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 win := ui.NewWindow(w.Name, w.Width, w.Height, menubar) win.SetBorderless(canvas) win.SetMargined(margin) win.OnClosing(func(*ui.Window) bool { - log(debugToolkit, "ui.Window().OnExit() SHOULD ATTEMPT CALLBACK here") - t.Dump() - if (w.Custom != nil) { - w.Custom() - return true - } - // if (w.Event != nil) { - // w.Event(w) - // return true - // } - log(debugToolkit, "andlabs.ui.Window().OnClosing() was not defined") - return false + newt.commonChange(newt.tw) + return true }) win.Show() - t.uiWindow = win - t.UiWindowBad = win // deprecate this as soon as possible - t.Name = w.Name + newt.uiWindow = win + // newt.UiWindowBad = win // deprecate this as soon as possible + newt.Name = w.Name - mapWidgetsToolkits(w, t) + mapWidgetsToolkits(w, newt) return } diff --git a/toolkit/widget.go b/toolkit/widget.go index 295a598..fcb6d31 100644 --- a/toolkit/widget.go +++ b/toolkit/widget.go @@ -11,8 +11,19 @@ package toolkit // Event() seems like a good name. // Could a protobuf be used here? (Can functions be passed?) type Widget struct { - Name string - Type string // after lots of back and forth, a simple string + Name string // "New", "Delete", "Set", aka something to do + 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 // We are not laying out PDF's here @@ -22,49 +33,61 @@ type Widget struct { X 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() - - // 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 Widget int +type WidgetType int // https://ieftimov.com/post/golang-datastructures-trees/ const ( - Unknown Widget = iota + Unknown WidgetType = iota Window Tab + Group Frame - Dropbox - Spinner + Button + Checkbox + Dropdown Label + Textbox + Slider + Spinner ) -func (s Widget) String() string { +func (s WidgetType) String() string { switch s { case Window: return "Window" case Tab: return "Tab" + case Group: + return "Group" case Frame: return "Frame" + case Button: + return "Button" + case Checkbox: + return "Checkbox" + case Dropdown: + return "Dropdown" case Label: return "Label" - case Dropbox: - return "Dropbox" + case Textbox: + return "Textbox" + case Slider: + return "Slider" + case Spinner: + return "Spinner" + case Unknown: + return "Unknown" } - return "unknown" + return "GuiToolkitTUndefinedType" } -*/ diff --git a/window.go b/window.go index 10af3b8..a17aa74 100644 --- a/window.go +++ b/window.go @@ -1,6 +1,7 @@ package gui import ( + "git.wit.org/wit/gui/toolkit" ) //import toolkit "git.wit.org/wit/gui/toolkit/andlabs" @@ -13,39 +14,33 @@ import ( // my guess). func NewWindow() *Node { var newNode *Node + var custom func() - title := Config.Title - // Windows are created off of the master node of the Binary Tree - newNode = Config.master.New(title, "Window") - - newNode.Widget.Width = Config.Width - newNode.Widget.Height = Config.Height - + // If the user didn't set a custom Exit() use the standard exit() function + // This makes sure the GUI properly closes everything (GTK, QT, console ui, etc exit) if (Config.Exit != nil) { - log("setting a custom exit") - newNode.custom = func() { + log(debugGui, "setting a custom exit") + 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) } } else { - log("not setting a custom exit") - } - - if (newNode.custom == nil) { - newNode.custom = func () {StandardExit(newNode)} - } - - newNode.Widget.Custom = newNode.custom - - log(debugGui, "gui.Node.Window()", 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 + log(debugGui, "setting the standard exit") + custom = func () { + log(debugChange, "Running StandardExit()") + StandardExit() } - aplug.NewWindow(&newNode.Widget) } + // Windows are created off of the master node of the Binary Tree + newNode = Config.master.New(Config.Title, toolkit.Window, custom) + newNode.widget.Width = Config.Width + newNode.widget.Height = Config.Height + + log(debugGui, "Window()", Config.Title) + + send(nil, newNode) return newNode }