From 7d1836390abb6856d63a4e85b66d4b5b09b5e9f4 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Fri, 3 Mar 2023 14:41:38 -0600 Subject: [PATCH] release as v0.6.5 good standard release really clean interaction to plugin really clean debug flags implementation common doAppend() idea, but it probably won't work re-implement combobox. this code base almost doesn't suck slider & spinner set values now tab set margin works convert dropdown to Send() lots of other changes to try to implement single line Entry() I guess use golang file names even though internalally the go developers use underscore chars in the actual go sources. Maybe there is a reason for that? go channel debug window does something make a debug window for channels. add sample icons Signed-off-by: Jeff Carr --- README-goreadme.md | 36 ++-- checkbox.go | 6 - cmds/buttonplugin/main.go | 6 - cmds/textbox/Makefile | 4 +- common.go | 24 +++ debug.go | 82 +++----- debug_flags.go => debugFlags.go | 16 +- debugGochan.go | 107 ++++++++++ debug_golang.go => debugGolang.go | 16 +- debug_widget.go => debugWidget.go | 185 ++++++++++++------ debug_window.go => debugWindow.go | 50 +---- dropdown.go | 37 +--- grid.go | 16 ++ int.go | 8 +- main.go | 6 +- plugin.go | 84 +------- structs.go | 3 + toolkit/andlabs/append.go | 103 ++++++++++ toolkit/andlabs/box.go | 14 +- toolkit/andlabs/checkbox.go | 24 +-- toolkit/andlabs/combobox.go | 100 ++++++++++ toolkit/andlabs/common.go | 143 +++++++++++++- toolkit/andlabs/debug.go | 102 ++-------- toolkit/andlabs/dropdown.go | 73 +++++-- toolkit/andlabs/grid.go | 102 ++++++++++ toolkit/andlabs/group.go | 33 +++- toolkit/andlabs/icon.go | 27 +++ toolkit/andlabs/label.go | 3 +- toolkit/andlabs/main.go | 7 +- toolkit/andlabs/plugin.go | 38 +++- toolkit/andlabs/resources/ping6.broken.png | Bin 0 -> 9486 bytes .../andlabs/resources/ping6.pure-bright.png | Bin 0 -> 11989 bytes toolkit/andlabs/resources/ping6.pure.png | Bin 0 -> 9072 bytes toolkit/andlabs/resources/ping6.working.png | Bin 0 -> 3654 bytes toolkit/andlabs/slider.go | 3 +- toolkit/andlabs/spinner.go | 3 +- toolkit/andlabs/structs.go | 2 +- toolkit/andlabs/tab.go | 10 +- toolkit/andlabs/textbox.go | 62 +++++- toolkit/widget.go | 9 + 40 files changed, 1072 insertions(+), 472 deletions(-) rename debug_flags.go => debugFlags.go (84%) create mode 100644 debugGochan.go rename debug_golang.go => debugGolang.go (90%) rename debug_widget.go => debugWidget.go (56%) rename debug_window.go => debugWindow.go (75%) create mode 100644 grid.go create mode 100644 toolkit/andlabs/append.go create mode 100644 toolkit/andlabs/combobox.go create mode 100644 toolkit/andlabs/grid.go create mode 100644 toolkit/andlabs/icon.go create mode 100644 toolkit/andlabs/resources/ping6.broken.png create mode 100644 toolkit/andlabs/resources/ping6.pure-bright.png create mode 100644 toolkit/andlabs/resources/ping6.pure.png create mode 100644 toolkit/andlabs/resources/ping6.working.png diff --git a/README-goreadme.md b/README-goreadme.md index a051b8a..fd4ec74 100644 --- a/README-goreadme.md +++ b/README-goreadme.md @@ -145,41 +145,41 @@ var WARN bool ## Functions -### func [DebugWidgetWindow](/debug_widget.go#L7) +### func [DebugWidgetWindow](/debugWidget.go#L107) `func DebugWidgetWindow(w *Node)` -### func [DebugWindow](/debug_window.go#L9) +### func [DebugWindow](/debugWindow.go#L9) `func DebugWindow()` Creates a window helpful for debugging this package -### func [Delete](/common.go#L66) +### func [Delete](/common.go#L90) `func Delete(c *Node)` -### func [Indent](/debug.go#L123) +### func [Indent](/debug.go#L101) `func Indent(a ...interface{})` -### func [InitPlugins](/main.go#L46) +### func [InitPlugins](/main.go#L50) `func InitPlugins(names []string)` -### func [LoadToolkit](/plugin.go#L56) +### func [LoadToolkit](/plugin.go#L43) `func LoadToolkit(name string) bool` loads and initializes a toolkit (andlabs/ui, gocui, etc) -### func [Main](/main.go#L87) +### func [Main](/main.go#L91) `func Main(f func())` This should not pass a function -### func [Queue](/main.go#L117) +### func [Queue](/main.go#L121) `func Queue(f func())` @@ -190,27 +190,19 @@ 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#L24) +### func [SetDebug](/debug.go#L27) `func SetDebug(s bool)` -### func [SetDebugChange](/debug.go#L58) +### func [SetFlag](/debug.go#L41) -`func SetDebugChange(s bool)` +`func SetFlag(s string, b bool)` -This passes the debugChange flag to the toolkit plugin - -### func [SetDebugToolkit](/debug.go#L43) - -`func SetDebugToolkit(s bool)` - -This passes the debugToolkit flag to the toolkit plugin - -### func [ShowDebugValues](/debug.go#L72) +### func [ShowDebugValues](/debug.go#L62) `func ShowDebugValues()` -### func [StandardExit](/main.go#L136) +### func [StandardExit](/main.go#L140) `func StandardExit()` @@ -243,7 +235,7 @@ This struct can be used with the go-arg package var Config GuiConfig ``` -### type [Node](/structs.go#L54) +### type [Node](/structs.go#L57) `type Node struct { ... }` diff --git a/checkbox.go b/checkbox.go index 068be7b..186f3a8 100644 --- a/checkbox.go +++ b/checkbox.go @@ -12,9 +12,3 @@ func (n *Node) NewCheckbox(name string) *Node { send(n, newNode) return newNode } - -func (n *Node) NewThing(name string) *Node { - newNode := n.New(name, toolkit.Button, nil) - send(n, newNode) - return newNode -} diff --git a/cmds/buttonplugin/main.go b/cmds/buttonplugin/main.go index 9ed47fa..0c72c3f 100644 --- a/cmds/buttonplugin/main.go +++ b/cmds/buttonplugin/main.go @@ -81,12 +81,6 @@ func buttonWindow() { gui.DebugWindow() }) - g.NewButton("gui.GolangDebugWindow()", func () { - // make a seperate window out of this - // w.GolangDebugWindow(false) - w.GolangDebugWindow(true) - }) - g.NewButton("LoadToolkit(andlabs)", func () { gui.LoadToolkit("andlabs") }) diff --git a/cmds/textbox/Makefile b/cmds/textbox/Makefile index 7b0e57d..6ca4329 100644 --- a/cmds/textbox/Makefile +++ b/cmds/textbox/Makefile @@ -1,5 +1,5 @@ run: build - ./textbox --gui-debug + GOTRACEBACK=all ./textbox --gui-debug build-release: go get -v -u -x . @@ -7,7 +7,7 @@ build-release: build: GO111MODULE="off" go get -v -x . - GO111MODULE="off" go build + GO111MODULE="off" GOTRACEBACK=all go build update: GO111MODULE="off" go get -v -u -x . diff --git a/common.go b/common.go index 22e4319..1518bc8 100644 --- a/common.go +++ b/common.go @@ -8,6 +8,13 @@ import ( // functions for handling text related GUI elements +func (n *Node) Add(str string) { + log(debugGui, "gui.Add() value =", str) + n.widget.Action = "Add" + n.widget.S = str + send(n.parent, n) +} + func (n *Node) SetText(str string) bool { log(debugChange, "gui.SetText() value =", str) n.widget.Action = "Set" @@ -16,6 +23,23 @@ func (n *Node) SetText(str string) bool { return true } +func (n *Node) Set(a any) bool { + log(debugChange, "gui.Set() value =", a) + n.widget.Action = "Set" + switch v := a.(type) { + case bool: + n.widget.B = a.(bool) + case string: + n.widget.S = a.(string) + case int: + n.widget.I = a.(int) + default: + log(debugError, "gui.Set() unknown type =", v, "a =", a) + } + send(n.parent, n) + return true +} + func (n *Node) AppendText(str string) bool { n.widget.Action = "Set" tmp := n.widget.S + str diff --git a/debug.go b/debug.go index 7fe9a6a..de78d89 100644 --- a/debug.go +++ b/debug.go @@ -10,69 +10,60 @@ import ( // various debugging flags var debugGui bool = false +var debugError bool = false var debugDump bool = false var debugNode bool = false 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 -// func GetDebug () bool { -// return debugGui -// } +// for printing out the binary tree +var listChildrenParent *Node +var listChildrenDepth int = 0 +var defaultPadding = " " func SetDebug (s bool) { debugGui = s - debugChange = s debugDump = s debugTabs = s debugPlugin = s debugNode = s debugToolkit = s - SetDebugChange(s) - SetDebugToolkit(s) + + SetFlag("Flags", s) + SetFlag("Toolkit", s) + SetFlag("Change", s) + SetFlag("Error", s) } -/* -func GetDebugToolkit () bool { - return debugToolkit -} -*/ - -// This passes the debugToolkit flag to the toolkit plugin -func SetDebugToolkit (s bool) { - debugToolkit = s - for _, aplug := range allPlugins { - log(debugPlugin, "gui.SetDebugToolkit() aplug =", aplug.name) - if (aplug.SetDebugToolkit == nil) { - log(debugPlugin, "\tgui.SetDebugToolkit() = nil", aplug.name) - continue - } - aplug.SetDebugToolkit(s) - return +func SetFlag (s string, b bool) { + switch s { + case "Error": + debugError = b + case "Change": + debugChange = b + case "Show": + // print them here? For now, just used to print settings in the plugins + default: + log(debugError, "Can't set unknown flag", s) } - log(debugPlugin, "\tgui.SetDebugToolkit() = nil in all plugins") -} -// This passes the debugChange flag to the toolkit plugin -func SetDebugChange (s bool) { - // debugToolkit = s - for _, aplug := range allPlugins { - log(debugPlugin, "gui.SetDebugChange() aplug =", aplug.name) - if (aplug.SetDebugChange == nil) { - log(debugPlugin, "\tgui.SetDebugChange() = nil", aplug.name) - continue - } - aplug.SetDebugChange(s) - return - } - log(debugPlugin, "\tgui.SetDebugChange() = nil in all plugins") + // send the flag to the toolkit + n := Config.flag + log(debugChange, "Set() toolkit flag", s, "to", b) + n.widget.Action = "Set" + n.widget.S = s + n.widget.B = b + send(nil, n) } func ShowDebugValues() { // The order here should match the order in the GUI // TODO: get the order from the node binary tree log(true, "Debug =", debugGui) + log(true, "DebugError =", debugError) log(true, "DebugChange =", debugChange) log(true, "DebugDump =", debugDump) log(true, "DebugTabs =", debugTabs) @@ -80,16 +71,7 @@ func ShowDebugValues() { log(true, "DebugNode =", debugNode) log(true, "DebugToolkit =", debugToolkit) - // dump out the debugging flags for the plugins - for _, aplug := range allPlugins { - log(debugPlugin, "gui.ShowDebug() aplug =", aplug.name) - if (aplug.ShowDebug == nil) { - log(debugPlugin, "\tgui.ShowDebug() = nil", aplug.name) - continue - } - aplug.ShowDebug() - return - } + SetFlag("Show", true) } func (n *Node) Dump() { @@ -116,10 +98,6 @@ func (n *Node) Dump() { Indent("NODE DUMP END") } -var listChildrenParent *Node -var listChildrenDepth int = 0 -var defaultPadding = " " - func Indent(a ...interface{}) { logindent(listChildrenDepth, defaultPadding, a...) } diff --git a/debug_flags.go b/debugFlags.go similarity index 84% rename from debug_flags.go rename to debugFlags.go index ea535c4..08aa766 100644 --- a/debug_flags.go +++ b/debugFlags.go @@ -15,7 +15,7 @@ func (n *Node) debugFlags(makeWindow bool) { w = NewWindow() w.Custom = w.StandardClose } else { - w = n.NewTab("Debug Flags") + w = n.NewTab("Flags") } w.Dump() @@ -36,12 +36,19 @@ func (n *Node) debugFlags(makeWindow bool) { log(debugGui, "Custom() n.widget =", cb1.widget.Name, cb1.widget.B) } + // errors. by default these always output somewhere + cbE := g.NewCheckbox("debugError") + cbE.Custom = func() { + debugError = cbE.widget.B + SetFlag("Error", debugError) + } + // debugging that will show you things like mouse clicks, user inputing text, etc // also set toolkit.DebugChange cb2 := g.NewCheckbox("debugChange") cb2.Custom = func() { debugChange = cb2.widget.B - SetDebugChange(cb2.widget.B) + SetFlag("Change", debugChange) log(debugGui, "Custom() n.widget =", cb2.widget.Name, cb2.widget.B) } @@ -74,8 +81,9 @@ func (n *Node) debugFlags(makeWindow bool) { // turns on debugging inside the plugin toolkit cb7 := g.NewCheckbox("debugToolkit") cb7.Custom = func() { - SetDebugToolkit(cb7.widget.B) - log(debugGui, "Custom() n.widget =", cb7.widget.Name, cb7.widget.B) + // 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 () { diff --git a/debugGochan.go b/debugGochan.go new file mode 100644 index 0000000..3183bdb --- /dev/null +++ b/debugGochan.go @@ -0,0 +1,107 @@ +// https://www.digitalocean.com/community/tutorials/how-to-run-multiple-functions-concurrently-in-go +// who came up with the idea of making community tutorials. that was a good idea! + +package gui + +import ( + "fmt" + "sync" +) + +var debugWG *sync.WaitGroup +var debugNumberChan chan int + +func (n *Node) debugGoChannels(makeWindow bool) { + var w, g *Node + + // Either: + // make a new window + // make a new tab in the existing window + if (makeWindow) { + Config.Title = "Debug GO Channels" + Config.Width = 300 + Config.Height = 400 + w = NewWindow() + w.Custom = w.StandardClose + } else { + w = n.NewTab("Chan") + } + w.Dump() + + g = w.NewGroup("Channel stuff") + + // var debugWG sync.WaitGroup + g.NewButton("init()", func () { + if (debugNumberChan == nil) { + log("making debugNumberChan channel") + debugNumberChan = make(chan int) + } else { + log("debugNumberChan already made") + } + debugWG = new(sync.WaitGroup) + }) + g.NewButton("go printInt(x) (read x values off the channel)", func () { + debugWG.Add(1) + go printInt(2, "routine1") + debugWG.Add(1) + go printInt(2, "routine2") + }) + g.NewButton("sendNumber(2) (chan <- 2, 4)", func () { + debugWG.Add(1) + debugWG.Add(1) + go sendNumber(2) + go sendNumber(4) + }) + g.NewButton("sendNumber(1) (chan <- 7)", func () { + debugWG.Add(1) + go sendNumber(7) + }) + g.NewButton("send 4 numbers (chan <- int)", func () { + log("generateNumbers(4)") + go generateNumbers(4) + }) + g.NewButton("debugWG.Done()", func () { + log("ran debugWG.Done()") + debugWG.Done() + }) + g.NewButton("close chan", func () { + close(debugNumberChan) + }) + g.NewButton("print", func () { + log("waitgroup counter is ?") + }) +} +func sendNumber(i int) { + log("START debugNumberChan <-", i, " (sending", i, "to channel)") + debugNumberChan <- i + debugWG.Wait() + log("END debugNumberChan sendNumber() done", i) +} + +func generateNumbers(total int) { + fmt.Printf("START generateNumbers()\n") + for idx := 1; idx <= total; idx++ { + log("ran debugNumberChan <= idx where idx =", idx) + fmt.Printf("S generateNumbers() sending %d to channel\n", idx) + debugNumberChan <- idx + // res, err := (<-r)() + fmt.Printf("E generateNumbers() sending %d to channel\n", idx) + } + debugWG.Wait() + fmt.Printf("END generateNumbers()\n") +} + +// i equals the number of times to read values from the channel +func printInt(i int, name string) { + tmp := 1 + log("START printInt", name, "read debugNumberChan()") + for num := range debugNumberChan { + log("printInt()",name, "read", num, "from channel") + debugWG.Done() + if (tmp == i) { + return + } + tmp += 1 + } + fmt.Printf("END printInt()", name, "read debugNumberChan\n") +} diff --git a/debug_golang.go b/debugGolang.go similarity index 90% rename from debug_golang.go rename to debugGolang.go index 87ccdb5..0a6edda 100644 --- a/debug_golang.go +++ b/debugGolang.go @@ -9,7 +9,7 @@ import ( "runtime/pprof" ) -func (n *Node) GolangDebugWindow(makeWindow bool) { +func (n *Node) debugGolangWindow(makeWindow bool) { var w, g, og, outputTextbox *Node // Either: @@ -22,7 +22,7 @@ func (n *Node) GolangDebugWindow(makeWindow bool) { w = NewWindow() w.Custom = w.StandardClose } else { - w = n.NewTab("GO") + w = n.NewTab("GOLANG") } w.Dump() @@ -93,6 +93,11 @@ func (n *Node) GolangDebugWindow(makeWindow bool) { 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 + // func Stack(buf []byte, all bool) int + }) + g.NewButton("debug.SetMemoryLimit(int)", func () { // TODO: //debug.SetMemoryLimit(1024 * 1024 * 100) @@ -109,6 +114,13 @@ func (n *Node) GolangDebugWindow(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/debug_widget.go b/debugWidget.go similarity index 56% rename from debug_widget.go rename to debugWidget.go index da15706..d76b554 100644 --- a/debug_widget.go +++ b/debugWidget.go @@ -4,6 +4,106 @@ import ( "strconv" ) +var debugGrid *Node + +func (n *Node) debugWidgets(makeWindow bool) { + var w, gList, gShow *Node + + // Either: + // make a new window + // make a new tab in the existing window + if (makeWindow) { + Config.Title = "Debug Widgets" + Config.Width = 300 + Config.Height = 400 + w = NewWindow() + w.Custom = w.StandardClose + } else { + w = n.NewTab("Widgets") + } + w.Dump() + + gList = w.NewGroup("Pick a widget to debug") + gShow = w.NewGroup("Added Widgets go here") + + gList.NewButton("Button", func () { + SetDebug(true) + a := gShow.NewButton("myButton", func () { + log("this code is more better") + }) + SetDebug(false) + DebugWidgetWindow(a) + }) + gList.NewButton("Checkbox", func () { + a := gShow.NewCheckbox("myCheckbox") + a.Custom = func () { + log("custom checkox func a =", a.widget.B, a.id) + } + DebugWidgetWindow(a) + }) + gList.NewButton("Label", func () { + a := gShow.NewLabel("mylabel") + DebugWidgetWindow(a) + }) + gList.NewButton("Textbox", func () { + a := gShow.NewTextbox("mytext") + a.Custom = func () { + log("custom TextBox() a =", a.widget.S, a.id) + } + DebugWidgetWindow(a) + }) + gList.NewButton("Slider", func () { + a := gShow.NewSlider("tmp slider", 10, 55) + a.Custom = func () { + log("custom slider() a =", a.widget.I, a.id) + } + DebugWidgetWindow(a) + }) + gList.NewButton("Spinner", func () { + a := gShow.NewSpinner("tmp spinner", 6, 32) + a.Custom = func () { + log("custom spinner() a =", a.widget.I, a.id) + } + DebugWidgetWindow(a) + }) + gList.NewButton("Dropdown", func () { + a := gShow.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) + } + DebugWidgetWindow(a) + }) + gList.NewButton("Combobox", func () { + a := gShow.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) + } + DebugWidgetWindow(a) + }) + gList.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 @@ -49,67 +149,32 @@ func DebugWidgetWindow(w *Node) { w.widget.S = "Set Value(20)" send(w.parent, w) }) + g.NewButton("Add('foo')", func () { + w.widget.Action = "Add" + w.widget.S = "foo" + send(w.parent, w) + }) + 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) + }) + g.NewButton("Add button to (1,1)", func () { + w.widget.Action = "AddGrid" + w.widget.B = false + send(w.parent, w) + }) g.NewButton("Delete()", func () { Delete(w) }) } - -func (n *Node) debugWidgets(makeWindow bool) { - var w, gList, gShow *Node - - // Either: - // make a new window - // make a new tab in the existing window - if (makeWindow) { - Config.Title = "Widgets" - Config.Width = 300 - Config.Height = 400 - w = NewWindow() - w.Custom = w.StandardClose - } else { - w = n.NewTab("Widgets") - } - w.Dump() - - gList = w.NewGroup("Pick a widget to debug") - gShow = w.NewGroup("Added Widgets go here") - - gList.NewButton("Button", func () { - a := gShow.NewButton("myButton", func () { - log("this code is more better") - }) - DebugWidgetWindow(a) - }) - gList.NewButton("Checkbox", func () { - a := gShow.NewCheckbox("myCheckbox") - a.Custom = func () { - log("custom checkox func a =", a.widget.B, a.id) - } - DebugWidgetWindow(a) - }) - gList.NewButton("Label", func () { - a := gShow.NewLabel("mylabel") - DebugWidgetWindow(a) - }) - gList.NewButton("Textbox", func () { - a := gShow.NewTextbox("mytext") - a.Custom = func () { - log("custom TextBox() a =", a.widget.S, a.id) - } - DebugWidgetWindow(a) - }) - gList.NewButton("Slider", func () { - a := gShow.NewSlider("tmp slider", 10, 55) - a.Custom = func () { - log("custom slider() a =", a.widget.S, a.id) - } - DebugWidgetWindow(a) - }) - gList.NewButton("Spinner", func () { - a := gShow.NewSpinner("tmp spinner", 6, 32) - a.Custom = func () { - log("custom spinner() a =", a.widget.S, a.id) - } - DebugWidgetWindow(a) - }) -} diff --git a/debug_window.go b/debugWindow.go similarity index 75% rename from debug_window.go rename to debugWindow.go index 0ee2271..a831869 100644 --- a/debug_window.go +++ b/debugWindow.go @@ -19,37 +19,28 @@ 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, junk, newThing *Node + var newN, gog, g1, g2, g3, dd *Node // time.Sleep(1 * time.Second) newN = n.NewTab(title) newN.Dump() //////////////////////// main debug things ////////////////////////////////// - gog = newN.NewGroup("GOLANG") - gog.NewLabel("go language") - gog.NewButton("GO Language Debug", func () { - newN.GolangDebugWindow(false) - }) + gog = newN.NewGroup("Debugging") + gog.NewButton("Debug Flags", func () { newN.debugFlags(false) }) gog.NewButton("Debug Widgets", func () { newN.debugWidgets(false) }) - - gog.NewLabel("wit/gui package") - gog.NewButton("Demo toolkit andlabs/ui", func () { - // DemoToolkitWindow() + gog.NewButton("GO Language Internals", func () { + newN.debugGolangWindow(false) }) - - junk = gog.NewButton("junk", func () { - log("click junk, get junk") + gog.NewButton("GO Channels debug", func () { + newN.debugGoChannels(false) }) - gog.NewLabel("tmp label") - - //////////////////////// window debugging things ////////////////////////////////// g1 = newN.NewGroup("Current Windows") dd = g1.NewDropdown("Window Dropdown") @@ -83,33 +74,6 @@ func (n *Node) DebugTab(title string) *Node { mapWindows[child.Name] = child } dd.SetDropdownName(last) - dd.NewButton("Delete(junk)", func () { - Delete(junk) - }) - dd.NewButton("myButton", func () { - gog.NewButton("myButton", func () { - log("this code is better") - }) - }) - dd.NewButton("add Hope", func () { - var i int = 1 - log("add hope?", i) - gog.NewButton("hope", func () { - i += 1 - log("write better code", i) - }) - }) - dd.NewButton("add newThing", func () { - var i, j int = 1, 1 - newThing = gog.NewThing("NewThing") - newThing.Custom = func() { - f := i + j - log("newThing!!! n.widget =", newThing.widget.Name, newThing.widget.B, f) - j = i - i = f - } - log("newThing!!! n.widget") - }) g2 = newN.NewGroup("Debug Window") g2.NewButton("SetMargined(tab)", func () { diff --git a/dropdown.go b/dropdown.go index 214cc5a..81746c6 100644 --- a/dropdown.go +++ b/dropdown.go @@ -6,41 +6,22 @@ import ( // add a new entry to the dropdown name func (n *Node) AddDropdownName(name string) { - for _, aplug := range allPlugins { - log(debugPlugin, "AddDropdownName() aplug =", aplug.name, "name =", name) - if (aplug.AddDropdownName == nil) { - log(debugPlugin, "\taplug.AddDropdownName() = nil") - continue - } - aplug.AddDropdownName(&n.widget, name) - } + n.Add(name) } // Set the dropdown menu to 'name' func (n *Node) SetDropdownName(name string) { - log(debugGui, "SetDropdownName() work. name =", name) - for _, aplug := range allPlugins { - log(debugPlugin, "SetDropdownName() aplug =", aplug.name, "name =", name) - if (aplug.SetDropdownName == nil) { - log(true, "\taplug.SetDropdownName() aplug = nil") - continue - } - aplug.SetDropdownName(&n.widget, name) - } + n.SetText(name) } func (n *Node) NewDropdown(name string) *Node { newNode := n.New(name, toolkit.Dropdown, nil) - - for _, aplug := range allPlugins { - log(debugGui, "gui.NewDropdown() aplug =", aplug.name, "name =", newNode.widget.Name) - if (aplug.NewDropdown == nil) { - log(debugGui, "\tgui.NewDropdown() aplug.NewDropdown = nil", aplug.name) - continue - } - aplug.NewDropdown(&n.widget, &newNode.widget) - } - - // TODO, this doesn't work for some reason (over-written by plugin?) + send(n, newNode) + return newNode +} + +func (n *Node) NewCombobox(name string) *Node { + newNode := n.New(name, toolkit.Combobox, nil) + send(n, newNode) return newNode } diff --git a/grid.go b/grid.go new file mode 100644 index 0000000..d0158fd --- /dev/null +++ b/grid.go @@ -0,0 +1,16 @@ +package gui + +import ( + "git.wit.org/wit/gui/toolkit" +) + +func (n *Node) NewGrid(name string, x int, y int) *Node { + newNode := n.New(name, toolkit.Grid, func() { + log(debugChange, "click() NewGrid not defined =", name) + }) + newNode.widget.X = x + newNode.widget.Y = y + + send(n, newNode) + return newNode +} diff --git a/int.go b/int.go index a7880dc..ff38afb 100644 --- a/int.go +++ b/int.go @@ -13,13 +13,7 @@ package gui Is it "has to go" or "should go"? Probably it makes sense to strictly inforce it. No "callback" functions. IPC only (go channels) */ func (n *Node) Int() int { - log(debugToolkit, "gui.Node.Int() for node name =", n.Name) - log(debugToolkit, SPEW, n) - - // FIXME: this needs to be redone - // i := n.toolkit.Value() - i := 3333 - return i + return n.widget.I } // which name to use? diff --git a/main.go b/main.go index d05f334..cc5bfcf 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package gui import ( "embed" + "git.wit.org/wit/gui/toolkit" ) // Windows doesn't support plugins. How can I keep andlabs and only compile it on windows? @@ -26,7 +27,8 @@ func init() { // Populates the top of the binary tree Config.master = addNode("guiBinaryTree") - go doGuiChan() + // used to pass debugging flags to the toolkit plugins + Config.flag = Config.master.New("flag", toolkit.Flag, nil) } func doGuiChan() { @@ -39,7 +41,9 @@ func doGuiChan() { log(true, "CHANNEL ACTION 2 !!!!!") return default: + log(true, "doGuiChan() nothing") } + log(true, "doGuiChan() for()") } } diff --git a/plugin.go b/plugin.go index 3b558f5..72005ca 100644 --- a/plugin.go +++ b/plugin.go @@ -35,19 +35,6 @@ type aplug struct { // simplifies passing to the plugin Send func(*toolkit.Widget, *toolkit.Widget) - - NewButton func(*toolkit.Widget, *toolkit.Widget) - NewGroup func(*toolkit.Widget, *toolkit.Widget) - NewCheckbox func(*toolkit.Widget, *toolkit.Widget) - NewTab func(*toolkit.Widget, *toolkit.Widget) - - NewDropdown func(*toolkit.Widget, *toolkit.Widget) - AddDropdownName func(*toolkit.Widget, string) - SetDropdownName func(*toolkit.Widget, string) - - SetDebugToolkit func(bool) - SetDebugChange func(bool) - ShowDebug func() } var allPlugins []*aplug @@ -71,6 +58,7 @@ func LoadToolkit(name string) bool { filename := name + ".so" loadPlugin(&newPlug, filename) if (newPlug.plug == nil) { + log(true, "attempt to find plugin", filename, "failed") return false } // newPlug.Ok = true @@ -92,19 +80,9 @@ func LoadToolkit(name string) bool { // This includes instructions like "Add", "Delete", "Disable", etc newPlug.Send = loadFunc2(&newPlug, "Send") - // newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup") - - newPlug.NewDropdown = loadFunc2(&newPlug, "NewDropdown") - newPlug.AddDropdownName = loadFuncS(&newPlug, "AddDropdownName") - newPlug.SetDropdownName = loadFuncS(&newPlug, "SetDropdownName") - - newPlug.SetDebugToolkit = loadFuncB(&newPlug, "SetDebugToolkit") - newPlug.SetDebugChange = loadFuncB(&newPlug, "SetDebugChange") - newPlug.ShowDebug = loadFuncE(&newPlug, "ShowDebug") - allPlugins = append(allPlugins, &newPlug) - log(debugGui, "gui.LoadToolkit() END", newPlug.name, filename) + log(debugPlugin, "gui.LoadToolkit() END", newPlug.name, filename) newPlug.Init() newPlug.LoadOk = true return true @@ -131,63 +109,6 @@ func loadFuncE(p *aplug, funcName string) func() { return newfunc } -func loadFunc1(p *aplug, funcName string) func(*toolkit.Widget) { - var newfunc func(*toolkit.Widget) - var ok bool - var test plugin.Symbol - - test, err = p.plug.Lookup(funcName) - if err != nil { - log(debugGui, "DID NOT FIND: name =", test, "err =", err) - return nil - } - - newfunc, ok = test.(func(*toolkit.Widget)) - if !ok { - log(debugGui, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name) - return nil - } - return newfunc -} - -func loadFuncS(p *aplug, funcName string) func(*toolkit.Widget, string) { - var newfunc func(*toolkit.Widget, string) - var ok bool - var test plugin.Symbol - - test, err = p.plug.Lookup(funcName) - if err != nil { - log(debugGui, "DID NOT FIND: name =", test, "err =", err) - return nil - } - - newfunc, ok = test.(func(*toolkit.Widget, string)) - if !ok { - log(debugGui, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name) - return nil - } - return newfunc -} - -func loadFuncB(p *aplug, funcName string) func(bool) { - var newfunc func(bool) - var ok bool - var test plugin.Symbol - - test, err = p.plug.Lookup(funcName) - if err != nil { - log(debugGui, "DID NOT FIND: name =", test, "err =", err) - return nil - } - - newfunc, ok = test.(func(bool)) - if !ok { - log(debugGui, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name) - return nil - } - return newfunc -} - func loadFunc2(p *aplug, funcName string) func(*toolkit.Widget, *toolkit.Widget) { var newfunc func(*toolkit.Widget, *toolkit.Widget) var ok bool @@ -276,6 +197,7 @@ func loadfile(filename string) *plugin.Plugin { return nil } log(debugGui, "plugin WORKED =", filename) + log(true, "loading plugin", filename, "worked") return plug } diff --git a/structs.go b/structs.go index b3589af..819464a 100644 --- a/structs.go +++ b/structs.go @@ -34,6 +34,9 @@ type GuiConfig struct { // This is the master node. The Binary Tree starts here master *Node + // A node off of master for passing debugging flags + flag *Node + // These are shortcuts to pass default values to make a new window Title string Width int diff --git a/toolkit/andlabs/append.go b/toolkit/andlabs/append.go new file mode 100644 index 0000000..811ffbc --- /dev/null +++ b/toolkit/andlabs/append.go @@ -0,0 +1,103 @@ +package main + +import ( + "git.wit.org/wit/gui/toolkit" + + "github.com/andlabs/ui" + _ "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) + + if (t.uiBox != nil) { + log(true, "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) + } + + // hack to pass a group + if (c == nil) { + log(true, "attempting to doAppend() on a uiGroup") + if (t.uiBox != nil) { + if (newt.Name == "output") { + t.uiBox.Append(newt.uiGroup, true) + } else { + t.uiBox.Append(newt.uiGroup, stretchy) + } + 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") + t.Dump(true) + newt.Dump(true) + t.uiBox = ui.NewHorizontalBox() + t.uiWindow.SetChild(t.uiBox) + log(true, "tried to make a box", t.uiBox) + if (newt.Name == "output") { + log(true, "tried to t.uiBox.Append(*c, true)") + if (t.uiBox == nil) { + log(true, "tried to t.uiBox.Append(*c, true)") + } + t.uiBox.Append(newt.uiGroup, true) + } else { + log(true, "tried to t.uiBox.Append(*c, stretchy)") + t.uiBox.Append(newt.uiGroup, stretchy) + } + return + } + + 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") + } + if (t.uiBox != nil) { + // TODO: temporary hack to make the output textbox 'fullscreen' + if (newt.Name == "output") { + t.uiBox.Append(*c, true) + } else { + t.uiBox.Append(*c, stretchy) + } + 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") + t.uiBox = ui.NewHorizontalBox() + t.uiWindow.SetChild(t.uiBox) + log(true, "tried to make a box") + if (newt.Name == "output") { + t.uiBox.Append(*c, true) + } else { + t.uiBox.Append(*c, stretchy) + } + return + } + + 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") +} diff --git a/toolkit/andlabs/box.go b/toolkit/andlabs/box.go index 430e78e..265d7c8 100644 --- a/toolkit/andlabs/box.go +++ b/toolkit/andlabs/box.go @@ -4,16 +4,16 @@ import "github.com/andlabs/ui" import _ "github.com/andlabs/ui/winmanifest" // create a new box -func (t *andlabsT) GetBox() *ui.Box { +func (t *andlabsT) getBox() *ui.Box { return t.uiBox } // create a new box -func (t *andlabsT) NewBox() *andlabsT { - log(debugToolkit, "gui.Toolbox.NewBox() START create default") +func (t *andlabsT) newBox() *andlabsT { + log(debugToolkit, "newBox() START create default") t.Dump(debugToolkit) if (t.uiGroup != nil) { - log(debugToolkit, "\tgui.Toolbox.NewBox() is a Group") + log(debugToolkit, "\tnewBox() is a Group") var newTK andlabsT vbox := ui.NewVerticalBox() @@ -24,7 +24,7 @@ func (t *andlabsT) NewBox() *andlabsT { return &newTK } if (t.uiBox != nil) { - log(debugToolkit, "\tgui.Toolbox.NewBox() is a Box") + log(debugToolkit, "\tnewBox() is a Box") var newTK andlabsT vbox := ui.NewVerticalBox() @@ -36,7 +36,7 @@ func (t *andlabsT) NewBox() *andlabsT { return &newTK } if (t.uiWindow != nil) { - log(debugToolkit, "\tgui.Toolbox.NewBox() is a Window") + log(debugToolkit, "\tnewBox() is a Window") var newT andlabsT vbox := ui.NewVerticalBox() @@ -48,7 +48,7 @@ func (t *andlabsT) NewBox() *andlabsT { // panic("WTF") return &newT } - log(debugToolkit, "\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box") + log(debugToolkit, "\tnewBox() FAILED. Couldn't figure out where to make a box") t.Dump(debugToolkit) return nil } diff --git a/toolkit/andlabs/checkbox.go b/toolkit/andlabs/checkbox.go index 29a8e4d..16e4eed 100644 --- a/toolkit/andlabs/checkbox.go +++ b/toolkit/andlabs/checkbox.go @@ -6,8 +6,8 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -func (t andlabsT) NewCheckbox(w *toolkit.Widget) *andlabsT { - log(debugToolkit, "NewCheckbox()", w.Name, w.Type) +func (t *andlabsT) newCheckbox(w *toolkit.Widget) *andlabsT { + log(debugToolkit, "newCheckbox()", w.Name, w.Type) var newt andlabsT newt.tw = w @@ -15,13 +15,13 @@ func (t andlabsT) NewCheckbox(w *toolkit.Widget) *andlabsT { return nil } - c := ui.NewCheckbox(w.Name) - newt.uiCheckbox = c + newt.uiCheckbox = ui.NewCheckbox(w.Name) newt.uiBox = t.uiBox - t.uiBox.Append(c, stretchy) + // t.doAppend(&newt, *newt.uiCheckbox) + t.uiBox.Append(newt.uiCheckbox, stretchy) - c.OnToggled(func(spin *ui.Checkbox) { - newt.tw.B = newt.Checked() + newt.uiCheckbox.OnToggled(func(spin *ui.Checkbox) { + newt.tw.B = newt.checked() log(debugChange, "val =", newt.tw.B) newt.commonChange(newt.tw) }) @@ -29,7 +29,7 @@ func (t andlabsT) NewCheckbox(w *toolkit.Widget) *andlabsT { return &newt } -func (t andlabsT) Checked() bool { +func (t *andlabsT) checked() bool { if t.broken() { return false } @@ -37,15 +37,15 @@ func (t andlabsT) Checked() bool { return t.uiCheckbox.Checked() } -func NewCheckbox(parentW *toolkit.Widget, w *toolkit.Widget) { - log(debugToolkit, "NewCheckbox()", w.Name) +func newCheckbox(parentW *toolkit.Widget, w *toolkit.Widget) { + log(debugToolkit, "newCheckbox()", w.Name) t := mapToolkits[parentW] if (t == nil) { listMap(debugError) return } - newt := t.NewCheckbox(w) + newt := t.newCheckbox(w) mapWidgetsToolkits(w, newt) } @@ -54,7 +54,7 @@ func doCheckbox(p *toolkit.Widget, c *toolkit.Widget) { return } if (c.Action == "New") { - NewCheckbox(p, c) + newCheckbox(p, c) return } ct := mapToolkits[c] diff --git a/toolkit/andlabs/combobox.go b/toolkit/andlabs/combobox.go new file mode 100644 index 0000000..08e7148 --- /dev/null +++ b/toolkit/andlabs/combobox.go @@ -0,0 +1,100 @@ +package main + +import ( + "github.com/andlabs/ui" + _ "github.com/andlabs/ui/winmanifest" + "git.wit.org/wit/gui/toolkit" +) + +func (t *andlabsT) newCombobox(w *toolkit.Widget) *andlabsT { + var newt andlabsT + log(debugToolkit, "newCombobox() START", w.Name) + + if t.broken() { + return nil + } + + newt.tw = w + s := ui.NewEditableCombobox() + newt.uiEditableCombobox = s + newt.uiBox = t.uiBox + t.uiBox.Append(s, stretchy) + + // initialize the index + newt.c = 0 + newt.val = make(map[int]string) + + s.OnChanged(func(spin *ui.EditableCombobox) { + newt.tw.S = spin.Text() + newt.commonChange(newt.tw) + }) + + return &newt +} + +func (t *andlabsT) AddComboboxName(title string) { + t.uiEditableCombobox.Append(title) + if (t.val == nil) { + log(debugToolkit, "make map didn't work") + return + } + t.val[t.c] = title + + // If this is the first menu added, set the dropdown to it + // if (t.c == 0) { + // } + t.c = t.c + 1 +} + +func newCombobox(parentW *toolkit.Widget, w *toolkit.Widget) { + log(debugToolkit, "newCombobox()", w.Name) + + t := mapToolkits[parentW] + if (t == nil) { + log(debugToolkit, "newCombobox() toolkit struct == nil. name=", parentW.Name, w.Name) + listMap(debugToolkit) + return + } + newt := t.newCombobox(w) + mapWidgetsToolkits(w, newt) +} + +func doCombobox(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + if (c.Action == "New") { + newCombobox(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(true, "Combobox() ct.broken", ct) + return + } + if (ct.uiEditableCombobox == nil) { + log(true, "Combobox() uiEditableCombobox == nil", ct) + return + } + log(true, "Going to attempt:", c.Action) + switch c.Action { + case "Add": + ct.AddComboboxName(c.S) + case "Enable": + ct.uiEditableCombobox.Enable() + case "Disable": + ct.uiEditableCombobox.Disable() + case "Show": + ct.uiEditableCombobox.Show() + case "Hide": + ct.uiEditableCombobox.Hide() + case "Set": + ct.uiEditableCombobox.SetText(c.S) + default: + log(true, "Can't do", c.Action, "to a Combobox") + } +} diff --git a/toolkit/andlabs/common.go b/toolkit/andlabs/common.go index 31b73e6..d2811cb 100644 --- a/toolkit/andlabs/common.go +++ b/toolkit/andlabs/common.go @@ -2,6 +2,7 @@ package main import ( "git.wit.org/wit/gui/toolkit" + "github.com/davecgh/go-spew/spew" ) // This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc @@ -11,7 +12,7 @@ func init() { setDefaultBehavior(true) } -func (t andlabsT) commonChange(tw *toolkit.Widget) { +func (t *andlabsT) commonChange(tw *toolkit.Widget) { log(debugChange, "commonChange() START widget =", t.Name, t.Type) if (tw == nil) { log(true, "commonChange() What the fuck. there is no widget t.tw == nil") @@ -35,7 +36,7 @@ func (t *andlabsT) broken() bool { if (t.uiBox == nil) { if (t.uiWindow != nil) { log(debugToolkit, "UiBox == nil. This is an empty window. Try to add a box") - t.NewBox() + t.newBox() return false } log(true, "UiBox == nil. I can't add a widget without a place to put it") @@ -60,3 +61,141 @@ func broken(w *toolkit.Widget) bool { } return false } + +func dump(p *toolkit.Widget, c *toolkit.Widget, b bool) { + log(b, "Parent:") + pt := mapToolkits[p] + if (pt == nil) { + log(b, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + pt.Dump(b) + + log(b, "Child:") + ct := mapToolkits[c] + if (ct == nil) { + log(b, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + 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 befbaa0..8b11f8c 100644 --- a/toolkit/andlabs/debug.go +++ b/toolkit/andlabs/debug.go @@ -2,7 +2,7 @@ package main import "git.wit.org/wit/gui/toolkit" -import "github.com/davecgh/go-spew/spew" +// import "github.com/davecgh/go-spew/spew" var defaultBehavior bool = true @@ -16,6 +16,7 @@ var margin bool // add space around the frames of windows var debugToolkit bool var debugChange bool var debugPlugin bool +var debugFlag bool var debugError bool = true // var DebugToolkit bool @@ -36,6 +37,7 @@ func setDefaultBehavior(s bool) { } } +/* func SetDebugToolkit (s bool) { debugToolkit = s log(true, "debugToolkit =", debugToolkit) @@ -47,98 +49,12 @@ func SetDebugChange (s bool) { log(true, "debugToolkit =", debugToolkit) log(true, "debugChange =", debugChange) } +*/ func ShowDebug () { log(true, "debugToolkit =", debugToolkit) - log(true, "debugChange =", debugChange) -} - -func GetDebugToolkit () bool { - return debugToolkit -} - -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 + log(true, "debugError =", debugError) + log(true, "debugChange =", debugChange) } func (t *andlabsT) Dump(b bool) { @@ -196,3 +112,9 @@ func widgetDump(b bool, w *toolkit.Widget) { log(b, "widget.X =", w.X) log(b, "widget.Y =", w.Y) } + +/* +func GetDebugToolkit () bool { + return debugToolkit +} +*/ diff --git a/toolkit/andlabs/dropdown.go b/toolkit/andlabs/dropdown.go index 935741c..57642e0 100644 --- a/toolkit/andlabs/dropdown.go +++ b/toolkit/andlabs/dropdown.go @@ -6,9 +6,9 @@ import ( "git.wit.org/wit/gui/toolkit" ) -func (t *andlabsT) NewDropdown(w *toolkit.Widget) *andlabsT { +func (t *andlabsT) newDropdown(w *toolkit.Widget) *andlabsT { var newt andlabsT - log(debugToolkit, "gui.Toolbox.NewDropdown() START", w.Name) + log(debugToolkit, "gui.Toolbox.newDropdown() START", w.Name) if t.broken() { return nil @@ -53,23 +53,10 @@ func (t *andlabsT) AddDropdownName(title string) { t.c = t.c + 1 } -func (t andlabsT) SetDropdown(i int) { +func (t *andlabsT) SetDropdown(i int) { t.uiCombobox.SetSelected(i) } -func NewDropdown(parentW *toolkit.Widget, w *toolkit.Widget) { - log(debugToolkit, "gui.andlabs.NewDropdown()", w.Name) - - t := mapToolkits[parentW] - if (t == nil) { - log(debugToolkit, "go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) - listMap(debugToolkit) - return - } - newt := t.NewDropdown(w) - mapWidgetsToolkits(w, newt) -} - func AddDropdownName(w *toolkit.Widget, s string) { log(debugToolkit, "gui.andlabs.AddDropdownName()", w.Name, "add:", s) @@ -94,3 +81,57 @@ func SetDropdownName(w *toolkit.Widget, s string) { t.SetDropdown(1) t.tw.S = s } + +func newDropdown(parentW *toolkit.Widget, w *toolkit.Widget) { + log(debugToolkit, "gui.andlabs.newDropdown()", w.Name) + + t := mapToolkits[parentW] + if (t == nil) { + log(debugToolkit, "go.andlabs.newDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) + listMap(debugToolkit) + return + } + newt := t.newDropdown(w) + mapWidgetsToolkits(w, newt) +} + +func doDropdown(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + if (c.Action == "New") { + newDropdown(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(true, "Dropdown() ct.broken", ct) + return + } + if (ct.uiCombobox == nil) { + log(true, "Dropdown() uiCombobox == nil", ct) + return + } + log(true, "Going to attempt:", c.Action) + switch c.Action { + case "Add": + ct.AddDropdownName(c.S) + // ct.uiCombobox.Enable() + case "Enable": + ct.uiCombobox.Enable() + case "Disable": + ct.uiCombobox.Disable() + case "Show": + ct.uiCombobox.Show() + case "Hide": + ct.uiCombobox.Hide() + case "Set": + ct.uiCombobox.SetSelected(1) + default: + log(true, "Can't do", c.Action, "to a Dropdown") + } +} diff --git a/toolkit/andlabs/grid.go b/toolkit/andlabs/grid.go new file mode 100644 index 0000000..8d09152 --- /dev/null +++ b/toolkit/andlabs/grid.go @@ -0,0 +1,102 @@ +package main + +import ( + "github.com/andlabs/ui" + _ "github.com/andlabs/ui/winmanifest" + + "git.wit.org/wit/gui/toolkit" +) + +// Grid numbering by (X,Y) +// ----------------------------- +// -- (1,1) -- (2,1) -- (3,1) -- +// -- (1,2) -- (2,1) -- (3,1) -- +// ----------------------------- +func newGrid(parentW *toolkit.Widget, w *toolkit.Widget) { + var newt *andlabsT + log(debugToolkit, "NewGrid()", w.Name) + + t := mapToolkits[parentW] + if (t == nil) { + listMap(debugError) + log(debugError, "ERROR newGrid() listMap()") + log(debugError, "ERROR FFFFFFFFFFFF listMap()") + log(debugError, "ERROR FFFFFFFFFFFF listMap()") + return + } + + log(debugToolkit, "NewGrid()", w.Name) + if t.broken() { + return + } + + newt = new(andlabsT) + + c := ui.NewGrid() + 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) { + + mapWidgetsToolkits(w, newt) +} + +func doGrid(p *toolkit.Widget, c *toolkit.Widget) { + if broken(c) { + return + } + if (c.Action == "New") { + newGrid(p, c) + return + } + ct := mapToolkits[c] + if (ct == nil) { + log(true, "Trying to do something on a widget that doesn't work or doesn't exist or something", c) + return + } + if ct.broken() { + log(true, "Grid() ct.broken", ct) + return + } + if (ct.uiGrid == nil) { + + log(true, "Grid() uiGrid == nil", ct) + return + } + log(true, "Going to attempt:", c.Action) + switch c.Action { + case "Enable": + ct.uiGrid.Enable() + case "Disable": + ct.uiGrid.Disable() + case "Show": + ct.uiGrid.Show() + case "Hide": + ct.uiGrid.Hide() + case "Set": + log(true, "Can I use 'Set' to place a *Node in a Grid?") + default: + log(true, "Can't do", c.Action, "to a Grid") + } +} diff --git a/toolkit/andlabs/group.go b/toolkit/andlabs/group.go index 613efb6..903cb4f 100644 --- a/toolkit/andlabs/group.go +++ b/toolkit/andlabs/group.go @@ -8,49 +8,62 @@ import ( ) func newGroup(parentW *toolkit.Widget, w *toolkit.Widget) { - log(debugToolkit, "gui.andlabs.NewGroup()", w.Name) + // log(debugToolkit, "gui.andlabs.NewGroup()", w.Name) + log(true, "NewGroup()", w.Name) t := mapToolkits[parentW] if (t == nil) { - log(debugToolkit, "go.andlabs.NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name) listMap(debugToolkit) } - newt := t.NewGroup(w.Name) + newt := t.rawGroup(w.Name) mapWidgetsToolkits(w, newt) } // make new Group here -func (t andlabsT) NewGroup(title string) *andlabsT { +func (t *andlabsT) rawGroup(title string) *andlabsT { var newt andlabsT + newt.Name = title - log(debugToolkit, "NewGroup() create", title) + log(debugToolkit, "NewGroup() create", newt.Name) - g := ui.NewGroup(title) + g := ui.NewGroup(newt.Name) g.SetMargined(margin) + newt.uiGroup = g + t.doAppend(&newt, nil) + /* if (t.uiBox != nil) { // TODO: temporary hack to make the output textbox 'fullscreen' - if (title == "output") { + if (newt.Name == "output") { t.uiBox.Append(g, true) } else { t.uiBox.Append(g, stretchy) } } else if (t.uiWindow != nil) { - t.uiWindow.SetChild(g) + 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") } + */ hbox := ui.NewVerticalBox() hbox.SetPadded(padded) g.SetChild(hbox) - newt.uiGroup = g newt.uiBox = hbox newt.uiWindow = t.uiWindow - newt.Name = title + newt.uiTab = t.uiTab return &newt } diff --git a/toolkit/andlabs/icon.go b/toolkit/andlabs/icon.go new file mode 100644 index 0000000..00c25f6 --- /dev/null +++ b/toolkit/andlabs/icon.go @@ -0,0 +1,27 @@ +package main + +var rawImage = []byte{ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, + 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, + 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, + 0x00, 0xca, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0xa5, 0x93, 0xb1, 0x0d, + 0xc2, 0x40, 0x0c, 0x45, 0x1d, 0xc4, 0x14, 0x0c, 0x12, 0x41, 0x0f, 0x62, + 0x12, 0x46, 0x80, 0x8a, 0x2e, 0x15, 0x30, 0x02, 0x93, 0x20, 0x68, 0x11, + 0x51, 0x06, 0x61, 0x0d, 0x88, 0x2d, 0x7f, 0xdb, 0x07, 0x87, 0x08, 0xdc, + 0x49, 0x91, 0x7d, 0xf6, 0xf7, 0xf3, 0x4f, 0xa4, 0x54, 0xbb, 0xeb, 0xf6, + 0x41, 0x05, 0x67, 0xcc, 0xb3, 0x9b, 0xfa, 0xf6, 0x17, 0x62, 0xdf, 0xcd, + 0x48, 0x00, 0x32, 0xbd, 0xa8, 0x1d, 0x72, 0xee, 0x3c, 0x47, 0x16, 0xfb, + 0x5c, 0x53, 0x8d, 0x03, 0x30, 0x14, 0x84, 0xf7, 0xd5, 0x89, 0x26, 0xc7, + 0x25, 0x10, 0x36, 0xe4, 0x05, 0xa2, 0x51, 0xbc, 0xc4, 0x1c, 0xc3, 0x1c, + 0xed, 0x30, 0x1c, 0x8f, 0x16, 0x3f, 0x02, 0x78, 0x33, 0x20, 0x06, 0x60, + 0x97, 0x70, 0xaa, 0x45, 0x7f, 0x85, 0x60, 0x5d, 0xb6, 0xf4, 0xc2, 0xc4, + 0x3e, 0x0f, 0x44, 0xcd, 0x1b, 0x20, 0x90, 0x0f, 0xed, 0x85, 0xa8, 0x55, + 0x05, 0x42, 0x43, 0xb4, 0x9e, 0xce, 0x71, 0xb3, 0xe8, 0x0e, 0xb4, 0xc4, + 0xc3, 0x39, 0x21, 0xb7, 0x73, 0xbd, 0xe4, 0x1b, 0xe4, 0x04, 0xb6, 0xaa, + 0x4f, 0x18, 0x2c, 0xee, 0x42, 0x31, 0x01, 0x84, 0xfa, 0xe0, 0xd4, 0x00, + 0xdf, 0xb6, 0x83, 0xf8, 0xea, 0xc2, 0x00, 0x10, 0xfc, 0x1a, 0x05, 0x30, + 0x74, 0x3b, 0xe0, 0xd1, 0x45, 0xb1, 0x83, 0xaa, 0xf4, 0x77, 0x7e, 0x02, + 0x87, 0x1f, 0x42, 0x7f, 0x9e, 0x2b, 0xe8, 0xdf, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +} diff --git a/toolkit/andlabs/label.go b/toolkit/andlabs/label.go index 6bdd9b2..fca9abb 100644 --- a/toolkit/andlabs/label.go +++ b/toolkit/andlabs/label.go @@ -27,7 +27,7 @@ func newLabel(parentW *toolkit.Widget, w *toolkit.Widget) { newt = new(andlabsT) - c := ui.NewLabel(w.Name + " FIX") + c := ui.NewLabel(w.Name) newt.uiLabel = c newt.uiBox = t.uiBox @@ -39,7 +39,6 @@ func newLabel(parentW *toolkit.Widget, w *toolkit.Widget) { mapWidgetsToolkits(w, newt) } - func doLabel(p *toolkit.Widget, c *toolkit.Widget) { if broken(c) { return diff --git a/toolkit/andlabs/main.go b/toolkit/andlabs/main.go index a72821a..20bbd8b 100644 --- a/toolkit/andlabs/main.go +++ b/toolkit/andlabs/main.go @@ -1,6 +1,7 @@ package main import ( + "embed" "git.wit.org/wit/gui/toolkit" "github.com/andlabs/ui" @@ -8,6 +9,9 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) +//go:embed resources +var res embed.FS + func Main(f func()) { log(debugToolkit, "Starting gui.Main() (using gtk via andlabs/ui)") ui.Main( func() { @@ -33,9 +37,8 @@ func Main(f func()) { // func Queue(f func()) { log(debugToolkit, "Sending function to ui.QueueMain()") - log(true, "THIS DOES BREAK. TODO: wrap this") + log(true, "using gui.Queue() in this plugin DOES BREAK. TODO: wrap this") ui.QueueMain(f) - // f() } func Init() { diff --git a/toolkit/andlabs/plugin.go b/toolkit/andlabs/plugin.go index 5bc40a0..8b75766 100644 --- a/toolkit/andlabs/plugin.go +++ b/toolkit/andlabs/plugin.go @@ -26,6 +26,12 @@ 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) + return + } + switch c.Type { case toolkit.Window: newWindow(c) @@ -45,10 +51,36 @@ func Send(p *toolkit.Widget, c *toolkit.Widget) { newSlider(p, c) case toolkit.Spinner: newSpinner(p, c) + case toolkit.Dropdown: + doDropdown(p, c) + case toolkit.Combobox: + doCombobox(p, c) + 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?") + // 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 "Show": + ShowDebug() + default: + log(debugError, "Can't set unknown flag", c.S) + } default: - log(true, "unknown parent =", p.Name, p.Type) - log(true, "unknown child =", c.Name, c.Type) - log(true, "Don't know how to do", c.Type, "yet") + 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") } } diff --git a/toolkit/andlabs/resources/ping6.broken.png b/toolkit/andlabs/resources/ping6.broken.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3e2ae10d0bb895ba1c3a99e51ca6375caf7260 GIT binary patch literal 9486 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 R;odt@Xlod#zf`pk{y%L48DRhb literal 0 HcmV?d00001 diff --git a/toolkit/andlabs/resources/ping6.pure-bright.png b/toolkit/andlabs/resources/ping6.pure-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..82c554db4fd06acdbd291b05559f253642ead996 GIT binary patch literal 11989 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 literal 0 HcmV?d00001 diff --git a/toolkit/andlabs/resources/ping6.pure.png b/toolkit/andlabs/resources/ping6.pure.png new file mode 100644 index 0000000000000000000000000000000000000000..9e08140fa7179ed8b446b6ad7572520a8b988921 GIT binary patch literal 9072 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 UdRtpybLh~~xTyYE)$aQL0S-nci2wiq literal 0 HcmV?d00001 diff --git a/toolkit/andlabs/resources/ping6.working.png b/toolkit/andlabs/resources/ping6.working.png new file mode 100644 index 0000000000000000000000000000000000000000..6767c59b1c2e69c092fb2694ea9568a3fb3d61c6 GIT binary patch literal 3654 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 P9}ECxWM){S?;Q6(XBgqD literal 0 HcmV?d00001 diff --git a/toolkit/andlabs/slider.go b/toolkit/andlabs/slider.go index 87639ca..f75947a 100644 --- a/toolkit/andlabs/slider.go +++ b/toolkit/andlabs/slider.go @@ -7,7 +7,7 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -func (t andlabsT) newSlider(w *toolkit.Widget) *andlabsT { +func (t *andlabsT) newSlider(w *toolkit.Widget) *andlabsT { // make new node here log(debugToolkit, w.Name, w.Type, w.X, w.Y) var newt andlabsT @@ -26,6 +26,7 @@ func (t andlabsT) newSlider(w *toolkit.Widget) *andlabsT { t.uiBox.Append(s, stretchy) s.OnChanged(func(spin *ui.Slider) { + newt.tw.I = newt.uiSlider.Value() newt.commonChange(newt.tw) }) diff --git a/toolkit/andlabs/spinner.go b/toolkit/andlabs/spinner.go index 1a7430e..2ee556c 100644 --- a/toolkit/andlabs/spinner.go +++ b/toolkit/andlabs/spinner.go @@ -7,7 +7,7 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -func (t andlabsT) newSpinner(w *toolkit.Widget) *andlabsT { +func (t *andlabsT) newSpinner(w *toolkit.Widget) *andlabsT { // make new node here log(debugToolkit, "newSpinner()", w.X, w.Y) var newt andlabsT @@ -24,6 +24,7 @@ func (t andlabsT) newSpinner(w *toolkit.Widget) *andlabsT { t.uiBox.Append(s, stretchy) s.OnChanged(func(s *ui.Spinbox) { + newt.tw.I = newt.uiSpinbox.Value() newt.commonChange(newt.tw) }) diff --git a/toolkit/andlabs/structs.go b/toolkit/andlabs/structs.go index 45b6d1d..3353401 100644 --- a/toolkit/andlabs/structs.go +++ b/toolkit/andlabs/structs.go @@ -28,9 +28,9 @@ type andlabsT struct { uiSpinbox *ui.Spinbox uiTab *ui.Tab uiWindow *ui.Window - // UiWindowBad *ui.Window // erase this uiMultilineEntry *ui.MultilineEntry uiEditableCombobox *ui.EditableCombobox + uiGrid *ui.Grid // used as a counter to work around limitations of widgets like combobox // this is probably fucked up and in many ways wrong because of unsafe goroutine threading diff --git a/toolkit/andlabs/tab.go b/toolkit/andlabs/tab.go index 995bbbd..aaac102 100644 --- a/toolkit/andlabs/tab.go +++ b/toolkit/andlabs/tab.go @@ -63,7 +63,7 @@ func tabSetMargined(tab *ui.Tab) { } func rawTab(w *ui.Window, name string) *andlabsT { - var t andlabsT + var newt andlabsT log(debugToolkit, "gui.toolkit.NewTab() ADD", name) if (w == nil) { @@ -83,10 +83,10 @@ func rawTab(w *ui.Window, name string) *andlabsT { tabSetMargined(tab) // TODO: run this in the right place(?) w.SetChild(tab) - t.uiWindow = w - t.uiTab = tab - t.uiBox = hbox - return &t + newt.uiWindow = w + newt.uiTab = tab + newt.uiBox = hbox + return &newt } func (t *andlabsT) appendTab(name string) *andlabsT { diff --git a/toolkit/andlabs/textbox.go b/toolkit/andlabs/textbox.go index e916fd9..ddc27a4 100644 --- a/toolkit/andlabs/textbox.go +++ b/toolkit/andlabs/textbox.go @@ -1,9 +1,11 @@ package main -import "git.wit.org/wit/gui/toolkit" +import ( + "git.wit.org/wit/gui/toolkit" -import "github.com/andlabs/ui" -import _ "github.com/andlabs/ui/winmanifest" + "github.com/andlabs/ui" + _ "github.com/andlabs/ui/winmanifest" +) func newTextbox(parentW *toolkit.Widget, w *toolkit.Widget) { log(debugToolkit, "NewTexbox()", w.Name) @@ -15,8 +17,9 @@ func newTextbox(parentW *toolkit.Widget, w *toolkit.Widget) { log(debugError, "FFFFFFFFFFFF listMap()") log(debugError, "FFFFFFFFFFFF listMap()") } + // t.NewTextbox(w) -// func (t andlabsT) NewTextbox(w *toolkit.Widget) *andlabsT { +// func (t *andlabsT) NewTextbox(w *toolkit.Widget) *andlabsT { var newt *andlabsT newt = new(andlabsT) @@ -37,6 +40,41 @@ func newTextbox(parentW *toolkit.Widget, w *toolkit.Widget) { t.uiBox.Append(c, stretchy) } + /* + // don't bother with "images" on andlabs/ui + "image" + "bytes" + _ "image/png" + "image/draw" + + if (w.Name == "image") { + log(true, "NewTextbox() trying to add a new image") + i := ui.NewImage(16, 16) + img, _, err := image.Decode(bytes.NewReader(rawImage)) + if err != nil { + panic(err) + } + nr, ok := img.(*image.RGBA) + if !ok { + i2 := image.NewRGBA(img.Bounds()) + draw.Draw(i2, i2.Bounds(), img, img.Bounds().Min, draw.Src) + nr = i2 + } + i.Append(nr) + t.uiBox.Append(i, true) + + var img *ui.Image + var icon []byte + var imgA image.Image + + icon, _ = res.ReadFile("resources/ping6.working.png") + // imgA, _, err := image.Decode(bytes.NewReader(b)) + imgA, _, _ = image.Decode(icon) + img.Append(imgA) + img.Append(icon) + } + */ + c.OnChanged(func(spin *ui.MultilineEntry) { w.S = newt.uiMultilineEntry.Text() // this is still dangerous @@ -81,9 +119,21 @@ func (t *andlabsT) doSimpleAction() { log(debugChange, "Going to attempt:", t.tw.Action) switch t.tw.Action { case "Enable": - t.uiMultilineEntry.Enable() + if (t.uiEntry != nil) { + t.uiEntry.Enable() + } else if (t.uiMultilineEntry != nil) { + t.uiMultilineEntry.Enable() + } else { + log(true, "don't know what to enable", t.Name) + } case "Disable": - t.uiMultilineEntry.Disable() + if (t.uiEntry != nil) { + t.uiEntry.Disable() + } else if (t.uiMultilineEntry != nil) { + t.uiMultilineEntry.Disable() + } else { + log(true, "don't know what to disable", t.Name) + } case "Show": t.uiMultilineEntry.Show() case "Hide": diff --git a/toolkit/widget.go b/toolkit/widget.go index fcb6d31..9241d5a 100644 --- a/toolkit/widget.go +++ b/toolkit/widget.go @@ -56,10 +56,13 @@ const ( Button Checkbox Dropdown + Combobox Label Textbox Slider Spinner + Grid + Flag ) func (s WidgetType) String() string { @@ -78,6 +81,8 @@ func (s WidgetType) String() string { return "Checkbox" case Dropdown: return "Dropdown" + case Combobox: + return "Combobox" case Label: return "Label" case Textbox: @@ -86,6 +91,10 @@ func (s WidgetType) String() string { return "Slider" case Spinner: return "Spinner" + case Grid: + return "Grid" + case Flag: + return "Flag" case Unknown: return "Unknown" }