diff --git a/Makefile b/Makefile index b25d255..c390cd0 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ cmds-helloconsole: github: git push origin master git push github master + git push github devel git push github --tags @echo @echo check https://github.com/wit-go/gui diff --git a/README-goreadme.md b/README-goreadme.md index 6177226..847ca85 100644 --- a/README-goreadme.md +++ b/README-goreadme.md @@ -107,42 +107,6 @@ external things which might be useful * [GO Style Guide] ``` -version v1.3 - -I like things to be easy. - -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! - -## Variables - -```golang -var INFO bool -``` - -```golang -var LOGOFF bool = false // turn this off, all logging stops - -``` - -```golang -var SPEW spewt -``` - -```golang -var WARN bool -``` - ## Functions ### func [DebugWidgetWindow](/debugWidget.go#L52) @@ -155,11 +119,15 @@ var WARN bool Creates a window helpful for debugging this package -### func [Indent](/debug.go#L130) +### func [ExampleCatcher](/chan.go#L37) + +`func ExampleCatcher(f func())` + +### func [Indent](/debug.go#L125) `func Indent(b bool, a ...interface{})` -### func [InitPlugins](/main.go#L56) +### func [InitPlugins](/main.go#L58) `func InitPlugins(names []string)` @@ -169,22 +137,15 @@ Creates a window helpful for debugging this package loads and initializes a toolkit (andlabs/ui, gocui, etc) -### func [Main](/main.go#L97) +### func [Main](/main.go#L121) `func Main(f func())` This should not pass a function -### func [Queue](/main.go#L127) +### func [Redraw](/redraw.go#L9) -`func Queue(f func())` - -Other goroutines must use this to access the GUI - -You can not acess / process the GUI thread directly from -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 Redraw(s string)` ### func [SetDebug](/debug.go#L28) @@ -194,11 +155,11 @@ For example: gui.Queue(NewWindow()) `func SetFlag(s string, b bool)` -### func [ShowDebugValues](/debug.go#L86) +### func [ShowDebugValues](/debug.go#L79) `func ShowDebugValues()` -### func [StandardExit](/main.go#L147) +### func [StandardExit](/main.go#L173) `func StandardExit()` @@ -216,13 +177,13 @@ This goroutine can be used like a watchdog timer ## Types -### type [GuiArgs](/structs.go#L25) +### type [GuiArgs](/structs.go#L26) `type GuiArgs struct { ... }` This struct can be used with the go-arg package -### type [GuiConfig](/structs.go#L33) +### type [GuiConfig](/structs.go#L34) `type GuiConfig struct { ... }` @@ -232,7 +193,7 @@ This struct can be used with the go-arg package var Config GuiConfig ``` -### type [Node](/structs.go#L57) +### type [Node](/structs.go#L58) `type Node struct { ... }` @@ -287,12 +248,22 @@ func main() { You get a window ``` +#### func [Start](/main.go#L98) + +`func Start() *Node` + +#### func [StartS](/main.go#L107) + +`func StartS(name string) *Node` + ### type [Symbol](/plugin.go#L16) `type Symbol any` ## Sub Packages +* [log](./log) + * [toolkit](./toolkit) --- diff --git a/button.go b/button.go index e176a34..a6026a1 100644 --- a/button.go +++ b/button.go @@ -6,11 +6,15 @@ func (n *Node) NewButton(name string, custom func()) *Node { newNode := n.New(name, toolkit.Button, custom) var a toolkit.Action - a.Type = toolkit.Add - // a.Widget = &newNode.widget - // a.Where = &n.widget - // action(&a) + a.Name = name + a.Text = name + a.ActionType = toolkit.Add + a.Callback = callback newaction(&a, newNode, n) return newNode } + +func callback(i int) { + log(debugError, "button callback() i =", i) +} diff --git a/chan.go b/chan.go index 65c79ba..54eb4e4 100644 --- a/chan.go +++ b/chan.go @@ -8,8 +8,10 @@ import ( // "regexp" // "git.wit.org/wit/gui/toolkit" "sync" + "runtime" "github.com/sourcegraph/conc" "github.com/sourcegraph/conc/stream" + "github.com/sourcegraph/conc/panics" ) func makeConc() { @@ -17,14 +19,42 @@ func makeConc() { defer wg.Wait() startTheThing(&wg) + log(debugError, "panic?") + sleep(2) + log(debugError, "panic? after sleep(5)") } func startTheThing(wg *conc.WaitGroup) { + f := func() { + log(debugError, "startTheThing() == about to panic now") + panic("test conc.WaitGroup") + } wg.Go(func() { - log(debugNow, "startTheThing()") + ExampleCatcher(f) }) } +func ExampleCatcher(f func()) { + var pc panics.Catcher + i := 0 + pc.Try(func() { i += 1 }) + pc.Try(f) + pc.Try(func() { i += 1 }) + + recovered := pc.Recovered() + + log(debugError, "panic.Recovered():", recovered.Value.(string)) + frames := runtime.CallersFrames(recovered.Callers) + for { + frame, more := frames.Next() + log(debugError, "\t", frame.Function) + + if !more { + break + } + } +} + func mapStream( in chan int, out chan int, diff --git a/checkbox.go b/checkbox.go index 353072f..8ece750 100644 --- a/checkbox.go +++ b/checkbox.go @@ -10,10 +10,9 @@ func (n *Node) NewCheckbox(name string) *Node { newNode := n.New(name, toolkit.Checkbox, nil) var a toolkit.Action - a.Type = toolkit.Add - // a.Widget = &newNode.widget - // a.Where = &n.widget - // action(&a, newNode, n) + a.ActionType = toolkit.Add + a.Name = name + a.Text = name newaction(&a, newNode, n) return newNode diff --git a/cmds/buttonplugin/Makefile b/cmds/buttonplugin/Makefile index 49d190c..12c23a8 100644 --- a/cmds/buttonplugin/Makefile +++ b/cmds/buttonplugin/Makefile @@ -8,7 +8,7 @@ run: build # ./buttonplugin >/tmp/buttonplugin.log 2>&1 - ./buttonplugin + ./buttonplugin >/tmp/witgui.log.stderr 2>&1 build-release: go get -v -u -x . @@ -21,3 +21,7 @@ build: update: GO111MODULE="off" go get -v -u -x . + +log: + reset + tail -f /tmp/witgui.* /tmp/guilogfile diff --git a/cmds/buttonplugin/main.go b/cmds/buttonplugin/main.go index 8a76a8b..b7f97d5 100644 --- a/cmds/buttonplugin/main.go +++ b/cmds/buttonplugin/main.go @@ -12,11 +12,7 @@ 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 @@ -54,27 +50,49 @@ var counter int = 5 // This creates a window func buttonWindow() { - var w, g *gui.Node + var w, t, g, more, more2 *gui.Node gui.Config.Title = title gui.Config.Width = 640 gui.Config.Height = 480 w = gui.NewWindow() - g = w.NewGroup("buttonGroup") + t = w.NewTab("buttonTab") + g = t.NewGroup("buttonGroup") - g.NewButton("this app is old", func () { + g.NewButton("this app is useful for plugin debuggin", func () { }) g.NewLabel("STDOUT is set to: " + outfile) g.NewButton("hello", func () { log.Println("world") }) + more = g.NewGroup("more") - g.NewButton("NewButton()", func () { + g.NewButton("Load 'democui'", func () { + // this set the xterm and mate-terminal window title. maybe works generally? + fmt.Println("\033]0;" + title + "blah \007") + gui.StartS("democui") + }) + + g.NewButton("Redraw 'democui'", func () { + fmt.Println("\033]0;" + title + "blah2 \007") + gui.Redraw("democui") + }) + + g.NewButton("NewButton(more)", func () { log.Println("new foobar 2. Adding button 'foobar 3'") name := "foobar " + strconv.Itoa(counter) counter += 1 - g.NewButton(name, func () { + more.NewButton(name, func () { + log.Println("Got all the way to main() name =", name) + }) + }) + + g.NewButton("NewButton(more2)", func () { + log.Println("new foobar 2. Adding button 'foobar 3'") + name := "foobar " + strconv.Itoa(counter) + counter += 1 + more2.NewButton(name, func () { log.Println("Got all the way to main() name =", name) }) }) @@ -83,30 +101,12 @@ func buttonWindow() { log.Println("new foobar 2. Adding button 'foobar 3'") name := "neat " + strconv.Itoa(counter) counter += 1 - g.NewGroup(name) + more.NewGroup(name) }) g.NewButton("gui.DebugWindow()", func () { gui.DebugWindow() }) - g.NewButton("LoadToolkit(andlabs)", func () { - gui.LoadToolkit("andlabs") - }) - - g.NewButton("LoadToolkit(gocui)", func () { - gui.LoadToolkit("gocui") - }) - - g.NewButton("Init()", func () { - log.Println("gui.Init() is deprecated(?)") - //gui.Init() - }) - - g.NewButton("Main()", func () { - go gui.Main(func () { - w := gui.NewWindow() - w.NewGroup("buttonGroup") - }) - }) + more2 = g.NewGroup("more2") } diff --git a/cmds/textbox/Makefile b/cmds/textbox/Makefile index 6ca4329..5785c10 100644 --- a/cmds/textbox/Makefile +++ b/cmds/textbox/Makefile @@ -1,5 +1,6 @@ run: build - GOTRACEBACK=all ./textbox --gui-debug + # GOTRACEBACK=all ./textbox --gui-debug + GOTRACEBACK=all ./textbox --gui-debug >/tmp/witgui.log.stderr 2>&1 build-release: go get -v -u -x . diff --git a/cmds/textbox/main.go b/cmds/textbox/main.go index 33d0cae..0dd17e6 100644 --- a/cmds/textbox/main.go +++ b/cmds/textbox/main.go @@ -24,7 +24,9 @@ func main() { arg.MustParse(&args) log.Println("Toolkit = ", args.Toolkit) - // gui.InitPlugins([]string{"andlabs"}) + // gui.SetDebug(true) + // gui.InitPlugins([]string{"gocui"}) + // gui.InitPlugins([]string{"democui"}) gui.Main(initGUI) } @@ -68,10 +70,10 @@ func addDemoTab(window *gui.Node, title string) { dd.AddDropdownName("more 2") dd.AddDropdownName("more 3") - g.SetNext(3,1) - g1.NewLabel("label (3,1)") - g.SetNext(3,2) - g1.NewLabel("label (3,2)") + // g.SetNext(3,1) + // g1.NewLabel("label (3,1)") + // g.SetNext(3,2) + // g1.NewLabel("label (3,2)") g2 := newNode.NewGroup("group 2") tb := g2.NewTextbox("tb") diff --git a/common.go b/common.go index 6abdf58..2218f9b 100644 --- a/common.go +++ b/common.go @@ -11,25 +11,25 @@ import ( func (n *Node) Show() { var a toolkit.Action - a.Type = toolkit.Show + a.ActionType = toolkit.Show newaction(&a, n, nil) } func (n *Node) Hide() { var a toolkit.Action - a.Type = toolkit.Hide + a.ActionType = toolkit.Hide newaction(&a, n, nil) } func (n *Node) Enable() { var a toolkit.Action - a.Type = toolkit.Enable + a.ActionType = toolkit.Enable newaction(&a, n, nil) } func (n *Node) Disable() { var a toolkit.Action - a.Type = toolkit.Disable + a.ActionType = toolkit.Disable newaction(&a, n, nil) } @@ -37,7 +37,7 @@ func (n *Node) Add(str string) { log(debugGui, "gui.Add() value =", str) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add a.S = str // a.Widget = &n.widget // action(&a) @@ -48,7 +48,7 @@ func (n *Node) AddText(str string) { log(debugChange, "AddText() value =", str) var a toolkit.Action - a.Type = toolkit.AddText + a.ActionType = toolkit.AddText a.S = str // a.Widget = &n.widget // action(&a) @@ -59,7 +59,7 @@ func (n *Node) SetText(str string) { log(debugChange, "SetText() value =", str) var a toolkit.Action - a.Type = toolkit.SetText + a.ActionType = toolkit.SetText a.S = str // a.Widget = &n.widget // action(&a) @@ -80,7 +80,7 @@ func (n *Node) SetNext(x int, y int) { func (n *Node) Set(val any) { log(debugChange, "Set() value =", val) var a toolkit.Action - a.Type = toolkit.Set + a.ActionType = toolkit.Set switch v := val.(type) { case bool: @@ -100,7 +100,7 @@ func (n *Node) Set(val any) { func (n *Node) AppendText(str string) { var a toolkit.Action - a.Type = toolkit.SetText + a.ActionType = toolkit.SetText tmp := n.widget.S + str log(debugChange, "AppendText() value =", tmp) a.S = tmp @@ -157,3 +157,50 @@ func commonCallback(n *Node) { n.Custom() } } + +func (n *Node) Margin() { + var a toolkit.Action + a.ActionType = toolkit.Margin + newaction(&a, n, nil) +} + +func (n *Node) Unmargin() { + var a toolkit.Action + a.ActionType = toolkit.Unmargin + newaction(&a, n, nil) +} + +func (n *Node) Pad() { + var a toolkit.Action + a.ActionType = toolkit.Pad + newaction(&a, n, nil) +} + +func (n *Node) Unpad() { + var a toolkit.Action + a.ActionType = toolkit.Unpad + newaction(&a, n, nil) +} + +func (n *Node) New2() *Node { + var newWin *Node + newWin = NewWindow() + log(debugError, "New2() END Main(f)") + return newWin +} + +func (n *Node) Window(title string) *Node { + log(debugError, "Window()", n) + n.SetText(title) + return n +} + +func (n *Node) Standard() *Node { + log(debugError, "Standard()") + return n +} + +func (n *Node) DoMargin() *Node { + log(debugError, "DoMargin()") + return n +} diff --git a/debug.go b/debug.go index f8df4ec..26fe5da 100644 --- a/debug.go +++ b/debug.go @@ -65,16 +65,9 @@ func SetFlag (s string, b bool) { log(debugGui, "Can't set unknown flag", s) } - // 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) // set flag in the plugin - var a toolkit.Action - a.Type = toolkit.SetFlag + a.ActionType = toolkit.Set + a.WidgetType = toolkit.Flag a.S = s a.B = b // a.Widget = &newNode.widget @@ -109,9 +102,11 @@ func (n *Node) Dump(b bool) { Indent(b, "Height = ", n.Height) Indent(b, "(X,Y) = ", n.X, n.Y) Indent(b, "Next (X,Y) = ", n.NextX, n.NextY) + /* Indent(b, "Widget Name = ", n.widget.Name) Indent(b, "Widget Type = ", n.widget.Type) - Indent(b, "Widget Id = ", n.widget.GetId()) + Indent(b, "Widget Id = ", n.widget.Id) + */ if (n.parent == nil) { Indent(b, "parent = nil") diff --git a/debugWidget.go b/debugWidget.go index 8ccc0d6..afe4302 100644 --- a/debugWidget.go +++ b/debugWidget.go @@ -111,7 +111,7 @@ func DebugWidgetWindow(w *Node) { activeWidget.Dump(true) var a toolkit.Action - a.Type = toolkit.Dump + a.ActionType = toolkit.Dump newaction(&a, activeWidget, nil) }) @@ -123,64 +123,53 @@ func DebugWidgetWindow(w *Node) { g = bugWidget.NewGroup("change things") g.NewButton("AddText()", func () { var a toolkit.Action - a.Type = toolkit.AddText + a.ActionType = toolkit.AddText a.S = activeLabelNewName.widget.S newaction(&a, activeWidget, nil) }) g.NewButton("SetText()", func () { var a toolkit.Action - a.Type = toolkit.SetText + a.ActionType = toolkit.SetText a.S = activeLabelNewName.widget.S newaction(&a, activeWidget, nil) }) g.NewButton("Margin()", func () { var a toolkit.Action - a.Type = toolkit.Margin + a.ActionType = toolkit.Margin newaction(&a, activeWidget, nil) }) g.NewButton("Unmargin()", func () { var a toolkit.Action - a.Type = toolkit.Unmargin + a.ActionType = toolkit.Unmargin newaction(&a, activeWidget, nil) }) g.NewButton("Pad()", func () { var a toolkit.Action - a.Type = toolkit.Pad + a.ActionType = toolkit.Pad newaction(&a, activeWidget, nil) }) g.NewButton("Unpad()", func () { var a toolkit.Action - a.Type = toolkit.Unpad + a.ActionType = toolkit.Unpad newaction(&a, activeWidget, nil) }) g.NewButton("Move(junk)", func () { var a toolkit.Action - a.Type = toolkit.Move + a.ActionType = toolkit.Move newaction(&a, activeWidget, activeJunk) }) g.NewButton("Delete()", func () { var a toolkit.Action - a.Type = toolkit.Delete + a.ActionType = toolkit.Delete newaction(&a, activeWidget, activeJunk) }) g = bugWidget.NewGroup("not working?") - g.NewButton("Dump Widget Values()", func () { - log("activeWidget.B =", activeWidget.widget.B) - log("activeWidget.I =", activeWidget.widget.I) - log("activeWidget.S =", activeWidget.widget.S) - log("activeWidget.X =", activeWidget.widget.X) - log("activeWidget.Y =", activeWidget.widget.Y) - log("activeWidget.Width =", activeWidget.widget.Width) - log("activeWidget.Height =", activeWidget.widget.Height) - log("activeWidget.Margin =", activeWidget.widget.Margin) - log("activeWidget.Expand =", activeWidget.widget.Expand) - }) activeJunk = bugWidget.NewGroup("junk:") activeJunk.NewLabel("test junk") if (activeWidget == nil) { - setActiveWidget(Config.master) + setActiveWidget(Config.rootNode) } } @@ -188,8 +177,7 @@ func (n *Node) debugAddWidgetButtons() { n.NewButton("Dropdown", func () { a := activeWidget.NewDropdown("tmp dropdown") a.AddText("this is better than tcl/tk") - a.AddText("make something for tim") - a.AddText("for qflow") + a.AddText("make something for tim for qflow") a.AddText("and for riscv") a.Custom = func () { log("custom dropdown() a =", a.widget.Name, a.widget.S, "id=", a.id) @@ -198,7 +186,7 @@ func (n *Node) debugAddWidgetButtons() { n.NewButton("Combobox", func () { a := activeWidget.NewCombobox("tmp combobox") a.AddText("mirrors.wit.com") - a.AddText("go.wit.org") + a.AddText("go.wit.com") a.Custom = func () { log("custom combobox() a =", a.widget.Name, a.widget.S, "id=", a.id) } @@ -213,12 +201,14 @@ func (n *Node) debugAddWidgetButtons() { // SetDebug(true) debugGrid = activeWidget.NewGrid("tmp grid", 2, 3) debugGridLabel = debugGrid.NewLabel("mirrors.wit.com") + /* debugGrid.SetNext(0,1) debugGrid.NewLabel("foo (0,1)") debugGrid.SetNext(1,1) debugGrid.NewLabel("foo (1,1)") debugGrid.SetNext(2,1) debugGrid.NewLabel("foo (2,1)") + */ // SetDebug(false) DebugWidgetWindow(debugGrid) }) @@ -316,7 +306,7 @@ func (n *Node) debugAddWidgetButton() { newNode := activeWidget.New(name, toolkit.Label, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add newaction(&a, newNode, activeWidget) // return newNode // activeWidget.NewLabel(name) diff --git a/debugWindow.go b/debugWindow.go index 2c85407..ddbddc2 100644 --- a/debugWindow.go +++ b/debugWindow.go @@ -74,15 +74,37 @@ func (n *Node) DebugTab(title string) *Node { dropdownWindowWidgets(g1) }) - g2 := newN.NewGroup("node things") + g2 := newN.NewGroup("more things") g2.NewButton("Node.ListChildren(true)", func () { if (activeWidget == nil) { - activeWidget = Config.master + activeWidget = Config.rootNode } activeWidget.ListChildren(true) }) + g2.NewButton("test conc", func () { + makeConc() + }) + + g2.NewButton("List Plugins", func () { + for _, aplug := range allPlugins { + log("Loaded plugin:", aplug.name, aplug.filename) + } + }) + + g2.NewButton("load plugin 'gocui'", func () { + StartS("gocui") + }) + + g2.NewButton("load plugin 'democui'", func () { + StartS("democui") + }) + + g2.NewButton("Redraw(democui)", func () { + Redraw("democui") + }) + return newN } @@ -105,7 +127,7 @@ func dropdownWindow(p *Node) { } // var last = "" - for _, child := range Config.master.children { + for _, child := range Config.rootNode.children { log(debugGui, "\t\t", child.id, child.Width, child.Height, child.Name) dd.AddDropdownName(child.Name) // last = child.Name @@ -145,5 +167,5 @@ func dropdownWindowWidgets(p *Node) { } // list everything in the binary tree - addDropdowns(Config.master) + addDropdowns(Config.rootNode) } diff --git a/dropdown.go b/dropdown.go index 2e23205..5a4e366 100644 --- a/dropdown.go +++ b/dropdown.go @@ -23,7 +23,7 @@ func (n *Node) NewDropdown(name string) *Node { newNode := n.New(name, toolkit.Dropdown, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add // a.Widget = &newNode.widget // a.Where = &n.widget // action(&a) @@ -36,7 +36,7 @@ func (n *Node) NewCombobox(name string) *Node { newNode := n.New(name, toolkit.Combobox, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add // a.Widget = &newNode.widget // a.Where = &n.widget // action(&a) diff --git a/grid.go b/grid.go index 2a3ce6a..cefe419 100644 --- a/grid.go +++ b/grid.go @@ -22,7 +22,7 @@ func (n *Node) NewGrid(name string, x int, y int) *Node { }) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add a.X = x a.Y = y newNode.X = x @@ -38,7 +38,9 @@ func (n *Node) NewBox(name string, b bool) *Node { newNode := n.New(name, toolkit.Box, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add + a.Name = name + a.Text = name a.B = b newaction(&a, newNode, n) diff --git a/group.go b/group.go index f46b6b6..e0aeca6 100644 --- a/group.go +++ b/group.go @@ -12,7 +12,7 @@ func (n *Node) NewGroup(name string) *Node { newNode = n.New(name, toolkit.Group, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add newaction(&a, newNode, n) newBox := newNode.NewBox("group vBox", false) diff --git a/image.go b/image.go index 5eb8fe1..2943142 100644 --- a/image.go +++ b/image.go @@ -9,7 +9,7 @@ func (n *Node) NewImage(name string) *Node { newNode = n.New(name, toolkit.Image, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add // a.Widget = &newNode.widget // a.Where = &n.widget // action(&a) diff --git a/label.go b/label.go index 406c4c2..8dd60b9 100644 --- a/label.go +++ b/label.go @@ -8,7 +8,9 @@ func (n *Node) NewLabel(text string) *Node { newNode := n.New(text, toolkit.Label, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add + a.Name = text + a.Text = text newaction(&a, newNode, n) return newNode diff --git a/log.go b/log.go index 754a883..103aeb7 100644 --- a/log.go +++ b/log.go @@ -1,125 +1,29 @@ -// -// version v1.3 -// -// I like things to be easy. -// -// 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 gui import ( - "os" - "runtime" - "runtime/pprof" - golog "log" - "time" - "reflect" - "github.com/davecgh/go-spew/spew" - // "net" + witlog "git.wit.org/wit/gui/log" ) -var LOGOFF bool = false // turn this off, all logging stops -var WARN bool -var INFO bool +// various debugging flags +var logNow bool = true // useful for active development +var logError bool = true +var logWarn bool = false +var logInfo bool = false +var logVerbose bool = false -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("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("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 -*/ +// var log interface{} func log(a ...any) { - if (LOGOFF) { - return - } - - if (a == nil) { - return - } - - var tbool bool - if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) { - // golog.Println("\t a[0] = bool") - if (a[0] == false) { - return - } - a[0] = "WIT/GUI" - } - - if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) { - a = a[1:] - spew.Dump(a) - return - } - - golog.Println(a...) + witlog.Where = "wit/gui" + witlog.Log(a...) } -func loggo() { - pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) - golog.Println("runtime.NumGoroutine() = ", runtime.NumGoroutine()) +func sleep(a ...any) { + witlog.Sleep(a...) +} + +func exit(a ...any) { + witlog.Exit(a...) } // b bool, print if true @@ -135,5 +39,5 @@ func logindent(b bool, depth int, format string, a ...any) { // array prepend(). Why isn't this a standard function. It should be: // a.prepend(debugGui, newFormat) a = append([]any{b, newFormat}, a...) - log(a...) + witlog.Log(a...) } diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..9862291 --- /dev/null +++ b/log/log.go @@ -0,0 +1,149 @@ +package witlog +// +// version v1.2 +// +// I like things to be easy. +// +// 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! +// + +import ( + "os" + "runtime" + "runtime/pprof" + golog "log" + "time" + "reflect" + "github.com/davecgh/go-spew/spew" + // "net" +) + +// various debugging flags +var LogNow bool = true // useful for active development +var LogError bool = true +var LogWarn bool = false +var LogInfo bool = false +var LogVerbose bool = false +var LogSleep bool = false + +var LOGOFF bool = false // turn this off, all logging stops +var debugToolkit bool = false // does spew stuff? + +var Where string = "gui/log" + +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(LogSleep, "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(LogError, "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] = Where + } + + if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) { + // a = a[1:] + a[0] = Where + if (debugToolkit) { + scs := spew.ConfigState{MaxDepth: 1} + scs.Dump(a) + // spew.Dump(a) + } + return + } + + golog.Println(a...) +} + +func loggo() { + pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) + golog.Println("runtime.NumGoroutine() = ", runtime.NumGoroutine()) +} + +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/main.go b/main.go index 9f4b93c..51a44c3 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package gui import ( // "embed" - // "git.wit.org/wit/gui/toolkit" + "git.wit.org/wit/gui/toolkit" ) // Windows doesn't support plugins. How can I keep andlabs and only compile it on windows? @@ -31,10 +31,12 @@ func init() { Config.Height = 480 // Populates the top of the binary tree - Config.master = addNode("guiBinaryTree") + Config.rootNode = addNode("guiBinaryTree") + Config.rootNode.WidgetType = toolkit.Root // used to pass debugging flags to the toolkit plugins - Config.flag = Config.master.New("flag", 0, nil) + Config.flag = Config.rootNode.New("flag", 0, nil) + Config.flag.WidgetType = toolkit.Flag } func doGuiChan() { @@ -57,7 +59,7 @@ func InitPlugins(names []string) { log(debugGui, "Starting gui.Init()") for _, aplug := range allPlugins { - log(debugGui, "gui.LoadToolkit() already loaded toolkit plugin =", aplug.name) + log(debugGui, "LoadToolkit() already loaded toolkit plugin =", aplug.name) for _, name := range names { if (name == aplug.name) { return @@ -93,6 +95,28 @@ func InitPlugins(names []string) { // StandardExit("golang wit/gui could not load a plugin TODO: do something to STDOUT (?)") } +func Start() *Node { + log(logInfo, "Start() Main(f)") + f := func() { + } + go Main(f) + sleep(1) + return Config.rootNode +} + +func StartS(name string) *Node { + log(logInfo, "Start() Main(f) for name =", name) + if (LoadToolkit(name) == false) { + return Config.rootNode + } + // will this really work on mswindows & macos? + f := func() { + } + go Main(f) + sleep(1) // temp hack until chan communication is setup + return Config.rootNode +} + // This should not pass a function func Main(f func()) { log(debugGui, "Starting gui.Main() (using gtk via andlabs/ui)") @@ -111,11 +135,12 @@ func Main(f func()) { } aplug.MainOk = true aplug.Main(f) - // f() } - // toolkit.Main(f) } +/* +This is deprecated and will be implemented more correctly with waitgroups + // This should never be exposed(?) // Other goroutines must use this to access the GUI @@ -135,6 +160,7 @@ func Queue(f func()) { aplug.Queue(f) } } +*/ // The window is destroyed but the application does not quit func (n *Node) StandardClose() { diff --git a/node.go b/node.go index f997571..b0bad5c 100644 --- a/node.go +++ b/node.go @@ -9,6 +9,7 @@ func (n *Node) New(title string, t toolkit.WidgetType, custom func()) *Node { var newN *Node newN = addNode(title) + newN.WidgetType = t newN.widget.Type = t // newN.widget.Action = "New" newN.Custom = custom @@ -44,7 +45,7 @@ func addNode(title string) *Node { n.Name = title n.widget.Name = title n.id = Config.counter - n.widget.SetId(n.id) + n.widget.Id = n.id log(debugNode, "addNode = widget setid =", n.id) Config.counter += 1 @@ -55,9 +56,11 @@ 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) diff --git a/plugin.go b/plugin.go index 28bb324..a9cf4f9 100644 --- a/plugin.go +++ b/plugin.go @@ -29,12 +29,12 @@ type aplug struct { // TODO: make Main() main() and never allow the user to call it // run plugin.Main() when the plugin is loaded Main func(func ()) // this never returns. Each plugin must have it's own goroutine - Queue func(func ()) // Should this return right away? Should it wait (can it wait?) + // Queue func(func ()) // Should this return right away? Should it wait (can it wait?) Quit func() // NewWindow func(*toolkit.Widget) // simplifies passing to the plugin - Send func(*toolkit.Widget, *toolkit.Widget) + // Send func(*toolkit.Widget, *toolkit.Widget) // should replace Send() Action func(*toolkit.Action) @@ -74,16 +74,11 @@ func LoadToolkit(name string) bool { newPlug.Main = loadFuncF(&newPlug, "Main") // should send things to the goroutine above - newPlug.Queue = loadFuncF(&newPlug, "Queue") + // newPlug.Queue = loadFuncF(&newPlug, "Queue") // unload the plugin and restore state newPlug.Quit = loadFuncE(&newPlug, "Quit") - // Sends a widget (button, checkbox, etc) and it's parent widget - // This includes instructions like "Add", "Delete", "Disable", etc -// newPlug.Send = loadFunc2(&newPlug, "Send") - - // This should replace Send() // Sends instructions like "Add", "Delete", "Disable", etc // Sends a widget (button, checkbox, etc) and it's parent widget newPlug.Action = loadFuncA(&newPlug, "Action") @@ -190,7 +185,8 @@ func loadPlugin(p *aplug, name string) { homeDir, err := os.UserHomeDir() if err != nil { - exit(err) + log(logError, "loadPlugin() error. exiting here?") + return } // attempt to write out the file from the internal resource @@ -230,36 +226,6 @@ func loadfile(filename string) *plugin.Plugin { return plug } -/* -// Sends a widget and what to do with it to the plugin -// parent = n, child = c -func send(p *Node, c *Node) { - for _, aplug := range allPlugins { - log(debugPlugin, "Send() aplug =", aplug.name, "type=", c.widget.Type, "action=", c.widget.Action, "name=", c.widget.Name) - if (aplug.Send == nil) { - log(debugPlugin, "Failed. Send() == nil for", aplug.name) - continue - } - aplug.Send(&c.parent.widget, &c.widget) - } -} -*/ - -// Sends a widget and what to do with it to the plugin -// parent = n, child = c -/* -func action(a *toolkit.Action) { - for _, aplug := range allPlugins { - log(debugPlugin, "Action() aplug =", aplug.name, "Action type=", a.Type) - if (aplug.Action == nil) { - log(debugPlugin, "Failed Action() == nil for", aplug.name) - continue - } - aplug.Action(a) - } -} -*/ - // Sends a widget and what to do with it to the plugin // parent = n, child = c @@ -268,16 +234,19 @@ func action(a *toolkit.Action) { func newaction(a *toolkit.Action, n *Node, where *Node) { if (n != nil) { a.Widget = &n.widget + a.WidgetId = n.id + a.WidgetType = n.widget.Type + a.ActionType = a.ActionType } // action(&a, newNode, n) // newaction(&a, newNode, n) if (where != nil) { log(debugGui, "Action() START on where X,Y, Next X,Y =", where.Name, where.X, where.Y, where.NextX, where.NextY) - a.Where = &where.widget + a.ParentId = where.id switch where.widget.Type { case toolkit.Grid: - where.Dump(true) + // where.Dump(true) log(debugGui, "Action() START on Grid (X,Y)", where.X, where.Y, "put next thing at (X,Y) =", where.NextX, where.NextY) // // fix values here if they are invalid. Index starts at 1 @@ -288,15 +257,15 @@ func newaction(a *toolkit.Action, n *Node, where *Node) { where.NextY = 1 } // - a.Where.X = where.NextX - a.Where.Y = where.NextY + a.X = where.NextX + a.Y = where.NextY log(debugGui, "Action() END on Grid (X,Y)", where.X, where.Y, "put next thing at (X,Y) =", where.NextX, where.NextY) default: } } for _, aplug := range allPlugins { - log(debugPlugin, "Action() aplug =", aplug.name, "Action type=", a.Type) + log(debugPlugin, "Action() aplug =", aplug.name, "Action type=", a.ActionType) if (aplug.Action == nil) { log(debugPlugin, "Failed Action() == nil for", aplug.name) continue @@ -307,19 +276,19 @@ func newaction(a *toolkit.Action, n *Node, where *Node) { if (where != nil) { switch where.widget.Type { case toolkit.Grid: - log(debugNow, "Action() START size (X,Y)", where.X, where.Y, "put next thing at (X,Y) =", where.NextX, where.NextY) + log(logInfo, "Action() START size (X,Y)", where.X, where.Y, "put next thing at (X,Y) =", where.NextX, where.NextY) where.NextY += 1 if (where.NextY > where.Y) { where.NextX += 1 where.NextY = 1 } - log(debugNow, "Action() END size (X,Y)", where.X, where.Y, "put next thing at (X,Y) =", where.NextX, where.NextY) + log(logInfo, "Action() END size (X,Y)", where.X, where.Y, "put next thing at (X,Y) =", where.NextX, where.NextY) where.Name = "jwc gridlaksdfjkl" where.Width = 320 where.Height = 240 // where.NextX = 5 // where.NextY = 7 - where.Dump(true) + // where.Dump(logInfo) default: } } diff --git a/redraw.go b/redraw.go new file mode 100644 index 0000000..38c3972 --- /dev/null +++ b/redraw.go @@ -0,0 +1,59 @@ +package gui + +import ( + "git.wit.org/wit/gui/toolkit" +) + +// This recreates the whole GUI for a plugin + +func Redraw(s string) { + var p *aplug + log(logNow, "attempt to feed the binary tree to", s) + for _, aplug := range allPlugins { + log("Loaded plugin:", aplug.name, aplug.filename) + if (aplug.name == s) { + log("Found plugin:", aplug.name, aplug.filename) + p = aplug + } + } + if (p == nil) { + log("Plugin", s, "is not loaded") + return + } + Config.rootNode.Redraw(p) +} + +// func (n *Node) ListChildren(dump bool, dropdown *Node, mapNodes map[string]*Node) { +func (n *Node) Redraw(p *aplug) { + if (n == nil) { + return + } + + n.redo(p) + for _, child := range n.children { + child.Redraw(p) + } + return +} + +func (n *Node) redo(p *aplug) { + log(logNow, "redo() on n.Widget") + + var a *toolkit.Action + a = new(toolkit.Action) + a.Name = n.Name + a.Text = n.Text + a.ActionType = toolkit.Add + a.WidgetType = n.WidgetType + a.WidgetId = n.id + a.Width = n.Width + a.Height = n.Height + + if (n.parent == nil) { + a.ParentId = 0 + } else { + a.ParentId = n.parent.id + } + + p.Action(a) +} diff --git a/slider.go b/slider.go index 2164340..1d2d23d 100644 --- a/slider.go +++ b/slider.go @@ -10,7 +10,7 @@ func (n *Node) NewSlider(name string, x int, y int) *Node { }) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add a.X = x a.Y = y // a.Widget = &newNode.widget diff --git a/spinner.go b/spinner.go index f9111ab..0f48e8f 100644 --- a/spinner.go +++ b/spinner.go @@ -10,7 +10,7 @@ func (n *Node) NewSpinner(name string, x int, y int) *Node { }) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add a.X = x a.Y = y // a.Widget = &newNode.widget diff --git a/structs.go b/structs.go index 5477d2e..94382d7 100644 --- a/structs.go +++ b/structs.go @@ -2,6 +2,7 @@ package gui import ( "git.wit.org/wit/gui/toolkit" + "sync" ) // @@ -32,9 +33,9 @@ type GuiArgs struct { type GuiConfig struct { // This is the master node. The Binary Tree starts here - master *Node + rootNode *Node - // A node off of master for passing debugging flags + // A node off of rootNode for passing debugging flags flag *Node // These are shortcuts to pass default values to make a new window @@ -56,10 +57,16 @@ type GuiConfig struct { // simply the name and the size of whatever GUI element exists type Node struct { id int + initOnce sync.Once widget toolkit.Widget + WidgetType toolkit.WidgetType - Name string +// Title string // what is visable to the user +// Desc string // a name useful for programming + + Text string // what is visable to the user + Name string // a name useful for programming // used for Windows Width int @@ -83,9 +90,4 @@ type Node struct { parent *Node children []*Node - - // is keeping - // deprecate these things if they don't really need to exist - // checked bool - // text string } diff --git a/tab.go b/tab.go index 702e99f..49632ee 100644 --- a/tab.go +++ b/tab.go @@ -11,8 +11,11 @@ func (n *Node) NewTab(text string) *Node { newNode := n.New(text, toolkit.Tab, nil) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add + a.Name = text + a.Text = text newaction(&a, newNode, n) - return newNode + newBox := newNode.NewBox(text, true) + return newBox } diff --git a/textbox.go b/textbox.go index aadf8aa..75703a2 100644 --- a/textbox.go +++ b/textbox.go @@ -10,7 +10,7 @@ func (n *Node) NewTextbox(name string) *Node { }) var a toolkit.Action - a.Type = toolkit.Add + a.ActionType = toolkit.Add // a.Widget = &newNode.widget // a.Where = &n.widget // action(&a) diff --git a/toolkit/andlabs/action.go b/toolkit/andlabs/action.go index 3272414..9d098df 100644 --- a/toolkit/andlabs/action.go +++ b/toolkit/andlabs/action.go @@ -4,40 +4,40 @@ import ( "git.wit.org/wit/gui/toolkit" ) -func show(w *toolkit.Widget) { - if (w == nil) { +func show(a *toolkit.Action) { + if (a == nil) { log(debugError, "nil is probably already hidden") return } - log(debugError, "show()", w.Name) + log(debugError, "show()", a.WidgetId) - t := mapToolkits[w] + t := andlabs[a.WidgetId] if (t == nil) { - log(debugToolkit, "show() toolkit struct == nil. for", w.Name) + log(debugError, "show() toolkit struct == nil. for", a.WidgetId) return } - if (w.B) { + if (a.B) { t.uiControl.Show() } else { t.uiControl.Hide() } } -func enable(w *toolkit.Widget) { - if (w == nil) { +func enable(a *toolkit.Action) { + if (a == nil) { log(debugError, "nil is probably already hidden") return } - log(debugError, "enable()", w.Name) + log(debugError, "enable() name =", a.WidgetId) - t := mapToolkits[w] + t := andlabs[a.WidgetId] if (t == nil) { - log(debugToolkit, "enable() toolkit struct == nil. for", w.Name) + log(debugToolkit, "enable() toolkit struct == nil. for id =", a.WidgetId) return } - if (w.B) { + if (a.B) { t.uiControl.Enable() } else { t.uiControl.Disable() @@ -45,21 +45,21 @@ func enable(w *toolkit.Widget) { } func pad(a *toolkit.Action) { - if (a.Widget == nil) { + if (a == nil) { log(debugError, "pad() ERROR: nil is probably already hidden") return } - log(debugError, "pad()", a.Widget.Name) + log(debugError, "pad()") - t := mapToolkits[a.Widget] + t := andlabs[a.WidgetId] if (t == nil) { - log(debugToolkit, "pad() toolkit struct == nil. for", a.Widget.Name) + log(debugError, "pad() toolkit struct == nil. for", a.WidgetId) return } - switch a.Widget.Type { + switch t.Type { case toolkit.Group: - switch a.Type { + switch a.ActionType { case toolkit.Margin: t.uiGroup.SetMargined(true) case toolkit.Unmargin: @@ -70,7 +70,7 @@ func pad(a *toolkit.Action) { t.uiGroup.SetMargined(false) } case toolkit.Tab: - switch a.Type { + switch a.ActionType { case toolkit.Margin: tabSetMargined(t.uiTab, true) case toolkit.Unmargin: @@ -81,7 +81,7 @@ func pad(a *toolkit.Action) { tabSetMargined(t.uiTab, false) } case toolkit.Window: - switch a.Type { + switch a.ActionType { case toolkit.Margin: t.uiWindow.SetMargined(true) case toolkit.Unmargin: @@ -92,7 +92,7 @@ func pad(a *toolkit.Action) { t.uiWindow.SetBorderless(true) } case toolkit.Grid: - switch a.Type { + switch a.ActionType { case toolkit.Margin: t.uiGrid.SetPadded(true) case toolkit.Unmargin: @@ -103,7 +103,7 @@ func pad(a *toolkit.Action) { t.uiGrid.SetPadded(false) } case toolkit.Box: - switch a.Type { + switch a.ActionType { case toolkit.Margin: t.uiBox.SetPadded(true) case toolkit.Unmargin: @@ -114,128 +114,120 @@ func pad(a *toolkit.Action) { t.uiBox.SetPadded(false) } case toolkit.Textbox: - log(debugError, "TODO: implement expand for", a.Type) - log(debugError, "TODO: implement expand for", a.Type) - log(debugError, "TODO: implement expand for", a.Type) - log(debugError, "TODO: implement expand for", a.Type) + log(debugError, "TODO: implement expand for", a.ActionType) + log(debugError, "TODO: implement expand for", a.ActionType) + log(debugError, "TODO: implement expand for", a.ActionType) + log(debugError, "TODO: implement expand for", a.ActionType) default: - log(debugError, "TODO: implement pad() for", a.Type) + log(debugError, "TODO: implement pad() for", a.ActionType) } } func move(a *toolkit.Action) { - if (a.Where == nil) { - log(debugError, "move() ERROR: can not move to nil") - return - } - if (a.Widget == nil) { - log(debugError, "move() ERROR: can not move nil") - return - } - log(debugNow, "move()", a.Widget.Name, "to", a.Where.Name) + log(debugNow, "move()", a.WidgetId, "to", a.ParentId) - tWidget := mapToolkits[a.Widget] + tWidget := andlabs[a.WidgetId] if (tWidget == nil) { - log(debugError, "move() ERROR: toolkit struct == nil. for", a.Widget.Name) + log(debugError, "move() ERROR: toolkit struct == nil. for", a.WidgetId) return } - tWhere := mapToolkits[a.Where] - if (tWhere == nil) { - log(debugError, "move() ERROR: toolkit struct == nil. for", a.Where.Name) + tParent := andlabs[a.ParentId] + if (tParent == nil) { + log(debugError, "move() ERROR: toolkit struct == nil. for", a.ParentId) return } - switch a.Where.Type { + switch tParent.Type { case toolkit.Group: - switch a.Type { + switch a.ActionType { case toolkit.Margin: - tWhere.uiGroup.SetMargined(true) + tParent.uiGroup.SetMargined(true) } case toolkit.Tab: - switch a.Type { + switch a.ActionType { case toolkit.Margin: - // tabSetMargined(tWhere.uiTab, true) + // tabSetMargined(tParent.uiTab, true) } case toolkit.Window: - switch a.Type { + switch a.ActionType { case toolkit.Pad: // t.uiWindow.SetBorderless(false) } case toolkit.Grid: - switch a.Type { + switch a.ActionType { case toolkit.Pad: // t.uiGrid.SetPadded(true) } case toolkit.Box: - log(debugNow, "TODO: move() for a =", a.Type) - log(debugNow, "TODO: move() where =", a.Where.Type) - log(debugNow, "TODO: move() for widget =", a.Widget.Type) + log(debugNow, "TODO: move() for a =", a.ActionType) + log(debugNow, "TODO: move() where =", a.ParentId) + log(debugNow, "TODO: move() for widget =", a.WidgetId) stretchy = true - tWhere.uiBox.Append(tWidget.uiControl, stretchy) - // log(debugNow, "is there a tWhere parent? =", tWhere.parent) - // tWhere.uiBox.Delete(0) + tParent.uiBox.Append(tWidget.uiControl, stretchy) + // log(debugNow, "is there a tParent parent? =", tParent.parent) + // tParent.uiBox.Delete(0) // this didn't work: // tWidget.uiControl.Disable() // sleep(.8) default: - log(debugError, "TODO: need to implement move() for a =", a.Type) - log(debugError, "TODO: need to implement move() for where =", a.Where.Type) - log(debugError, "TODO: need to implement move() for widget =", a.Widget.Type) + log(debugError, "TODO: need to implement move() for a =", a.ActionType) + log(debugError, "TODO: need to implement move() for where =", a.ParentId) + log(debugError, "TODO: need to implement move() for widget =", a.WidgetId) } } func uiDelete(a *toolkit.Action) { - if (a.Where == nil) { + if (andlabs[a.ParentId] == nil) { log(debugError, "uiDelete() ERROR: can not uiDelete to nil") return } - if (a.Widget == nil) { + if (andlabs[a.WidgetId] == nil) { log(debugError, "uiDelete() ERROR: can not uiDelete nil") return } - log(debugNow, "uiDelete()", a.Widget.Name, "to", a.Where.Name) + log(debugNow, "uiDelete()", a.WidgetId, "to", a.ParentId) - tWidget := mapToolkits[a.Widget] + tWidget := andlabs[a.WidgetId] if (tWidget == nil) { - log(debugError, "uiDelete() ERROR: toolkit struct == nil. for", a.Widget.Name) + log(debugError, "uiDelete() ERROR: toolkit struct == nil. for", a.WidgetId) return } - tWhere := mapToolkits[a.Where] - if (tWhere == nil) { - log(debugError, "uiDelete() ERROR: toolkit struct == nil. for", a.Where.Name) + tParent := andlabs[a.ParentId] + if (tParent == nil) { + log(debugError, "uiDelete() ERROR: toolkit struct == nil. for", a.ParentId) return } - switch a.Where.Type { + switch tParent.Type { case toolkit.Group: - switch a.Type { + switch a.ActionType { case toolkit.Margin: - tWhere.uiGroup.SetMargined(true) + tParent.uiGroup.SetMargined(true) } case toolkit.Tab: - switch a.Type { + switch a.ActionType { case toolkit.Margin: - // tabSetMargined(tWhere.uiTab, true) + // tabSetMargined(tParent.uiTab, true) } case toolkit.Window: - switch a.Type { + switch a.ActionType { case toolkit.Pad: // t.uiWindow.SetBorderless(false) } case toolkit.Grid: - switch a.Type { + switch a.ActionType { case toolkit.Pad: // t.uiGrid.SetPadded(true) } case toolkit.Box: - log(debugNow, "tWidget.boxC =", tWhere.Name) - log(debugNow, "is there a tWhere parent? =", tWhere.parent) + log(debugNow, "tWidget.boxC =", tParent.Name) + log(debugNow, "is there a tParent parent? =", tParent.parent) if (tWidget.boxC < 1) { - log(debugNow, "Can not delete from Box. already empty. tWidget.boxC =", tWhere.boxC) + log(debugNow, "Can not delete from Box. already empty. tWidget.boxC =", tParent.boxC) return } tWidget.uiBox.Delete(0) @@ -244,10 +236,10 @@ func uiDelete(a *toolkit.Action) { // this didn't work: // tWidget.uiControl.Disable() // sleep(.8) - // tWhere.uiBox.Append(tWidget.uiControl, stretchy) + // tParent.uiBox.Append(tWidget.uiControl, stretchy) default: - log(debugError, "TODO: need to implement uiDelete() for a =", a.Type) - log(debugError, "TODO: need to implement uiDelete() for where =", a.Where.Type) - log(debugError, "TODO: need to implement uiDelete() for widget =", a.Widget.Type) + log(debugError, "TODO: need to implement uiDelete() for a =", a.ActionType) + log(debugError, "TODO: need to implement uiDelete() for where =", a.ParentId) + log(debugError, "TODO: need to implement uiDelete() for widget =", a.WidgetId) } } diff --git a/toolkit/andlabs/add.go b/toolkit/andlabs/add.go index 707a87f..b03ee9c 100644 --- a/toolkit/andlabs/add.go +++ b/toolkit/andlabs/add.go @@ -8,40 +8,46 @@ import ( ) func actionDump(b bool, a *toolkit.Action) { - log(b, "dump() Widget.Type =", a.Type) - log(b, "dump() Widget.S =", a.S) - log(b, "dump() Widget.I =", a.I) - log(b, "dump() Widget =", a.Widget) - log(b, "dump() Where =", a.Where) + log(b, "actionDump() Widget.Type =", a.ActionType) + log(b, "actionDump() Widget.S =", a.S) + log(b, "actionDump() Widget.I =", a.I) + log(b, "actionDump() WidgetId =", a.WidgetId) + log(b, "actionDump() ParentId =", a.ParentId) } func add(a *toolkit.Action) { - if (a.Widget == nil) { - log(debugError, "add() error. w.Widget == nil") + if (andlabs[a.WidgetId] != nil) { + log(debugError, "add() error. can't make a widget that already exists. id =", a.WidgetId) actionDump(debugError, a) return } + if (a.WidgetId == 0) { + log(debugError, "add() error. w.WidgetId == 0") + actionDump(debugError, a) + return + } + // for now, window gets handled without checking where == nil) - if (a.Widget.Type == toolkit.Window) { + if (a.WidgetType == toolkit.Window) { doWindow(a) return } - t := mapToolkits[a.Where] - if (t == nil) { + if (andlabs[a.ParentId] == nil) { // listMap(debugError) // memory corruption? - log(debugError, "add() Widget.Name =", a.Widget.Name, a.Widget.Type) - // log(debugError, "add() Where.Name =", a.Where.Name) - log(debugError, "ERROR add() ERROR a.Where map to t == nil.") + log(debugError, "add() Widget.Name =", a.Name) + log(debugError, "add() Widget.Type =", a.WidgetType) + log(debugError, "ERROR add() ERROR a.Parent map to t == nil. WidgetId =", a.WidgetId, "ParentId =", a.ParentId) + exit("can not add()") return } - switch a.Widget.Type { + switch a.WidgetType { case toolkit.Window: doWindow(a) return case toolkit.Tab: - doTab(a) + newTab(a) return case toolkit.Label: newLabel(a) @@ -80,7 +86,7 @@ func add(a *toolkit.Action) { newImage(a) return default: - log(debugError, "add() error TODO: ", a.Widget.Type, a.Widget.Name) + log(debugError, "add() error TODO: ", a.WidgetType, a.Name) } } @@ -109,18 +115,34 @@ func add(a *toolkit.Action) { // -- (0,1) -- (1,1) -- (1,1) -- // ----------------------------- func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool { - log(debugAction, "place() START", a.Widget.Type, a.Widget.Name) + log(debugAction, "place() START", a.WidgetType, a.Name) + + // add the structure to the array + if (andlabs[a.WidgetId] == nil) { + log(logInfo, "newTab() MAPPED", a.WidgetId, a.ParentId) + andlabs[a.WidgetId] = newt + newt.Type = a.WidgetType + } else { + log(debugError, "newTab() DO WHAT?", a.WidgetId, a.ParentId) + log(debugError, "THIS IS BAD") + } if (newt.uiControl == nil) { - log(debugError, "place() ERROR uiControl == nil", a.Where.Type, a.Where.Name) + log(debugError, "place() ERROR uiControl == nil", a.ParentId) return false } - switch a.Where.Type { + where := andlabs[a.ParentId] + if (where == nil) { + log(debugError, "place() ERROR where == nil", a.ParentId) + return false + } + + switch where.Type { case toolkit.Grid: - log(debugGrid, "add() Grid try at Where X,Y =", a.Where.X, a.Where.Y) - newt.gridX = a.Where.X - newt.gridY = a.Where.Y + log(debugGrid, "add() Grid try at Parent X,Y =", a.X, a.Y) + newt.gridX = a.X + newt.gridY = a.Y log(debugGrid, "add() Grid try at gridX,gridY", newt.gridX, newt.gridY) // at the very end, subtract 1 from X & Y since andlabs/ui starts counting at zero t.uiGrid.Append(newt.uiControl, @@ -130,14 +152,14 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool { case toolkit.Group: if (t.uiBox == nil) { t.uiGroup.SetChild(newt.uiControl) - log(debugGrid, "add() hack Group to use this as the box?", a.Widget.Name, a.Widget.Type) + log(debugGrid, "add() hack Group to use this as the box?", a.Name, a.WidgetType) t.uiBox = newt.uiBox } else { t.uiBox.Append(newt.uiControl, stretchy) } return true case toolkit.Tab: - t.uiBox.Append(newt.uiControl, stretchy) + t.uiTab.Append(a.Text, newt.uiControl) t.boxC += 1 return true case toolkit.Box: @@ -148,7 +170,7 @@ func place(a *toolkit.Action, t *andlabsT, newt *andlabsT) bool { t.uiWindow.SetChild(newt.uiControl) return true default: - log(debugError, "add() how?", a.Where.Type) + log(debugError, "add() how?", a.ParentId) } return false } diff --git a/toolkit/andlabs/box.go b/toolkit/andlabs/box.go index cc7451d..527041d 100644 --- a/toolkit/andlabs/box.go +++ b/toolkit/andlabs/box.go @@ -9,19 +9,17 @@ import ( // make new Box here func newBox(a *toolkit.Action) { - w := a.Widget - parentW := a.Where - log(debugToolkit, "newBox()", w.Name) + log(debugToolkit, "newBox()", a.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "newBox() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "newBox() toolkit struct == nil. name=", a.Name) listMap(debugToolkit) } - newt := t.rawBox(w.Name, a.B) + newt := t.rawBox(a.Text, a.B) newt.boxC = 0 place(a, t, newt) - mapWidgetsToolkits(a, newt) + andlabs[a.WidgetId] = newt } // make new Box using andlabs/ui diff --git a/toolkit/andlabs/button.go b/toolkit/andlabs/button.go index 741ce3a..1f9fdaf 100644 --- a/toolkit/andlabs/button.go +++ b/toolkit/andlabs/button.go @@ -10,27 +10,27 @@ import ( func newButton(a *toolkit.Action) { var t, newt *andlabsT var b *ui.Button - w := a.Widget - log(debugToolkit, "newButton()", w.Name) + log(debugToolkit, "newButton()", a.Name) - t = mapToolkits[a.Where] + t = andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "newButton() toolkit struct == nil. name=", a.Where.Name, w.Name) + log(debugToolkit, "newButton() toolkit struct == nil. name=", a.Name) return } newt = new(andlabsT) - b = ui.NewButton(w.Name) + b = ui.NewButton(a.Text) newt.uiButton = b newt.uiControl = b - newt.tw = w + newt.tw = a.Widget + newt.Type = a.WidgetType newt.parent = t b.OnClicked(func(*ui.Button) { - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) }) place(a, t, newt) - mapWidgetsToolkits(a, newt) + // mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/checkbox.go b/toolkit/andlabs/checkbox.go index 2ff7ccf..f73a284 100644 --- a/toolkit/andlabs/checkbox.go +++ b/toolkit/andlabs/checkbox.go @@ -6,10 +6,13 @@ 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(a *toolkit.Action) *andlabsT { var newt andlabsT + w := a.Widget + log(debugToolkit, "newCheckbox()", w.Name, w.Type) newt.tw = w + newt.Type = w.Type + newt.wId = a.WidgetId newt.uiCheckbox = ui.NewCheckbox(w.Name) newt.uiControl = newt.uiCheckbox @@ -17,7 +20,7 @@ func (t *andlabsT) newCheckbox(w *toolkit.Widget) *andlabsT { newt.uiCheckbox.OnToggled(func(spin *ui.Checkbox) { newt.tw.B = newt.checked() log(debugChange, "val =", newt.tw.B) - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) }) return &newt @@ -28,16 +31,13 @@ func (t *andlabsT) checked() bool { } func newCheckbox(a *toolkit.Action) { - w := a.Widget - parentW := a.Where - log(debugToolkit, "newCheckbox()", w.Name) + log(debugToolkit, "newCheckbox()", a.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { listMap(debugError) return } - newt := t.newCheckbox(w) + newt := t.newCheckbox(a) place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/combobox.go b/toolkit/andlabs/combobox.go index e200b3b..e7d51a7 100644 --- a/toolkit/andlabs/combobox.go +++ b/toolkit/andlabs/combobox.go @@ -6,11 +6,14 @@ import ( "git.wit.org/wit/gui/toolkit" ) -func (t *andlabsT) newCombobox(w *toolkit.Widget) *andlabsT { +func (t *andlabsT) newCombobox(a *toolkit.Action) *andlabsT { var newt andlabsT + w := a.Widget log(debugToolkit, "newCombobox() START", w.Name) newt.tw = w + newt.wId = a.WidgetId + newt.Type = w.Type s := ui.NewEditableCombobox() newt.uiEditableCombobox = s newt.uiControl = s @@ -21,7 +24,7 @@ func (t *andlabsT) newCombobox(w *toolkit.Widget) *andlabsT { s.OnChanged(func(spin *ui.EditableCombobox) { newt.tw.S = spin.Text() - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) }) return &newt @@ -42,17 +45,14 @@ func (t *andlabsT) AddComboboxName(title string) { } func newCombobox(a *toolkit.Action) { - w := a.Widget - parentW := a.Where - log(debugToolkit, "newCombobox()", w.Name) + log(debugToolkit, "newCombobox()", a.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "newCombobox() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "newCombobox() toolkit struct == nil. name=", a.Name) listMap(debugToolkit) return } - newt := t.newCombobox(w) + newt := t.newCombobox(a) place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/common.go b/toolkit/andlabs/common.go index 5cfaaa5..5e1b0fb 100644 --- a/toolkit/andlabs/common.go +++ b/toolkit/andlabs/common.go @@ -4,7 +4,7 @@ import ( "git.wit.org/wit/gui/toolkit" ) -func (t *andlabsT) commonChange(tw *toolkit.Widget) { +func (t *andlabsT) commonChange(tw *toolkit.Widget, wId int) { log(debugChange, "commonChange() START widget =", t.tw.Name, t.tw.Type) if (tw == nil) { log(true, "commonChange() What the fuck. there is no widget t.tw == nil") @@ -15,23 +15,21 @@ func (t *andlabsT) commonChange(tw *toolkit.Widget) { return } tw.Custom() + + if (andlabs[wId] == nil) { + log(debugError, "commonChange() ERROR: wId map == nil", wId) + return + } + sendToChan(wId) + log(debugChange, "commonChange() END Widget.Custom()", t.tw.Name, t.tw.Type) } -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) +func sendToChan(i int) { + if (callback == nil) { + log(debugError, "commonChange() SHOULD SEND int back here, but callback == nil", i) 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) + log(debugError, "commonChange() Running callback() i =", i) + callback(i) } diff --git a/toolkit/andlabs/debug.go b/toolkit/andlabs/debug.go index 7d69485..a581657 100644 --- a/toolkit/andlabs/debug.go +++ b/toolkit/andlabs/debug.go @@ -90,6 +90,7 @@ func widgetDump(b bool, w *toolkit.Widget) { return } + /* log(b, "widget.Name =", w.Name) log(b, "widget.Type =", w.Type) log(b, "widget.Custom =", w.Custom) @@ -99,6 +100,7 @@ func widgetDump(b bool, w *toolkit.Widget) { log(b, "widget.Height =", w.Height) log(b, "widget.X =", w.X) log(b, "widget.Y =", w.Y) + */ } /* diff --git a/toolkit/andlabs/delete.go b/toolkit/andlabs/delete.go index d335324..2d2e04a 100644 --- a/toolkit/andlabs/delete.go +++ b/toolkit/andlabs/delete.go @@ -6,21 +6,21 @@ 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) +func destroy(pId int, cId int) { + log(true, "delete()", pId, cId) - pt := mapToolkits[p] - ct := mapToolkits[c] + pt := andlabs[pId] + ct := andlabs[cId] if (ct == nil) { - log(true, "delete FAILED (ct = mapToolkit[c] == nil) for c", c.Name, c.Type) + log(true, "delete FAILED (ct = mapToolkit[c] == nil) for c", pId, cId) // this pukes out a whole universe of shit // listMap() return } - switch ct.tw.Type { + switch ct.Type { case toolkit.Button: - log(true, "Should delete Button here:", c.Name) + log(true, "Should delete Button here:", ct.Name) log(true, "Parent:") pt.Dump(true) log(true, "Child:") @@ -38,16 +38,15 @@ func destroy(p *toolkit.Widget, c *toolkit.Widget) { } case toolkit.Window: - log(true, "Should delete Window here:", c.Name) + log(true, "Should delete Window here:", ct.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.tw.Type, pt.tw.Name, pt.uiButton) log(true, "Don't know how to delete ct =", ct.tw.Type, ct.tw.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) + log(true, "Fuckit, let's destroy a button") if (ct.uiButton != nil) { pt.uiBox.Delete(4) ct.uiButton.Destroy() diff --git a/toolkit/andlabs/dropdown.go b/toolkit/andlabs/dropdown.go index eac1324..d020ed8 100644 --- a/toolkit/andlabs/dropdown.go +++ b/toolkit/andlabs/dropdown.go @@ -6,11 +6,14 @@ import ( "git.wit.org/wit/gui/toolkit" ) -func (t *andlabsT) newDropdown(w *toolkit.Widget) *andlabsT { +func (t *andlabsT) newDropdown(a *toolkit.Action) *andlabsT { var newt andlabsT - log(debugToolkit, "gui.Toolbox.newDropdown() START", w.Name) + w := a.Widget + log(debugToolkit, "gui.Toolbox.newDropdown() START", a.Name) newt.tw = w + newt.Type = w.Type + newt.wId = a.WidgetId s := ui.NewCombobox() newt.uiCombobox = s newt.uiControl = s @@ -26,7 +29,7 @@ func (t *andlabsT) newDropdown(w *toolkit.Widget) *andlabsT { newt.text = "error" } newt.tw.S = newt.val[i] - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) }) return &newt @@ -53,9 +56,9 @@ func (t *andlabsT) SetDropdown(i int) { } func AddDropdownName(a *toolkit.Action) { - log(debugToolkit, "gui.andlabs.AddDropdownName()", a.Widget.Name, "add:", a.S) + log(debugToolkit, "gui.andlabs.AddDropdownName()", a.WidgetId, "add:", a.S) - t := mapToolkits[a.Widget] + t := andlabs[a.WidgetId] if (t == nil) { log(debugToolkit, "go.andlabs.AddDropdownName() toolkit struct == nil. name=", a.Widget.Name, a.S) listMap(debugToolkit) @@ -64,31 +67,30 @@ func AddDropdownName(a *toolkit.Action) { t.AddDropdownName(a.S) } -func SetDropdownName(w *toolkit.Widget, s string) { - log(debugChange, "gui.andlabs.SetDropdown()", w.Name, ",", s) +func SetDropdownName(a *toolkit.Action, s string) { + log(debugChange, "gui.andlabs.SetDropdown()", a.WidgetId, ",", s) - t := mapToolkits[w] + t := andlabs[a.WidgetId] if (t == nil) { - log(debugError, "ERROR: SetDropdown() FAILED mapToolkits[w] == nil. name=", w.Name, s) + log(debugError, "ERROR: SetDropdown() FAILED mapToolkits[w] == nil. name=", a.WidgetId, s) listMap(debugError) return } t.SetDropdown(1) + // TODO: send back to wit/gui goroutine with the chan t.tw.S = s } func newDropdown(a *toolkit.Action) { - w := a.Widget - parentW := a.Where - log(debugToolkit, "gui.andlabs.newDropdown()", w.Name) + log(debugToolkit, "gui.andlabs.newDropdown()", a.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "go.andlabs.newDropdown() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "go.andlabs.newDropdown() toolkit struct == nil. name=", a.WidgetId) listMap(debugToolkit) return } - newt := t.newDropdown(w) + newt := t.newDropdown(a) place(a, t, newt) - mapWidgetsToolkits(a, newt) + // mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/grid.go b/toolkit/andlabs/grid.go index f009ab3..be05b70 100644 --- a/toolkit/andlabs/grid.go +++ b/toolkit/andlabs/grid.go @@ -14,9 +14,7 @@ import ( // ----------------------------- func newGrid(a *toolkit.Action) { var newt *andlabsT - log(debugToolkit, "newGrid()", a.Widget.Name, "to", a.Where.Type) - - t := mapToolkits[a.Where] + log(debugToolkit, "newGrid()", a.WidgetId, "to", a.ParentId) newt = new(andlabsT) @@ -24,9 +22,10 @@ func newGrid(a *toolkit.Action) { newt.uiGrid = c newt.uiControl = c newt.tw = a.Widget + newt.Type = toolkit.Grid newt.gridX = 0 newt.gridY = 0 + t := andlabs[a.ParentId] place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/group.go b/toolkit/andlabs/group.go index a44c5b6..0769151 100644 --- a/toolkit/andlabs/group.go +++ b/toolkit/andlabs/group.go @@ -9,17 +9,15 @@ import ( func newGroup(a *toolkit.Action) { w := a.Widget - parentW := a.Where log(debugToolkit, "NewGroup()", w.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "NewGroup() toolkit struct == nil. name=", w.Name) listMap(debugToolkit) } newt := t.rawGroup(w.Name) place(a, t, newt) - mapWidgetsToolkits(a, newt) } // make new Group here @@ -34,13 +32,5 @@ func (t *andlabsT) rawGroup(title string) *andlabsT { newt.uiGroup = g newt.uiControl = g -// hbox := ui.NewVerticalBox() -// hbox.SetPadded(padded) -// g.SetChild(hbox) - -// newt.uiBox = hbox -// newt.uiWindow = t.uiWindow -// newt.uiTab = t.uiTab - return &newt } diff --git a/toolkit/andlabs/image.go b/toolkit/andlabs/image.go index d16f711..a3d1cb6 100644 --- a/toolkit/andlabs/image.go +++ b/toolkit/andlabs/image.go @@ -10,17 +10,15 @@ import ( // make new Image here func newImage(a *toolkit.Action) { w := a.Widget - parentW := a.Where log(debugToolkit, "newImage()", w.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "newImage() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "newImage() toolkit struct == nil. name=", w.Name) listMap(debugToolkit) } newt := t.rawImage(w.Name) place(a, t, newt) - mapWidgetsToolkits(a, newt) } // make new Image using andlabs/ui diff --git a/toolkit/andlabs/label.go b/toolkit/andlabs/label.go index 144c2c1..c6bd670 100644 --- a/toolkit/andlabs/label.go +++ b/toolkit/andlabs/label.go @@ -12,7 +12,7 @@ func newLabel(a *toolkit.Action) { w := a.Widget log(debugToolkit, "NewLabel()", w.Name) - t := mapToolkits[a.Where] + t := andlabs[a.ParentId] if (t == nil) { listMap(debugError) log(debugError, "ERROR newLabel() listMap()") @@ -30,5 +30,4 @@ func newLabel(a *toolkit.Action) { newt.uiControl = c place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/log.go b/toolkit/andlabs/log.go index 43b90cb..77b10e2 100644 --- a/toolkit/andlabs/log.go +++ b/toolkit/andlabs/log.go @@ -1,137 +1,25 @@ -// -// version v1.2 -// -// I like things to be easy. -// -// 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" - "runtime" - "runtime/pprof" - golog "log" - "time" - "reflect" - "github.com/davecgh/go-spew/spew" - // "net" + witlog "git.wit.org/wit/gui/log" ) -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 -*/ +// various debugging flags +var logNow bool = true // useful for active development +var logError bool = true +var logWarn bool = false +var logInfo bool = false +var logVerbose bool = false 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/Andlabs" - } - - if (reflect.TypeOf(a[0]) == reflect.TypeOf(SPEW)) { - // a = a[1:] - a[0] = "GUI/Toolkit/Andlabs" - if (debugToolkit) { - scs := spew.ConfigState{MaxDepth: 1} - scs.Dump(a) - // spew.Dump(a) - } - return - } - - golog.Println(a...) + witlog.Where = "wit/gui/andlabs" + witlog.Log(a...) } -func loggo() { - pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) - golog.Println("runtime.NumGoroutine() = ", runtime.NumGoroutine()) +func sleep(a ...any) { + witlog.Sleep(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 exit(a ...any) { + witlog.Exit(a...) } diff --git a/toolkit/andlabs/main.go b/toolkit/andlabs/main.go index c719352..1ad7a60 100644 --- a/toolkit/andlabs/main.go +++ b/toolkit/andlabs/main.go @@ -2,7 +2,7 @@ package main import ( "embed" - "git.wit.org/wit/gui/toolkit" + // "git.wit.org/wit/gui/toolkit" "github.com/andlabs/ui" // the _ means we only need this for the init() @@ -43,8 +43,10 @@ func Init() { // log(debugToolkit, "gui/toolkit init() Setting defaultBehavior = true") setDefaultBehavior(true) - mapWidgets = make(map[*andlabsT]*toolkit.Widget) - mapToolkits = make(map[*toolkit.Widget]*andlabsT) + // mapWidgets = make(map[*andlabsT]*toolkit.Widget) + // mapToolkits = make(map[*toolkit.Widget]*andlabsT) + + andlabs = make(map[int]*andlabsT) } // TODO: properly exit the plugin since Quit() doesn't do it diff --git a/toolkit/andlabs/plugin.go b/toolkit/andlabs/plugin.go index 60cdbfa..6c2dd76 100644 --- a/toolkit/andlabs/plugin.go +++ b/toolkit/andlabs/plugin.go @@ -31,43 +31,55 @@ func Action(a *toolkit.Action) { rawAction(a) } + if (callback == nil) { + if (a.Callback != nil) { + log(debugNow, "setting Callback", a.Callback) + callback = a.Callback + } + } + // f() Queue(f) } func rawAction(a *toolkit.Action) { - log(debugAction, "Action() START a.Type =", a.Type) + log(debugAction, "Action() START a.ActionType =", a.ActionType) log(debugAction, "Action() START a.S =", a.S) log(debugAction, "Action() START a.Widget =", a.Widget) - switch a.Type { + log(logInfo, "Action() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId) + switch a.WidgetType { + case toolkit.Flag: + flag(a) + return + } + + switch a.ActionType { case toolkit.Add: add(a) case toolkit.Show: a.Widget.B = true - show(a.Widget) + show(a) case toolkit.Hide: a.Widget.B = false - show(a.Widget) + show(a) case toolkit.Enable: a.Widget.B = true - enable(a.Widget) + enable(a) case toolkit.Disable: a.Widget.B = false - enable(a.Widget) + enable(a) case toolkit.Get: setText(a) case toolkit.GetText: switch a.Widget.Type { case toolkit.Textbox: - t := mapToolkits[a.Widget] + t := andlabs[a.WidgetId] a.S = t.s } case toolkit.Set: setText(a) - case toolkit.SetFlag: - flag(a) case toolkit.SetText: setText(a) case toolkit.AddText: @@ -82,15 +94,13 @@ func rawAction(a *toolkit.Action) { pad(a) case toolkit.Delete: uiDelete(a) - case toolkit.Flag: - flag(a) case toolkit.Move: - log(debugNow, "attempt to move() =", a.Type, a.Widget) + log(debugNow, "attempt to move() =", a.ActionType, a.Widget) move(a) default: - log(debugError, "Action() Unknown =", a.Type, a.Widget) + log(debugError, "Action() Unknown =", a.ActionType, a.Widget) } - log(debugAction, "Action() END =", a.Type, a.Widget) + log(debugAction, "Action() END =", a.ActionType, a.Widget) } func flag(a *toolkit.Action) { @@ -122,70 +132,70 @@ func flag(a *toolkit.Action) { } func setText(a *toolkit.Action) { - w := a.Widget - if (w == nil) { - log(debugError, "setText error. w.Widget == nil") + t := andlabs[a.WidgetId] + if (t == nil) { + log(debugError, "setText error. andlabs[id] == nil", a.WidgetId) actionDump(debugError, a) return } - t := mapToolkits[w] - log(debugChange, "setText() Attempt on", w.Type, "with", a.S) + log(debugChange, "setText() Attempt on", t.Type, "with", a.S) - switch w.Type { + switch t.Type { case toolkit.Window: t.uiWindow.SetTitle(a.S) case toolkit.Tab: case toolkit.Group: t.uiGroup.SetTitle(a.S) case toolkit.Checkbox: - switch a.Type { + switch a.ActionType { case toolkit.SetText: t.uiCheckbox.SetText(a.S) case toolkit.Get: - w.B = t.uiCheckbox.Checked() + t.tw.B = t.uiCheckbox.Checked() case toolkit.Set: - t.uiCheckbox.SetChecked(a.B) - w.B = a.B + // TODO: commented out while working on chan + // t.uiCheckbox.SetChecked(a.B) + t.tw.B = a.B default: - log(debugError, "setText() unknown", a.Type, "on checkbox", w.Name) + log(debugError, "setText() unknown", a.ActionType, "on checkbox", t.tw.Name) } case toolkit.Textbox: - switch a.Type { + switch a.ActionType { case toolkit.Set: t.uiMultilineEntry.SetText(a.S) case toolkit.SetText: t.uiMultilineEntry.SetText(a.S) case toolkit.Get: - w.S = t.s + t.tw.S = t.s case toolkit.GetText: - w.S = t.s + t.tw.S = t.s default: - log(debugError, "setText() unknown", a.Type, "on checkbox", w.Name) + log(debugError, "setText() unknown", a.ActionType, "on checkbox", t.tw.Name) } case toolkit.Label: t.uiLabel.SetText(a.S) case toolkit.Button: t.uiButton.SetText(a.S) case toolkit.Slider: - switch a.Type { + switch a.ActionType { case toolkit.Get: - w.I = t.uiSlider.Value() + t.tw.I = t.uiSlider.Value() case toolkit.Set: t.uiSlider.SetValue(a.I) default: - log(debugError, "setText() unknown", a.Type, "on checkbox", w.Name) + log(debugError, "setText() unknown", a.ActionType, "on checkbox", t.tw.Name) } case toolkit.Spinner: - switch a.Type { + switch a.ActionType { case toolkit.Get: - w.I = t.uiSpinbox.Value() + t.tw.I = t.uiSpinbox.Value() case toolkit.Set: t.uiSpinbox.SetValue(a.I) default: - log(debugError, "setText() unknown", a.Type, "on checkbox", w.Name) + log(debugError, "setText() unknown", a.ActionType, "on checkbox", t.tw.Name) } case toolkit.Dropdown: - switch a.Type { + switch a.ActionType { case toolkit.AddText: AddDropdownName(a) case toolkit.Set: @@ -199,7 +209,7 @@ func setText(a *toolkit.Action) { log(debugChange, "i, s", i, s) if (a.S == s) { t.uiCombobox.SetSelected(i) - log(debugChange, "setText() Dropdown worked.", w.S) + log(debugChange, "setText() Dropdown worked.", t.tw.S) return } } @@ -213,14 +223,14 @@ func setText(a *toolkit.Action) { t.uiCombobox.SetSelected(i) } case toolkit.Get: - w.S = t.s + t.tw.S = t.s case toolkit.GetText: - w.S = t.s + t.tw.S = t.s default: - log(debugError, "setText() unknown", a.Type, "on checkbox", w.Name) + log(debugError, "setText() unknown", a.ActionType, "on checkbox", t.tw.Name) } case toolkit.Combobox: - switch a.Type { + switch a.ActionType { case toolkit.AddText: t.AddComboboxName(a.S) case toolkit.Set: @@ -230,13 +240,13 @@ func setText(a *toolkit.Action) { t.uiEditableCombobox.SetText(a.S) t.s = a.S case toolkit.Get: - w.S = t.s + t.tw.S = t.s case toolkit.GetText: - w.S = t.s + t.tw.S = t.s default: - log(debugError, "setText() unknown", a.Type, "on checkbox", w.Name) + log(debugError, "setText() unknown", a.ActionType, "on checkbox", t.tw.Name) } default: - log(debugError, "plugin Send() Don't know how to setText on", w.Type, "yet", a.Type) + log(debugError, "plugin Send() Don't know how to setText on", t.tw.Type, "yet", a.ActionType) } } diff --git a/toolkit/andlabs/slider.go b/toolkit/andlabs/slider.go index 181b258..5a16bff 100644 --- a/toolkit/andlabs/slider.go +++ b/toolkit/andlabs/slider.go @@ -7,19 +7,21 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -func (t *andlabsT) newSlider(w *toolkit.Widget) *andlabsT { - // make new node here - log(debugToolkit, w.Name, w.Type, w.X, w.Y) +func (t *andlabsT) newSlider(a *toolkit.Action) *andlabsT { var newt andlabsT + w := a.Widget + // log(debugToolkit, w.Name, w.Type, w.X, w.Y) - s := ui.NewSlider(w.X, w.Y) + s := ui.NewSlider(a.X, a.Y) newt.uiSlider = s newt.uiControl = s newt.tw = w + newt.Type = toolkit.Slider + newt.wId = a.WidgetId s.OnChanged(func(spin *ui.Slider) { newt.tw.I = newt.uiSlider.Value() - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) }) return &newt @@ -28,17 +30,15 @@ func (t *andlabsT) newSlider(w *toolkit.Widget) *andlabsT { func newSlider(a *toolkit.Action) { var newt *andlabsT w := a.Widget - parentW := a.Where log(debugToolkit, "newSlider()", w.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugError, "newSlider() ERROR toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugError, "newSlider() ERROR toolkit struct == nil. name=", w.Name) return } - w.X = a.X - w.Y = a.Y - newt = t.newSlider(w) + // w.X = a.X + // w.Y = a.Y + newt = t.newSlider(a) place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/spinner.go b/toolkit/andlabs/spinner.go index 6a47472..58e0934 100644 --- a/toolkit/andlabs/spinner.go +++ b/toolkit/andlabs/spinner.go @@ -7,19 +7,21 @@ import ( _ "github.com/andlabs/ui/winmanifest" ) -func (t *andlabsT) newSpinner(w *toolkit.Widget) *andlabsT { - // make new node here - log(debugToolkit, "newSpinner()", w.X, w.Y) +func (t *andlabsT) newSpinner(a *toolkit.Action) *andlabsT { var newt andlabsT + w := a.Widget + // log(debugToolkit, "newSpinner()", w.X, w.Y) - s := ui.NewSpinbox(w.X, w.Y) + s := ui.NewSpinbox(a.X, a.Y) newt.uiSpinbox = s newt.uiControl = s newt.tw = w + newt.wId = a.WidgetId + newt.Type = toolkit.Spinner s.OnChanged(func(s *ui.Spinbox) { newt.tw.I = newt.uiSpinbox.Value() - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) }) return &newt @@ -28,16 +30,12 @@ func (t *andlabsT) newSpinner(w *toolkit.Widget) *andlabsT { func newSpinner(a *toolkit.Action) { var newt *andlabsT w := a.Widget - parentW := a.Where - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugError, "NewSpinner() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugError, "NewSpinner() toolkit struct == nil. name=", w.Name) return } - w.X = a.X - w.Y = a.Y - newt = t.newSpinner(w) + newt = t.newSpinner(a) place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/structs.go b/toolkit/andlabs/structs.go index 9b053af..1fb9a79 100644 --- a/toolkit/andlabs/structs.go +++ b/toolkit/andlabs/structs.go @@ -5,14 +5,19 @@ import "git.wit.org/wit/gui/toolkit" import "github.com/andlabs/ui" import _ "github.com/andlabs/ui/winmanifest" +var andlabs map[int]*andlabsT +var callback func(int) + // stores the raw toolkit internals type andlabsT struct { - id string + wId int // widget ID + Type toolkit.WidgetType Name string // Type toolkit.WidgetType Width int Height int + tw *toolkit.Widget parent *andlabsT diff --git a/toolkit/andlabs/tab.go b/toolkit/andlabs/tab.go index b0920ac..0753338 100644 --- a/toolkit/andlabs/tab.go +++ b/toolkit/andlabs/tab.go @@ -19,36 +19,43 @@ import ( once there is one. If you send a Window here, it will replace any existing tabs rather than adding a new one */ -func (t *andlabsT) newTab(name string) *andlabsT { +func (t *andlabsT) newTab(a *toolkit.Action) { // var w *ui.Window var newt *andlabsT - log(debugToolkit, "gui.toolkit.AddTab()") - - if (t.uiWindow == nil) { - log(debugToolkit, "gui.Toolkit.UiWindow == nil. I can't add a toolbar without window") - return nil - } + log(debugToolkit, "newTab() START", a.WidgetId, a.ParentId) if (t.uiTab == nil) { + if (t.uiWindow == nil) { + log(debugToolkit, "newTab() uiWindow == nil. I can't add a toolbar without window", a.WidgetId, a.ParentId) + return + } // this means you have to make a new tab - log(debugToolkit, "gui.toolkit.NewTab() GOOD. This should be the first tab:", name) - newt = rawTab(t.uiWindow, name) + log(debugToolkit, "newTab() GOOD. This should be the first tab:", a.WidgetId, a.ParentId) + newt = rawTab(t.uiWindow, a.Text) t.uiTab = newt.uiTab } else { // this means you have to append a tab - log(debugToolkit, "gui.toolkit.NewTab() GOOD. This should be an additional tab:", name) - newt = t.appendTab(name) + log(debugToolkit, "newTab() GOOD. This should be an additional tab:", a.WidgetId, a.ParentId) + newt = t.appendTab(a.Text) } - newt.Name = name + // add the structure to the array + if (andlabs[a.WidgetId] == nil) { + log(logInfo, "newTab() MAPPED", a.WidgetId, a.ParentId) + andlabs[a.WidgetId] = newt + newt.Type = a.Widget.Type + } else { + log(debugError, "newTab() DO WHAT?", a.WidgetId, a.ParentId) + log(debugError, "THIS IS BAD") + } + + newt.Name = a.Name log(debugToolkit, "t:") t.Dump(debugToolkit) log(debugToolkit, "newt:") newt.Dump(debugToolkit) - - return newt } // This sets _all_ the tabs to Margin = true @@ -64,29 +71,21 @@ func tabSetMargined(tab *ui.Tab, b bool) { func rawTab(w *ui.Window, name string) *andlabsT { var newt andlabsT - log(debugToolkit, "gui.toolkit.NewTab() ADD", name) + log(debugToolkit, "rawTab() START", name) if (w == nil) { - log(debugToolkit, "gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window") - log(debugToolkit, "gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window") - log(debugToolkit, "gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window") + log(debugError, "UiWindow == nil. I can't add a tab without a window") + log(debugError, "UiWindow == nil. I can't add a tab without a window") + log(debugError, "UiWindow == nil. I can't add a tab without a window") sleep(1) return nil } - log(debugToolkit, "gui.toolkit.AddTab() START name =", name) + tab := ui.NewTab() - w.SetMargined(margin) - - hbox := ui.NewHorizontalBox() // this makes everything go along the horizon - hbox.SetPadded(padded) - tab.Append(name, hbox) - tabSetMargined(tab, margin) // TODO: run this in the right place(?) w.SetChild(tab) - - newt.uiWindow = w newt.uiTab = tab newt.uiControl = tab - newt.uiBox = hbox + log(debugToolkit, "rawTab() END", name) return &newt } @@ -120,20 +119,14 @@ func (t *andlabsT) appendTab(name string) *andlabsT { } func newTab(a *toolkit.Action) { - parentW := a.Where - w := a.Widget - var newt *andlabsT - log(debugToolkit, "gui.andlabs.NewTab()", w.Name) + // w := a.Widget + log(debugToolkit, "newTab()", a.ParentId) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "newTab() parent toolkit == nil. new tab can not be made =", a.ParentId) + log(debugToolkit, "look for a window? check for an existing tab?") return } - newt = t.newTab(w.Name) - mapWidgetsToolkits(a, newt) -} - -func doTab(a *toolkit.Action) { - newTab(a) + t.newTab(a) } diff --git a/toolkit/andlabs/textbox.go b/toolkit/andlabs/textbox.go index cff61f2..ef39d33 100644 --- a/toolkit/andlabs/textbox.go +++ b/toolkit/andlabs/textbox.go @@ -17,6 +17,7 @@ func (t *andlabsT) newTextbox(w *toolkit.Widget) *andlabsT { newt.Name = w.Name newt.tw = w + newt.Type = toolkit.Textbox c.OnChanged(func(spin *ui.MultilineEntry) { t.s = spin.Text() @@ -29,16 +30,14 @@ func (t *andlabsT) newTextbox(w *toolkit.Widget) *andlabsT { func newTextbox(a *toolkit.Action) { w := a.Widget - parentW := a.Where log(debugToolkit, "newCombobox()", w.Name) - t := mapToolkits[parentW] + t := andlabs[a.ParentId] if (t == nil) { - log(debugToolkit, "newCombobox() toolkit struct == nil. name=", parentW.Name, w.Name) + log(debugToolkit, "newCombobox() toolkit struct == nil. name=", w.Name) listMap(debugToolkit) return } newt := t.newTextbox(w) place(a, t, newt) - mapWidgetsToolkits(a, newt) } diff --git a/toolkit/andlabs/widget.go b/toolkit/andlabs/widget.go index e4a2bb7..45c584a 100644 --- a/toolkit/andlabs/widget.go +++ b/toolkit/andlabs/widget.go @@ -1,69 +1,24 @@ package main import ( - "git.wit.org/wit/gui/toolkit" + // "git.wit.org/wit/gui/toolkit" ) // This is a map between the widgets in wit/gui and the internal structures of gocui -var mapWidgets map[*andlabsT]*toolkit.Widget -var mapToolkits map[*toolkit.Widget]*andlabsT +// var mapWidgets map[*andlabsT]*toolkit.Widget +// var mapToolkits map[*toolkit.Widget]*andlabsT // This lists out the known mappings // deprecate and use instead the GUI interface func listMap(b bool) { log(b, "listMap() disabled HERE. output too big") return - for t, w := range mapWidgets { - log(b, "andlabs =", t.Name, "widget =", w.Name) - } log(b, "listMap() HERE mapToolkits()") - for w, t := range mapToolkits { - log(b, "andlabs =", t, "widget =", w.Name) + for i, t := range andlabs { + log(b, "andlabs =", t, "widgetId =", i) t.Dump(b) } log(b, "listMap() HERE mapWidgets()") log(b, "listMap() HERE FIXME. output too big") } - -func mapWidgetsToolkits(a *toolkit.Action, t *andlabsT) { - w := a.Widget - if ((mapToolkits[w] == nil) && (mapWidgets[t] == nil)) { - log(debugToolkit, "map a new widget", w, t) - mapToolkits[w] = t - mapWidgets[t] = w - return - } - - if (mapToolkits[w] != nil) { - tw := mapToolkits[w] - if (tw == nil) { - // logic corruption somewhere? Have you been deleting things recently? - log(true, "mapToolkits[w] is set, but mapWidgets[t] is nil") - panic("WTF mapWidgets[t] == nil") - } - log(debugToolkit, "mapToolkits[w] is", tw) - if (tw == nil) { - log(debugError, "BAD map? mapWidgets[w] tw == nil") - } else { - log(debugError, "BAD map? mapWidgets[w] is", tw) - tw.Dump(debugError) - } - } - - if (mapWidgets[t] != nil) { - wt := mapWidgets[t] - if (mapToolkits[w] == nil) { - // logic corruption somewhere? Have you been deleting things recently? - log(true, "mapWidgets[t] is set, but mapToolkits[w] is nil") - panic("WTF mapToolkits[w] == nil") - } - if (wt == nil) { - log(debugError, "BAD map? mapWidgets[t] wt == nil") - } else { - log(debugError, "BAD map? mapWidgets[t] is", wt) - widgetDump(debugError, wt) - } - } - log(debugToolkit, "map of widget worked", w.Type, ",", w.Name) -} diff --git a/toolkit/andlabs/window.go b/toolkit/andlabs/window.go index 9181d5f..2fee729 100644 --- a/toolkit/andlabs/window.go +++ b/toolkit/andlabs/window.go @@ -19,7 +19,7 @@ func newWindow(a *toolkit.Action) { w := a.Widget var newt *andlabsT - log(debugToolkit, "toolkit NewWindow", w.Name, w.Width, w.Height) + // log(debugToolkit, "toolkit NewWindow", w.Name, w.Width, w.Height) if (w == nil) { log(debugToolkit, "wit/gui plugin error. widget == nil") @@ -27,13 +27,15 @@ func newWindow(a *toolkit.Action) { } newt = new(andlabsT) newt.tw = w + newt.Type = toolkit.Window + newt.wId = a.WidgetId // menubar bool is if the OS defined border on the window should be used - win := ui.NewWindow(w.Name, w.Width, w.Height, menubar) + win := ui.NewWindow(w.Name, a.Width, a.Height, menubar) win.SetBorderless(canvas) win.SetMargined(margin) win.OnClosing(func(*ui.Window) bool { - newt.commonChange(newt.tw) + newt.commonChange(newt.tw, a.WidgetId) return true }) win.Show() @@ -42,16 +44,17 @@ func newWindow(a *toolkit.Action) { // newt.UiWindowBad = win // deprecate this as soon as possible newt.Name = w.Name - mapWidgetsToolkits(a, newt) + andlabs[a.WidgetId] = newt return } func (t *andlabsT) SetWindowTitle(title string) { log(debugToolkit, "toolkit NewWindow", t.Name, "title", title) win := t.uiWindow - if (win != nil) { - win.SetTitle(title) + if (win == nil) { + log(debugError, "Error: no window", t.wId) } else { + win.SetTitle(title) log(debugToolkit, "Setting the window title", title) } } diff --git a/toolkit/democui/, b/toolkit/democui/, new file mode 100644 index 0000000..762f8eb --- /dev/null +++ b/toolkit/democui/, @@ -0,0 +1,191 @@ +// Copyright 2014 The gocui Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "errors" + "fmt" + "log" + + "github.com/awesome-gocui/gocui" +) + +func main() { + g, err := gocui.NewGui(gocui.OutputNormal, true) + if err != nil { + log.Panicln(err) + } + defer g.Close() + + g.Cursor = false + g.Mouse = true + + g.SetManagerFunc(layout) + + if err := keybindings(g); err != nil { + log.Panicln(err) + } + + if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { + log.Panicln(err) + } +} + +var initialMouseX, initialMouseY, xOffset, yOffset int +var globalMouseDown, msgMouseDown, movingMsg bool + +func layout(g *gocui.Gui) error { + maxX, maxY := g.Size() + if _, err := g.View("msg"); msgMouseDown && err == nil { + moveMsg(g) + } + if v, err := g.SetView("global", -1, -1, maxX, maxY, 0); err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + v.Frame = false + } + if v, err := g.SetView("but1", 2, 2, 22, 7, 0); err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + v.SelBgColor = gocui.ColorGreen + v.SelFgColor = gocui.ColorBlack + fmt.Fprintln(v, "Button 1 - line 1") + fmt.Fprintln(v, "Button 1 - line 2") + fmt.Fprintln(v, "Button 1 - line 3") + fmt.Fprintln(v, "Button 1 - line 4") + if _, err := g.SetCurrentView("but1"); err != nil { + return err + } + } + if v, err := g.SetView("but2", 24, 2, 44, 4, 0); err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + v.SelBgColor = gocui.ColorGreen + v.SelFgColor = gocui.ColorBlack + fmt.Fprintln(v, "Button 2 - line 1") + } + updateHighlightedView(g) + return nil +} + +func keybindings(g *gocui.Gui) error { + if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { + return err + } + for _, n := range []string{"but1", "but2"} { + if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil { + return err + } + } + if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil { + return err + } + if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil { + return err + } + return nil +} + +func quit(g *gocui.Gui, v *gocui.View) error { + return gocui.ErrQuit +} + +func showMsg(g *gocui.Gui, v *gocui.View) error { + var l string + var err error + + if _, err := g.SetCurrentView(v.Name()); err != nil { + return err + } + + _, cy := v.Cursor() + if l, err = v.Line(cy); err != nil { + l = "" + } + + maxX, maxY := g.Size() + if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) { + v.Clear() + v.SelBgColor = gocui.ColorCyan + v.SelFgColor = gocui.ColorBlack + fmt.Fprintln(v, l) + } + return nil +} + +func updateHighlightedView(g *gocui.Gui) { + mx, my := g.MousePosition() + for _, view := range g.Views() { + view.Highlight = false + } + if v, err := g.ViewByPosition(mx, my); err == nil { + v.Highlight = true + } +} + +func moveMsg(g *gocui.Gui) { + mx, my := g.MousePosition() + if !movingMsg && (mx != initialMouseX || my != initialMouseY) { + movingMsg = true + } + g.SetView("msg", mx-xOffset, my-yOffset, mx-xOffset+20, my-yOffset+2, 0) +} + +func msgDown(g *gocui.Gui, v *gocui.View) error { + initialMouseX, initialMouseY = g.MousePosition() + if vx, vy, _, _, err := g.ViewPosition("msg"); err == nil { + xOffset = initialMouseX - vx + yOffset = initialMouseY - vy + msgMouseDown = true + } + return nil +} + +func globalDown(g *gocui.Gui, v *gocui.View) error { + mx, my := g.MousePosition() + if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil { + if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 { + return msgDown(g, v) + } + } + globalMouseDown = true + maxX, _ := g.Size() + msg := fmt.Sprintf("Mouse down at: %d,%d", mx, my) + x := mx - len(msg)/2 + if x < 0 { + x = 0 + } else if x+len(msg)+1 > maxX-1 { + x = maxX - 1 - len(msg) - 1 + } + if v, err := g.SetView("globalDown", x, my-1, x+len(msg)+1, my+1, 0); err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + v.WriteString(msg) + } + return nil +} + +func mouseUp(g *gocui.Gui, v *gocui.View) error { + if msgMouseDown { + msgMouseDown = false + if movingMsg { + movingMsg = false + return nil + } else { + g.DeleteView("msg") + } + } else if globalMouseDown { + globalMouseDown = false + g.DeleteView("globalDown") + } + return nil +} diff --git a/toolkit/democui/Makefile b/toolkit/democui/Makefile index 6f3f7d9..96b8928 100644 --- a/toolkit/democui/Makefile +++ b/toolkit/democui/Makefile @@ -9,3 +9,7 @@ plugin: objdump: objdump -t ../democui.so |less + +log: + reset + tail -f /tmp/witgui.* /tmp/guilogfile diff --git a/toolkit/democui/click.go b/toolkit/democui/click.go new file mode 100644 index 0000000..adc611c --- /dev/null +++ b/toolkit/democui/click.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "errors" + "strconv" + + "github.com/awesome-gocui/gocui" + // "git.wit.org/wit/gui/toolkit" +) + +func click(g *gocui.Gui, v *gocui.View) error { + var l string + var err error + + log(logNow, "click() START", v.Name()) + i, err := strconv.Atoi(v.Name()) + if (err != nil) { + log(logNow, "click() Can't find widget. error =", err) + } else { + log(logNow, "click() Found widget id =", i) + if (me.widgets[i] != nil) { + w := me.widgets[i] + log(logNow, "click() Found widget =", w) + } + } + + if _, err := g.SetCurrentView(v.Name()); err != nil { + return err + } + + _, cy := v.Cursor() + if l, err = v.Line(cy); err != nil { + l = "" + } + + maxX, maxY := g.Size() + if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) { + v.Clear() + v.SelBgColor = gocui.ColorCyan + v.SelFgColor = gocui.ColorBlack + fmt.Fprintln(v, l) + } + + // this seems to delete the button(?) + // g.SetViewOnBottom(v.Name()) + log(logNow, "click() END") + return nil +} diff --git a/toolkit/democui/common.go b/toolkit/democui/common.go new file mode 100644 index 0000000..799ac9c --- /dev/null +++ b/toolkit/democui/common.go @@ -0,0 +1,90 @@ +package main + +import ( + "github.com/awesome-gocui/gocui" + "git.wit.org/wit/gui/toolkit" +) + +func setupWidgetT(a *toolkit.Action) *cuiWidget { + var w *cuiWidget + w = new(cuiWidget) + + w.name = a.Name + w.text = a.Text + + w.widgetType = a.WidgetType + w.id = a.WidgetId + if (w.id > me.highest) { + me.highest = w.id + } + w.parentId = a.ParentId + me.widgets[w.id] = w + + // w.showWidgetPlacement(logNow) + return w +} + +// ColorBlack ColorRed ColorGreen ColorYellow ColorBlue ColorMagenta ColorCyan ColorWhite +// gocui.GetColor("#FFAA55") // Dark Purple +func (w *cuiWidget) SetDefaultWidgetColor() { + log(logInfo, "SetDefaultWidgetColor() on", w.widgetType, w.name) + if (w.v == nil) { + log(logError, "SetDefaultWidgetColor() failed on view == nil") + return + } + w.SetDefaultHighlight() + switch w.widgetType { + case toolkit.Button: + w.v.BgColor = gocui.ColorGreen + w.v.FrameColor = gocui.ColorGreen + case toolkit.Checkbox: + w.v.BgColor = gocui.GetColor("#FFAA55") // Dark Purple + w.v.FrameColor = gocui.GetColor("#FFEE11") + case toolkit.Dropdown: + w.v.BgColor = gocui.ColorCyan + w.v.FrameColor = gocui.ColorGreen + case toolkit.Textbox: + w.v.BgColor = gocui.ColorYellow + w.v.FrameColor = gocui.ColorGreen + case toolkit.Slider: + w.v.BgColor = gocui.GetColor("#FFAA55") // Dark Purple + w.v.FrameColor = gocui.ColorRed + case toolkit.Label: + w.v.FrameColor = gocui.ColorRed + default: + w.v.BgColor = gocui.ColorYellow + } +} + +// SetColor("#FFAA55") // purple +func (w *cuiWidget) SetColor(c string) { + if (w.v == nil) { + log(logError, "SetColor() failed on view == nil") + return + } + w.v.SelBgColor = gocui.ColorCyan + w.v.SelFgColor = gocui.ColorBlack + switch c { + case "Green": + w.v.BgColor = gocui.ColorGreen + case "Purple": + w.v.BgColor = gocui.GetColor("#FFAA55") + case "Yellow": + w.v.BgColor = gocui.ColorYellow + case "Blue": + w.v.BgColor = gocui.ColorBlue + case "Red": + w.v.BgColor = gocui.ColorRed + default: + w.v.BgColor = gocui.GetColor(c) + } +} + +func (w *cuiWidget) SetDefaultHighlight() { + if (w.v == nil) { + log(logError, "SetColor() failed on view == nil") + return + } + w.v.SelBgColor = gocui.ColorGreen + w.v.SelFgColor = gocui.ColorBlack +} diff --git a/toolkit/democui/debug.go b/toolkit/democui/debug.go index d024925..bb2a06d 100644 --- a/toolkit/democui/debug.go +++ b/toolkit/democui/debug.go @@ -1,86 +1,46 @@ package main -import "git.wit.org/wit/gui/toolkit" +import ( + "fmt" + "strconv" -var defaultBehavior bool = true + "git.wit.org/wit/gui/toolkit" + "github.com/awesome-gocui/gocui" +) -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 +// 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 + me.defaultBehavior = s + if (me.defaultBehavior) { + log(logInfo, "Setting this toolkit to use the default behavior.") + log(logInfo, "This is the 'guessing' part as defined by the wit/gui 'Principles'. Refer to the docs.") + me.stretchy = false + me.padded = true + me.menubar = true + me.margin = true + me.canvas = false + me.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.") + log(logInfo, "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 { +func actionDump(b bool, a *toolkit.Action) { + if (a == nil) { + log(b, "action = nil") 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) + + log(b, "a.Name =", a.Name) + log(b, "a.Text =", a.Text) + log(b, "a.WidgetId =", a.WidgetId) + log(b, "a.ParentId =", a.ParentId) + log(b, "a.B =", a.B) + log(b, "a.S =", a.S) + widgetDump(b, a.Widget) } -*/ func widgetDump(b bool, w *toolkit.Widget) { if (w == nil) { @@ -88,6 +48,7 @@ func widgetDump(b bool, w *toolkit.Widget) { return } + /* log(b, "widget.Name =", w.Name) log(b, "widget.Type =", w.Type) log(b, "widget.Custom =", w.Custom) @@ -97,10 +58,66 @@ func widgetDump(b bool, w *toolkit.Widget) { log(b, "widget.Height =", w.Height) log(b, "widget.X =", w.X) log(b, "widget.Y =", w.Y) + */ } -/* -func GetDebugToolkit () bool { - return debugToolkit +func dumpWidgets(g *gocui.Gui, v *gocui.View) { + for _, view := range g.Views() { + i, _ := strconv.Atoi(view.Name()) + if (me.widgets[i] != nil) { + continue + } + log(logNow, "dump() not a widget. view.Name =", view.Name()) + } + + for i := 0; i <= me.highest; i++ { + w := me.widgets[i] + if (w == nil) { + continue + } + w.showWidgetPlacement(logNow, "") + + if (w.v == nil) { + log(logError, "dump() ERROR w.v == nil") + } else { + if (strconv.Itoa(i) != w.v.Name()) { + log(logError, "dump() ERROR unequal str.Itoa(i) =", strconv.Itoa(i)) + log(logError, "dump() ERROR unequal w.v.Name() =", w.v.Name()) + } + } + } +} + +func adjustWidgets() { + for i := 0; i <= me.highest; i++ { + w := me.widgets[i] + if (w == nil) { + continue + } + p := me.widgets[w.parentId] + if (p != nil) { + w.setParentLogical(p) + } + } +} + +func (w *cuiWidget) showWidgetPlacement(b bool, s string) { + log(b, "dump()", s, + fmt.Sprintf("(wId,pId)=(%3d,%3d)", w.id, w.parentId), + fmt.Sprintf("real()=(%3d,%3d,%3d,%3d)", w.realSize.w0, w.realSize.h0, w.realSize.w1, w.realSize.h1), + "next()=(", w.nextX, ",", w.nextY, ")", + "logical()=(", w.logicalSize.w0, ",", w.logicalSize.h0, ",", w.logicalSize.w1, ",", w.logicalSize.h1, ")", + w.widgetType, ",", w.name) + if (w.realWidth != (w.realSize.w1 - w.realSize.w0)) { + log(b, "dump()", s, + "badsize()=(", w.realWidth, ",", w.realHeight, ")", + "badreal()=(", w.realSize.w0, ",", w.realSize.h0, ",", w.realSize.w1, ",", w.realSize.h1, ")", + w.widgetType, ",", w.name) + } + if (w.realHeight != (w.realSize.h1 - w.realSize.h0)) { + log(b, "dump()", s, + "badsize()=(", w.realWidth, ",", w.realHeight, ")", + "badreal()=(", w.realSize.w0, ",", w.realSize.h0, ",", w.realSize.w1, ",", w.realSize.h1, ")", + w.widgetType, ",", w.name) + } } -*/ diff --git a/toolkit/democui/help.go b/toolkit/democui/help.go new file mode 100644 index 0000000..f012fef --- /dev/null +++ b/toolkit/democui/help.go @@ -0,0 +1,46 @@ +// Copyright 2014 The gocui Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "errors" + "fmt" + + "github.com/awesome-gocui/gocui" +) + +func addHelp() { + me.baseGui.SetManagerFunc(helplayout) +} + +func helplayout(g *gocui.Gui) error { + var err error + maxX, _ := g.Size() + + help, err := g.SetView("help", maxX-32, 0, maxX-1, 12, 0) + if err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + help.SelBgColor = gocui.ColorGreen + help.SelFgColor = gocui.ColorBlack + fmt.Fprintln(help, "KEYBINDINGS") + fmt.Fprintln(help, "Enter: Click Button") + fmt.Fprintln(help, "Tab/Space: Switch Buttons") + fmt.Fprintln(help, "") + fmt.Fprintln(help, "h: Help") + fmt.Fprintln(help, "Backspace: Delete Button") + fmt.Fprintln(help, "Arrow keys: Move Button") + fmt.Fprintln(help, "t: Move Button to the top") + fmt.Fprintln(help, "b: Move Button to the button") + fmt.Fprintln(help, "STDOUT: /tmp/witgui.log") + fmt.Fprintln(help, "Ctrl-C or Q: Exit") + if _, err := g.SetCurrentView("help"); err != nil { + return err + } + } + me.helpLabel = help + return nil +} diff --git a/toolkit/democui/keybindings.go b/toolkit/democui/keybindings.go new file mode 100644 index 0000000..8e5e937 --- /dev/null +++ b/toolkit/democui/keybindings.go @@ -0,0 +1,45 @@ +// Copyright 2014 The gocui Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "github.com/awesome-gocui/gocui" +) + +func defaultKeybindings(g *gocui.Gui) error { + if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { + return err + } + for _, n := range []string{"but1", "but2", "help", "but3"} { + if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil { + return err + } + } + if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil { + return err + } + if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, msgDown); err != nil { + return err + } + addDebugKeys(g) + return nil +} + +// dump out the widgets +func addDebugKeys(g *gocui.Gui) { + g.SetKeybinding("", 'd', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + dumpWidgets(g, v) + return nil + }) + g.SetKeybinding("", 'r', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + adjustWidgets() + return nil + }) +} diff --git a/toolkit/democui/log.go b/toolkit/democui/log.go index afd1280..2d7e27e 100644 --- a/toolkit/democui/log.go +++ b/toolkit/democui/log.go @@ -1,135 +1,30 @@ -// -// 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" + witlog "git.wit.org/wit/gui/log" ) -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 -*/ +// various debugging flags +var logNow bool = true // useful for active development +var logError bool = true +var logWarn bool = false +var logInfo bool = false +var logVerbose bool = false 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...) + witlog.Where = "wit/democui" + witlog.Log(a...) } -func logindent(depth int, format string, a ...interface{}) { - var tabs string - for i := 0; i < depth; i++ { - tabs = tabs + format - } +func sleep(a ...any) { + witlog.Sleep(a...) +} - // newFormat := tabs + strconv.Itoa(depth) + " " + format - newFormat := tabs + format - log(debugToolkit, newFormat, a) +func exit(a ...any) { + witlog.Exit(a...) } func setOutput(f *os.File) { - golog.SetOutput(f) + witlog.SetOutput(f) } diff --git a/toolkit/democui/main.go b/toolkit/democui/main.go new file mode 100644 index 0000000..19b326d --- /dev/null +++ b/toolkit/democui/main.go @@ -0,0 +1,67 @@ +// Copyright 2014 The gocui Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "os" +) + +/* +func OnExit(f func(string)) { + Custom = f +} +*/ + +func Init() { + log(logInfo, "Init() of democui") + me.widgets = make(map[int]*cuiWidget) + me.defaultWidth = 10 + me.defaultHeight = 2 + me.defaultBehavior = true +} + +func Exit() { + // TODO: exit correctly + me.baseGui.Close() +} + +/* +func mouseClick(name string) { + // output screws up the console. Need to fix this by redirecting all console output to a file from log.Println() + // log.Println("g.Close()") + // g.Close() + + log("Found andlabs Running custom function for the mouse click") + Custom(name) + // panic("got andlabs") +} +*/ + +func Main(f func()) { + log("start Init()") + + outf, err := os.OpenFile("/tmp/witgui.log", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) + if err != nil { + exit("error opening file: %v", err) + } + defer outf.Close() + + setOutput(outf) + log("This is a test log entry") + + MouseMain() +} + +/* +func StartConsoleMouse() { + defer g.Close() + log("start Main()") + + if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { + exit(err) + } + log("exit Main()") +} +*/ diff --git a/toolkit/democui/mouse.go b/toolkit/democui/mouse.go index efda307..fc74d27 100644 --- a/toolkit/democui/mouse.go +++ b/toolkit/democui/mouse.go @@ -7,85 +7,54 @@ package main import ( "errors" "fmt" - "os" "github.com/awesome-gocui/gocui" ) -var g *gocui.Gui -var err error -var Custom func(string) - -func OnExit(f func(string)) { - Custom = f -} - -func Exit() { - g.Close() -} - -func mouseClick(name string) { - // output screws up the console. Need to fix this by redirecting all console output to a file from log.Println() - // log.Println("g.Close()") - // g.Close() - - log("Found andlabs Running custom function for the mouse click") - Custom(name) - // panic("got andlabs") -} - -func Init() { - log("start Init()") - - f, err := os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) +func MouseMain() { + g, err := gocui.NewGui(gocui.OutputNormal, true) if err != nil { - exit("error opening file: %v", err) + panic(err) } - defer f.Close() + defer g.Close() - setOutput(f) - log("This is a test log entry") - - g, err = gocui.NewGui(gocui.OutputNormal, true) - if err != nil { - exit(err) - } + me.baseGui = g g.Cursor = true g.Mouse = true g.SetManagerFunc(layout) - if err := keybindings(g); err != nil { - exit(err) + if err := defaultKeybindings(g); err != nil { + panic(err) } - log("exit Init()") -} - -func StartConsoleMouse() { - defer g.Close() - log("start Main()") if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { - exit(err) + panic(err) } - log("exit Main()") } func layout(g *gocui.Gui) error { - if v, err := g.SetView("but1", 2, 2, 22, 17, 0); err != nil { + maxX, maxY := g.Size() + if _, err := g.View("msg"); msgMouseDown && err == nil { + moveMsg(g) + } + if v, err := g.SetView("global", -1, -1, maxX, maxY, 0); err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + v.Frame = false + } + if v, err := g.SetView("but1", 2, 2, 22, 7, 0); err != nil { if !errors.Is(err, gocui.ErrUnknownView) { return err } - v.Highlight = true v.SelBgColor = gocui.ColorGreen v.SelFgColor = gocui.ColorBlack - fmt.Fprintln(v, "andlabs") - fmt.Fprintln(v, "addDemoTab") - fmt.Fprintln(v, "DemoToolkitWindow") - fmt.Fprintln(v, "DebugWindow") - fmt.Fprintln(v, "do nothing") - fmt.Fprintln(v, "exit") + fmt.Fprintln(v, "Button 1 - line 1") + fmt.Fprintln(v, "Button 1 - line 2") + fmt.Fprintln(v, "Button 1 - line 3") + fmt.Fprintln(v, "Button 1 - line 4") if _, err := g.SetCurrentView("but1"); err != nil { return err } @@ -94,59 +63,12 @@ func layout(g *gocui.Gui) error { if !errors.Is(err, gocui.ErrUnknownView) { return err } - v.Highlight = true v.SelBgColor = gocui.ColorGreen v.SelFgColor = gocui.ColorBlack fmt.Fprintln(v, "Button 2 - line 1") } - if v, err := g.SetView("but3", 24, 2, 44, 4, 0); err != nil { - if !errors.Is(err, gocui.ErrUnknownView) { - return err - } - v.Highlight = true - v.SelBgColor = gocui.ColorGreen - v.SelFgColor = gocui.ColorBlack - fmt.Fprintln(v, "Button 2 - line 1") - } - if v, err := g.SetView("but4", 24, 2, 44, 4, 0); err != nil { - if !errors.Is(err, gocui.ErrUnknownView) { - return err - } - v.Highlight = true - v.SelBgColor = gocui.ColorGreen - v.SelFgColor = gocui.ColorBlack - fmt.Fprintln(v, "Button 2 - line 1") - } - if v, err := g.SetView("but5", 24, 2, 44, 4, 0); err != nil { - if !errors.Is(err, gocui.ErrUnknownView) { - return err - } - v.Highlight = true - v.SelBgColor = gocui.ColorGreen - v.SelFgColor = gocui.ColorBlack - fmt.Fprintln(v, "Button 2 - line 1") - } - return nil -} - -func keybindings(g *gocui.Gui) error { - if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { - return err - } - for _, n := range []string{"but1", "but2"} { - if err := g.SetKeybinding(n, gocui.MouseLeft, gocui.ModNone, showMsg); err != nil { - return err - } - } - if err := g.SetKeybinding("msg", gocui.MouseLeft, gocui.ModNone, delMsg); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.MouseRight, gocui.ModNone, delMsg); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.MouseMiddle, gocui.ModNone, delMsg); err != nil { - return err - } + helplayout(g) + updateHighlightedView(g) return nil } @@ -168,18 +90,80 @@ func showMsg(g *gocui.Gui, v *gocui.View) error { } maxX, maxY := g.Size() - if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err != nil { - if !errors.Is(err, gocui.ErrUnknownView) { - return err - } - mouseClick(l) + if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) { + v.Clear() + v.SelBgColor = gocui.ColorCyan + v.SelFgColor = gocui.ColorBlack fmt.Fprintln(v, l) } return nil } -func delMsg(g *gocui.Gui, v *gocui.View) error { - // Error check removed, because delete could be called multiple times with the above keybindings - g.DeleteView("msg") +func updateHighlightedView(g *gocui.Gui) { + mx, my := g.MousePosition() + for _, view := range g.Views() { + view.Highlight = false + } + if v, err := g.ViewByPosition(mx, my); err == nil { + v.Highlight = true + } +} + +func moveMsg(g *gocui.Gui) { + mx, my := g.MousePosition() + if !movingMsg && (mx != initialMouseX || my != initialMouseY) { + movingMsg = true + } + g.SetView("msg", mx-xOffset, my-yOffset, mx-xOffset+20, my-yOffset+2, 0) +} + +func msgDown(g *gocui.Gui, v *gocui.View) error { + initialMouseX, initialMouseY = g.MousePosition() + if vx, vy, _, _, err := g.ViewPosition("msg"); err == nil { + xOffset = initialMouseX - vx + yOffset = initialMouseY - vy + msgMouseDown = true + } + return nil +} + +func globalDown(g *gocui.Gui, v *gocui.View) error { + mx, my := g.MousePosition() + if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil { + if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 { + return msgDown(g, v) + } + } + globalMouseDown = true + maxX, _ := g.Size() + msg := fmt.Sprintf("Mouse down at: %d,%d", mx, my) + x := mx - len(msg)/2 + if x < 0 { + x = 0 + } else if x+len(msg)+1 > maxX-1 { + x = maxX - 1 - len(msg) - 1 + } + if v, err := g.SetView("globalDown", x, my-1, x+len(msg)+1, my+1, 0); err != nil { + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + v.WriteString(msg) + } + return nil +} + +func mouseUp(g *gocui.Gui, v *gocui.View) error { + if msgMouseDown { + msgMouseDown = false + if movingMsg { + movingMsg = false + return nil + } else { + g.DeleteView("msg") + } + } else if globalMouseDown { + globalMouseDown = false + g.DeleteView("globalDown") + } return nil } diff --git a/toolkit/democui/plugin.go b/toolkit/democui/plugin.go index 2c0d42e..86125d4 100644 --- a/toolkit/democui/plugin.go +++ b/toolkit/democui/plugin.go @@ -4,112 +4,15 @@ 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() + me.baseGui.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.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") - } +func Action(a *toolkit.Action) { + log(logNow, "Action()", a) + w := setupWidgetT(a) + place(w, a) + log(logInfo, "Action() END") } diff --git a/toolkit/democui/structs.go b/toolkit/democui/structs.go new file mode 100644 index 0000000..37a8f28 --- /dev/null +++ b/toolkit/democui/structs.go @@ -0,0 +1,127 @@ +// LICENSE: same as the go language itself +// Copyright 2023 WIT.COM + +// all structures and variables are local (aka lowercase) +// since the plugin should be isolated to access only +// by functions() to insure everything here is run +// inside a dedicated goroutine + +package main + +import ( + "fmt" + "sync" + "github.com/awesome-gocui/gocui" + "git.wit.org/wit/gui/toolkit" +) + +// const delta = 1 + +// It's probably a terrible idea to call this 'me' +var me config + +type config struct { + highest int // highest widgetId + baseGui *gocui.Gui // the main gocui handle + widgets map[int]*cuiWidget + callback func(int) + helpLabel *gocui.View + + defaultBehavior bool + defaultWidth int + defaultHeight int + nextW int // where the next window or tab flag should go + + bookshelf bool // do you want things arranged in the box like a bookshelf or a stack? + canvas bool // if set to true, the windows are a raw canvas + menubar bool // for windows + stretchy bool // expand things like buttons to the maximum size + padded bool // add space between things like buttons + margin bool // add space around the frames of windows +} + +/* +// 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 +*/ + +var ( +// g *gocui.Gui +// Custom func(string) + + initialMouseX, initialMouseY, xOffset, yOffset int + globalMouseDown, msgMouseDown, movingMsg bool + +// err error +) + +// the gocui way +// the logical size of the widget +// corner starts at in the upper left corner +type rectType struct { + // this is the gocui way + w0, h0, w1, h1 int // left top right bottom +} + +/* +type realSizeT struct { + width, height int +} +*/ + + +type cuiWidget struct { + id int // widget ID + parentId int + widgetType toolkit.WidgetType + + name string // a descriptive name of the widget + text string // the current text being displayed + + visable bool // widget types like 'box' are 'false' + realWidth int // the real width + realHeight int // the real height + realSize rectType // the display size of this widget + logicalSize rectType // the logical size. Includes all the child widgets + + nextX int + nextY int + + // horizontal=true means layout widgets like books on a bookshelf + // horizontal=false means layout widgets like books in a stack + horizontal bool `default:false` + + tainted bool + v *gocui.View + baseGui *gocui.Gui // use gogui.Manager ? as 'workspaces?' + + // writeMutex protects locks the write process + writeMutex sync.Mutex + + // deprecate + // logicalWidth int `default:8` + // logicalHeight int `default:2` + // rect rectType + // current rectType // the logical size. Includes all the child widgets + // width int + // height int +} + +// from the gocui devs: +// Write appends a byte slice into the view's internal buffer. Because +// View implements the io.Writer interface, it can be passed as parameter +// of functions like fmt.Fprintf, fmt.Fprintln, io.Copy, etc. Clear must +// be called to clear the view's buffer. + +func (w *cuiWidget) Write(p []byte) (n int, err error) { + w.tainted = true + w.writeMutex.Lock() + defer w.writeMutex.Unlock() + // v.makeWriteable(v.wx, v.wy) + // v.writeRunes(bytes.Runes(p)) + fmt.Fprintln(w.v, p) + log(logNow, "widget.Write()") + + return len(p), nil +} diff --git a/toolkit/democui/view.go b/toolkit/democui/view.go new file mode 100644 index 0000000..8699bf6 --- /dev/null +++ b/toolkit/democui/view.go @@ -0,0 +1,317 @@ +package main + +import ( + "fmt" + "errors" + "strconv" + + "github.com/awesome-gocui/gocui" + "git.wit.org/wit/gui/toolkit" +) + +var adjusted bool = false + +// expands the logical size of the parents +func (w *cuiWidget) setParentLogical(p *cuiWidget) { + if (w.visable) { + // expand the parent logicalsize to include the widget realSize + if (p.logicalSize.w0 > w.realSize.w0) { + p.logicalSize.w0 = w.realSize.w0 + adjusted = true + } + if (p.logicalSize.h0 > w.realSize.h0) { + p.logicalSize.h0 = w.realSize.h0 + adjusted = true + } + if (p.logicalSize.w1 < w.realSize.w1) { + p.logicalSize.w1 = w.realSize.w1 + adjusted = true + } + if (p.logicalSize.h1 < w.realSize.h1) { + p.logicalSize.h1 = w.realSize.h1 + adjusted = true + } + } else { + // expand the parent logicalsize to include the widget logicalsize + if (p.logicalSize.w0 > w.logicalSize.w0) { + p.logicalSize.w0 = w.logicalSize.w0 + adjusted = true + } + if (p.logicalSize.h0 > w.logicalSize.h0) { + p.logicalSize.h0 = w.logicalSize.h0 + adjusted = true + } + if (p.logicalSize.w1 < w.logicalSize.w1) { + p.logicalSize.w1 = w.logicalSize.w1 + adjusted = true + } + if (p.logicalSize.h1 < w.logicalSize.h1) { + p.logicalSize.h1 = w.logicalSize.h1 + adjusted = true + } + } + if (w.visable) { + // adjust the widget realSize to the top left corner of the logicalsize + if (w.logicalSize.w0 > w.realSize.w0) { + w.realSize.w0 = w.logicalSize.w0 + w.realSize.w1 = w.realSize.w0 + w.realWidth + adjusted = true + } + if (w.logicalSize.h0 > w.realSize.h0) { + w.realSize.h0 = w.logicalSize.h0 + w.realSize.h1 = w.realSize.h0 + w.realHeight + adjusted = true + } + } + w.showWidgetPlacement(logNow, "setParentLogical() widget") + p.showWidgetPlacement(logNow, "setParentLogical() parent") + if (w.id == 0) || (p.id == 0) { + // stop resizing when you hit the root widget + return + } + // pass the logical resizing up + pP := me.widgets[p.parentId] + if (pP != nil) { + p.setParentLogical(pP) + } +} + +var fakeStartWidth int = 80 +var fakeStartHeight int = 0 +func (w *cuiWidget) setFake() { + if (w.visable) { + return + } + // setup fake labels for non-visable things off screen + w.realWidth = me.defaultWidth + w.realHeight = me.defaultHeight + w.realSize.w0 = fakeStartWidth + w.realSize.h0 = fakeStartHeight + w.realSize.w1 = w.realSize.w0 + me.defaultWidth + w.realSize.h1 = w.realSize.h0 + me.defaultHeight + fakeStartHeight += 2 + w.showWidgetPlacement(logNow, "setFake()") +} + +func drawView(w *cuiWidget) *gocui.View { + var newName string = "" + newName = strconv.Itoa(w.id) + if (me.baseGui == nil) { + log(logError, "drawView() me.baseGui == nil") + return nil + } + + a := w.realSize.w0 + b := w.realSize.h0 + c := w.realSize.w1 + d := w.realSize.h1 + v, err := me.baseGui.SetView(newName, a, b, c, d, 0) + if err == nil { + log(logError, "drawView() internal plugin error err = nil") + return nil + } + if !errors.Is(err, gocui.ErrUnknownView) { + log(logError, "drawView() internal plugin error error.IS()", err) + return nil + } + w.v = v + + return v +} + +func boxedPlace(w *cuiWidget) { + t := len(w.name) + if (w.id == 0) { + w.realWidth = 0 + w.realHeight = 0 + return + } + p := me.widgets[w.parentId] + if (p == nil) { + log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil") + return + } + + switch p.widgetType { + case toolkit.Box: + w.realWidth = t + 3 + w.realHeight = me.defaultHeight + w.realSize.w0 = p.nextX + w.realSize.h0 = p.nextY + w.realSize.w1 = p.nextX + w.realWidth + w.realSize.h1 = p.nextY + w.realHeight + + w.logicalSize.w0 = p.nextX + w.logicalSize.h0 = p.nextY + w.logicalSize.w1 = p.nextX + w.realWidth + w.logicalSize.h1 = p.nextY + w.realHeight + + w.nextX = p.nextX + w.nextY = p.nextY + if (w.horizontal) { + log(logNow, "PARENT BOX IS HORIZONTAL") + p.nextX += w.realWidth + } else { + log(logNow, "PARENT BOX IS VERTICAL") + p.nextY += w.realHeight + } + case toolkit.Group: + w.realWidth = t + 3 + w.realHeight = me.defaultHeight + + w.realSize.w0 = p.nextX + w.realSize.h0 = p.nextY + w.realSize.w1 = p.nextX + w.realWidth + w.realSize.h1 = p.nextY + w.realHeight + + w.logicalSize.w0 = p.nextX + w.logicalSize.h0 = p.nextY + w.logicalSize.w1 = p.nextX + w.realWidth + w.logicalSize.h1 = p.nextY + w.realHeight + + w.nextX = w.logicalSize.w0 + 3 // default group padding + w.nextY = w.logicalSize.h1 + + // increment parent + p.nextY += w.realHeight + default: + w.realWidth = t + 3 + w.realHeight = me.defaultHeight + w.realSize.w0 = p.nextX + w.realSize.h0 = p.nextY + w.realSize.w1 = w.realSize.w0 + w.realWidth + w.realSize.h1 = w.realSize.h0 + w.realHeight + + // increment parent + p.nextY += w.realHeight + } + p.showWidgetPlacement(logNow, "bP parent") + w.showWidgetPlacement(logNow, "bP widget") +} + +func findPlace(w *cuiWidget, a *toolkit.Action) { + t := len(w.name) + w.visable = true + switch w.widgetType { + case toolkit.Root: + w.visable = false + w.setFake() + w.showWidgetPlacement(logNow, "Root:") + case toolkit.Flag: + w.visable = false + w.setFake() + w.showWidgetPlacement(logNow, "Flag:") + case toolkit.Window: + w.realWidth = t + 3 + w.realHeight = me.defaultHeight + + w.realSize.w0 = me.nextW + w.realSize.h0 = 0 + w.realSize.w1 = w.realSize.w0 + w.realWidth + w.realSize.h1 = w.realHeight + + w.logicalSize.w0 = me.nextW + w.logicalSize.h0 = 0 + w.logicalSize.w1 = w.logicalSize.w0 + w.realWidth + w.logicalSize.h1 = w.realHeight + + w.nextX = w.logicalSize.w0 + t // default group padding + w.nextY = w.logicalSize.h1 + + me.nextW += w.realWidth + w.showWidgetPlacement(logNow, "window:") + case toolkit.Tab: + w.realWidth = t + 3 + w.realHeight = me.defaultHeight + + w.realSize.w0 = me.nextW + w.realSize.h0 = 0 + w.realSize.w1 = w.realSize.w0 + w.realWidth + w.realSize.h1 = w.realHeight + + w.logicalSize.w0 = me.nextW + w.logicalSize.h0 = 0 + w.logicalSize.w1 = w.logicalSize.w0 + w.realWidth + w.logicalSize.h1 = w.realHeight + + w.nextX = w.logicalSize.w0 + t // default group padding + w.nextY = w.logicalSize.h1 + me.nextW += w.realWidth + w.showWidgetPlacement(logNow, "tab:") + case toolkit.Grid: + p := me.widgets[w.parentId] + w.horizontal = a.B + w.visable = false + w.setFake() + + if (p == nil) { + log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil") + return + } + w.logicalSize.w0 = p.nextX + w.logicalSize.h0 = p.nextY + w.logicalSize.w1 = p.nextX + w.logicalSize.h1 = p.nextY + + w.nextX = p.nextX + w.nextY = p.nextY + w.showWidgetPlacement(logNow, "grid:") + case toolkit.Box: + p := me.widgets[w.parentId] + w.horizontal = a.B + w.visable = false + w.setFake() + + if (p == nil) { + log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil") + return + } + w.logicalSize.w0 = p.nextX + w.logicalSize.h0 = p.nextY + w.logicalSize.w1 = p.nextX + w.logicalSize.h1 = p.nextY + + w.nextX = p.nextX + w.nextY = p.nextY + w.showWidgetPlacement(logNow, "box:") + case toolkit.Group: + p := me.widgets[w.parentId] + w.horizontal = a.B + w.visable = false + w.setFake() + + if (p == nil) { + log(logError, "ERRRRRRRRRRRORRRRRRRRRRRRR: parentId widget == nil") + return + } + w.logicalSize.w0 = p.nextX + w.logicalSize.h0 = p.nextY + w.logicalSize.w1 = p.nextX + w.logicalSize.h1 = p.nextY + + w.nextX = p.nextX + w.nextY = p.nextY + w.showWidgetPlacement(logNow, "group:") + default: + boxedPlace(w) + } +} + +func place(w *cuiWidget, a *toolkit.Action) { + log(logInfo, "place() START") + findPlace(w, a) + v := drawView(w) + if (v == nil) { + log(logError, "place() drawView(w) returned nil") + return + } + me.baseGui.SetKeybinding(v.Name(), gocui.MouseLeft, gocui.ModNone, click) + + v.Wrap = true + fmt.Fprintln(v, " " + w.name) + + w.SetDefaultWidgetColor() + + log(logInfo, "place() END") + return +} diff --git a/toolkit/gocui/debug.go b/toolkit/gocui/debug.go index 1e424f7..b38fd83 100644 --- a/toolkit/gocui/debug.go +++ b/toolkit/gocui/debug.go @@ -88,6 +88,7 @@ func widgetDump(b bool, w *toolkit.Widget) { return } + /* log(b, "widget.Name =", w.Name) // log(b, "widget.Action =", w.Action) log(b, "widget.Type =", w.Type) @@ -98,6 +99,7 @@ func widgetDump(b bool, w *toolkit.Widget) { log(b, "widget.Height =", w.Height) log(b, "widget.X =", w.X) log(b, "widget.Y =", w.Y) + */ } /* diff --git a/toolkit/gocui/log.go b/toolkit/gocui/log.go index afd1280..527d057 100644 --- a/toolkit/gocui/log.go +++ b/toolkit/gocui/log.go @@ -1,135 +1,22 @@ -// -// 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" + witlog "git.wit.org/wit/gui/log" ) -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...) + witlog.Log(a...) } -func logindent(depth int, format string, a ...interface{}) { - var tabs string - for i := 0; i < depth; i++ { - tabs = tabs + format - } +func sleep(a ...any) { + witlog.Sleep(a...) +} - // newFormat := tabs + strconv.Itoa(depth) + " " + format - newFormat := tabs + format - log(debugToolkit, newFormat, a) +func exit(a ...any) { + witlog.Exit(a...) } func setOutput(f *os.File) { - golog.SetOutput(f) + witlog.SetOutput(f) } diff --git a/toolkit/widget.go b/toolkit/widget.go index 450cd8b..0a1dda3 100644 --- a/toolkit/widget.go +++ b/toolkit/widget.go @@ -7,6 +7,8 @@ type ActionType int // // All Toolkit interactions should be done via a channel or Queue() // TODO: FIGURE OUT HOW TO IMPLEMENT THIS +// https://ieftimov.com/post/golang-datastructures-trees/ +// TODO: protobuf ? // // This is the only thing that is passed between the toolkit plugin // @@ -18,7 +20,6 @@ type ActionType int // Could a protobuf be used here? (Can functions be passed?) type Widget struct { Name string - // Action string // "New", "Delete", "Set", aka something to do Type WidgetType // This function is how you interact with the toolkit @@ -29,7 +30,7 @@ type Widget struct { Callback func() // re-adding an id to test channels - id int + Id int // This is how the values are passed back and forth // values from things like checkboxes & dropdown's @@ -39,32 +40,22 @@ type Widget struct { // 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 - // We are not laying out PDF's here - // This is used for things like a slider(0,100) - Width int - Height int - X int - Y int - - // Put space around elements to improve look & feel - Margin bool - - // Make widgets fill up the space available - Expand bool } type Action struct { - Type ActionType + ActionType ActionType + WidgetType WidgetType + + WidgetId int + ParentId int + + Text string // what is visable to the user + Name string // a name useful for programming // this should be the widget // if the action is New, Hide, Enable, etc Widget *Widget - - // this is the widget - // where the other one should be put on New, Move, etc - Where *Widget + Callback func(int) // This is how the values are passed back and forth // values from things like checkboxes & dropdown's @@ -90,31 +81,30 @@ type Action struct { Expand bool } - -// https://ieftimov.com/post/golang-datastructures-trees/ -// TODO: protobuf ? const ( Unknown WidgetType = iota - Window - Tab // internally, this should be a window (?) - Frame // should windows and tab's be frames (?) - Grid // a grid of frames ? - Group // internally, this should be a grid (?) - Box // internally, this should be a grid (?) + Root // the master 'root' node of the binary tree + Flag // used to send configuration values to plugins + Window // in certain gui's (ncurses), these are tabs + Tab // internally, this is a window + Frame // deprecate? + Grid // like drawers in a chest + Group // like the 'Appetizers' section on a menu + Box // a vertical or horizontal stack of widgets Button - Checkbox + Checkbox // select 'on' or 'off' Dropdown - Combobox // dropdown with edit=true (?) + Combobox // dropdown with edit=true Label - Textbox // is this a Label with edit=true? - Slider - Spinner - Image - Area - Form - Font - Color - Dialog + Textbox // is this a Label with edit=true + Slider // like a progress bar + Spinner // like setting the oven temperature + Image // TODO + Area // TODO + Form // TODO + Font // TODO + Color // TODO + Dialog // TODO ) const ( @@ -122,7 +112,6 @@ const ( Delete Get Set - SetFlag GetText SetText AddText @@ -137,11 +126,14 @@ const ( Append Move Dump - Flag ) func (s WidgetType) String() string { switch s { + case Root: + return "Root" + case Flag: + return "Flag" case Window: return "Window" case Tab: @@ -185,7 +177,7 @@ func (s WidgetType) String() string { case Unknown: return "Unknown" } - return "Widget.Type.String() Error" + return "WidgetType.String() Error" } func (s ActionType) String() string { @@ -198,8 +190,6 @@ func (s ActionType) String() string { return "Get" case Set: return "Set" - case SetFlag: - return "SetFlag" case GetText: return "GetText" case SetText: @@ -226,22 +216,8 @@ func (s ActionType) String() string { return "Append" case Move: return "Move" - case Flag: - return "Flag" case Dump: return "Dump" } - return "Action.Type.String() Error" -} - -// 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 + return "ActionType.String() Error" } diff --git a/window.go b/window.go index 6be91a3..8ca2475 100644 --- a/window.go +++ b/window.go @@ -34,16 +34,15 @@ func NewWindow() *Node { } } // Windows are created off of the master node of the Binary Tree - newNode = Config.master.New(Config.Title, toolkit.Window, custom) + newNode = Config.rootNode.New(Config.Title, toolkit.Window, custom) - newNode.widget.Width = Config.Width - newNode.widget.Height = Config.Height - - log(debugGui, "Window()", Config.Title) + log(logInfo, "NewWindow()", Config.Title) var a toolkit.Action - a.Type = toolkit.Add - newaction(&a, newNode, Config.master) + a.ActionType = toolkit.Add + a.Width = Config.Width + a.Height = Config.Height + newaction(&a, newNode, Config.rootNode) return newNode }