diff options
| author | Jeff Carr <[email protected]> | 2023-03-12 08:47:16 -0500 |
|---|---|---|
| committer | Jeff Carr <[email protected]> | 2023-03-12 08:47:16 -0500 |
| commit | 20f13a4b5be1a986e1085214f492a0afe6db322f (patch) | |
| tree | 35d633c45a36798126520269e13ae70dd70b5b20 | |
| parent | 49202eeafdad8e5780fefdad3d2f87fd4354725e (diff) | |
Squashed commit of the following:
commit 448abc843e2241bab6c399f7a836dccba1defc18
Author: Jeff Carr <[email protected]>
Date: Sun Mar 12 08:35:28 2023 -0500
this should probably be a new release now
Signed-off-by: Jeff Carr <[email protected]>
commit a4064f7a6c5ac67437768aa2bc67c75dafc91c4c
Author: Jeff Carr <[email protected]>
Date: Sat Mar 11 03:18:23 2023 -0600
able to work on add 'Box' and play with 'Image'
Signed-off-by: Jeff Carr <[email protected]>
commit 6e59573d85e82ecb005805f50711dddc2df50480
Author: Jeff Carr <[email protected]>
Date: Sat Mar 11 03:04:34 2023 -0600
rearrange widget debugging
Signed-off-by: Jeff Carr <[email protected]>
commit e0570de75c6eb1b4f49e541d9ef5d83ae4434d3d
Author: Jeff Carr <[email protected]>
Date: Sat Mar 11 02:29:20 2023 -0600
debugging is lots smarter
Signed-off-by: Jeff Carr <[email protected]>
commit ece32a1e43d91cd197d0a8497ad2f034c46126e1
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 21:38:23 2023 -0600
first pass on a node delete
Signed-off-by: Jeff Carr <[email protected]>
commit c91cb0eddb0f73f8dea9b21a16cd76c7e2c19a33
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 21:06:29 2023 -0600
can recreate window list
Signed-off-by: Jeff Carr <[email protected]>
commit 470f9dc26aefd3626b319264fe151aa48d4d5377
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 12:07:34 2023 -0600
attempt to ressurect mouse in the console plugin
Signed-off-by: Jeff Carr <[email protected]>
commit 747bb53e06dda458cc8cd77b665f4d9d07f5e925
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 10:47:14 2023 -0600
jesus. gocui actually builds and works again as a plugin
it didn't take too much to change it
Signed-off-by: Jeff Carr <[email protected]>
commit 9283c65c8e9b8d2630b251ad952b6b52caddb307
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 07:26:53 2023 -0600
show/hide/etc for window widgets
Signed-off-by: Jeff Carr <[email protected]>
commit 5724cd7ffd8595ae049a7c9c21cb2f1a993c4b76
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 06:40:36 2023 -0600
compiles and runs
Signed-off-by: Jeff Carr <[email protected]>
commit 44a5e69ce17cb506adfe24ca72cc86caa9ebcc70
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 05:57:15 2023 -0600
more debugging improvements
Signed-off-by: Jeff Carr <[email protected]>
commit b86f145f0252e7545b2e7fa78e1d5960cacb7bad
Author: Jeff Carr <[email protected]>
Date: Fri Mar 10 03:42:32 2023 -0600
set margin on tab's works
Signed-off-by: Jeff Carr <[email protected]>
commit d2218c08cf44acd5f017a8faa1439ee6d2fd46d5
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 16:26:21 2023 -0600
ignore all *.so files
Signed-off-by: Jeff Carr <[email protected]>
commit e21934fff3cfea30b04df01bf0714f6927aa78f4
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 16:25:15 2023 -0600
can't embed the toolkit/*.so files here
Signed-off-by: Jeff Carr <[email protected]>
commit f1e6c5fc9c8ca36db3ad6109d64612b6850fa856
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 16:21:14 2023 -0600
andlabs group widget has Show() and Hide()
Signed-off-by: Jeff Carr <[email protected]>
commit e8487504aa76ca99c4891b777585a428fda0ef62
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 16:07:56 2023 -0600
pass the node id into the plugin to use in channels
Signed-off-by: Jeff Carr <[email protected]>
commit 3667940a77af4e3855facb9247771d595477302f
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 14:20:21 2023 -0600
fix SetText() on Label
Signed-off-by: Jeff Carr <[email protected]>
commit 311d6be66db84b63fb7124df64e2e9be0f0b76a4
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 14:06:46 2023 -0600
still compiles and runs
Signed-off-by: Jeff Carr <[email protected]>
commit ee4e9b21ef59a97f902c6dae2a57ac7b3063fe3b
Author: Jeff Carr <[email protected]>
Date: Thu Mar 9 11:02:34 2023 -0600
compiles
Signed-off-by: Jeff Carr <[email protected]>
Signed-off-by: Jeff Carr <[email protected]>
60 files changed, 1941 insertions, 767 deletions
@@ -1,13 +1,14 @@ *.swp # ignore compiled plugins -toolkit/*.so +*.so cmds/buttonplugin/buttonplugin cmds/console-ui-helloworld/console-ui-helloworld cmds/debug/debug cmds/helloworld/helloworld cmds/textbox/textbox +cmds/*/helloconsole # temporary files when building debian packages /*.deb @@ -9,6 +9,9 @@ all: README.md make clean make plugins +build-dep: + apt install -f libgtk-3-dev + # should update every go dependancy (?) update: git pull @@ -16,13 +19,14 @@ update: deb: cd debian && make + dpkg-deb -c go-wit-gui*.deb -wit mirrors examples: \ all \ + cmds-helloworld \ cmds-buttonplugin \ cmds-console-ui-helloworld \ - cmds-helloworld \ cmds-textbox \ cmds-debug @@ -32,6 +36,7 @@ cmds-buttonplugin: cmds-console-ui-helloworld: make -C cmds/console-ui-helloworld +# this is the most basic one. This syntax should always work cmds-helloworld: make -C cmds/helloworld @@ -41,6 +46,9 @@ cmds-debug: cmds-textbox: make -C cmds/textbox +cmds-helloconsole: + make -C cmds/plugin-consoleonly + # sync repo to the github backup # git remote add github [email protected]:witorg/gui.git # git remote add github2 [email protected]:wit-go/gui.git @@ -64,11 +72,14 @@ clean: rm -f toolkit/*.so cd debian && make clean -plugins: plugins-gocui plugins-andlabs +plugins: plugins-gocui plugins-democui plugins-andlabs plugins-gocui: make -C toolkit/gocui +plugins-democui: + make -C toolkit/democui + plugins-andlabs: cd toolkit/andlabs/ && GO111MODULE="off" go build -buildmode=plugin -o ../andlabs.so # make -C toolkit/andlabs diff --git a/README-goreadme.md b/README-goreadme.md index fd4ec74..bf993de 100644 --- a/README-goreadme.md +++ b/README-goreadme.md @@ -145,11 +145,11 @@ var WARN bool ## Functions -### func [DebugWidgetWindow](/debugWidget.go#L107) +### func [DebugWidgetWindow](/debugWidget.go#L56) `func DebugWidgetWindow(w *Node)` -### func [DebugWindow](/debugWindow.go#L9) +### func [DebugWindow](/debugWindow.go#L21) `func DebugWindow()` @@ -159,11 +159,11 @@ Creates a window helpful for debugging this package `func Delete(c *Node)` -### func [Indent](/debug.go#L101) +### func [Indent](/debug.go#L116) `func Indent(a ...interface{})` -### func [InitPlugins](/main.go#L50) +### func [InitPlugins](/main.go#L56) `func InitPlugins(names []string)` @@ -173,13 +173,13 @@ Creates a window helpful for debugging this package loads and initializes a toolkit (andlabs/ui, gocui, etc) -### func [Main](/main.go#L91) +### func [Main](/main.go#L97) `func Main(f func())` This should not pass a function -### func [Queue](/main.go#L121) +### func [Queue](/main.go#L127) `func Queue(f func())` @@ -190,23 +190,24 @@ other goroutines. This is due to the nature of how Linux, MacOS and Windows work (they all work differently. suprise. surprise.) For example: gui.Queue(NewWindow()) -### func [SetDebug](/debug.go#L27) +### func [SetDebug](/debug.go#L26) `func SetDebug(s bool)` -### func [SetFlag](/debug.go#L41) +### func [SetFlag](/debug.go#L42) `func SetFlag(s string, b bool)` -### func [ShowDebugValues](/debug.go#L62) +### func [ShowDebugValues](/debug.go#L75) `func ShowDebugValues()` -### func [StandardExit](/main.go#L140) +### func [StandardExit](/main.go#L147) `func StandardExit()` -The window is destroyed but the application does not quit +The window is destroyed and the application exits +TODO: properly exit the plugin since Quit() doesn't do it ### func [Watchdog](/watchdog.go#L15) diff --git a/cmds/buttonplugin/log.go b/cmds/buttonplugin/log.go index 642ff7b..fb85cfa 100644 --- a/cmds/buttonplugin/log.go +++ b/cmds/buttonplugin/log.go @@ -27,7 +27,11 @@ func init() { arg.MustParse(&args) fmt.Println(args.Foo, args.Bar, args.User) - f1, err = os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) + log.Println() + log.Println("STDOUT is now at /tmp/guilogfile") + log.Println("STDOUT is now at /tmp/guilogfile") + log.Println() + f1, err = os.OpenFile(outfile, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) if err != nil { log.Fatalf("error opening file: %v", err) } diff --git a/cmds/buttonplugin/main.go b/cmds/buttonplugin/main.go index 0c72c3f..8a76a8b 100644 --- a/cmds/buttonplugin/main.go +++ b/cmds/buttonplugin/main.go @@ -10,13 +10,18 @@ import ( ) var title string = "Demo Plugin Window" +var outfile string = "/tmp/guilogfile" + +// this is broken. delete this func main() { + // this set the xterm and mate-terminal window title. maybe works generally? fmt.Println("\033]0;" + title + "\007") // time.Sleep(5 * time.Second) // var w *gui.Node + // this doesn't seem to work - captureSTDOUT() + // captureSTDOUT() // gui.LoadToolkit("default") // panic("WTF gocui not happening") @@ -57,6 +62,10 @@ func buttonWindow() { w = gui.NewWindow() g = w.NewGroup("buttonGroup") + g.NewButton("this app is old", func () { + }) + g.NewLabel("STDOUT is set to: " + outfile) + g.NewButton("hello", func () { log.Println("world") }) diff --git a/cmds/plugin-consoleonly/Makefile b/cmds/plugin-consoleonly/Makefile new file mode 100644 index 0000000..a8279f6 --- /dev/null +++ b/cmds/plugin-consoleonly/Makefile @@ -0,0 +1,14 @@ +run: build + ./helloconsole + +build-release: + go get -v -u -x . + go install -v -o helloconsole + helloconsole + +build: + GO111MODULE="off" go get -v -x . + GO111MODULE="off" go build -v -o helloconsole + +update: + GO111MODULE="off" go get -v -u -x . diff --git a/cmds/plugin-consoleonly/args.go b/cmds/plugin-consoleonly/args.go new file mode 100644 index 0000000..dc4a322 --- /dev/null +++ b/cmds/plugin-consoleonly/args.go @@ -0,0 +1,31 @@ +// This creates a simple hello world window +package main + +import ( + "log" + "git.wit.org/wit/gui" + arg "github.com/alexflint/go-arg" +) + +type LogOptions struct { + LogFile string + Verbose bool + User string `arg:"env:USER"` +} + +var args struct { + LogOptions + gui.GuiArgs +} + +func init() { + arg.MustParse(&args) + log.Println("Toolkit = ", args.Toolkit) + + if (args.GuiDebug) { + gui.DebugWindow() + } + if (args.GuiVerbose) { + gui.SetDebug(true) + } +} diff --git a/cmds/plugin-consoleonly/main.go b/cmds/plugin-consoleonly/main.go new file mode 100644 index 0000000..1003530 --- /dev/null +++ b/cmds/plugin-consoleonly/main.go @@ -0,0 +1,34 @@ +// This is a simple example +package main + +import ( + "log" + "git.wit.org/wit/gui" +) + +func main() { + gui.InitPlugins([]string{"gocui"}) + // gui.InitPlugins([]string{"democui"}) + gui.Main(helloworld) +} + +// This creates a window +func helloworld() { + var w *gui.Node + gui.Config.Title = "helloworld golang wit/gui window" + gui.Config.Width = 640 + gui.Config.Height = 480 + + w = gui.NewWindow() + w.NewButton("hello", func () { + log.Println("world") + }) + w.NewButton("Flags", func () { + log.Println("the debugging flags window") + w.DebugFlags(false) + }) + w.NewButton("Widgets", func () { + w.DebugWidgets(false) + log.Println("debug the widgets window") + }) +} @@ -17,7 +17,7 @@ func (n *Node) Add(str string) { func (n *Node) SetText(str string) bool { log(debugChange, "gui.SetText() value =", str) - n.widget.Action = "Set" + n.widget.Action = "SetText" n.widget.S = str send(n.parent, n) return true @@ -17,7 +17,6 @@ var debugTabs bool = false var debugFlags bool = false var debugChange bool = false // shows user events like mouse and keyboard var debugPlugin bool = false -var debugToolkit bool = false // for printing out the binary tree var listChildrenParent *Node @@ -26,28 +25,42 @@ var defaultPadding = " " func SetDebug (s bool) { debugGui = s - debugDump = s debugTabs = s - debugPlugin = s - debugNode = s - debugToolkit = s + SetFlag("Node", s) + SetFlag("Tabs", s) + SetFlag("Dump", s) SetFlag("Flags", s) - SetFlag("Toolkit", s) + SetFlag("Plugin", s) SetFlag("Change", s) SetFlag("Error", s) + + // This flag is only for the internal toolkit debugging + SetFlag("Toolkit", s) } func SetFlag (s string, b bool) { switch s { + case "Toolkit": + // This flag is only for internal toolkit debugging + case "Tabs": + debugTabs = b + case "Node": + debugNode = b + case "Dump": + debugDump = b case "Error": debugError = b case "Change": debugChange = b + case "Flags": + debugFlags = b + case "Plugin": + debugPlugin = b case "Show": - // print them here? For now, just used to print settings in the plugins + // ShowDebugValues() // print them here? default: - log(debugError, "Can't set unknown flag", s) + log(debugGui, "Can't set unknown flag", s) } // send the flag to the toolkit @@ -69,7 +82,6 @@ func ShowDebugValues() { log(true, "DebugTabs =", debugTabs) log(true, "DebugPlugin =", debugPlugin) log(true, "DebugNode =", debugNode) - log(true, "DebugToolkit =", debugToolkit) SetFlag("Show", true) } @@ -79,21 +91,24 @@ func (n *Node) Dump() { return } Indent("NODE DUMP START") - Indent("id = ", n.id) - Indent("Name = ", n.Name) - Indent("Width = ", n.Width) - Indent("Height = ", n.Height) + Indent("id = ", n.id) + Indent("Name = ", n.Name) + Indent("Width = ", n.Width) + Indent("Height = ", n.Height) + Indent("Widget Name = ", n.widget.Name) + Indent("Widget Type = ", n.widget.Type) + Indent("Widget Id = ", n.widget.GetId()) if (n.parent == nil) { - Indent("parent = nil") + Indent("parent = nil") } else { - Indent("parent.id =", n.parent.id) + Indent("parent.id =", n.parent.id) } if (n.children != nil) { - Indent("children = ", n.children) + Indent("children = ", n.children) } if (n.Custom != nil) { - Indent("Custom = ", n.Custom) + Indent("Custom = ", n.Custom) } Indent("NODE DUMP END") } @@ -102,8 +117,8 @@ func Indent(a ...interface{}) { logindent(listChildrenDepth, defaultPadding, a...) } -func (n *Node) dumpWidget() { - var info string +func (n *Node) dumpWidget() string { + var info, d string info = n.widget.Type.String() @@ -115,25 +130,39 @@ func (n *Node) dumpWidget() { info += " = " + strconv.FormatBool(n.widget.B) } + d = strconv.Itoa(n.id) + " " + info + + var tabs string + for i := 0; i < listChildrenDepth; i++ { + tabs = tabs + defaultPadding + } + d = tabs + d logindent(listChildrenDepth, defaultPadding, n.id, info) + return d } -func (n *Node) ListChildren(dump bool) { - n.dumpWidget() +func (n *Node) ListChildren(dump bool, dropdown *Node, mapNodes map[string]*Node) { + s := n.dumpWidget() + if (dropdown != nil) { + dropdown.AddDropdownName(s) + if (mapNodes != nil) { + mapNodes[s] = n + } + } if (dump == true) { n.Dump() } if len(n.children) == 0 { if (n.parent == nil) { - } else { - log(debugNode, "\t\t\tparent =",n.parent.id) - if (listChildrenParent != nil) { - log(debugNode, "\t\t\tlistChildrenParent =",listChildrenParent.id) - if (listChildrenParent.id != n.parent.id) { - // log("parent.child does not match child.parent") - exit("parent.child does not match child.parent") - } + return + } + log(debugNode, "\t\t\tparent =",n.parent.id) + if (listChildrenParent != nil) { + log(debugNode, "\t\t\tlistChildrenParent =",listChildrenParent.id) + if (listChildrenParent.id != n.parent.id) { + // log("parent.child does not match child.parent") + exit("parent.child does not match child.parent") } } log(debugNode, "\t\t", n.id, "has no children") @@ -158,7 +187,7 @@ func (n *Node) ListChildren(dump bool) { } listChildrenParent = n listChildrenDepth += 1 - child.ListChildren(dump) + child.ListChildren(dump, dropdown, mapNodes) listChildrenDepth -= 1 } return diff --git a/debugFlags.go b/debugFlags.go index 08aa766..322d2a2 100644 --- a/debugFlags.go +++ b/debugFlags.go @@ -2,7 +2,7 @@ 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) { +func (n *Node) DebugFlags(makeWindow bool) { var w, g *Node // Either: @@ -17,76 +17,68 @@ func (n *Node) debugFlags(makeWindow bool) { } else { w = n.NewTab("Flags") } - w.Dump() - g = w.NewGroup("Debug Flags") + g = w.NewGroup("Show") - g.NewButton("Turn on all Debug Flags", func () { + g.NewButton("Dump Flags", func () { + ShowDebugValues() + }) + + g.NewButton("All On", func () { SetDebug(true) }) - g.NewButton("Turn off all Debug Flags", func () { + g.NewButton("All Off", func () { SetDebug(false) }) + g = w.NewGroup("List") // generally useful debugging - cb1 := g.NewCheckbox("debugGui") + cb1 := g.NewCheckbox("debug Gui (like verbose=1)") cb1.Custom = func() { debugGui = cb1.widget.B log(debugGui, "Custom() n.widget =", cb1.widget.Name, cb1.widget.B) } // errors. by default these always output somewhere - cbE := g.NewCheckbox("debugError") + cbE := g.NewCheckbox("debug Error (bad things. default=true)") cbE.Custom = func() { - debugError = cbE.widget.B - SetFlag("Error", debugError) + SetFlag("Error", cbE.widget.B) } // debugging that will show you things like mouse clicks, user inputing text, etc // also set toolkit.DebugChange - cb2 := g.NewCheckbox("debugChange") + cb2 := g.NewCheckbox("debug Change (keyboard and mouse events)") cb2.Custom = func() { - debugChange = cb2.widget.B - SetFlag("Change", debugChange) - log(debugGui, "Custom() n.widget =", cb2.widget.Name, cb2.widget.B) + SetFlag("Change", cb2.widget.B) } // supposed to tell if you are going to dump full variable output - cb3 := g.NewCheckbox("debugDump") + cb3 := g.NewCheckbox("debug Dump (show lots of output)") cb3.Custom = func() { - debugDump = cb3.widget.B - log(debugGui, "Custom() n.widget =", cb3.widget.Name, cb3.widget.B) + SetFlag("Dump", cbE.widget.B) } - cb4 := g.NewCheckbox("debugTabs") + cb4 := g.NewCheckbox("debug Tabs (tabs and windows)") cb4.Custom = func() { - debugTabs = cb4.widget.B - log(debugGui, "Custom() n.widget =", cb4.widget.Name, cb4.widget.B) + SetFlag("Tabs", 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("debug Node (the binary tree)") + cb6.Custom = func() { + SetFlag("Plugin", cb6.widget.B) } - cb6 := g.NewCheckbox("debugNode") - cb6.Custom = func() { - debugNode = cb6.widget.B - log(debugGui, "Custom() n.widget =", cb6.widget.Name, cb6.widget.B) + // should show you when things go into or come back from the plugin + cb5 := g.NewCheckbox("debug Plugin (plugin interaction)") + cb5.Custom = func() { + SetFlag("Plugin", cb5.widget.B) } // turns on debugging inside the plugin toolkit - cb7 := g.NewCheckbox("debugToolkit") + cb7 := g.NewCheckbox("debug Toolkit (the plugin internals)") cb7.Custom = func() { // SetDebugToolkit(cb7.widget.B) SetFlag("Toolkit", cb7.widget.B) - log(debugFlags, "Custom() n.widget =", cb7.widget.Name, cb7.widget.B) } - - g.NewButton("Dump Debug Flags", func () { - ShowDebugValues() - }) } diff --git a/debugGochan.go b/debugGochan.go index 3183bdb..fbc3652 100644 --- a/debugGochan.go +++ b/debugGochan.go @@ -11,7 +11,7 @@ import ( var debugWG *sync.WaitGroup var debugNumberChan chan int -func (n *Node) debugGoChannels(makeWindow bool) { +func (n *Node) DebugGoChannels(makeWindow bool) { var w, g *Node // Either: diff --git a/debugGolang.go b/debugGolang.go index 0a6edda..55b1521 100644 --- a/debugGolang.go +++ b/debugGolang.go @@ -9,7 +9,7 @@ import ( "runtime/pprof" ) -func (n *Node) debugGolangWindow(makeWindow bool) { +func (n *Node) DebugGolangWindow(makeWindow bool) { var w, g, og, outputTextbox *Node // Either: @@ -17,8 +17,8 @@ func (n *Node) debugGolangWindow(makeWindow bool) { // make a new tab in the existing window if (makeWindow) { Config.Title = "GO" - Config.Width = 300 - Config.Height = 400 + Config.Width = 1280 + Config.Height = 720 w = NewWindow() w.Custom = w.StandardClose } else { @@ -32,19 +32,26 @@ func (n *Node) debugGolangWindow(makeWindow bool) { tmp, _ := debug.ReadBuildInfo() outputTextbox.SetText(tmp.String()) }) - g.NewButton("debug.PrintStack()", func () { - outputTextbox.SetText(string(debug.Stack())) - }) - g.NewButton("pprof.Lookup(goroutine)", func () { + g.NewButton("runtime.NumGoroutine()", func () { buf := new(bytes.Buffer) pprof.Lookup("goroutine").WriteTo(buf, 1) outputTextbox.SetText(buf.String()) + + outputTextbox.AppendText(fmt.Sprintln("runtime.NumGoroutine() = ", runtime.NumGoroutine())) }) g.NewButton("pprof.Lookup(heap)", func () { buf := new(bytes.Buffer) pprof.Lookup("heap").WriteTo(buf, 1) outputTextbox.SetText(buf.String()) }) + g.NewButton("debug.PrintStack(current)", 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(block)", func () { buf := new(bytes.Buffer) pprof.Lookup("block").WriteTo(buf, 1) @@ -91,7 +98,9 @@ func (n *Node) debugGolangWindow(makeWindow bool) { panic("test") }) - g.NewLabel("TODO:") + g = w.NewGroup("TODO: finish these") + + // g.NewLabel("TODO:") g.NewButton("runtime.Stack(true)", func () { // TODO: https://stackoverflow.com/questions/61127053/how-to-list-all-the-running-goroutines-in-a-go-program @@ -114,13 +123,6 @@ func (n *Node) debugGolangWindow(makeWindow bool) { g.NewButton("debug.SetTraceback('all')", func () { debug.SetTraceback("all") }) - g.NewButton("runtime.NumGoroutine()", func () { - buf := new(bytes.Buffer) - pprof.Lookup("goroutine").WriteTo(buf, 1) - outputTextbox.SetText(buf.String()) - - outputTextbox.AppendText(fmt.Sprintln("runtime.NumGoroutine() = ", runtime.NumGoroutine())) - }) // deprecated (probably) by String() implementation within golang g.NewButton("dumpModuleInfo() (deprecate)", func () { diff --git a/debugWidget.go b/debugWidget.go index d76b554..031f76d 100644 --- a/debugWidget.go +++ b/debugWidget.go @@ -2,179 +2,272 @@ package gui import ( "strconv" + "git.wit.org/wit/gui/toolkit" ) + +// global var for checking to see if this +// window/tab for debugging a widget exists +// check the binary tree instead (?) for a window called "Widgets" (bad idea) +var bugWidget *Node + +// the widget all these actions are run against +var activeWidget *Node +// the label where the user can see which widget is active +var activeLabel *Node +var activeLabelType *Node + +// tmp junk var debugGrid *Node +var debugGridLabel *Node +var debugWidgetBut1, debugWidgetBut2 *Node + +func setActiveWidget(w *Node) { + if (activeLabel == nil) { + // the debug window doesn't exist yet + // TODO: make a fake binary tree for this(?) + return + } + if (w == nil) { + log(debugError, "setActiveWidget() was sent nil !!!") + return + } + activeWidget = w + log(true, "The Widget is set to", w.id, w.Name) + title := "ID =" + strconv.Itoa(w.id) + " " + w.widget.Name + activeLabel.SetText(title) + activeLabelType.SetText("widget.Type = " + w.widget.Type.String()) + + // temporary stuff + if (w.widget.Type == toolkit.Window) { + debugWidgetBut1.widget.Action = "Enable" + send(debugWidgetBut1.parent, debugWidgetBut1) + debugWidgetBut2.widget.Action = "Enable" + send(debugWidgetBut2.parent, debugWidgetBut2) + } else { + debugWidgetBut1.widget.Action = "Disable" + send(debugWidgetBut1.parent, debugWidgetBut1) + debugWidgetBut2.widget.Action = "Disable" + send(debugWidgetBut2.parent, debugWidgetBut2) + } + return +} -func (n *Node) debugWidgets(makeWindow bool) { - var w, gList, gShow *Node +func DebugWidgetWindow(w *Node) { + if (bugWidget != nil) { + // this window was already created. Just change the widget we are working against + setActiveWidget(w) + return + } // Either: // make a new window // make a new tab in the existing window - if (makeWindow) { - Config.Title = "Debug Widgets" + if (makeTabs) { + Config.Title = "Widgets" Config.Width = 300 Config.Height = 400 - w = NewWindow() - w.Custom = w.StandardClose + bugWidget = NewWindow() + bugWidget.Custom = bugWidget.StandardClose } else { - w = n.NewTab("Widgets") + bugWidget = bugWin.NewTab("Widgets") } - w.Dump() - gList = w.NewGroup("Pick a widget to debug") - gShow = w.NewGroup("Added Widgets go here") + g := bugWidget.NewGroup("widget:") + + activeLabel = g.NewLabel("undef") + activeLabelType = g.NewLabel("undef") + + // common things that should work against each widget + g = bugWidget.NewGroup("common things") + g.NewButton("Disable()", func () { + activeWidget.widget.Action = "Disable" + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Enable()", func () { + activeWidget.widget.Action = "Enable" + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Show()", func () { + activeWidget.widget.Action = "Show" + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Hide()", func () { + activeWidget.widget.Action = "Hide" + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Delete()", func () { + Delete(activeWidget) + }) + g.NewButton("Dump()", func () { + g := debugGui + d := debugDump + debugGui = true + debugDump = true + activeWidget.Dump() + debugGui = g + debugDump = d + }) + + newG := bugWidget.NewGroup("add things") + newG.debugAddWidgetButtons() + + g = bugWidget.NewGroup("change things") + g.NewButton("SetMargin(true)", func () { + activeWidget.widget.Action = "SetMargin" + activeWidget.widget.B = true + send(activeWidget.parent, activeWidget) + }) + g.NewButton("SetMargin(false)", func () { + activeWidget.widget.Action = "SetMargin" + activeWidget.widget.B = false + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Value()", func () { + log("activeWidget.B =", activeWidget.widget.B) + log("activeWidget.I =", activeWidget.widget.I) + log("activeWidget.S =", activeWidget.widget.S) + }) + g.NewButton("Set(true)", func () { + activeWidget.widget.Action = "Set" + activeWidget.widget.B = true + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Set(false)", func () { + activeWidget.widget.Action = "Set" + activeWidget.widget.B = false + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Set(20)", func () { + activeWidget.widget.Action = "Set" + activeWidget.widget.B = true + activeWidget.widget.I = 20 + activeWidget.widget.S = "20" + send(activeWidget.parent, activeWidget) + }) + g.NewButton("SetText('foo')", func () { + activeWidget.widget.Action = "Set" + activeWidget.widget.S = "foo" + send(activeWidget.parent, activeWidget) + }) + g.NewButton("Delete()", func () { + activeWidget.widget.Action = "Delete" + send(activeWidget.parent, activeWidget) + }) + debugWidgetBut1 = g.NewButton("SetRaw(true)", func () { + activeWidget.widget.Action = "SetRaw" + activeWidget.widget.B = true + send(activeWidget.parent, activeWidget) + }) + debugWidgetBut2 = g.NewButton("SetRaw(false)", func () { + activeWidget.widget.Action = "SetRaw" + activeWidget.widget.B = false + send(activeWidget.parent, activeWidget) + }) - gList.NewButton("Button", func () { - SetDebug(true) - a := gShow.NewButton("myButton", func () { - log("this code is more better") - }) - SetDebug(false) - DebugWidgetWindow(a) + g = bugWidget.NewGroup("not working?") + g.NewButton("Add('foo')", func () { + activeWidget.widget.Action = "Add" + activeWidget.widget.S = "foo" + send(activeWidget.parent, activeWidget) }) - gList.NewButton("Checkbox", func () { - a := gShow.NewCheckbox("myCheckbox") + g.NewButton("Add button to (1,1)", func () { + activeWidget.widget.Action = "AddGrid" + activeWidget.widget.B = false + send(activeWidget, debugGridLabel) + // debugGrid = gShoactiveWidget.NewGrid("tmp grid", 2, 3) + }) + + setActiveWidget(g) +} + +func (n *Node) debugAddWidgetButtons() { + n.NewButton("Button", func () { + a := activeWidget.NewButton("myButton", nil) a.Custom = func () { - log("custom checkox func a =", a.widget.B, a.id) + log("this code is more better", a.widget.B, "id=", a.id) } - DebugWidgetWindow(a) }) - gList.NewButton("Label", func () { - a := gShow.NewLabel("mylabel") - DebugWidgetWindow(a) + n.NewButton("Checkbox", func () { + a := activeWidget.NewCheckbox("myCheckbox") + a.Custom = func () { + log("custom checkox func a=", a.widget.B, "id=", a.id) + } + }) + n.NewButton("Label", func () { + activeWidget.NewLabel("mylabel") }) - gList.NewButton("Textbox", func () { - a := gShow.NewTextbox("mytext") + n.NewButton("Textbox", func () { + a := activeWidget.NewTextbox("mytext") a.Custom = func () { - log("custom TextBox() a =", a.widget.S, a.id) + log("custom TextBox() a =", a.widget.S, "id=", a.id) } - DebugWidgetWindow(a) }) - gList.NewButton("Slider", func () { - a := gShow.NewSlider("tmp slider", 10, 55) + n.NewButton("Slider", func () { + a := activeWidget.NewSlider("tmp slider", 10, 55) a.Custom = func () { - log("custom slider() a =", a.widget.I, a.id) + log("custom slider() a =", a.widget.I, "id=", a.id) } - DebugWidgetWindow(a) }) - gList.NewButton("Spinner", func () { - a := gShow.NewSpinner("tmp spinner", 6, 32) + n.NewButton("Spinner", func () { + a := activeWidget.NewSpinner("tmp spinner", 6, 32) a.Custom = func () { - log("custom spinner() a =", a.widget.I, a.id) + log("custom spinner() a =", a.widget.I, "id=", a.id) } - DebugWidgetWindow(a) }) - gList.NewButton("Dropdown", func () { - a := gShow.NewDropdown("tmp dropdown") + n.NewButton("Dropdown", func () { + a := activeWidget.NewDropdown("tmp dropdown") a.AddDropdownName("this is better than tcl/tk") a.AddDropdownName("make something for tim") a.AddDropdownName("for qflow") a.Add("and for riscv") a.Custom = func () { - log("custom dropdown() a =", a.widget.Name, a.widget.S) + log("custom dropdown() a =", a.widget.Name, a.widget.S, "id=", a.id) } - DebugWidgetWindow(a) }) - gList.NewButton("Combobox", func () { - a := gShow.NewCombobox("tmp combobox") + n.NewButton("Combobox", func () { + a := activeWidget.NewCombobox("tmp combobox") a.Add("mirrors.wit.com") a.Add("go.wit.org") a.Custom = func () { - log("custom combobox() a =", a.widget.Name, a.widget.S) + log("custom combobox() a =", a.widget.Name, a.widget.S, "id=", a.id) } - DebugWidgetWindow(a) }) - gList.NewButton("Grid", func () { + n.NewButton("Grid", func () { // Grid numbering by (X,Y) // ----------------------------- // -- (1,1) -- (2,1) -- (3,1) -- // -- (1,2) -- (2,1) -- (3,1) -- // ----------------------------- - SetDebug(true) - debugGrid = gShow.NewGrid("tmp grid", 2, 3) - debugGrid.NewLabel("mirrors.wit.com") - SetDebug(false) - DebugWidgetWindow(debugGrid) - }) - gList.NewButton("Image", func () { - a := gShow.NewTextbox("image") - DebugWidgetWindow(a) - }) -} - -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) + // SetDebug(true) + debugGrid = activeWidget.NewGrid("tmp grid", 2, 3) + debugGridLabel = debugGrid.NewLabel("mirrors.wit.com") + // SetDebug(false) + DebugWidgetWindow(debugGrid) }) - 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) + n.NewButton("Image", func () { + activeWidget.NewImage("image") }) - g.NewButton("Add('foo')", func () { - w.widget.Action = "Add" - w.widget.S = "foo" - send(w.parent, w) + n.NewButton("Tab", func () { + activeWidget.NewTab("myTab") }) - g.NewButton("Delete('foo')", func () { - w.widget.Action = "Delete" - w.widget.S = "foo" - send(w.parent, w) - }) - g.NewButton("SetMargin(true)", func () { - w.widget.Action = "SetMargin" - w.widget.B = true - send(w.parent, w) - }) - g.NewButton("SetMargin(false)", func () { - w.widget.Action = "SetMargin" - w.widget.B = false - send(w.parent, w) + n.NewButton("Group", func () { + a := activeWidget.NewGroup("myGroup") + a.Custom = func () { + log("this code is more better", a.widget.B, "id=", a.id) + } }) - g.NewButton("Add button to (1,1)", func () { - w.widget.Action = "AddGrid" - w.widget.B = false - send(w.parent, w) + n.NewButton("Box(horizontal)", func () { + a := activeWidget.NewBox("hBox", true) + a.Custom = func () { + log("this code is more better", a.widget.B, "id=", a.id) + } }) - g.NewButton("Delete()", func () { - Delete(w) + n.NewButton("Box(vertical)", func () { + a := activeWidget.NewBox("vBox", true) + a.Custom = func () { + log("this code is more better", a.widget.B, "id=", a.id) + } }) } diff --git a/debugWindow.go b/debugWindow.go index a831869..8b1caa7 100644 --- a/debugWindow.go +++ b/debugWindow.go @@ -1,7 +1,19 @@ package gui +import ( + "git.wit.org/wit/gui/toolkit" +) + +// TODO: move all this shit into somewhere not global + +// main debugging window var bugWin *Node +// if there should be new windows or just tabs +var makeTabs bool = true + var mapWindows map[string]*Node +var checkd, checkdn, checkdt, checkdtk, lb1, lb2 *Node +var myButton *Node /* Creates a window helpful for debugging this package @@ -15,120 +27,122 @@ func DebugWindow() { bugWin.DebugTab("Debug Tab") } -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 *Node // time.Sleep(1 * time.Second) newN = n.NewTab(title) newN.Dump() //////////////////////// main debug things ////////////////////////////////// - gog = newN.NewGroup("Debugging") + gog = newN.NewGroup("Debugging Windows:") + + // generally useful debugging + cb := gog.NewCheckbox("Seperate windows") + cb.Custom = func() { + makeTabs = cb.widget.B + log(debugGui, "Custom() n.widget =", cb.widget.Name, cb.widget.B) + } + makeTabs = false + cb.Set(false) gog.NewButton("Debug Flags", func () { - newN.debugFlags(false) + newN.DebugFlags(makeTabs) }) gog.NewButton("Debug Widgets", func () { - newN.debugWidgets(false) + DebugWidgetWindow(newN) }) gog.NewButton("GO Language Internals", func () { - newN.debugGolangWindow(false) + newN.DebugGolangWindow(makeTabs) }) gog.NewButton("GO Channels debug", func () { - newN.debugGoChannels(false) + newN.DebugGoChannels(makeTabs) }) -//////////////////////// 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) + gog.NewLabel("Force Quit:") - // initialize the windows map if it hasn't been - if (mapWindows == nil) { - mapWindows = make(map[string]*Node) - } + gog.NewButton("os.Exit()", func () { + exit() + }) - 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) { - log(debugGui, "\t\t\tparent =",child.parent.id) - } else { - log(debugGui, "\t\t\tno parent") - panic("no parent") - } - if (dump == true) { - child.Dump() - } - dd.AddDropdownName(child.Name) - last = child.Name - mapWindows[child.Name] = child - } - dd.SetDropdownName(last) +//////////////////////// window debugging things ////////////////////////////////// + g1 = newN.NewGroup("list things") - g2 = newN.NewGroup("Debug Window") - g2.NewButton("SetMargined(tab)", func () { - log(debugChange, "START SetMargined(tab)", g2.Name) - // name := dd.GetText() - name := dd.widget.S - log(true, "name =", name) - log(debugChange, "name =", name) - log(debugChange, "mapWindows[name] =", mapWindows[name]) - /* - for s, n := range mapWindows { - log(debugChange, "\tname =", name) - log(debugChange, "\tmapWindows s =", s) - log(debugChange, "\tmapWindows[s] =", n) - } - */ - bugWin = mapWindows[name] - log(debugChange, "END dd.widget.S =", dd.widget.S) - // gw.UiTab.SetMargined(*gw.TabNumber, true) - }) - g2.NewButton("Hide(tab)", func () { - log(debugChange, "\tclick() START", g2.Name) - // gw.UiTab.Hide() + g1.NewButton("List Windows", func () { + dropdownWindow(g1) }) - g2.NewButton("Show(tab)", func () { - // gw.UiTab.Show() - }) - g2.NewButton("Delete(tab)", func () { - // gw.UiTab.Delete(*gw.TabNumber) - }) - g2.NewButton("change Title", func () { - // mainWindow.SetText("hello world") - }) - g2.NewButton("Quit", func () { - exit() + g1.NewButton("List Window Widgets", func () { + dropdownWindowWidgets(g1) }) - ///////////////////////////////////////////////////// - g3 = newN.NewGroup("Node Debug") + g2 := newN.NewGroup("node things") - g3.NewButton("Node.Dump()", func () { - debugGui = true - debugDump = true - bugWin.Dump() + g2.NewButton("Actions Window", func () { + DebugWidgetWindow(activeWidget) }) - g3.NewButton("Node.ListChildren(false)", func () { + g2.NewButton("Node.ListChildren(false)", func () { + g := debugGui + d := debugDump debugGui = true debugDump = true - bugWin.ListChildren(false) + activeWidget.ListChildren(false, nil, nil) + debugGui = g + debugDump = d }) - g3.NewButton("Node.ListChildren(true)", func () { + g2.NewButton("Node.ListChildren(true)", func () { + g := debugGui + d := debugDump debugGui = true debugDump = true - bugWin.ListChildren(true) + activeWidget.ListChildren(true, nil, nil) + debugGui = g + debugDump = d }) return newN } + +func dropdownWindow(p *Node) { + var mapWindows map[string]*Node + mapWindows = make(map[string]*Node) + + dd := p.NewDropdown("Window Dropdown") + dd.Custom = func() { + name := dd.widget.S + activeWidget = mapWindows[name] + setActiveWidget(activeWidget) + log("The Window was set to", name) + } + log(debugGui, "dd =", dd) + + // var last = "" + for _, child := range Config.master.children { + log(debugGui, "\t\t", child.id, child.Width, child.Height, child.Name) + // skip the fake "Flag" node + if (child.widget.Type == toolkit.Flag) { + continue + } + dd.AddDropdownName(child.Name) + // last = child.Name + mapWindows[child.Name] = child + if (activeWidget == nil) { + activeWidget = child + } + } + // dd.SetDropdownName(last) +} + +func dropdownWindowWidgets(p *Node) { + var mapWindows map[string]*Node + mapWindows = make(map[string]*Node) + + dd := p.NewDropdown("Window Widgets Dropdown") + dd.Custom = func() { + name := dd.widget.S + activeWidget = mapWindows[name] + setActiveWidget(activeWidget) + } + log(debugGui, "dd =", dd) + + activeWidget.ListChildren(true, dd, mapWindows) +} diff --git a/dropdown.go b/dropdown.go index 81746c6..e69e2bf 100644 --- a/dropdown.go +++ b/dropdown.go @@ -1,5 +1,10 @@ package gui +// functions to create 'Dropdown' and 'Combobox' +// Combobox is a Dropdown you can edit +// Thererfore, AddDropdownName() is used on both combobox and dropdown nodes +// since it is the same. confusing names? maybe... + import ( "git.wit.org/wit/gui/toolkit" ) @@ -3,7 +3,21 @@ module git.wit.org/wit/gui go 1.17 require ( + github.com/alexflint/go-arg v1.4.3 github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e + github.com/awesome-gocui/gocui v1.1.0 github.com/davecgh/go-spew v1.1.1 golang.org/x/image v0.0.0-20221017200508-ffcb3fe7d1bf ) + +require ( + github.com/alexflint/go-scalar v1.2.0 // indirect + github.com/gdamore/encoding v1.0.0 // indirect + github.com/gdamore/tcell/v2 v2.6.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect +) @@ -1,7 +1,35 @@ +github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/uo= +github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA= +github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= +github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= +github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e h1:wSQCJiig/QkoUnpvelSPbLiZNWvh2yMqQTQvIQqSUkU= github.com/andlabs/ui v0.0.0-20200610043537-70a69d6ae31e/go.mod h1:5G2EjwzgZUPnnReoKvPWVneT8APYbyKkihDVAHUi0II= +github.com/awesome-gocui/gocui v1.1.0 h1:db2j7yFEoHZjpQFeE2xqiatS8bm1lO3THeLwE6MzOII= +github.com/awesome-gocui/gocui v1.1.0/go.mod h1:M2BXkrp7PR97CKnPRT7Rk0+rtswChPtksw/vRAESGpg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= +github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= +github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= +github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -22,14 +50,23 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -14,3 +14,24 @@ func (n *Node) NewGrid(name string, x int, y int) *Node { send(n, newNode) return newNode } + +// a box is just a grid with a single set of widgets that are either horizontal or vertical +func (n *Node) NewBox(name string, horizontal bool) *Node { + var newNode *Node + newNode = n.New(name, toolkit.Box, nil) + + newNode.widget.X = 3 + newNode.widget.Y = 1 + newNode.widget.B = horizontal + + send(n, newNode) + return newNode +} + +func (n *Node) AddGrid(a *Node, x int, y int) { + n.widget.X = x + n.widget.Y = y + + a.widget.Action = "AddGrid" + send(n, a) +} @@ -4,8 +4,7 @@ import ( "git.wit.org/wit/gui/toolkit" ) -// TODO: which name is better. AddGroup or NewGroup ? -// first reaction is NewGroup +// TODO: treat a "Group" like a "Grid" func (n *Node) NewGroup(name string) *Node { var newNode *Node newNode = n.New(name, toolkit.Group, nil) diff --git a/image.go b/image.go new file mode 100644 index 0000000..b71b517 --- /dev/null +++ b/image.go @@ -0,0 +1,12 @@ +package gui + +import ( + "git.wit.org/wit/gui/toolkit" +) + +func (n *Node) NewImage(name string) *Node { + var newNode *Node + newNode = n.New(name, toolkit.Image, nil) + send(n, newNode) + return newNode +} @@ -1,7 +1,7 @@ package gui import ( - "embed" + // "embed" "git.wit.org/wit/gui/toolkit" ) @@ -12,9 +12,15 @@ import ( const Xaxis = 0 // stack things horizontally const Yaxis = 1 // stack things vertically -// may this plugin work when all other plugins fail -//go:embed toolkit/gocui.so -var res embed.FS +/* + // TODO: 2023/03/03 rethink how to get a plugin or figure out how + // golang packages can include a binary. Pull from /usr/go/go-gui/ ? + // may this plugin work when all other plugins fail + + // if this is in the plugin, the packages can't work with go.mod builds + # don't do this in the plugin // go:embed /usr/lib/go-gui/toolkit/gocui.so + # don't do this in the plugin var res embed.FS +*/ func init() { log("init() has been run") @@ -136,7 +142,8 @@ func (n *Node) StandardClose() { log(debugGui, "wit/gui Standard Window Close. n.Custom exit =", n.Custom) } -// The window is destroyed but the application does not quit +// The window is destroyed and the application exits +// TODO: properly exit the plugin since Quit() doesn't do it func StandardExit() { log("wit/gui Standard Window Exit. running os.Exit()") log("gui.Node.StandardExit() attempt to exit each toolkit plugin") @@ -146,6 +153,5 @@ func StandardExit() { aplug.Quit() } } - exit(0) } @@ -16,6 +16,12 @@ func (n *Node) New(title string, t toolkit.WidgetType, custom func()) *Node { // 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() { + log(debugChange, "Trying to find Window Close. widget.Action =", newN.widget.Action) + log(debugChange, "Trying to find Window Close. widget.Type =", newN.widget.Type) + if (newN.widget.Type == toolkit.Window) { + log(debugChange, "Need to delete newN here") + n.Delete(newN) + } if (newN.Custom == nil) { log(debugChange, "newT.Custom() == nil. Not doing anything. SEND SOMETHING TO THE CHANNEL") return @@ -38,9 +44,40 @@ func addNode(title string) *Node { n := new(Node) n.Name = title n.widget.Name = title - n.id = Config.counter - Config.counter += 1 + n.widget.SetId(n.id) + log(debugNode, "addNode = widget setid =", n.id) + Config.counter += 1 return n } + +func (n *Node) Parent() *Node { + return n.parent +} + +func (n *Node) Window() *Node { + return n.parent +} + +func (n *Node) Append(child *Node) { + n.children = append(n.children, child) + if (debugNode) { + log(debugNode, "child node:") + child.Dump() + log(debugNode, "parent node:") + n.Dump() + } +} + +func (n *Node) Delete(d *Node) { + for i, child := range n.children { + log(debugNode, "\t", i, child.id, child.Width, child.Height, child.Name) + if (child.id == d.id) { + log(debugNode, "\t\t Deleting this") + n.children = append(n.children[:i], n.children[i+1:]...) + return + } + } + log(debugError, "did not find node to delete", d.id, d.Width, d.Height, d.Name) +} @@ -205,7 +205,7 @@ func loadfile(filename string) *plugin.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) + log(debugPlugin, "Send() aplug =", aplug.name, "type=", c.widget.Type, "action=", c.widget.Action, "name=", c.widget.Name) if (aplug.Send == nil) { log(debugPlugin, "\tSend() failed (aplug.Selete = nil) for", aplug.name) continue @@ -75,21 +75,3 @@ type Node struct { // checked bool // text string } - -func (n *Node) Parent() *Node { - return n.parent -} - -func (n *Node) Window() *Node { - return n.parent -} - -func (n *Node) Append(child *Node) { - n.children = append(n.children, child) - if (debugGui) { - log(debugNode, "child node:") - child.Dump() - log(debugNode, "parent node:") - n.Dump() - } -} diff --git a/toolkit/andlabs/append.go b/toolkit/andlabs/append.go index 811ffbc..4578c94 100644 --- a/toolkit/andlabs/append.go +++ b/toolkit/andlabs/append.go @@ -7,41 +7,35 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -// make new Group here -func (t *andlabsT) doAppend(newt *andlabsT, c *ui.Control) { - - if (newt.tw != nil) { - if (newt.tw.Type == toolkit.Grid) { - log(true, "doAppend() going to attempt uiGrid") - // hack to add shit to a grid - button1 := ui.NewButton("a(0,2)") - newt.uiGrid.Append(button1, - 0, 2, 1, 1, - false, ui.AlignFill, false, ui.AlignFill) - button2 := ui.NewButton("a(1,2)") - newt.uiGrid.Append(button2, - 1, 2, 1, 1, - false, ui.AlignFill, false, ui.AlignFill) +// move all the append code here +func (t *andlabsT) doAppend(kind toolkit.WidgetType, newt *andlabsT, c *ui.Control) { + if (kind == toolkit.Grid) { + log(debugToolkit, "doAppend() attempt to append a ui.Control into a uiGrid") + // hack to add shit to a grid + button1 := ui.NewButton("a(0,2)") + newt.uiGrid.Append(button1, + 0, 2, 1, 1, + false, ui.AlignFill, false, ui.AlignFill) + button2 := ui.NewButton("a(1,2)") + newt.uiGrid.Append(button2, + 1, 2, 1, 1, + false, ui.AlignFill, false, ui.AlignFill) - if (t.uiBox != nil) { - log(true, "doAppend() on uiGrid to a uiBox") - if (newt.Name == "output") { - t.uiBox.Append(newt.uiGrid, true) - } else { + if (t.uiBox != nil) { + log(debugToolkit, "doAppend() on uiGrid to a uiBox") + if (newt.Name == "output") { + t.uiBox.Append(newt.uiGrid, true) + } else { t.uiBox.Append(newt.uiGrid, stretchy) - } - return } - log(true, "doAppend() on uiGrid failed") return } - } else { - log(true, "doAppend() newt.tw == nil ERROR on newt.Name =", newt.Name) + log(debugToolkit, "doAppend() on uiGrid failed") + return } - // hack to pass a group - if (c == nil) { - log(true, "attempting to doAppend() on a uiGroup") + if (kind == toolkit.Group) { + log(debugToolkit, "doAppend() attempt a uiGroup") if (t.uiBox != nil) { if (newt.Name == "output") { t.uiBox.Append(newt.uiGroup, true) @@ -52,20 +46,19 @@ func (t *andlabsT) doAppend(newt *andlabsT, c *ui.Control) { } if (t.uiWindow != nil) { - log(true, "This is a raw window without a box. probably make a box here and add the group to that") - t.Dump(true) - newt.Dump(true) + log(debugToolkit, "This is a raw window without a box. probably make a box here and add the group to that") + newt.Dump(debugToolkit) t.uiBox = ui.NewHorizontalBox() t.uiWindow.SetChild(t.uiBox) - log(true, "tried to make a box", t.uiBox) + log(debugToolkit, "tried to make a box", t.uiBox) if (newt.Name == "output") { - log(true, "tried to t.uiBox.Append(*c, true)") + log(debugToolkit, "tried to t.uiBox.Append(*c, true)") if (t.uiBox == nil) { - log(true, "tried to t.uiBox.Append(*c, true)") + log(debugToolkit, "tried to t.uiBox.Append(*c, true)") } t.uiBox.Append(newt.uiGroup, true) } else { - log(true, "tried to t.uiBox.Append(*c, stretchy)") + log(debugToolkit, "tried to t.uiBox.Append(*c, stretchy)") t.uiBox.Append(newt.uiGroup, stretchy) } return @@ -75,7 +68,13 @@ func (t *andlabsT) doAppend(newt *andlabsT, c *ui.Control) { log(debugError, "probably could just make a box here?") exit("internal wit/gui error") } - if (t.uiBox != nil) { + + if (kind == toolkit.Textbox) { + if (t.uiBox == nil) { + log(debugError, "NewTextbox() 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") + } // TODO: temporary hack to make the output textbox 'fullscreen' if (newt.Name == "output") { t.uiBox.Append(*c, true) @@ -84,11 +83,12 @@ func (t *andlabsT) doAppend(newt *andlabsT, c *ui.Control) { } return } + if (t.uiWindow != nil) { - log(true, "This is a raw window without a box. probably make a box here and add the group to that") + log(debugToolkit, "This is a raw window without a box. probably make a box here and add the group to that") t.uiBox = ui.NewHorizontalBox() t.uiWindow.SetChild(t.uiBox) - log(true, "tried to make a box") + log(debugToolkit, "tried to make a box") if (newt.Name == "output") { t.uiBox.Append(*c, true) } else { diff --git a/toolkit/andlabs/button.go b/toolkit/andlabs/button.go index deb34fa..4ae791c 100644 --- a/toolkit/andlabs/button.go +++ b/toolkit/andlabs/button.go @@ -10,11 +10,11 @@ import ( func newButton(parentW *toolkit.Widget, w *toolkit.Widget) { var t, newt *andlabsT var b *ui.Button - log(debugToolkit, "gui.andlabs.NewButton()", w.Name) + log(debugToolkit, "newButton()", w.Name) t = mapToolkits[parentW] if (t == nil) { - log(debugToolkit, "go.andlabs.NewButton() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "newButton() toolkit struct == nil. name=", parentW.Name, w.Name) return } @@ -32,22 +32,32 @@ func newButton(parentW *toolkit.Widget, w *toolkit.Widget) { newt.commonChange(newt.tw) }) - log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box parent t:", w.Name) - log(debugToolkit, "gui.Toolbox.NewButton() about to append to Box new t:", w.Name) + log(debugToolkit, "newButton() about to append to Box parent t:", w.Name) + log(debugToolkit, "newButton() about to append to Box new t:", w.Name) + if (debugToolkit) { + ShowDebug () + } if (t.uiBox != nil) { t.uiBox.Append(b, stretchy) } else if (t.uiWindow != nil) { t.uiWindow.SetChild(b) } else { - log(debugToolkit, "ERROR: wit/gui andlabs couldn't place this button in a box or a window") - log(debugToolkit, "ERROR: wit/gui andlabs couldn't place this button in a box or a window") + log(debugError, "ERROR: wit/gui andlabs couldn't place this button in a box or a window") + log(debugError, "ERROR: wit/gui andlabs couldn't place this button in a box or a window") return } mapWidgetsToolkits(w, newt) } +// This routine is very specific to this toolkit +// It's annoying and has to be copied to each widget when there are changes +// it could be 'simplfied' maybe or made to be more generic, but this is as far as I've gotten +// it's probably not worth working much more on this toolkit, the andlabs/ui has been great and got me here! +// but it's time to write direct GTK, QT, macos and windows toolkit plugins +// -- jcarr 2023/03/09 + func doButton(p *toolkit.Widget, c *toolkit.Widget) { if broken(c) { return @@ -58,18 +68,18 @@ func doButton(p *toolkit.Widget, c *toolkit.Widget) { } 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) + log(debugError, "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) + log(debugError, "Button() ct.broken", ct) return } if (ct.uiButton == nil) { - log(true, "Button() uiButton == nil", ct) + log(debugError, "Button() uiButton == nil", ct) return } - log(true, "Going to attempt:", c.Action) + log(debugToolkit, "Going to attempt:", c.Action) switch c.Action { case "Enable": ct.uiButton.Enable() @@ -82,6 +92,6 @@ func doButton(p *toolkit.Widget, c *toolkit.Widget) { case "Set": ct.uiButton.SetText(c.S) default: - log(true, "Can't do", c.Action, "to a Button") + log(debugError, "Can't do", c.Action, "to a Button") } } diff --git a/toolkit/andlabs/checkbox.go b/toolkit/andlabs/checkbox.go index 16e4eed..d28d3dc 100644 --- a/toolkit/andlabs/checkbox.go +++ b/toolkit/andlabs/checkbox.go @@ -70,7 +70,7 @@ func doCheckbox(p *toolkit.Widget, c *toolkit.Widget) { log(true, "checkbox() uiCheckbox == nil", ct) return } - log(true, "Going to attempt:", c.Action) + log(debugChange, "Going to attempt:", c.Action) switch c.Action { case "Enable": ct.uiCheckbox.Enable() @@ -80,10 +80,11 @@ func doCheckbox(p *toolkit.Widget, c *toolkit.Widget) { ct.uiCheckbox.Show() case "Hide": ct.uiCheckbox.Hide() - case "Set": + case "SetText": ct.uiCheckbox.SetText(c.S) + case "Set": ct.uiCheckbox.SetChecked(c.B) default: - log(true, "Can't do", c.Action, "to a checkbox") + log(debugError, "Can't do", c.Action, "to a checkbox") } } diff --git a/toolkit/andlabs/combobox.go b/toolkit/andlabs/combobox.go index 08e7148..3395406 100644 --- a/toolkit/andlabs/combobox.go +++ b/toolkit/andlabs/combobox.go @@ -80,7 +80,7 @@ func doCombobox(p *toolkit.Widget, c *toolkit.Widget) { log(true, "Combobox() uiEditableCombobox == nil", ct) return } - log(true, "Going to attempt:", c.Action) + log(debugChange, "Going to attempt:", c.Action) switch c.Action { case "Add": ct.AddComboboxName(c.S) @@ -95,6 +95,6 @@ func doCombobox(p *toolkit.Widget, c *toolkit.Widget) { case "Set": ct.uiEditableCombobox.SetText(c.S) default: - log(true, "Can't do", c.Action, "to a Combobox") + log(debugError, "Can't do", c.Action, "to a Combobox") } } diff --git a/toolkit/andlabs/common.go b/toolkit/andlabs/common.go index d2811cb..2e3997b 100644 --- a/toolkit/andlabs/common.go +++ b/toolkit/andlabs/common.go @@ -2,16 +2,9 @@ package main import ( "git.wit.org/wit/gui/toolkit" - "github.com/davecgh/go-spew/spew" +// "github.com/davecgh/go-spew/spew" ) -// 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 - // log(debugToolkit, "gui/toolkit init() Setting defaultBehavior = true") - setDefaultBehavior(true) -} - func (t *andlabsT) commonChange(tw *toolkit.Widget) { log(debugChange, "commonChange() START widget =", t.Name, t.Type) if (tw == nil) { @@ -30,6 +23,7 @@ func (t *andlabsT) commonChange(tw *toolkit.Widget) { // 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 } @@ -52,6 +46,7 @@ func (t *andlabsT) broken() bool { t.Dump(debugToolkit) return false } + */ return false } func broken(w *toolkit.Widget) bool { @@ -79,123 +74,3 @@ func dump(p *toolkit.Widget, c *toolkit.Widget, b bool) { } ct.Dump(b) } - -func setMarginNew(w *toolkit.Widget, b bool) { - wt := mapToolkits[w] - log(true, "START setMarginNew", w.Name) - if (wt == nil) { - return - } - if (wt.uiGroup != nil) { - log(true, "uiGroup.SetMargined(true)") - wt.uiGroup.SetMargined(b) - } - if (wt.uiTab != nil) { - i := wt.uiTab.NumPages() - log(true, "tab.NumPages() =", i) - for i > 0 { - i -= 1 - log(true, "uiTab.SetMargined(true) for i =", i) - wt.uiTab.SetMargined(i, b) - } - } else { - log(true, "no uitab") - } - if (wt.uiWindow != nil) { - log(true, "uiWindow.SetMargined(true)") - wt.uiWindow.SetMargined(b) - } - log(true, "END setMarginNew", w.Name) -} - -func setMargin(p *toolkit.Widget, c *toolkit.Widget, b bool) { - log(true, "Starting to implement SetMargin here") - dump(p, c, true) - - setMarginNew(c, b) - setMarginNew(p, b) -} - -func (t *andlabsT) String() string { - return t.GetText() -} - -func (t *andlabsT) GetText() string { - log(debugToolkit, "GetText() Enter debugToolkit=", debugToolkit) - if (t.uiEntry != nil) { - log(debugToolkit, "uiEntry.Text() =", t.uiEntry.Text()) - return t.uiEntry.Text() - } - if (t.uiMultilineEntry != nil) { - log(debugToolkit, "uiMultilineEntry.Text() =", t.uiMultilineEntry.Text()) - text := t.uiMultilineEntry.Text() - log(debugToolkit, "uiMultilineEntry.Text() =", text) - t.text = text - return text - } - if (t.uiCombobox != nil) { - log(debugToolkit, "uiCombobox() =", t.text) - return t.text - } - return "" -} - -func (t *andlabsT) SetText(s string) bool { - log(debugToolkit, "Text() SetText() Enter") - if (t.uiEntry != nil) { - log(debugToolkit, "Value() =", t.uiEntry.Text) - t.uiEntry.SetText(s) - return true - } - if (t.uiMultilineEntry != nil) { - log(debugToolkit, "Value() =", t.uiMultilineEntry.Text) - t.uiMultilineEntry.SetText(s) - return true - } - return false -} - -func sanity(t *andlabsT) bool { - if (debugToolkit) { - log(debugToolkit, "Value() Enter") - scs := spew.ConfigState{MaxDepth: 1} - scs.Dump(t) - } - if (t.uiEntry == nil) { - log(debugToolkit, "Value() =", t.uiEntry.Text) - return false - } - return true -} - -func (t *andlabsT) SetValue(i int) bool { - log(debugToolkit, "SetValue() START") - if (sanity(t)) { - return false - } - t.Dump(debugToolkit) - // panic("got to toolkit.SetValue") - return true -} - -func (t *andlabsT) Value() int { - if (debugToolkit) { - log(debugToolkit, "Value() Enter") - scs := spew.ConfigState{MaxDepth: 1} - scs.Dump(t) - } - if (t == nil) { - log(debugToolkit, "Value() can not get value t == nil") - return 0 - } - if (t.uiSlider != nil) { - log(debugToolkit, "Value() =", t.uiSlider.Value) - return t.uiSlider.Value() - } - if (t.uiSpinbox != nil) { - log(debugToolkit, "Value() =", t.uiSpinbox.Value) - return t.uiSpinbox.Value() - } - log(debugToolkit, "Value() Could not find a ui element to get a value from") - return 0 -} diff --git a/toolkit/andlabs/debug.go b/toolkit/andlabs/debug.go index 8b11f8c..f2902ca 100644 --- a/toolkit/andlabs/debug.go +++ b/toolkit/andlabs/debug.go @@ -2,8 +2,6 @@ package main import "git.wit.org/wit/gui/toolkit" -// import "github.com/davecgh/go-spew/spew" - var defaultBehavior bool = true var bookshelf bool // do you want things arranged in the box like a bookshelf or a stack? @@ -16,9 +14,8 @@ var margin bool // add space around the frames of windows var debugToolkit bool var debugChange bool var debugPlugin bool -var debugFlag bool +var debugFlags 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 func setDefaultBehavior(s bool) { @@ -37,24 +34,12 @@ func setDefaultBehavior(s bool) { } } -/* -func SetDebugToolkit (s bool) { - debugToolkit = s - log(true, "debugToolkit =", debugToolkit) - log(true, "debugChange =", debugChange) -} - -func SetDebugChange (s bool) { - debugChange = s - log(true, "debugToolkit =", debugToolkit) - log(true, "debugChange =", debugChange) -} -*/ - func ShowDebug () { log(true, "debugToolkit =", debugToolkit) - log(true, "debugError =", debugError) log(true, "debugChange =", debugChange) + log(true, "debugPlugin =", debugPlugin) + log(true, "debugFlags =", debugFlags) + log(true, "debugError =", debugError) } func (t *andlabsT) Dump(b bool) { diff --git a/toolkit/andlabs/delete.go b/toolkit/andlabs/delete.go new file mode 100644 index 0000000..4232521 --- /dev/null +++ b/toolkit/andlabs/delete.go @@ -0,0 +1,56 @@ +package main + +// 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" + +// 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 + } + + 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/dropdown.go b/toolkit/andlabs/dropdown.go index 57642e0..35d391b 100644 --- a/toolkit/andlabs/dropdown.go +++ b/toolkit/andlabs/dropdown.go @@ -48,7 +48,7 @@ func (t *andlabsT) AddDropdownName(title string) { // 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.uiCombobox.SetSelected(0) } t.c = t.c + 1 } @@ -105,18 +105,18 @@ func doDropdown(p *toolkit.Widget, c *toolkit.Widget) { } 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) + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) return } if ct.broken() { - log(true, "Dropdown() ct.broken", ct) + log(debugError, "Dropdown() ct.broken", ct) return } if (ct.uiCombobox == nil) { - log(true, "Dropdown() uiCombobox == nil", ct) + log(debugError, "Dropdown() uiCombobox == nil", ct) return } - log(true, "Going to attempt:", c.Action) + log(debugChange, "Going to attempt:", c.Action) switch c.Action { case "Add": ct.AddDropdownName(c.S) @@ -131,7 +131,29 @@ func doDropdown(p *toolkit.Widget, c *toolkit.Widget) { ct.uiCombobox.Hide() case "Set": ct.uiCombobox.SetSelected(1) + case "SetText": + var orig int + var i int = -1 + var s string + orig = ct.uiCombobox.Selected() + log(debugError, "TODO: set a Dropdown by the name selected =", orig, ct.c, c.S) + // try to find the string + for i, s = range ct.val { + log(debugError, "i, s", i, s) + if (c.S == s) { + ct.uiCombobox.SetSelected(i) + return + } + } + // if i == -1, then there are not any things in the menu to select + if (i == -1) { + return + } + // if the string was never set, then set the dropdown to the last thing added to the menu + if (orig == -1) { + ct.uiCombobox.SetSelected(i) + } default: - log(true, "Can't do", c.Action, "to a Dropdown") + log(debugError, "Can't do", c.Action, "to a Dropdown") } } diff --git a/toolkit/andlabs/grid.go b/toolkit/andlabs/grid.go index 8d09152..47a70e3 100644 --- a/toolkit/andlabs/grid.go +++ b/toolkit/andlabs/grid.go @@ -36,29 +36,7 @@ func newGrid(parentW *toolkit.Widget, w *toolkit.Widget) { newt.uiGrid = c newt.uiBox = t.uiBox newt.tw = w - t.doAppend(newt, nil) - /* - if (defaultBehavior) { - t.uiBox.Append(c, stretchy) - } - - button1 := ui.NewButton("a(0,0)") - c.Append(button1, - 0, 0, 1, 1, - false, ui.AlignFill, false, ui.AlignFill) - - button2 := ui.NewButton("a(1,0)") - c.Append(button2, - 1, 0, 1, 1, - false, ui.AlignFill, false, ui.AlignFill) - */ - - // Append(child Control, - // left, top int, - // xspan, yspan int, - // hexpand bool, halign Align, - // vexpand bool, valign Align) { - + t.doAppend(toolkit.Grid, newt, nil) mapWidgetsToolkits(w, newt) } @@ -72,19 +50,18 @@ func doGrid(p *toolkit.Widget, c *toolkit.Widget) { } 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) + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) return } if ct.broken() { - log(true, "Grid() ct.broken", ct) + log(debugError, "Grid() ct.broken", ct) return } if (ct.uiGrid == nil) { - - log(true, "Grid() uiGrid == nil", ct) + log(debugError, "Grid() uiGrid == nil", ct) return } - log(true, "Going to attempt:", c.Action) + log(debugChange, "Going to attempt:", c.Action) switch c.Action { case "Enable": ct.uiGrid.Enable() @@ -93,10 +70,22 @@ func doGrid(p *toolkit.Widget, c *toolkit.Widget) { case "Show": ct.uiGrid.Show() case "Hide": + log(debugError, "trying Hide on grid") ct.uiGrid.Hide() + case "SetMargin": + log(debugError, "trying SetMargin on grid") + ct.uiGrid.SetPadded(c.B) case "Set": - log(true, "Can I use 'Set' to place a *Node in a Grid?") + log(debugError, "Can I use 'Set' to place a *Node in a Grid?") + /* + case "AddGrid": + log(true, "how do I add a thing to a grid?") + dump(p, c, true) + newt.uiGrid.Append(button1, + 0, 2, 1, 1, + false, ui.AlignFill, false, ui.AlignFill) + */ default: - log(true, "Can't do", c.Action, "to a Grid") + log(debugError, "Can't do", c.Action, "to a Grid") } } diff --git a/toolkit/andlabs/group.go b/toolkit/andlabs/group.go index 903cb4f..717da42 100644 --- a/toolkit/andlabs/group.go +++ b/toolkit/andlabs/group.go @@ -8,8 +8,7 @@ import ( ) func newGroup(parentW *toolkit.Widget, w *toolkit.Widget) { - // log(debugToolkit, "gui.andlabs.NewGroup()", w.Name) - log(true, "NewGroup()", w.Name) + log(debugToolkit, "NewGroup()", w.Name) t := mapToolkits[parentW] if (t == nil) { @@ -31,31 +30,7 @@ func (t *andlabsT) rawGroup(title string) *andlabsT { g.SetMargined(margin) newt.uiGroup = g - t.doAppend(&newt, nil) - /* - if (t.uiBox != nil) { - // TODO: temporary hack to make the output textbox 'fullscreen' - if (newt.Name == "output") { - t.uiBox.Append(g, true) - } else { - t.uiBox.Append(g, stretchy) - } - } else if (t.uiWindow != nil) { - log(true, "This is a raw window without a box. probably make a box here and add the group to that") - t.uiBox = ui.NewHorizontalBox() - t.uiWindow.SetChild(t.uiBox) - log(true, "tried to make a box") - if (newt.Name == "output") { - t.uiBox.Append(g, true) - } else { - t.uiBox.Append(g, stretchy) - } - } else { - 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") - } - */ + t.doAppend(toolkit.Group, &newt, nil) hbox := ui.NewVerticalBox() hbox.SetPadded(padded) @@ -67,3 +42,56 @@ func (t *andlabsT) rawGroup(title string) *andlabsT { return &newt } + +// This routine is very specific to this toolkit +// It's annoying and has to be copied to each widget when there are changes +// it could be 'simplfied' maybe or made to be more generic, but this is as far as I've gotten +// it's probably not worth working much more on this toolkit, the andlabs/ui has been great and got me here! +// but it's time to write direct GTK, QT, macos and windows toolkit plugins +// -- jcarr 2023/03/09 + +func doGroup(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + log(debugChange, "Going to attempt:", c.Action) + if (c.Action == "New") { + newGroup(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(debugError, "Group() ct.broken", ct) + return + } + if (ct.uiGroup == nil) { + log(debugError, "Label() uiGroup == nil", ct) + return + } + switch c.Action { + case "Enable": + ct.uiGroup.Enable() + case "Disable": + ct.uiGroup.Disable() + case "Show": + ct.uiGroup.Show() + case "Hide": + ct.uiGroup.Hide() + case "Get": + c.S = ct.uiGroup.Title() + case "Set": + ct.uiGroup.SetTitle(c.S) + case "SetText": + ct.uiGroup.SetTitle(c.S) + case "SetMargin": + ct.uiGroup.SetMargined(c.B) + case "Destroy": + ct.uiGroup.Destroy() + default: + log(debugError, "Can't do", c.Action, "to a Group") + } +} diff --git a/toolkit/andlabs/label.go b/toolkit/andlabs/label.go index fca9abb..6fa4baa 100644 --- a/toolkit/andlabs/label.go +++ b/toolkit/andlabs/label.go @@ -39,29 +39,36 @@ func newLabel(parentW *toolkit.Widget, w *toolkit.Widget) { mapWidgetsToolkits(w, newt) } +// This routine is very specific to this toolkit +// It's annoying and has to be copied to each widget when there are changes +// it could be 'simplfied' maybe or made to be more generic, but this is as far as I've gotten +// it's probably not worth working much more on this toolkit, the andlabs/ui has been great and got me here! +// but it's time to write direct GTK, QT, macos and windows toolkit plugins +// -- jcarr 2023/03/09 + func doLabel(p *toolkit.Widget, c *toolkit.Widget) { if broken(c) { return } + log(debugChange, "Going to attempt:", c.Action) 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) + log(debugError, "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) + log(debugError, "Label() ct.broken", ct) return } if (ct.uiLabel == nil) { - log(true, "Label() uiLabel == nil", ct) + log(debugError, "Label() uiLabel == nil", ct) return } - log(true, "Going to attempt:", c.Action) switch c.Action { case "Enable": ct.uiLabel.Enable() @@ -71,9 +78,11 @@ func doLabel(p *toolkit.Widget, c *toolkit.Widget) { ct.uiLabel.Show() case "Hide": ct.uiLabel.Hide() + case "SetText": + ct.uiLabel.SetText(c.S) case "Set": ct.uiLabel.SetText(c.S) default: - log(true, "Can't do", c.Action, "to a Label") + log(debugError, "Can't do", c.Action, "to a Label") } } diff --git a/toolkit/andlabs/log.go b/toolkit/andlabs/log.go index 98b4e54..43b90cb 100644 --- a/toolkit/andlabs/log.go +++ b/toolkit/andlabs/log.go @@ -103,12 +103,12 @@ func log(a ...any) { if (a[0] == false) { return } - a[0] = "WIT/GUI/Toolkit" + a[0] = "GUI/Toolkit/Andlabs" } if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) { // a = a[1:] - a[0] = "WIT/GUI/Toolkit" + a[0] = "GUI/Toolkit/Andlabs" if (debugToolkit) { scs := spew.ConfigState{MaxDepth: 1} scs.Dump(a) diff --git a/toolkit/andlabs/main.go b/toolkit/andlabs/main.go index 20bbd8b..c719352 100644 --- a/toolkit/andlabs/main.go +++ b/toolkit/andlabs/main.go @@ -16,11 +16,6 @@ func Main(f func()) { log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") ui.Main( func() { log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") - log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") - log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") - log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") - log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") - log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") // time.Sleep(1 * time.Second) // NewWindow2("helloworld2", 200, 100) f() @@ -37,17 +32,22 @@ func Main(f func()) { // func Queue(f func()) { log(debugToolkit, "Sending function to ui.QueueMain()") - log(true, "using gui.Queue() in this plugin DOES BREAK. TODO: wrap this") + log(debugPlugin, "using gui.Queue() in this plugin DOES BREAK. TODO: solve this with channels") ui.QueueMain(f) } +// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc func Init() { log(debugToolkit, "Init()") + // Can you pass values to a plugin init() ? Otherwise, there is no way to safely print + // log(debugToolkit, "gui/toolkit init() Setting defaultBehavior = true") + setDefaultBehavior(true) mapWidgets = make(map[*andlabsT]*toolkit.Widget) mapToolkits = make(map[*toolkit.Widget]*andlabsT) } +// TODO: properly exit the plugin since Quit() doesn't do it func Quit() { log(debugToolkit, "Quit() TODO: close the toolkit cleanly") } diff --git a/toolkit/andlabs/plugin.go b/toolkit/andlabs/plugin.go index 8b75766..8cac830 100644 --- a/toolkit/andlabs/plugin.go +++ b/toolkit/andlabs/plugin.go @@ -26,31 +26,33 @@ func Send(p *toolkit.Widget, c *toolkit.Widget) { } log(debugPlugin, "Send() child =", c.Name, ",", c.Action, ",", c.Type) + /* if (c.Action == "SetMargin") { - log(true, "need to implement SetMargin here") - setMargin(p, c, c.B) + log(debugError, "need to implement SetMargin here") + setMargin(c, c.B) return } + */ switch c.Type { case toolkit.Window: - newWindow(c) + doWindow(c) case toolkit.Tab: - newTab(p, c) + doTab(p, c) case toolkit.Group: - newGroup(p, c) + doGroup(p, c) case toolkit.Button: doButton(p, c) case toolkit.Checkbox: doCheckbox(p, c) case toolkit.Label: - newLabel(p, c) + doLabel(p, c) case toolkit.Textbox: doTextbox(p, c) case toolkit.Slider: - newSlider(p, c) + doSlider(p, c) case toolkit.Spinner: - newSpinner(p, c) + doSpinner(p, c) case toolkit.Dropdown: doDropdown(p, c) case toolkit.Combobox: @@ -58,79 +60,32 @@ func Send(p *toolkit.Widget, c *toolkit.Widget) { case toolkit.Grid: doGrid(p, c) case toolkit.Flag: - log(debugFlag, "plugin Send() flag parent =", p.Name, p.Type) - log(debugFlag, "plugin Send() flag child =", c.Name, c.Type) - log(debugFlag, "plugin Send() flag child.Action =", c.Action) - log(debugFlag, "plugin Send() flag child.S =", c.S) - log(debugFlag, "plugin Send() flag child.B =", c.B) - log(debugFlag, "plugin Send() what to flag?") + // log(debugFlags, "plugin Send() flag parent =", p.Name, p.Type) + // log(debugFlags, "plugin Send() flag child =", c.Name, c.Type) + // log(debugFlags, "plugin Send() flag child.Action =", c.Action) + // log(debugFlags, "plugin Send() flag child.S =", c.S) + // log(debugFlags, "plugin Send() flag child.B =", c.B) + // log(debugFlags, "plugin Send() what to flag?") // should set the checkbox to this value switch c.S { - case "Error": - debugError = c.B case "Toolkit": debugToolkit = c.B case "Change": debugChange = c.B + case "Plugin": + debugPlugin = c.B + case "Flags": + debugFlags = c.B + case "Error": + debugError = c.B case "Show": ShowDebug() default: log(debugError, "Can't set unknown flag", c.S) } default: - log(true, "plugin Send() unknown parent =", p.Name, p.Type) - log(true, "plugin Send() unknown child =", c.Name, c.Type) - log(true, "plugin Send() Don't know how to do", c.Type, "yet") - } -} - -// 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 - } - - 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() - } + log(debugError, "plugin Send() unknown parent =", p.Name, p.Type) + log(debugError, "plugin Send() unknown child =", c.Name, c.Type) + log(debugError, "plugin Send() Don't know how to do", c.Type, "yet") } } diff --git a/toolkit/andlabs/slider.go b/toolkit/andlabs/slider.go index f75947a..f31bc25 100644 --- a/toolkit/andlabs/slider.go +++ b/toolkit/andlabs/slider.go @@ -35,13 +35,60 @@ func (t *andlabsT) newSlider(w *toolkit.Widget) *andlabsT { func newSlider(parentW *toolkit.Widget, w *toolkit.Widget) { var newt *andlabsT - log(debugToolkit, "gui.andlabs.NewTab()", w.Name) + log(debugToolkit, "newSlider()", w.Name) t := mapToolkits[parentW] if (t == nil) { - log(debugToolkit, "go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugError, "newSlider() ERROR toolkit struct == nil. name=", parentW.Name, w.Name) return } newt = t.newSlider(w) mapWidgetsToolkits(w, newt) } + +// This routine is very specific to this toolkit +// It's annoying and has to be copied to each widget when there are changes +// it could be 'simplfied' maybe or made to be more generic, but this is as far as I've gotten +// it's probably not worth working much more on this toolkit, the andlabs/ui has been great and got me here! +// but it's time to write direct GTK, QT, macos and windows toolkit plugins +// -- jcarr 2023/03/09 + +func doSlider(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + log(debugChange, "Going to attempt:", c.Action) + if (c.Action == "New") { + newSlider(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(debugError, "Slider() ct.broken", ct) + return + } + if (ct.uiSlider == nil) { + log(debugError, "Label() uiSlider == nil", ct) + return + } + switch c.Action { + case "Enable": + ct.uiSlider.Enable() + case "Disable": + ct.uiSlider.Disable() + case "Show": + ct.uiSlider.Show() + case "Hide": + ct.uiSlider.Hide() + case "Set": + ct.uiSlider.SetValue(c.I) + case "Get": + c.I = ct.uiSlider.Value() + default: + log(debugError, "Can't do", c.Action, "to a Slider") + } +} diff --git a/toolkit/andlabs/spinner.go b/toolkit/andlabs/spinner.go index 2ee556c..2e87541 100644 --- a/toolkit/andlabs/spinner.go +++ b/toolkit/andlabs/spinner.go @@ -36,9 +36,56 @@ func newSpinner(parentW *toolkit.Widget, w *toolkit.Widget) { t := mapToolkits[parentW] if (t == nil) { - log(debugToolkit, "go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugError, "NewSpinner() toolkit struct == nil. name=", parentW.Name, w.Name) return } newt = t.newSpinner(w) mapWidgetsToolkits(w, newt) } + +// This routine is very specific to this toolkit +// It's annoying and has to be copied to each widget when there are changes +// it could be 'simplfied' maybe or made to be more generic, but this is as far as I've gotten +// it's probably not worth working much more on this toolkit, the andlabs/ui has been great and got me here! +// but it's time to write direct GTK, QT, macos and windows toolkit plugins +// -- jcarr 2023/03/09 + +func doSpinner(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + log(debugChange, "Going to attempt:", c.Action) + if (c.Action == "New") { + newSpinner(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(debugError, "Spinner() ct.broken", ct) + return + } + if (ct.uiSpinbox == nil) { + log(debugError, "Label() uiSpinbox == nil", ct) + return + } + switch c.Action { + case "Enable": + ct.uiSpinbox.Enable() + case "Disable": + ct.uiSpinbox.Disable() + case "Show": + ct.uiSpinbox.Show() + case "Hide": + ct.uiSpinbox.Hide() + case "Set": + ct.uiSpinbox.SetValue(c.I) + case "Get": + c.I = ct.uiSpinbox.Value() + default: + log(debugError, "Can't do", c.Action, "to a Spinbox") + } +} diff --git a/toolkit/andlabs/tab.go b/toolkit/andlabs/tab.go index aaac102..9dcd3fa 100644 --- a/toolkit/andlabs/tab.go +++ b/toolkit/andlabs/tab.go @@ -130,3 +130,53 @@ func newTab(parentW *toolkit.Widget, w *toolkit.Widget) { newt = t.newTab(w.Name) mapWidgetsToolkits(w, newt) } + +func doTab(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + if (c.Action == "New") { + newTab(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(debugError, "Tab() ct.broken", ct) + return + } + if (ct.uiTab == nil) { + + log(debugError, "Tab() uiTab == nil", ct) + return + } + log(debugChange, "Going to attempt:", c.Action) + switch c.Action { + case "Enable": + ct.uiTab.Enable() + case "Disable": + ct.uiTab.Disable() + case "Show": + ct.uiTab.Show() + case "Hide": + ct.uiTab.Hide() + case "Get": + c.I = ct.uiTab.NumPages() + case "Add": + log(true, "how do I add a tab here in doTab()?") + dump(p, c, true) + case "SetMargin": + i := ct.uiTab.NumPages() + log(true, "tab.NumPages() =", i) + for i > 0 { + i -= 1 + log(true, "uiTab.SetMargined(true) for i =", i) + ct.uiTab.SetMargined(i, c.B) + } + default: + log(debugError, "Can't do", c.Action, "to a Tab") + } +} diff --git a/toolkit/andlabs/textbox.go b/toolkit/andlabs/textbox.go index ddc27a4..9f7c3b4 100644 --- a/toolkit/andlabs/textbox.go +++ b/toolkit/andlabs/textbox.go @@ -95,11 +95,11 @@ func doTextbox(p *toolkit.Widget, c *toolkit.Widget) { } 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) + log(debugError, "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) + log(debugError, "Textbox() ct.broken", ct) return } if (ct.uiMultilineEntry == nil) { @@ -124,7 +124,7 @@ func (t *andlabsT) doSimpleAction() { } else if (t.uiMultilineEntry != nil) { t.uiMultilineEntry.Enable() } else { - log(true, "don't know what to enable", t.Name) + log(debugError, "don't know what to enable", t.Name) } case "Disable": if (t.uiEntry != nil) { @@ -132,12 +132,14 @@ func (t *andlabsT) doSimpleAction() { } else if (t.uiMultilineEntry != nil) { t.uiMultilineEntry.Disable() } else { - log(true, "don't know what to disable", t.Name) + log(debugError, "don't know what to disable", t.Name) } case "Show": t.uiMultilineEntry.Show() case "Hide": t.uiMultilineEntry.Hide() + case "SetText": + t.uiMultilineEntry.SetText(t.tw.S) case "Set": t.uiMultilineEntry.SetText(t.tw.S) default: diff --git a/toolkit/andlabs/widget.go b/toolkit/andlabs/widget.go index 58f8514..2ea15d1 100644 --- a/toolkit/andlabs/widget.go +++ b/toolkit/andlabs/widget.go @@ -16,7 +16,7 @@ func listMap(b bool) { for t, w := range mapWidgets { log(b, "andlabs =", t.Name, "widget =", w.Name) } - log(debugToolkit, "listMap() HERE mapToolkits()") + log(b, "listMap() HERE mapToolkits()") for w, t := range mapToolkits { log(b, "andlabs =", t, "widget =", w.Name) t.Dump(b) @@ -40,12 +40,12 @@ func mapWidgetsToolkits(w *toolkit.Widget, t *andlabsT) { log(true, "mapToolkits[w] is set, but mapWidgets[t] is nil") panic("WTF mapWidgets[t] == nil") } - log(true, "mapToolkits[w] is", tw) + log(debugToolkit, "mapToolkits[w] is", tw) if (tw == nil) { - log(true, "BAD map? mapWidgets[w] tw == nil") + log(debugError, "BAD map? mapWidgets[w] tw == nil") } else { - log(true, "BAD map? mapWidgets[w] is", tw) - tw.Dump(true) + log(debugError, "BAD map? mapWidgets[w] is", tw) + tw.Dump(debugError) } } @@ -57,10 +57,10 @@ func mapWidgetsToolkits(w *toolkit.Widget, t *andlabsT) { panic("WTF mapToolkits[w] == nil") } if (wt == nil) { - log(true, "BAD map? mapWidgets[t] wt == nil") + log(debugError, "BAD map? mapWidgets[t] wt == nil") } else { - log(true, "BAD map? mapWidgets[t] is", wt) - widgetDump(true, wt) + log(debugError, "BAD map? mapWidgets[t] is", wt) + widgetDump(debugError, 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 40cd410..8251e30 100644 --- a/toolkit/andlabs/window.go +++ b/toolkit/andlabs/window.go @@ -53,3 +53,47 @@ func (t *andlabsT) SetWindowTitle(title string) { log(debugToolkit, "Setting the window title", title) } } + +func doWindow(c *toolkit.Widget) { + if broken(c) { + return + } + if (c.Action == "New") { + newWindow(c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(debugError, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if (ct.uiWindow == nil) { + log(debugError, "Window() uiWindow == nil", ct) + return + } + log(debugChange, "Going to attempt:", c.Action) + switch c.Action { + case "Show": + ct.uiWindow.Show() + case "Hide": + ct.uiWindow.Hide() + case "Enable": + ct.uiWindow.Enable() + case "Disable": + ct.uiWindow.Disable() + case "Get": + c.S = ct.uiWindow.Title() + case "Set": + ct.uiWindow.SetTitle(c.S) + case "SetText": + ct.uiWindow.SetTitle(c.S) + case "SetMargin": + ct.uiWindow.SetMargined(c.B) + case "SetBorder": + ct.uiWindow.SetBorderless(c.B) + case "Delete": + ct.uiWindow.Destroy() + default: + log(debugError, "Can't do", c.Action, "to a Window") + } +} diff --git a/toolkit/democui/Makefile b/toolkit/democui/Makefile new file mode 100644 index 0000000..6f3f7d9 --- /dev/null +++ b/toolkit/democui/Makefile @@ -0,0 +1,11 @@ +all: plugin + ldd ../democui.so + +build: + GO111MODULE="off" go build + +plugin: + GO111MODULE="off" go build -buildmode=plugin -o ../democui.so + +objdump: + objdump -t ../democui.so |less diff --git a/toolkit/democui/debug.go b/toolkit/democui/debug.go new file mode 100644 index 0000000..817ee6e --- /dev/null +++ b/toolkit/democui/debug.go @@ -0,0 +1,107 @@ +package main + +import "git.wit.org/wit/gui/toolkit" + +var defaultBehavior bool = true + +var bookshelf bool // do you want things arranged in the box like a bookshelf or a stack? +var canvas bool // if set to true, the windows are a raw canvas +var menubar bool // for windows +var stretchy bool // expand things like buttons to the maximum size +var padded bool // add space between things like buttons +var margin bool // add space around the frames of windows + +var debugToolkit bool +var debugChange bool +var debugPlugin bool +var debugFlags bool +var debugError bool = true + +// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc +func setDefaultBehavior(s bool) { + defaultBehavior = s + if (defaultBehavior) { + log(debugToolkit, "Setting this toolkit to use the default behavior.") + log(debugToolkit, "This is the 'guessing' part as defined by the wit/gui 'Principles'. Refer to the docs.") + stretchy = false + padded = true + menubar = true + margin = true + canvas = false + bookshelf = true // 99% of the time, things make a vertical stack of objects + } else { + log(debugToolkit, "This toolkit is set to ignore the default behavior.") + } +} + +func ShowDebug () { + log(true, "debugToolkit =", debugToolkit) + log(true, "debugChange =", debugChange) + log(true, "debugPlugin =", debugPlugin) + log(true, "debugFlags =", debugFlags) + log(true, "debugError =", debugError) +} + +/* +func (t *gocuiT) Dump(b bool) { + if ! b { + return + } + log(b, "Name = ", t.Name, t.Width, t.Height) + if (t.uiBox != nil) { + log(b, "uiBox =", t.uiBox) + } + if (t.uiButton != nil) { + log(b, "uiButton =", t.uiButton) + } + if (t.uiCombobox != nil) { + log(b, "uiCombobox =", t.uiCombobox) + } + if (t.uiWindow != nil) { + log(b, "uiWindow =", t.uiWindow) + } + if (t.uiTab != nil) { + log(b, "uiTab =", t.uiTab) + } + if (t.uiGroup != nil) { + log(b, "uiGroup =", t.uiGroup) + } + if (t.uiEntry != nil) { + log(b, "uiEntry =", t.uiEntry) + } + if (t.uiMultilineEntry != nil) { + log(b, "uiMultilineEntry =", t.uiMultilineEntry) + } + if (t.uiSlider != nil) { + log(b, "uiSlider =", t.uiSlider) + } + if (t.uiCheckbox != nil) { + log(b, "uiCheckbox =", t.uiCheckbox) + } + 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) +} + +/* +func GetDebugToolkit () bool { + return debugToolkit +} +*/ diff --git a/toolkit/democui/log.go b/toolkit/democui/log.go new file mode 100644 index 0000000..afd1280 --- /dev/null +++ b/toolkit/democui/log.go @@ -0,0 +1,135 @@ +// +// version v1.3 +// +// I like things to be easy. +// +// combining logging inside of a gui made me do this +// +// this means all the log settings are in one place. it should allow +// things to be over-ridden externally to the library +// but still allow command line --args to pass debugging settings +// +// I also have a generic sleep() and exit() in here because it's simple +// +// Usage: +// +// log("something", foo, bar) +// var DEBUG bool = true +// log(DEBUG, "something else", someOtherVariable) # if DEBUG == false, return doing nothing +// log(SPEW, "something else", someOtherVariable) # this get's sent to spew.Dump(). Very useful for debugging! +// +package main + +import ( + "os" + golog "log" + "time" + "reflect" + "github.com/davecgh/go-spew/spew" +) + +var LOGOFF bool = false // turn this off, all logging stops +var WARN bool +var INFO bool + +type spewt struct { + a bool +} + +var SPEW spewt + + +/* + sleep() # you know what this does? sleeps for 1 second. yep. dump. easy. + sleep(.1) # you know what this does? yes, it sleeps for 1/10th of a second +*/ +func sleep(a ...any) { + if (a == nil) { + time.Sleep(time.Second) + return + } + + log(true, "sleep", a[0]) + + switch a[0].(type) { + case int: + time.Sleep(time.Duration(a[0].(int)) * time.Second) + case float64: + time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond) + default: + log("sleep a[0], type = ", a[0], reflect.TypeOf(a[0])) + } +} + +/* + exit() # yep. exits. I guess everything must be fine + exit(3) # I guess 3 it is then + exit("dont like apples") # ok. I'll make a note of that +*/ +func exit(a ...any) { + log(true, "exit", a) + //if (a) { + // os.Exit(a) + //} + os.Exit(0) +} + +/* + I've spent, am spending, too much time thinking about 'logging'. 'log', 'logrus', 'zap', whatever. + I'm not twitter. i don't give a fuck about how many nanoseconds it takes to log. Anyway, this + implementation is probably faster than all of those because you just set one bool to FALSE + and it all stops. + Sometimes I need to capture to stdout, sometimes stdout can't + work because it doesn't exist for the user. This whole thing is a PITA. Then it's spread + over 8 million references in every .go file. I'm tapping out and putting + it in one place. here it is. Also, this makes having debug levels really fucking easy. + You can define whatever level of logging you want from anywhere (command line) etc. + + log() # doesn't do anything + log(stuff) # sends it to whatever log you define in a single place. here is the place +*/ + +func log(a ...any) { + if (LOGOFF) { + return + } + + if (a == nil) { + return + } + var tbool bool + if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) { + if (a[0] == false) { + return + } + a[0] = "GUI/Toolkit/gocui" + } + + if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) { + // a = a[1:] + a[0] = "GUI/Toolkit/gocui" + if (debugToolkit) { + scs := spew.ConfigState{MaxDepth: 1} + scs.Dump(a) + // spew.Dump(a) + } + return + } + + golog.Println(a...) +} + +func logindent(depth int, format string, a ...interface{}) { + var tabs string + for i := 0; i < depth; i++ { + tabs = tabs + format + } + + // newFormat := tabs + strconv.Itoa(depth) + " " + format + newFormat := tabs + format + log(debugToolkit, newFormat, a) +} + +func setOutput(f *os.File) { + golog.SetOutput(f) +} diff --git a/toolkit/gocui/orig/mouse.go b/toolkit/democui/mouse.go index 7c77b14..efda307 100644 --- a/toolkit/gocui/orig/mouse.go +++ b/toolkit/democui/mouse.go @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package toolkit +package main import ( "errors" "fmt" - "log" "os" "github.com/awesome-gocui/gocui" @@ -30,26 +29,26 @@ func mouseClick(name string) { // log.Println("g.Close()") // g.Close() - log.Println("Found andlabs Running custom function for the mouse click") + log("Found andlabs Running custom function for the mouse click") Custom(name) // panic("got andlabs") } func Init() { - log.Println("start Init()") + log("start Init()") f, err := os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) if err != nil { - log.Fatalf("error opening file: %v", err) + exit("error opening file: %v", err) } defer f.Close() - log.SetOutput(f) - log.Println("This is a test log entry") + setOutput(f) + log("This is a test log entry") g, err = gocui.NewGui(gocui.OutputNormal, true) if err != nil { - log.Panicln(err) + exit(err) } g.Cursor = true @@ -58,19 +57,19 @@ func Init() { g.SetManagerFunc(layout) if err := keybindings(g); err != nil { - log.Panicln(err) + exit(err) } - log.Println("exit Init()") + log("exit Init()") } func StartConsoleMouse() { defer g.Close() - log.Println("start Main()") + log("start Main()") if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { - log.Panicln(err) + exit(err) } - log.Println("exit Main()") + log("exit Main()") } func layout(g *gocui.Gui) error { diff --git a/toolkit/democui/plugin.go b/toolkit/democui/plugin.go new file mode 100644 index 0000000..0b26f8f --- /dev/null +++ b/toolkit/democui/plugin.go @@ -0,0 +1,113 @@ +package main + +import ( + // if you include more than just this import + // then your plugin might be doing something un-ideal (just a guess from 2023/02/27) + "git.wit.org/wit/gui/toolkit" + + "github.com/awesome-gocui/gocui" +) + +// This is a map between the widgets in wit/gui and the internal structures of gocui +var viewWidget map[*gocui.View]*toolkit.Widget +var stringWidget map[string]*toolkit.Widget + +func Quit() { + g.Close() +} + +// This lists out the know mappings +func listMap() { + for v, w := range viewWidget { + log("view =", v.Name, "widget name =", w.Name) + } + for s, w := range stringWidget { + log("string =", s, "widget =", w) + } +} + + +// +// 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(debugPlugin, "Send() child =", c.Name, ",", c.Action, ",", c.Type) + + /* + if (c.Action == "SetMargin") { + log(debugError, "need to implement SetMargin here") + setMargin(c, c.B) + return + } + */ + + switch c.Type { + /* + case toolkit.Window: + // doWindow(c) + case toolkit.Tab: + // doTab(p, c) + case toolkit.Group: + newGroup(p, c) + case toolkit.Button: + newButton(p, c) + case toolkit.Checkbox: + // doCheckbox(p, c) + case toolkit.Label: + // doLabel(p, c) + case toolkit.Textbox: + // doTextbox(p, c) + case toolkit.Slider: + // doSlider(p, c) + case toolkit.Spinner: + // doSpinner(p, c) + case toolkit.Dropdown: + // doDropdown(p, c) + case toolkit.Combobox: + // doCombobox(p, c) + case toolkit.Grid: + // doGrid(p, c) + */ + case toolkit.Flag: + // log(debugFlags, "plugin Send() flag parent =", p.Name, p.Type) + // log(debugFlags, "plugin Send() flag child =", c.Name, c.Type) + // log(debugFlags, "plugin Send() flag child.Action =", c.Action) + // log(debugFlags, "plugin Send() flag child.S =", c.S) + // log(debugFlags, "plugin Send() flag child.B =", c.B) + // log(debugFlags, "plugin Send() what to flag?") + // should set the checkbox to this value + switch c.S { + case "Toolkit": + debugToolkit = c.B + case "Change": + debugChange = c.B + case "Plugin": + debugPlugin = c.B + case "Flags": + debugFlags = c.B + case "Error": + debugError = c.B + case "Show": + ShowDebug() + default: + log(debugError, "Can't set unknown flag", c.S) + } + default: + log(debugError, "plugin Send() unknown parent =", p.Name, p.Type) + log(debugError, "plugin Send() unknown child =", c.Name, c.Type) + log(debugError, "plugin Send() Don't know how to do", c.Type, "yet") + } +} diff --git a/toolkit/gocui/button.go b/toolkit/gocui/button.go index 5b41c48..355dc30 100644 --- a/toolkit/gocui/button.go +++ b/toolkit/gocui/button.go @@ -3,17 +3,15 @@ package main import ( "errors" "fmt" - "log" "strings" "github.com/awesome-gocui/gocui" "git.wit.org/wit/gui/toolkit" ) -func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) { - log.Println("gui.gocui.AddButton()", w.Name) +func newButton(parentW *toolkit.Widget, w *toolkit.Widget) { + log(true, "AddButton()", w.Name) addButton(w.Name) - // viewWidget[v] = w stringWidget[w.Name] = w listMap() } @@ -25,11 +23,11 @@ func addButton(name string) *gocui.View { } v, err := baseGui.SetView(name, currentX, currentY, currentX+t+3, currentY+2, 0) if err == nil { - log.Println("wit/gui internal plugin error", err) + log("wit/gui internal plugin error", err) return nil } if !errors.Is(err, gocui.ErrUnknownView) { - log.Println("wit/gui internal plugin error", err) + log("wit/gui internal plugin error", err) return nil } @@ -39,10 +37,10 @@ func addButton(name string) *gocui.View { currentView, err := baseGui.SetCurrentView(name) if err != nil { - log.Println("wit/gui internal plugin error", err) + log("wit/gui internal plugin error", err) return nil } - log.Println("wit/gui addbutton() current view name =", currentView.Name()) + log("wit/gui addbutton() current view name =", currentView.Name()) views = append(views, name) curView = len(views) - 1 diff --git a/toolkit/gocui/debug.go b/toolkit/gocui/debug.go new file mode 100644 index 0000000..817ee6e --- /dev/null +++ b/toolkit/gocui/debug.go @@ -0,0 +1,107 @@ +package main + +import "git.wit.org/wit/gui/toolkit" + +var defaultBehavior bool = true + +var bookshelf bool // do you want things arranged in the box like a bookshelf or a stack? +var canvas bool // if set to true, the windows are a raw canvas +var menubar bool // for windows +var stretchy bool // expand things like buttons to the maximum size +var padded bool // add space between things like buttons +var margin bool // add space around the frames of windows + +var debugToolkit bool +var debugChange bool +var debugPlugin bool +var debugFlags bool +var debugError bool = true + +// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc +func setDefaultBehavior(s bool) { + defaultBehavior = s + if (defaultBehavior) { + log(debugToolkit, "Setting this toolkit to use the default behavior.") + log(debugToolkit, "This is the 'guessing' part as defined by the wit/gui 'Principles'. Refer to the docs.") + stretchy = false + padded = true + menubar = true + margin = true + canvas = false + bookshelf = true // 99% of the time, things make a vertical stack of objects + } else { + log(debugToolkit, "This toolkit is set to ignore the default behavior.") + } +} + +func ShowDebug () { + log(true, "debugToolkit =", debugToolkit) + log(true, "debugChange =", debugChange) + log(true, "debugPlugin =", debugPlugin) + log(true, "debugFlags =", debugFlags) + log(true, "debugError =", debugError) +} + +/* +func (t *gocuiT) Dump(b bool) { + if ! b { + return + } + log(b, "Name = ", t.Name, t.Width, t.Height) + if (t.uiBox != nil) { + log(b, "uiBox =", t.uiBox) + } + if (t.uiButton != nil) { + log(b, "uiButton =", t.uiButton) + } + if (t.uiCombobox != nil) { + log(b, "uiCombobox =", t.uiCombobox) + } + if (t.uiWindow != nil) { + log(b, "uiWindow =", t.uiWindow) + } + if (t.uiTab != nil) { + log(b, "uiTab =", t.uiTab) + } + if (t.uiGroup != nil) { + log(b, "uiGroup =", t.uiGroup) + } + if (t.uiEntry != nil) { + log(b, "uiEntry =", t.uiEntry) + } + if (t.uiMultilineEntry != nil) { + log(b, "uiMultilineEntry =", t.uiMultilineEntry) + } + if (t.uiSlider != nil) { + log(b, "uiSlider =", t.uiSlider) + } + if (t.uiCheckbox != nil) { + log(b, "uiCheckbox =", t.uiCheckbox) + } + 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) +} + +/* +func GetDebugToolkit () bool { + return debugToolkit +} +*/ diff --git a/toolkit/gocui/gocui.go b/toolkit/gocui/gocui.go index 0d7c5a5..0a302bc 100644 --- a/toolkit/gocui/gocui.go +++ b/toolkit/gocui/gocui.go @@ -7,7 +7,6 @@ package main import ( "errors" "fmt" - "log" "os" "git.wit.org/wit/gui/toolkit" @@ -34,17 +33,20 @@ var ( func Init() { baseGui, err = gocui.NewGui(gocui.OutputNormal, true) if err != nil { - log.Panicln(err) + exit(err) } baseGui.Highlight = true baseGui.SelFgColor = gocui.ColorRed baseGui.SelFrameColor = gocui.ColorRed + baseGui.Cursor = true + baseGui.Mouse = true + baseGui.SetManagerFunc(layout) if err := initKeybindings(baseGui); err != nil { - log.Panicln(err) + exit(err) } viewWidget = make(map[*gocui.View]*toolkit.Widget) @@ -54,17 +56,17 @@ func Init() { outf, err = os.OpenFile("/tmp/witgui.log", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) if err != nil { - log.Fatalf("error opening file: %v", err) + exit("error opening file: %v", err) } // hmm. where to put this? // defer outf.Close() - log.SetOutput(outf) - log.Println("This is a test log entry") + setOutput(outf) + log("This is a test log entry") } func Queue(f func()) { - log.Println("QUEUEEEEE") + log("QUEUEEEEE") f() } @@ -79,7 +81,7 @@ func Main(f func()) { // addButton("test 3") f() if err := baseGui.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { - log.Panicln(err) + exit(err) } baseGui.Close() os.Exit(0) diff --git a/toolkit/gocui/group.go b/toolkit/gocui/group.go index 7cea346..2d8600c 100644 --- a/toolkit/gocui/group.go +++ b/toolkit/gocui/group.go @@ -1,18 +1,16 @@ package main import ( - "log" - "git.wit.org/wit/gui/toolkit" ) -func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) { +func newGroup(parentW *toolkit.Widget, w *toolkit.Widget) { if (parentW == nil) { - log.Println("wit/gui plugin error. parent widget == nil") + log(debugError, "plugin error. parent widget == nil") return } if (w == nil) { - log.Println("wit/gui plugin error. widget == nil") + log(debugPlugin, "plugin error. widget == nil") return } if (w.Name == "") { @@ -21,18 +19,18 @@ func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) { if (w.Name == "") { w.Name = "nil newGroup" } - log.Println("gui.gocui.AddGroup", w.Name) + log("AddGroup", w.Name) addGroup(w.Name) stringWidget[w.Name] = w } func addGroup(name string) { - log.Println("addGroup() START name =", name) - log.Println("addGroup() START groupSize =", groupSize, "currentY =", currentY, "currentX =", currentX) + log("addGroup() START name =", name) + log("addGroup() START groupSize =", groupSize, "currentY =", currentY, "currentX =", currentX) currentY = 2 currentX += groupSize + 5 groupSize = 0 - log.Println("addGroup() START, RESET Y = 3, RESET X = ", currentX) + log("addGroup() START, RESET Y = 3, RESET X = ", currentX) } diff --git a/toolkit/gocui/keybindings.go b/toolkit/gocui/keybindings.go index 3443320..43dbf47 100644 --- a/toolkit/gocui/keybindings.go +++ b/toolkit/gocui/keybindings.go @@ -5,17 +5,12 @@ package main import ( -// "errors" -// "fmt" - "log" -// "strings" - "github.com/awesome-gocui/gocui" "git.wit.org/wit/gui/toolkit" ) func initKeybindings(g *gocui.Gui) error { - log.Println("got to initKeybindings") + log("got to initKeybindings") if err := g.SetKeybinding("", 'q', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error { return gocui.ErrQuit @@ -54,7 +49,7 @@ func initKeybindings(g *gocui.Gui) error { } if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error { - log.Println("tab", v.Name()) + log("tab", v.Name()) return nextView(g, true) }); err != nil { return err @@ -73,27 +68,27 @@ func initKeybindings(g *gocui.Gui) error { } if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error { - log.Println("down", v.Name()) + log("down", v.Name()) return moveView(g, v, 0, delta) }); err != nil { return err } if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error { - log.Println("up", v.Name()) + log("up", v.Name()) return moveView(g, v, 0, -delta) }); err != nil { return err } if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error { - log.Println("enter", v.Name()) + log("enter", v.Name()) var w *toolkit.Widget w = stringWidget[v.Name()] if (w == nil) { - log.Println("COULD NOT FIND WIDGET", v.Name()) + log("COULD NOT FIND WIDGET", v.Name()) } else { - log.Println("FOUND WIDGET!", w) + log("FOUND WIDGET!", w) if (w.Custom != nil) { w.Custom() return nil @@ -123,14 +118,14 @@ func initKeybindings(g *gocui.Gui) error { } if err := g.SetKeybinding("", 'h', gocui.ModNone, func(g *gocui.Gui, v *gocui.View) error { - log.Println("help", v.Name()) + log("help", v.Name()) tmp, _ := g.SetViewOnTop("help") - log.Println("help 2", tmp.Name()) + log("help 2", tmp.Name()) // g.SetView("help", 2, 2, 30, 15, 0); g.SetCurrentView("help") // moveView(g, tmp, 0, -delta) if err := g.DeleteView("help"); err != nil { - log.Fatalln("gocui SetKeybinding()", err) + exit("gocui SetKeybinding()", err) } return nil }); err != nil { diff --git a/toolkit/gocui/log.go b/toolkit/gocui/log.go new file mode 100644 index 0000000..afd1280 --- /dev/null +++ b/toolkit/gocui/log.go @@ -0,0 +1,135 @@ +// +// version v1.3 +// +// I like things to be easy. +// +// combining logging inside of a gui made me do this +// +// this means all the log settings are in one place. it should allow +// things to be over-ridden externally to the library +// but still allow command line --args to pass debugging settings +// +// I also have a generic sleep() and exit() in here because it's simple +// +// Usage: +// +// log("something", foo, bar) +// var DEBUG bool = true +// log(DEBUG, "something else", someOtherVariable) # if DEBUG == false, return doing nothing +// log(SPEW, "something else", someOtherVariable) # this get's sent to spew.Dump(). Very useful for debugging! +// +package main + +import ( + "os" + golog "log" + "time" + "reflect" + "github.com/davecgh/go-spew/spew" +) + +var LOGOFF bool = false // turn this off, all logging stops +var WARN bool +var INFO bool + +type spewt struct { + a bool +} + +var SPEW spewt + + +/* + sleep() # you know what this does? sleeps for 1 second. yep. dump. easy. + sleep(.1) # you know what this does? yes, it sleeps for 1/10th of a second +*/ +func sleep(a ...any) { + if (a == nil) { + time.Sleep(time.Second) + return + } + + log(true, "sleep", a[0]) + + switch a[0].(type) { + case int: + time.Sleep(time.Duration(a[0].(int)) * time.Second) + case float64: + time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond) + default: + log("sleep a[0], type = ", a[0], reflect.TypeOf(a[0])) + } +} + +/* + exit() # yep. exits. I guess everything must be fine + exit(3) # I guess 3 it is then + exit("dont like apples") # ok. I'll make a note of that +*/ +func exit(a ...any) { + log(true, "exit", a) + //if (a) { + // os.Exit(a) + //} + os.Exit(0) +} + +/* + I've spent, am spending, too much time thinking about 'logging'. 'log', 'logrus', 'zap', whatever. + I'm not twitter. i don't give a fuck about how many nanoseconds it takes to log. Anyway, this + implementation is probably faster than all of those because you just set one bool to FALSE + and it all stops. + Sometimes I need to capture to stdout, sometimes stdout can't + work because it doesn't exist for the user. This whole thing is a PITA. Then it's spread + over 8 million references in every .go file. I'm tapping out and putting + it in one place. here it is. Also, this makes having debug levels really fucking easy. + You can define whatever level of logging you want from anywhere (command line) etc. + + log() # doesn't do anything + log(stuff) # sends it to whatever log you define in a single place. here is the place +*/ + +func log(a ...any) { + if (LOGOFF) { + return + } + + if (a == nil) { + return + } + var tbool bool + if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) { + if (a[0] == false) { + return + } + a[0] = "GUI/Toolkit/gocui" + } + + if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) { + // a = a[1:] + a[0] = "GUI/Toolkit/gocui" + if (debugToolkit) { + scs := spew.ConfigState{MaxDepth: 1} + scs.Dump(a) + // spew.Dump(a) + } + return + } + + golog.Println(a...) +} + +func logindent(depth int, format string, a ...interface{}) { + var tabs string + for i := 0; i < depth; i++ { + tabs = tabs + format + } + + // newFormat := tabs + strconv.Itoa(depth) + " " + format + newFormat := tabs + format + log(debugToolkit, newFormat, a) +} + +func setOutput(f *os.File) { + golog.SetOutput(f) +} diff --git a/toolkit/gocui/plugin.go b/toolkit/gocui/plugin.go index 5be26f3..2b01acc 100644 --- a/toolkit/gocui/plugin.go +++ b/toolkit/gocui/plugin.go @@ -1,8 +1,8 @@ package main import ( - "log" - + // if you include more than just this import + // then your plugin might be doing something un-ideal (just a guess from 2023/02/27) "git.wit.org/wit/gui/toolkit" "github.com/awesome-gocui/gocui" @@ -19,10 +19,97 @@ func Quit() { // This lists out the know mappings func listMap() { for v, w := range viewWidget { - log.Println("view =", v.Name, "widget name =", w.Name) + log("view =", v.Name, "widget name =", w.Name) } for s, w := range stringWidget { - log.Println("string =", s, "widget =", w) + log("string =", s, "widget =", w) } } + +// +// 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(debugPlugin, "Send() child =", c.Name, ",", c.Action, ",", c.Type) + + /* + if (c.Action == "SetMargin") { + log(debugError, "need to implement SetMargin here") + setMargin(c, c.B) + return + } + */ + + switch c.Type { + /* + case toolkit.Window: + // doWindow(c) + case toolkit.Tab: + // doTab(p, c) + */ + case toolkit.Group: + newGroup(p, c) + case toolkit.Button: + newButton(p, c) + /* + case toolkit.Checkbox: + // doCheckbox(p, c) + case toolkit.Label: + // doLabel(p, c) + case toolkit.Textbox: + // doTextbox(p, c) + case toolkit.Slider: + // doSlider(p, c) + case toolkit.Spinner: + // doSpinner(p, c) + case toolkit.Dropdown: + // doDropdown(p, c) + case toolkit.Combobox: + // doCombobox(p, c) + case toolkit.Grid: + // doGrid(p, c) + */ + case toolkit.Flag: + // log(debugFlags, "plugin Send() flag parent =", p.Name, p.Type) + // log(debugFlags, "plugin Send() flag child =", c.Name, c.Type) + // log(debugFlags, "plugin Send() flag child.Action =", c.Action) + // log(debugFlags, "plugin Send() flag child.S =", c.S) + // log(debugFlags, "plugin Send() flag child.B =", c.B) + // log(debugFlags, "plugin Send() what to flag?") + // should set the checkbox to this value + switch c.S { + case "Toolkit": + debugToolkit = c.B + case "Change": + debugChange = c.B + case "Plugin": + debugPlugin = c.B + case "Flags": + debugFlags = c.B + case "Error": + debugError = c.B + case "Show": + ShowDebug() + default: + log(debugError, "Can't set unknown flag", c.S) + } + default: + log(debugError, "plugin Send() unknown parent =", p.Name, p.Type) + log(debugError, "plugin Send() unknown child =", c.Name, c.Type) + log(debugError, "plugin Send() Don't know how to do", c.Type, "yet") + } +} diff --git a/toolkit/gocui/views.go b/toolkit/gocui/views.go index defe2b2..8b17acf 100644 --- a/toolkit/gocui/views.go +++ b/toolkit/gocui/views.go @@ -7,7 +7,6 @@ package main import ( "errors" "fmt" - "log" "strings" "github.com/awesome-gocui/gocui" @@ -71,11 +70,11 @@ func moveView(g *gocui.Gui, v *gocui.View, dx, dy int) error { if err != nil { return err } - log.Println(x0, y0, x1, y1) + log(x0, y0, x1, y1) if _, err := g.SetView(name, x0+dx, y0+dy, x1+dx, y1+dy, 0); err != nil { return err } x0, y0, x1, y1, err = g.ViewPosition(name) - log.Println(x0, y0, x1, y1) + log(x0, y0, x1, y1) return nil } diff --git a/toolkit/gocui/window.go b/toolkit/gocui/window.go index b2d241d..67948d6 100644 --- a/toolkit/gocui/window.go +++ b/toolkit/gocui/window.go @@ -1,18 +1,16 @@ package main import ( - "log" - "git.wit.org/wit/gui/toolkit" ) func NewWindow(w *toolkit.Widget) { if (w == nil) { - log.Println("wit/gui plugin error. widget == nil") + log("wit/gui plugin error. widget == nil") return } if (w.Name == "") { w.Name = "nil newWindow" } - log.Println("gui.gocui.AddWindow", w.Name) + log("gui.gocui.AddWindow", w.Name) } diff --git a/toolkit/widget.go b/toolkit/widget.go index 9241d5a..30169ba 100644 --- a/toolkit/widget.go +++ b/toolkit/widget.go @@ -11,18 +11,26 @@ package toolkit // Event() seems like a good name. // Could a protobuf be used here? (Can functions be passed?) type Widget struct { - 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 + Name string + Action string // "New", "Delete", "Set", aka something to do Type WidgetType + // This function is how you interact with the toolkit + // latest attempt. seems to work so far (2023/02/28) + // Hopefully this will be the barrier between the goroutines + // TODO: move this interaction to channels + Custom func() + + // re-adding an id to test channels + id int + // 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) + // maybe safe if there is correctly working Custom() between goroutines? + // (still probably not, almost certainly not. not possible. layer violation?) S string // not safe to have 'S' // This GUI is intended for simple things @@ -38,10 +46,6 @@ type Widget struct { // 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() } type WidgetType int @@ -62,6 +66,8 @@ const ( Slider Spinner Grid + Box + Image Flag ) @@ -93,6 +99,10 @@ func (s WidgetType) String() string { return "Spinner" case Grid: return "Grid" + case Box: + return "Box" + case Image: + return "Image" case Flag: return "Flag" case Unknown: @@ -100,3 +110,15 @@ func (s WidgetType) String() string { } return "GuiToolkitTUndefinedType" } + +// this is hopefully just used in a very few places for +// debuging the interaction between go apps and the underlying +// toolkits. Hopefully this is less prone to problems and can +// detect memory leaks, threading problems, memory allocation & mapping errors, etc +func (w *Widget) GetId() int { + return w.id +} + +func (w *Widget) SetId(i int) { + w.id = i +} |
