summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2021-10-31 14:21:36 -0500
committerJeff Carr <[email protected]>2021-10-31 14:21:36 -0500
commit213c7d153b06d3e1211d1cdeae1e4f7833cb89f7 (patch)
tree53b489c9df4ea1784be0d626df1497b04183c9be
parent36e2c6d2e3c266f32325985e98c3776755fdd511 (diff)
REFACTOR: refactor everything to gui.Node structv0.2
Signed-off-by: Jeff Carr <[email protected]>
-rw-r--r--.gitignore3
-rw-r--r--area.go10
-rw-r--r--box.go110
-rw-r--r--button.go56
-rw-r--r--cmds/gui-demo/Makefile5
-rw-r--r--cmds/gui-demo/demo-window.go33
-rw-r--r--cmds/gui-demo/main.go68
-rw-r--r--cmds/gui-example/Makefile (renamed from gui-example/Makefile)0
-rw-r--r--cmds/gui-example/demo-window.go105
-rw-r--r--cmds/gui-example/main.go68
-rw-r--r--cmds/gui-example/os.go99
-rw-r--r--debug-window.go (renamed from window-debug.go)193
-rw-r--r--debug.go66
-rw-r--r--demo-window-andlabs-ui.go (renamed from window-template.go)14
-rw-r--r--demo-window.go28
-rw-r--r--doc.go72
-rw-r--r--entry.go40
-rw-r--r--example_test.go45
-rw-r--r--find.go156
-rw-r--r--gui-example/main.go43
-rw-r--r--gui.go8
-rw-r--r--main.go28
-rw-r--r--new-structs.go249
-rw-r--r--structs.go159
-rw-r--r--table.go12
-rw-r--r--tableCallbacks.go3
-rw-r--r--window.go250
27 files changed, 1531 insertions, 392 deletions
diff --git a/.gitignore b/.gitignore
index bb1e72d..1445c95 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
*.swp
-gui-example/gui-example
+cmds/gui-example/gui-example
+cmds/gui-demo/gui-demo
diff --git a/area.go b/area.go
index 0cc7531..7c42c6c 100644
--- a/area.go
+++ b/area.go
@@ -107,10 +107,10 @@ func (ah GuiArea) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) {
return false
}
-func ShowTextBox(box *GuiBox, newText *ui.AttributedString, custom func(*GuiButton), name string) {
+func (b *GuiBox) ShowTextBox(newText *ui.AttributedString, custom func(*GuiButton), name string) {
log.Println("ShowTextBox() START")
- gw := box.Window
+ gw := b.Window
if (gw == nil) {
log.Println("ShowTextBox() ERROR gw = nil")
return
@@ -127,10 +127,10 @@ func ShowTextBox(box *GuiBox, newText *ui.AttributedString, custom func(*GuiButt
*/
// TODO: allow padded & axis here
- box.UiBox.SetPadded(true)
+ b.UiBox.SetPadded(true)
// add(gw.BoxMap["MAINBOX"], newbox)
- makeGenericArea(box, newText, custom)
- box.UiBox.Append(box.Window.Area.UiArea, true)
+ makeGenericArea(b, newText, custom)
+ b.UiBox.Append(b.Window.Area.UiArea, true)
}
diff --git a/box.go b/box.go
index 2640742..7a61f55 100644
--- a/box.go
+++ b/box.go
@@ -1,6 +1,7 @@
package gui
import "log"
+import "os"
// import "reflect"
import "github.com/andlabs/ui"
@@ -34,6 +35,7 @@ func add(box *GuiBox, newbox *GuiBox) {
newbox.Window.BoxMap["MAINBOX"] = newbox
log.Println("gui.add() END")
+ panic("gui.add() MAINBOX gui.add() END")
return
} else {
log.Println("\tgui.add() ERROR DONT KNOW HOW TO ADD TO A RAW WINDOW YET")
@@ -41,33 +43,77 @@ func add(box *GuiBox, newbox *GuiBox) {
}
log.Println("\tgui.add() ERROR DON'T KNOW HOW TO add to Window as MAINBOX DONE")
log.Println("gui.add() END")
+ panic("gui.add() gui.add() END")
return
}
log.Println("\tgui.add() adding", newbox.Name, "to", box.Name)
// copy the box settings over
newbox.Window = box.Window
- if (box.UiBox == nil) {
- log.Println("\tgui.add() ERROR box.UiBox == nil")
- panic("crap")
+ if (box.node == nil) {
+ box.Dump()
+ panic("gui.add() ERROR box.node == nil")
}
+
if (newbox.UiBox == nil) {
- log.Println("\tgui.add() ERROR newbox.UiBox == nil")
- panic("crap")
+ panic("gui.add() ERROR newbox.UiBox == nil")
+ }
+
+ if (box.UiBox == nil) {
+ box.Dump()
+ // panic("gui.add() ERROR box.UiBox == nil")
+ return
+ // TODO: fix this whole add() function // Oct 9
}
- // log.Println("\tgui.add() newbox.UiBox == ", newbox.UiBox.GetParent())
- // spew.Dump(newbox.UiBox)
box.UiBox.Append(newbox.UiBox, false)
+ box.Dump()
+ panic("gui.add()")
// add the newbox to the Window.BoxMap[]
box.Window.BoxMap[newbox.Name] = newbox
log.Println("gui.add() END")
}
-func NewBox(box *GuiBox, axis int, name string) *GuiBox {
- log.Println("VerticalBox START")
+func (n *Node) AddBox(axis int, name string) *Node {
+ newBox := new(GuiBox)
+ newBox.Window = n.window
+ newBox.Name = name
+
+ if (n.box == nil) {
+ n.box = newBox
+ }
+
+ // make a new box & a new node
+ newNode := n.makeNode(name, 111, 100 + Config.counter)
+ newNode.box = newBox
+ Config.counter += 1
+
+ var uiBox *ui.Box
+ if (axis == Xaxis) {
+ uiBox = ui.NewHorizontalBox()
+ } else {
+ uiBox = ui.NewVerticalBox()
+ }
+ uiBox.SetPadded(true)
+ newBox.UiBox = uiBox
+ newNode.uiBox = uiBox
+
+ n.Append(newNode)
+ // add(n.box, newBox)
+ return newNode
+}
+
+func (b *GuiBox) NewBox(axis int, name string) *GuiBox {
+ log.Println("gui.NewBox() START")
+ n := b.FindNode()
+ if (n == nil) {
+ log.Println("gui.NewBox() SERIOUS ERROR. CAN NOT FIND NODE")
+ os.Exit(0)
+ } else {
+ log.Println("gui.NewBox() node =", n.Name)
+ }
var newbox *GuiBox
newbox = new(GuiBox)
- newbox.Window = box.Window
+ newbox.Window = b.Window
newbox.Name = name
var uiBox *ui.Box
@@ -78,13 +124,18 @@ func NewBox(box *GuiBox, axis int, name string) *GuiBox {
}
uiBox.SetPadded(true)
newbox.UiBox = uiBox
- add(box, newbox)
+ add(b, newbox)
+ // panic("gui.NewBox")
return newbox
}
func HardBox(gw *GuiWindow, axis int, name string) *GuiBox {
log.Println("HardBox() START axis =", axis)
+ if (gw.node == nil) {
+ gw.Dump()
+ panic("gui.HardBox() gw.node == nil")
+ }
// add a Vertical Seperator if there is already a box
// Is this right?
box := gw.BoxMap["MAINBOX"]
@@ -134,3 +185,40 @@ func VerticalBreak(box *GuiBox) {
tmp := ui.NewVerticalSeparator()
box.UiBox.Append(tmp, false)
}
+
+func (n *Node) AddComboBox(title string, s ...string) *Node {
+ box := n.uiBox
+ if (box == nil) {
+ return n
+ }
+
+ ecbox := ui.NewEditableCombobox()
+
+ for id, name := range s {
+ log.Println("Adding Combobox Entry:", id, name)
+ ecbox.Append(name)
+ }
+
+ ecbox.OnChanged(func(*ui.EditableCombobox) {
+ test := ecbox.Text()
+ log.Println("node.Name = '" + n.Name + "' text for '" + title + "' is now: '" + test + "'")
+ })
+
+ box.Append(ecbox, false)
+
+ newNode := n.AddNode(title)
+ newNode.uiText = ecbox
+ return newNode
+}
+
+func (n *Node) OnChanged(f func()) {
+ f()
+}
+
+func (n *Node) GetText() string {
+ if (n.uiText == nil) {
+ return ""
+ }
+ ecbox := n.uiText
+ return ecbox.Text()
+}
diff --git a/button.go b/button.go
index 825b79b..8ad0a3b 100644
--- a/button.go
+++ b/button.go
@@ -1,10 +1,12 @@
package gui
import "log"
+import "reflect"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew"
+
// This is the default mouse click handler
// Every mouse click that hasn't been assigned to
// something specific will fall into this routine
@@ -50,6 +52,60 @@ func guiButtonClick(button *GuiButton) {
}
}
+func (n *Node) AddButton(name string, custom func(*Node)) *Node {
+ if (n.uiBox == nil) {
+ log.Println("gui.Node.AppendButton() filed node.UiBox == nil")
+ return n
+ }
+ button := ui.NewButton(name)
+ log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox))
+ log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button))
+ n.uiBox.Append(button, false)
+ n.uiButton = button
+
+ newNode := n.makeNode(name, 888, 888 + Config.counter)
+ newNode.uiButton = button
+ newNode.custom = custom
+
+ button.OnClicked(func(*ui.Button) {
+ log.Println("gui.AppendButton() Button Clicked. Running custom()")
+ custom(newNode)
+ })
+ // panic("AppendButton")
+ // time.Sleep(3 * time.Second)
+ return newNode
+}
+
+func (n *Node) CreateButton(custom func(*GuiButton), name string, values interface {}) *Node {
+ newNode := n.AddBox(Xaxis, "test CreateButton")
+ box := newNode.FindBox()
+ if (box == nil) {
+ panic("node.CreateButton().FindBox() == nil")
+ }
+ newUiB := ui.NewButton(name)
+ newUiB.OnClicked(defaultButtonClick)
+
+ var newB *GuiButton
+ newB = new(GuiButton)
+ newB.B = newUiB
+ if (box.UiBox == nil) {
+ log.Println("CreateButton() box.Window == nil")
+ // ErrorWindow(box.Window, "Login Failed", msg) // can't even do this
+ panic("maybe print an error and return nil? or make a fake button?")
+ } else {
+ // uibox := box.UiBox
+ // uibox.Append(newUiB, true)
+ }
+ newB.Box = box
+ newB.Custom = custom
+ newB.Values = values
+
+ Data.AllButtons = append(Data.AllButtons, newB)
+
+ box.Append(newB.B, false)
+ return newNode
+}
+
func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton {
newUiB := ui.NewButton(name)
newUiB.OnClicked(defaultButtonClick)
diff --git a/cmds/gui-demo/Makefile b/cmds/gui-demo/Makefile
new file mode 100644
index 0000000..2dbc808
--- /dev/null
+++ b/cmds/gui-demo/Makefile
@@ -0,0 +1,5 @@
+run: build
+ ./gui-demo
+
+build:
+ GO111MODULE="off" go build
diff --git a/cmds/gui-demo/demo-window.go b/cmds/gui-demo/demo-window.go
new file mode 100644
index 0000000..fd8e8f4
--- /dev/null
+++ b/cmds/gui-demo/demo-window.go
@@ -0,0 +1,33 @@
+package main
+
+import "log"
+
+import "git.wit.org/wit/gui"
+
+func demoClick (n *gui.Node) {
+ log.Println("demoClick() Dumping node:")
+ n.Dump()
+}
+
+func addDemoTab(n *gui.Node, title string) {
+ newNode := n.AddTab(title, nil)
+ if (gui.Config.Debug) {
+ newNode.Dump()
+ }
+ newNode.ListChildren(false)
+
+ groupNode1 := newNode.AddGroup("group 1")
+ groupNode1.AddComboBox("demoCombo1", "foo", "bar", "stuff")
+ groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff")
+
+ groupNode1.Dump()
+
+ butNode1 := groupNode1.AddButton("button1", demoClick)
+ butNode1.Dump()
+
+ butNode2 := groupNode1.AddButton("button2", demoClick)
+ butNode2.Dump()
+
+ groupNode2 := newNode.AddGroup("group 2")
+ groupNode2.AddComboBox("demoCombo2", "more 1", "more 2", "more 3")
+}
diff --git a/cmds/gui-demo/main.go b/cmds/gui-demo/main.go
new file mode 100644
index 0000000..8eae878
--- /dev/null
+++ b/cmds/gui-demo/main.go
@@ -0,0 +1,68 @@
+package main
+
+import (
+ "log"
+ "os"
+ "time"
+
+ "git.wit.org/wit/gui"
+)
+
+// This initializes the first window
+//
+// Then starts a goroutine to demonstrate how to
+// inject things into the GUI
+func main() {
+ log.Println("Starting my Control Panel")
+
+ go gui.Main(initGUI)
+
+ watchGUI()
+}
+
+// This initializes the first window
+func initGUI() {
+ gui.Config.Title = "WIT GUI Window Demo 1"
+ gui.Config.Width = 640
+ gui.Config.Height = 480
+ gui.Config.Exit = myExit
+ node1 := gui.NewWindow()
+ addDemoTab(node1, "A Simple Tab Demo")
+
+ gui.Config.Title = "WIT GUI Window Demo 2"
+ gui.Config.Width = 640
+ gui.Config.Height = 240
+ gui.Config.Exit = myExit
+ node2 := gui.NewWindow()
+ node2.DemoAndlabsUiTab("A Simple andlabs/ui Tab Demo")
+}
+
+// This demonstrates how to properly interact with the GUI
+// You can not involke the GUI from external goroutines in most cases.
+func watchGUI() {
+ var i = 1
+ for {
+ log.Println("Waiting", i, "seconds")
+ i += 1
+ time.Sleep(1 * time.Second)
+ if i == 4 {
+ log.Println("Opening a Debug Window via the gui.Queue()")
+ gui.Config.Width = 800
+ gui.Config.Height = 300
+ gui.Config.Exit = myDebugExit
+ gui.Queue(gui.DebugWindow)
+ }
+ }
+}
+
+func myExit(n *gui.Node) {
+ log.Println()
+ log.Println("Entered myExit() on node.Name =", n.Name)
+ log.Println()
+ os.Exit(0)
+}
+
+func myDebugExit(n *gui.Node) {
+ log.Println("Entered myDebugExit() on node.Name =", n.Name)
+ log.Println("Don't actually os.Exit()")
+}
diff --git a/gui-example/Makefile b/cmds/gui-example/Makefile
index 5028ebd..5028ebd 100644
--- a/gui-example/Makefile
+++ b/cmds/gui-example/Makefile
diff --git a/cmds/gui-example/demo-window.go b/cmds/gui-example/demo-window.go
new file mode 100644
index 0000000..993900d
--- /dev/null
+++ b/cmds/gui-example/demo-window.go
@@ -0,0 +1,105 @@
+package main
+
+import "log"
+import "reflect"
+
+import "git.wit.org/wit/gui"
+
+import "github.com/davecgh/go-spew/spew"
+
+func demoClick (n *gui.Node) {
+ log.Println("demoClick() Dumping node:")
+ n.Dump()
+}
+
+var username = "jcarr"
+var hostname = "fire"
+
+func newClick (n *gui.Node) {
+ var tmp []string
+ junk := "ssh -v " + username + "@" + hostname
+ log.Println("junk = " , junk)
+ xterm(junk)
+ log.Println("tmp = " , reflect.ValueOf(tmp).Kind())
+ // spew.Dump(tmp)
+}
+
+func addDemoTab(n *gui.Node, title string) {
+ newNode := n.AddTab(title, nil)
+ if (gui.Config.Debug) {
+ newNode.Dump()
+ }
+ newNode.ListChildren(false)
+
+ groupNode1 := newNode.AddGroup("group 1")
+ cbNode := groupNode1.AddComboBox("username", "root", "jcarr", "hugo")
+ cbNode.OnChanged(func () {
+ username = cbNode.GetText()
+ })
+ groupNode1.AddComboBox("demoCombo3", "foo 3", "bar", "stuff")
+
+ groupNode1.Dump()
+
+ butNode1 := groupNode1.AddButton("button1", demoClick)
+ butNode1.Dump()
+
+ butNode2 := groupNode1.AddButton("button2", newClick)
+ butNode2.Dump()
+
+ groupNode2 := newNode.AddGroup("group 2")
+ groupNode2.AddComboBox("demoCombo2", "more 1", "more 2", "more 3")
+
+ gNode := newNode.AddGroup("domU")
+ makeSSHbutton(gNode, "hugo@www", "www.wit.org")
+ makeSSHbutton(gNode, "check.lab", "check.lab.wit.org")
+ makeSSHbutton(gNode, "gobuild.lab", "gobuild.lab.wit.org")
+ makeSSHbutton(gNode, "gobuild2.lab", "gobuild2.lab.wit.org")
+
+/////////////////////////////// Column DNS ////////////////////////////////
+ gNode = newNode.AddGroup("dns")
+ makeSSHbutton(gNode, "bind.wit.org", "bind.wit.org")
+ makeSSHbutton(gNode, "ns1.wit.com", "ns1.wit.com")
+ makeSSHbutton(gNode, "ns2.wit.com", "ns2.wit.com")
+ makeSSHbutton(gNode, "coredns", "coredns.lab.wit.org")
+
+/////////////////////////////// PHYS 530 //////////////////////////////////
+ gNode = newNode.AddGroup("phys 530")
+ // makeXtermButton(gNode, "openwrt", "SUBDOMAIN", "ssh -4 -v root@openwrt")
+ gNode.AddButton("openwrt", func (*gui.Node) {
+ stuff := "ssh -4 -v root@openwrt"
+ xterm(stuff)
+ })
+ makeSSHbutton (gNode, "mirrors", "mirrors.wit.org")
+ makeSSHbutton (gNode, "node004", "node004.lab.wit.org")
+ makeSSHbutton (gNode, "lenovo-z70", "lenovo-z70.lab.wit.org")
+
+/////////////////////////////// PHYS 522 //////////////////////////////////
+ gNode = newNode.AddGroup("phys 522")
+ // makeXtermButton(gNode, "openwrt2", "SUBDOMAIN", "ssh -4 -v root@openwrt2")
+ gNode.AddButton("openwrt2", func (*gui.Node) {
+ stuff := "ssh -4 -v root@openwrt2"
+ xterm(stuff)
+ })
+ makeSSHbutton (gNode, "fire.lab", "fire.lab.wit.org")
+ makeSSHbutton (gNode, "predator", "predator.lab.wit.org")
+
+/////////////////////////////// FLOAT /////////////////////////////////////
+ gNode = newNode.AddGroup("float")
+ makeSSHbutton(gNode, "root@asus-n501vw", "asus-n501vw.lab.wit.org")
+}
+
+func makeSSHbutton (n *gui.Node, name string, hostname string) {
+ bNode := n.AddButton(name, func (*gui.Node) {
+ var tmp []string
+ if (username == "") {
+ username = "root"
+ }
+ junk := "ssh -v " + username + "@" + hostname
+ log.Println("junk = " , junk)
+ log.Println("username = '" + username + "'")
+ xterm(junk)
+ log.Println("tmp = " , reflect.ValueOf(tmp).Kind())
+ spew.Dump(tmp)
+ })
+ bNode.Dump()
+}
diff --git a/cmds/gui-example/main.go b/cmds/gui-example/main.go
new file mode 100644
index 0000000..8eae878
--- /dev/null
+++ b/cmds/gui-example/main.go
@@ -0,0 +1,68 @@
+package main
+
+import (
+ "log"
+ "os"
+ "time"
+
+ "git.wit.org/wit/gui"
+)
+
+// This initializes the first window
+//
+// Then starts a goroutine to demonstrate how to
+// inject things into the GUI
+func main() {
+ log.Println("Starting my Control Panel")
+
+ go gui.Main(initGUI)
+
+ watchGUI()
+}
+
+// This initializes the first window
+func initGUI() {
+ gui.Config.Title = "WIT GUI Window Demo 1"
+ gui.Config.Width = 640
+ gui.Config.Height = 480
+ gui.Config.Exit = myExit
+ node1 := gui.NewWindow()
+ addDemoTab(node1, "A Simple Tab Demo")
+
+ gui.Config.Title = "WIT GUI Window Demo 2"
+ gui.Config.Width = 640
+ gui.Config.Height = 240
+ gui.Config.Exit = myExit
+ node2 := gui.NewWindow()
+ node2.DemoAndlabsUiTab("A Simple andlabs/ui Tab Demo")
+}
+
+// This demonstrates how to properly interact with the GUI
+// You can not involke the GUI from external goroutines in most cases.
+func watchGUI() {
+ var i = 1
+ for {
+ log.Println("Waiting", i, "seconds")
+ i += 1
+ time.Sleep(1 * time.Second)
+ if i == 4 {
+ log.Println("Opening a Debug Window via the gui.Queue()")
+ gui.Config.Width = 800
+ gui.Config.Height = 300
+ gui.Config.Exit = myDebugExit
+ gui.Queue(gui.DebugWindow)
+ }
+ }
+}
+
+func myExit(n *gui.Node) {
+ log.Println()
+ log.Println("Entered myExit() on node.Name =", n.Name)
+ log.Println()
+ os.Exit(0)
+}
+
+func myDebugExit(n *gui.Node) {
+ log.Println("Entered myDebugExit() on node.Name =", n.Name)
+ log.Println("Don't actually os.Exit()")
+}
diff --git a/cmds/gui-example/os.go b/cmds/gui-example/os.go
new file mode 100644
index 0000000..ce5db8d
--- /dev/null
+++ b/cmds/gui-example/os.go
@@ -0,0 +1,99 @@
+package main
+
+import "log"
+import "strings"
+import "os"
+import "os/exec"
+import "io/ioutil"
+import "errors"
+// import "bufio"
+
+// import "github.com/davecgh/go-spew/spew"
+
+/*
+import "time"
+import "runtime"
+import "runtime/debug"
+import "runtime/pprof"
+
+import "git.wit.org/wit/gui"
+import "git.wit.org/wit/shell"
+import "github.com/gobuffalo/packr"
+*/
+
+func runSimpleCommand(s string) {
+ cmd := strings.TrimSpace(s) // this is like 'chomp' in perl
+ cmd = strings.TrimSuffix(cmd, "\n") // this is like 'chomp' in perl
+ cmdArgs := strings.Fields(cmd)
+ runLinuxCommand(cmdArgs)
+}
+
+var geom string = "120x30+500+500"
+
+func xterm(cmd string) {
+ var tmp []string
+ var argsXterm = []string{"nohup", "xterm", "-geometry", geom}
+ tmp = append(argsXterm, "-hold", "-e", cmd)
+ log.Println("xterm cmd=", cmd)
+ go runCommand(tmp)
+}
+
+func runCommand(cmdArgs []string) {
+ log.Println("runCommand() START", cmdArgs)
+ process := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
+ // process := exec.Command("xterm", "-e", "ping localhost")
+ log.Println("runCommand() process.Start()")
+ process.Start()
+ log.Println("runCommand() process.Wait()")
+ err := process.Wait()
+ lookupError(err)
+ log.Println("runCommand() NEED TO CHECK THE TIME HERE TO SEE IF THIS WORKED")
+ log.Println("runCommand() OTHERWISE INFORM THE USER")
+ log.Println("runCommand() END", cmdArgs)
+}
+
+func lookupError(err error) {
+ var (
+ ee *exec.ExitError
+ pe *os.PathError
+ )
+
+ if errors.As(err, &ee) {
+ log.Println("ran, but non-zero exit code =", ee.ExitCode()) // ran, but non-zero exit code
+ } else if errors.As(err, &pe) {
+ log.Printf("os.PathError = %v", pe) // "no such file ...", "permission denied" etc.
+ } else if err != nil {
+ log.Printf("something really bad happened general err = %v", err) // something really bad happened!
+ if exitError, ok := err.(*exec.ExitError); ok {
+ log.Printf("exitError.ExitCode() is %d\n", exitError.ExitCode())
+ }
+ } else {
+ log.Println("success! // ran without error (exit code zero)")
+ }
+}
+
+func runLinuxCommand(cmdArgs []string) (string, error) {
+ process := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
+
+ process.Stdin = os.Stdin
+ process.Stderr = os.Stderr
+
+ stdOut, err := process.StdoutPipe()
+ if err != nil {
+ return "", err
+ }
+
+ if err := process.Start(); err != nil {
+ return "", err
+ }
+
+ bytes, err := ioutil.ReadAll(stdOut)
+ if err != nil {
+ return "", err
+ }
+ err = process.Wait()
+ lookupError(err)
+
+ log.Println(string(bytes))
+ return string(bytes), err
+}
diff --git a/window-debug.go b/debug-window.go
index 704ef7b..19f276d 100644
--- a/window-debug.go
+++ b/debug-window.go
@@ -2,6 +2,8 @@ package gui
import (
"log"
+ // "fmt"
+ "strconv"
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
@@ -9,22 +11,36 @@ import (
)
var names = make([]string, 100)
+var nodeNames = make([]string, 100)
-func makeWindowDebug() ui.Control {
+func DebugWindow() {
+ Config.Title = "DebugWindow()"
+ node := NewWindow()
+ node.DebugTab("WIT GUI Debug Tab")
+}
+
+// TODO: remove this crap
+// What does this actually do?
+// It populates the nodeNames in a map. No, not a map, an array.
+// What is the difference again? (other than one being in order and a predefined length)
+func addNodeName(c *ui.Combobox, s string, id string) {
+ c.Append(s)
+ nodeNames[y] = id
+ y = y + 1
+}
+
+func makeWindowDebug() *ui.Box {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
/////////////////////////////////////////////////////
- vbox := addGroup(hbox, "Numbers")
- pbar := ui.NewProgressBar()
- vbox.Append(pbar, false)
-
- /////////////////////////////////////////////////////
- vbox = addGroup(hbox, "Window")
+ vbox := addGroup(hbox, "range Data.WindowMap")
cbox := ui.NewCombobox()
for name, _ := range Data.WindowMap {
- log.Println("range Data.WindowMap() name =", name)
+ if (Config.Debug) {
+ log.Println("range Data.WindowMap() name =", name)
+ }
addName(cbox, name)
}
cbox.SetSelected(0)
@@ -122,6 +138,11 @@ func makeWindowDebug() ui.Control {
/////////////////////////////////////////////////////
vbox = addGroup(hbox, "Global Debug")
+ dump3 := addButton(vbox, "Dump Windows")
+ dump3.OnClicked(func(*ui.Button) {
+ DumpWindows()
+ })
+
dump2 := addButton(vbox, "Dump Boxes")
dump2.OnClicked(func(*ui.Button) {
DumpBoxes()
@@ -132,11 +153,112 @@ func makeWindowDebug() ui.Control {
DumpMap()
})
+ /////////////////////////////////////////////////////
+ nodeBox := addGroup(hbox, "Windows:")
+ nodeCombo := ui.NewCombobox()
+
+ for name, node := range Data.NodeMap {
+ if (Config.Debug) {
+ log.Println("range Data.NodeMap() name =", name)
+ }
+ tmp := node.id + " (" + name + ")"
+ addNodeName(nodeCombo, tmp, node.id)
+ }
+ nodeCombo.SetSelected(0)
+
+ nodeBox.Append(nodeCombo, false)
+
+ nodeCombo.OnSelected(func(*ui.Combobox) {
+ y := nodeCombo.Selected()
+ log.Println("y =", y)
+ log.Println("nodeNames[y] =", nodeNames[y])
+ node := Data.findId(nodeNames[y])
+ if (node != nil) {
+ node.Dump()
+ }
+ })
+
+ /////////////////////////////////////////////////////
+ vbox = addGroup(hbox, "Node Debug")
+
+ n1 := addButton(vbox, "Data.DumpNodeMap()")
+ n1.OnClicked(func(*ui.Button) {
+ Data.DumpNodeMap()
+ })
+
+ n1 = addButton(vbox, "Data.ListChildren(false)")
+ n1.OnClicked(func(*ui.Button) {
+ Data.ListChildren(false)
+ })
+
+ n1 = addButton(vbox, "Data.ListChildren(true)")
+ n1.OnClicked(func(*ui.Button) {
+ Data.ListChildren(true)
+ })
+
+ n1 = addButton(vbox, "Node.Dump()")
+ n1.OnClicked(func(*ui.Button) {
+ y := nodeCombo.Selected()
+ log.Println("y =", y)
+ log.Println("nodeNames[y] =", nodeNames[y])
+ node := Data.findId(nodeNames[y])
+ if (node != nil) {
+ node.Dump()
+ }
+ })
+
+ n1 = addButton(vbox, "Node.ListChildren(false)")
+ n1.OnClicked(func(*ui.Button) {
+ y := nodeCombo.Selected()
+ log.Println("y =", y)
+ log.Println("nodeNames[y] =", nodeNames[y])
+ node := Data.findId(nodeNames[y])
+ if (node != nil) {
+ node.ListChildren(false)
+ }
+ })
+
+ n1 = addButton(vbox, "Node.ListChildren(true)")
+ n1.OnClicked(func(*ui.Button) {
+ y := nodeCombo.Selected()
+ log.Println("y =", y)
+ log.Println("nodeNames[y] =", nodeNames[y])
+ node := Data.findId(nodeNames[y])
+ if (node != nil) {
+ node.ListChildren(true)
+ }
+ })
+
+ n1 = addButton(vbox, "Node.AddDebugTab")
+ n1.OnClicked(func(*ui.Button) {
+ y := nodeCombo.Selected()
+ log.Println("y =", y)
+ log.Println("nodeNames[y] =", nodeNames[y])
+ node := Data.findId(nodeNames[y])
+ if (node != nil) {
+ node.DebugTab("added this DebugTab")
+ }
+ })
+
+ n1 = addButton(vbox, "Node.DemoAndlabsUiTab")
+ n1.OnClicked(func(*ui.Button) {
+ y := nodeCombo.Selected()
+ log.Println("y =", y)
+ log.Println("nodeNames[y] =", nodeNames[y])
+ node := Data.findId(nodeNames[y])
+ if (node != nil) {
+ node.DemoAndlabsUiTab("ran gui.AddDemoAndlabsUiTab() " + strconv.Itoa(Config.counter))
+ }
+ })
+
return hbox
}
+// TODO: remove this crap
var x int = 0
+var y int = 0
+// TODO: remove this crap
func addName(c *ui.Combobox, s string) {
c.Append(s)
names[x] = s
@@ -155,33 +277,11 @@ func addGroup(b *ui.Box, name string) *ui.Box {
return vbox
}
-func FindWindow(s string) *GuiWindow {
- for name, window := range Data.WindowMap {
- if name == s {
- return window
- }
- }
- log.Printf("COULD NOT FIND WINDOW", s)
- return nil
-}
-
-func FindBox(s string) *GuiBox {
- for name, window := range Data.WindowMap {
- if name != s {
- continue
- }
- for name, abox := range window.BoxMap {
- log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
- return abox
- }
- log.Println("gui.FindBox() NEED TO INIT WINDOW name =", name)
- }
- log.Println("gui.FindBox() COULD NOT FIND BOX", s)
- return nil
-}
-
func dumpBox(s string) {
- for name, window := range Data.WindowMap {
+ var name string
+ var window *GuiWindow
+
+ for name, window = range Data.WindowMap {
if name != s {
continue
}
@@ -198,6 +298,7 @@ func dumpBox(s string) {
log.Println("gui.dumpBox() BoxMap START")
for name, abox := range window.BoxMap {
log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
+ abox.Dump()
if name == "MAINBOX" {
if Config.Debug {
scs := spew.ConfigState{MaxDepth: 1}
@@ -228,3 +329,27 @@ func addButton(box *ui.Box, name string) *ui.Button {
box.Append(button, false)
return button
}
+
+func (n *Node) DebugTab(title string) {
+ newNode := n.AddTab(title, makeWindowDebug())
+ if (Config.DebugNode) {
+ newNode.Dump()
+ }
+ tabSetMargined(newNode.uiTab)
+}
+
+// This sets _all_ the tabs to Margin = true
+//
+// TODO: do proper tab tracking (will be complicated). low priority
+func tabSetMargined(tab *ui.Tab) {
+ if (Config.DebugTabs) {
+ log.Println("tabSetMargined() IGNORE THIS")
+ }
+ c := tab.NumPages()
+ for i := 0; i < c; i++ {
+ if (Config.DebugTabs) {
+ log.Println("tabSetMargined() i =", i)
+ }
+ tab.SetMargined(i, true)
+ }
+}
diff --git a/debug.go b/debug.go
index 8c1e947..0b0baa4 100644
--- a/debug.go
+++ b/debug.go
@@ -8,14 +8,13 @@ import (
"github.com/davecgh/go-spew/spew"
)
-// import "reflect"
-
-// import "github.com/andlabs/ui"
-// import _ "github.com/andlabs/ui/winmanifest"
-
-//
-// Dump out debugging information every 4 seconds
+// WatchGUI() opens a goroutine
//
+// From that goroutine, it dumps out debugging information every 4 seconds
+/*
+ TODO: add configuration triggers on what to dump out
+ TODO: allow this to be sent to /var/log, syslogd, systemd's journalctl, etc
+*/
func WatchGUI() {
count := 0
@@ -32,6 +31,12 @@ func WatchGUI() {
}
}
+func DumpWindows() {
+ for name, _ := range Data.WindowMap {
+ log.Println("gui.DumpWindows() window =", name)
+ }
+}
+
func DumpMap() {
for name, window := range Data.WindowMap {
log.Println("gui.DumpBoxes() MAP: ", name)
@@ -106,3 +111,50 @@ func addTableTab() {
log.Println("Sleep for 1 second, then try to add new tabs")
time.Sleep(1 * time.Second)
}
+
+func (dn *GuiData) DumpNodeMap() {
+ log.Println("DebugDataNodeMap():")
+ for name, node := range dn.NodeMap {
+ log.Println("\tNode =", node.id, node.Width, node.Height, name)
+ if (node.children == nil) {
+ log.Println("\t\tNo children")
+ } else {
+ log.Println("\t\tHas children:", node.children)
+ }
+ // node.SetName("yahoo")
+ // log.Println("\tData.NodeMap node =", node)
+ }
+}
+
+/*
+func DebugDataNodeChildren() {
+ if Data.NodeMap == nil {
+ log.Println("DebugDataNodeChildren() NodeMap == nil")
+ return
+ }
+ log.Println("DebugDataNodeChildren():")
+ for name, node := range Data.NodeMap {
+ log.Println("\tNode name =", node.Width, node.Height, name)
+ if (node.children == nil) {
+ log.Println("\t\tNo children")
+ break
+ }
+ log.Println("\t\tHas children:", node.children)
+ }
+}
+*/
+
+func (dn *GuiData) ListChildren(dump bool) {
+ if Data.NodeMap == nil {
+ log.Println("gui.Data.ListChildren() Data.NodeMap == nil")
+ return
+ }
+ log.Println("gui.Data.ListChildren() Data.NodeMap:")
+ for name, node := range Data.NodeMap {
+ log.Println("\tgui.Data.ListChildren() node =", node.id, node.Width, node.Height, name)
+ if (dump == true) {
+ node.Dump()
+ }
+ node.ListChildren(dump)
+ }
+}
diff --git a/window-template.go b/demo-window-andlabs-ui.go
index c3e30ef..e11ffe9 100644
--- a/window-template.go
+++ b/demo-window-andlabs-ui.go
@@ -4,7 +4,19 @@ import "log"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
-func makeWindowTemplate() ui.Control {
+// This will create a tab in a window using direct
+// calls to andlabs/ui. This can be used to bypass
+// the obvuscation added in this package if it is desired
+// or needed.
+func (n *Node) DemoAndlabsUiTab(title string) {
+ newNode := n.AddTab(title, makeAndlabsUiTab())
+ if (Config.DebugNode) {
+ newNode.Dump()
+ }
+ tabSetMargined(newNode.uiTab)
+}
+
+func makeAndlabsUiTab() *ui.Box {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
diff --git a/demo-window.go b/demo-window.go
new file mode 100644
index 0000000..16566c4
--- /dev/null
+++ b/demo-window.go
@@ -0,0 +1,28 @@
+package gui
+
+// import "log"
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+var mybox *ui.Box
+
+func (n *Node) AddGroup(title string) *Node {
+ if (n == nil) {
+ return nil
+ }
+ hbox := n.uiBox
+ if (hbox == nil) {
+ return n
+ }
+ group := ui.NewGroup(title)
+ group.SetMargined(true)
+ hbox.Append(group, true)
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(true)
+ group.SetChild(vbox)
+
+ newNode := n.AddNode(title)
+ newNode.uiBox = vbox
+ return newNode
+}
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..2b324c9
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,72 @@
+/*
+Package wit/gui implements a abstraction layer for Go visual elements in
+a cross platform way. Right now, this abstraction is built on top of
+the GUI toolkit 'andlabs/ui' which does the cross platform support.
+
+A quick overview of the features, some general design guidelines
+and principles for how this package should generally work:
+
+ * GUI elements are stored in a tree of nodes
+ * When in doubt, it's ok to guess. We will return something close.
+ * It tries to make your code simple
+
+Quick Start
+
+This section demonstrates how to quickly get started with spew. See the
+sections below for further details on formatting and configuration options.
+
+To dump a variable with full newlines, indentation, type, and pointer
+information use Dump, Fdump, or Sdump:
+
+ package main
+
+ import (
+ "git.wit.org/wit/gui"
+ )
+
+ func main() {
+ gui.Main(initGUI)
+ }
+
+ // This initializes the first window
+ func initGUI() {
+ gui.Config.Title = "WIT GUI Window 1"
+ gui.Config.Width = 640
+ gui.Config.Height = 480
+ node1 := gui.NewWindow()
+ addDemoTab(node1, "A Simple Tab Demo")
+ }
+
+ func addDemoTab(n *gui.Node, title string) {
+ newNode := n.AddTab(title, nil)
+
+ groupNode1 := newNode.AddGroup("group 1")
+ groupNode1.AddComboBox("demoCombo2", "more 1", "more 2", "more 3")
+ }
+
+Configuration Options
+
+Configuration of the GUI is handled by fields in the ConfigType type. For
+convenience, all of the top-level functions use a global state available
+via the gui.Config global.
+
+The following configuration options are available:
+ * Width
+ When creating a new window, this is the width
+
+ * Height
+ When creating a new window, this is the height
+
+ * Debug
+ When 'true' log more output
+
+GUI Usage
+
+Errors
+
+Since it is possible for custom Stringer/error interfaces to panic, spew
+detects them and handles them internally by printing the panic information
+inline with the output. Since spew is intended to provide deep pretty printing
+capabilities on structures, it intentionally does not return any errors.
+*/
+package gui
diff --git a/entry.go b/entry.go
index d7f31c9..c10b7d0 100644
--- a/entry.go
+++ b/entry.go
@@ -13,26 +13,46 @@ func NewLabel(box *GuiBox, text string) {
box.Append(ui.NewLabel(text), false)
}
-func GetText(box *GuiBox, name string) string {
- if (box == nil) {
- log.Println("gui.GetText() ERROR box == nil")
- return ""
- }
- if (box.Window.EntryMap == nil) {
+func (n *Node) NewLabel(text string) *Node {
+ // make new node here
+ // n.Append(ui.NewLabel(text), false)
+ newNode := makeNode(n, text, 333, 334)
+ newNode.Dump()
+ // panic("node.NewLabel()")
+
+ n.Append(newNode)
+ return newNode
+}
+
+func (b *GuiBox) GetText(name string) string {
+ if (b.Window.EntryMap == nil) {
log.Println("gui.GetText() ERROR b.Box.Window.EntryMap == nil")
return ""
}
- spew.Dump(box.Window.EntryMap)
- if (box.Window.EntryMap[name] == nil) {
+ spew.Dump(b.Window.EntryMap)
+ if (b.Window.EntryMap[name] == nil) {
log.Println("gui.GetText() ERROR box.Window.EntryMap[", name, "] == nil ")
return ""
}
- e := box.Window.EntryMap[name]
+ e := b.Window.EntryMap[name]
log.Println("gui.GetText() box.Window.EntryMap[", name, "] = ", e.UiEntry.Text())
log.Println("gui.GetText() END")
return e.UiEntry.Text()
}
+func (n *Node) SetText(value string) error {
+ log.Println("gui.SetText() value =", value)
+ if (n.uiText != nil) {
+ n.uiText.SetText(value)
+ return nil
+ }
+ if (n.uiButton != nil) {
+ n.uiButton.SetText(value)
+ return nil
+ }
+ return nil
+}
+
func SetText(box *GuiBox, name string, value string) error {
if (box == nil) {
return fmt.Errorf("gui.SetText() ERROR box == nil")
@@ -42,7 +62,7 @@ func SetText(box *GuiBox, name string, value string) error {
}
spew.Dump(box.Window.EntryMap)
if (box.Window.EntryMap[name] == nil) {
- return fmt.Errorf("gui.SetText() ERROR box.Window.EntryMap[", name, "] == nil ")
+ return fmt.Errorf("gui.SetText() ERROR box.Window.EntryMap[" + name + "] == nil ")
}
e := box.Window.EntryMap[name]
log.Println("gui.SetText() box.Window.EntryMap[", name, "] = ", e.UiEntry.Text())
diff --git a/example_test.go b/example_test.go
new file mode 100644
index 0000000..f65cad1
--- /dev/null
+++ b/example_test.go
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013-2016 Dave Collins <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package gui_test
+
+import (
+ "git.wit.org/wit/gui"
+)
+
+// This example demonstrates how to create a NewWindow()
+//
+// Interacting with a GUI in a cross platform fashion adds some
+// unusual problems. To obvuscate those, andlabs/ui starts a
+// goroutine that interacts with the native gui toolkits
+// on the Linux, MacOS, Windows, etc.
+//
+// Because of this oddity, to initialize a new window, the
+// function is not passed any arguements and instead passes
+// the information via the Config type.
+//
+func ExampleNewWindow() {
+ // Define the name and size
+ gui.Config.Title = "WIT GUI Window 1"
+ gui.Config.Width = 640
+ gui.Config.Height = 480
+
+ // Create the Window
+ gui.NewWindow()
+
+ // Output:
+ // You get a window
+}
diff --git a/find.go b/find.go
new file mode 100644
index 0000000..e046161
--- /dev/null
+++ b/find.go
@@ -0,0 +1,156 @@
+package gui
+
+import (
+ "log"
+ "os"
+
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+// "github.com/davecgh/go-spew/spew"
+)
+
+func (n *Node) FindTab() *ui.Tab {
+ return n.uiTab
+}
+
+func (n *Node) FindControl() *ui.Control {
+ return n.uiControl
+}
+
+func (n *Node) FindBox() *GuiBox {
+ if (n.box != nil) {
+ return n.box
+ }
+ if (n.parent != nil) {
+ p := n.parent
+ return p.box
+ }
+ return n.box
+}
+
+func (n *Node) FindWindowBox() *GuiBox {
+ if (n.box == nil) {
+ panic("SERIOUS ERROR n.box == nil in FindWindowBox()")
+ }
+ return n.box
+}
+
+func (w *GuiWindow) FindNode() *Node {
+ return w.node
+}
+
+func (b *GuiBox) FindNode() *Node {
+ log.Println("gui.FindNode() on GuiBox")
+ if b.node != nil {
+ return b.node
+ }
+ Data.ListChildren(true)
+ b.Dump()
+ log.Println("gui.FindNode() on GuiBox is nil")
+ os.Exit(-1)
+ return nil
+}
+
+func FindWindow(s string) *GuiWindow {
+ for name, window := range Data.WindowMap {
+ if name == s {
+ return window
+ }
+ }
+ log.Printf("COULD NOT FIND WINDOW " + s)
+ return nil
+}
+
+func FindBox(s string) *GuiBox {
+ for name, window := range Data.WindowMap {
+ if name != s {
+ continue
+ }
+ for name, abox := range window.BoxMap {
+ log.Printf("gui.DumpBoxes() \tBOX mapname=%-12s abox.Name=%-12s", name, abox.Name)
+ return abox
+ }
+ log.Println("gui.FindBox() NEED TO INIT WINDOW name =", name)
+ }
+ log.Println("gui.FindBox() COULD NOT FIND BOX", s)
+ return nil
+}
+
+func FindNode(name string) *Node {
+ if Data.NodeMap == nil {
+ log.Println("gui.FindNode() gui.Data.NodeMap == nil")
+ return nil
+ }
+ log.Println("gui.FindNode() searching Data.NodeMap:")
+ for id, node := range Data.NodeMap {
+ log.Println("\tData.NodeMap name =", node.Width, node.Height, id)
+ node.Dump()
+ if (name == node.Name) {
+ return node
+ }
+ newNode := findByName(node, name)
+ if (newNode != nil) {
+ return newNode
+ }
+ log.Println("gui.FindNode() could not find node name =", name)
+ os.Exit(-1)
+ }
+ log.Println("gui.FindNode() could not find node name =", name)
+ return nil
+}
+
+func (dn *GuiData) findId(id string) *Node {
+ if Data.NodeMap == nil {
+ log.Println("gui.Data.findId() map == nil")
+ return nil
+ }
+ // log.Println("Dumping Data.NodeMap:")
+ for name, node := range Data.NodeMap {
+ // log.Println("\tData.NodeMap name =", node.id, node.Width, node.Height, name)
+ if (id == node.id) {
+ log.Println("\tgui.Data.findId() found node =", node.id, node.Width, node.Height, name)
+ return node
+ }
+ // TODO: fix // Oct 9
+ // node.findId(id)
+ }
+ return nil
+}
+
+func findByIdDFS(node *Node, id string) *Node {
+ log.Println("findByIdDFS()", id, node)
+ node.Dump()
+ if node.id == id {
+ log.Println("Found node id =", id, node)
+ return node
+ }
+
+ if len(node.children) > 0 {
+ for _, child := range node.children {
+ newNode := findByIdDFS(child, id)
+ if (newNode != nil) {
+ return newNode
+ }
+ }
+ }
+ return nil
+}
+
+func findByName(node *Node, name string) *Node {
+ log.Println("findByName()", name, node)
+ node.Dump()
+ if node.Name == name {
+ log.Println("findByName() Found node name =", name, node)
+ return node
+ }
+
+ if len(node.children) > 0 {
+ for _, child := range node.children {
+ newNode := findByName(child, name)
+ if (newNode != nil) {
+ return newNode
+ }
+ }
+ }
+ return nil
+}
diff --git a/gui-example/main.go b/gui-example/main.go
deleted file mode 100644
index 1ff286d..0000000
--- a/gui-example/main.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package main
-
-import (
- "log"
- "os"
- "time"
-
- "git.wit.org/wit/gui"
-)
-
-func customExit(gw *gui.GuiWindow) {
- log.Println("Should Exit Here")
- os.Exit(0)
-}
-
-func main() {
- log.Println("starting my Control Panel")
-
- gui.Config.Width = 800
- gui.Config.Height = 300
- gui.Config.Exit = customExit
-
- go gui.Main(initGUI)
-
- watchGUI()
-}
-
-func initGUI() {
- gui.NewWindow("jcarr start", 640, 480)
-}
-
-func watchGUI() {
- var i = 1
- for {
- log.Println("Waiting for customExit()", i)
- i += 1
- time.Sleep(time.Second)
- if i == 3 {
- log.Println("Sending ExampleWindow to gui.Queue()")
- gui.Queue(gui.DebugWindow)
- }
- }
-}
diff --git a/gui.go b/gui.go
index 97e3c24..4174133 100644
--- a/gui.go
+++ b/gui.go
@@ -18,6 +18,14 @@ func init() {
Data.buttonMap = make(map[*ui.Button]*GuiButton)
Data.WindowMap = make(map[string]*GuiWindow)
+ Data.NodeMap = make(map[string]*Node)
+
+ Data.NodeSlice = make([]*Node, 0)
+
+ Config.counter = 0
+ Config.prefix = "wit"
+ Config.DebugNode = false
+ Config.DebugTabs = false
}
func GuiInit() {
diff --git a/main.go b/main.go
index 09d105f..70e0e65 100644
--- a/main.go
+++ b/main.go
@@ -12,7 +12,7 @@ func Main(f func()) {
ui.Main(f)
}
-// Other goroutines must use this
+// 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
@@ -23,28 +23,12 @@ func Queue(f func()) {
ui.QueueMain(f)
}
+/*
func ExampleWindow() {
log.Println("START gui.ExampleWindow()")
- title := "Test Window"
- box := InitWindow(nil, title, 0)
- window := box.Window
- log.Println("box =", box)
- log.Println("window =", window)
- box.AddDebugTab("jcarr Debug")
-
- window.UiWindow.Show()
-}
-
-func DebugWindow() {
- log.Println("START gui.ExampleWindow()")
-
- title := "Debug Window"
- box := InitWindow(nil, title, 0)
- window := box.Window
- log.Println("box =", box)
- log.Println("window =", window)
- box.AddDebugTab("jcarr Debug")
-
- window.UiWindow.Show()
+ Config.Title = "ExampleWindow"
+ node := NewWindow()
+ node.AddDebugTab("jcarr Debug")
}
+*/
diff --git a/new-structs.go b/new-structs.go
index 0fa326a..4f9989e 100644
--- a/new-structs.go
+++ b/new-structs.go
@@ -2,12 +2,42 @@ package gui
import (
"log"
+ "fmt"
+// "reflect"
+
+ // "github.com/davecgh/go-spew/spew"
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
)
+type Element int
+
// https://ieftimov.com/post/golang-datastructures-trees/
+const (
+ Unknown Element = iota
+ Window
+ Tab
+ Box
+ Label
+ Combo
+)
+
+func (s Element) String() string {
+ switch s {
+ case Window:
+ return "window"
+ case Tab:
+ return "tab"
+ case Box:
+ return "box"
+ case Label:
+ return "label"
+ case Combo:
+ return "combo"
+ }
+ return "unknown"
+}
type Node struct {
id string
@@ -15,32 +45,227 @@ type Node struct {
Width int
Height int
- uiType *ui.Control
+ parent *Node
children []*Node
+
+ window *GuiWindow
+ box *GuiBox
+ custom func(*Node)
+
+ uiControl *ui.Control
+ uiButton *ui.Button
+ uiWindow *ui.Window
+ uiTab *ui.Tab
+ uiBox *ui.Box
+ uiText *ui.EditableCombobox
+}
+
+func (n *Node) Parent() *Node {
+ return n.parent
+}
+
+func (n *Node) Window() *Node {
+ return n.parent
+}
+
+func (n *Node) Dump() {
+ log.Println("gui.Node.Dump() id = ", n.id)
+ log.Println("gui.Node.Dump() Name = ", n.Name)
+ log.Println("gui.Node.Dump() Width = ", n.Width)
+ log.Println("gui.Node.Dump() Height = ", n.Height)
+
+ if (n.parent == nil) {
+ log.Println("gui.Node.Dump() parent = nil")
+ } else {
+ log.Println("gui.Node.Dump() parent = ", n.parent.id)
+ }
+ log.Println("gui.Node.Dump() children = ", n.children)
+
+ log.Println("gui.Node.Dump() window = ", n.window)
+ log.Println("gui.Node.Dump() box = ", n.box)
+
+ log.Println("gui.Node.Dump() uiWindow = ", n.uiWindow)
+ log.Println("gui.Node.Dump() uiTab = ", n.uiTab)
+ log.Println("gui.Node.Dump() uiBox = ", n.uiBox)
+ log.Println("gui.Node.Dump() uiControl = ", n.uiControl)
+ log.Println("gui.Node.Dump() uiButton = ", n.uiButton)
+ if (n.id == "") {
+ panic("gui.Node.Dump() id == nil")
+ }
+}
+
+
+func (n *Node) SetBox(box *GuiBox) {
+ n.box = box
}
-func (n Node) SetName(name string) {
+func (n *Node) SetName(name string) {
// n.uiType.SetName(name)
- log.Println("n.uiType =", n.uiType)
+ if (n.uiWindow != nil) {
+ log.Println("node is a window. setting title =", name)
+ n.uiWindow.SetTitle(name)
+ return
+ }
+ log.Println("*ui.Control =", n.uiControl)
return
}
-func (n Node) Append(child Node) {
+func (n *Node) Append(child *Node) {
// if (n.UiBox == nil) {
// return
// }
- // n.uiType.Append(child, x)
+ n.children = append(n.children, child)
+ if (Config.Debug) {
+ log.Println("child node:")
+ child.Dump()
+ log.Println("parent node:")
+ n.Dump()
+ }
+ // time.Sleep(3 * time.Second)
}
-func findByIdDFS(node *Node, id string) *Node {
- if node.id == id {
- return node
+func (n *Node) List() {
+ findByIdDFS(n, "test")
+}
+
+var listChildrenParent *Node
+var listChildrenDepth int = 0
+
+func indentPrintln(depth int, format string, a ...interface{}) {
+ var tabs string
+ for i := 0; i < depth; i++ {
+ tabs = tabs + "\t"
}
- if len(node.children) > 0 {
- for _, child := range node.children {
- findByIdDFS(child, id)
+ // newFormat := tabs + strconv.Itoa(depth) + " " + format
+ newFormat := tabs + format
+ log.Println(newFormat, a)
+}
+
+func (n *Node) ListChildren(dump bool) {
+ indentPrintln(listChildrenDepth, "\t", n.id, n.Width, n.Height, n.Name)
+
+ if (dump == true) {
+ n.Dump()
+ }
+ if len(n.children) == 0 {
+ if (n.parent == nil) {
+ } else {
+ if (Config.DebugNode) {
+ log.Println("\t\t\tparent =",n.parent.id)
+ }
+ if (listChildrenParent != nil) {
+ if (Config.DebugNode) {
+ log.Println("\t\t\tlistChildrenParent =",listChildrenParent.id)
+ }
+ if (listChildrenParent.id != n.parent.id) {
+ log.Println("parent.child does not match child.parent")
+ panic("parent.child does not match child.parent")
+ }
+ }
+ }
+ if (Config.DebugNode) {
+ log.Println("\t\t", n.id, "has no children")
+ }
+ return
+ }
+ for _, child := range n.children {
+ // log.Println("\t\t", child.id, child.Width, child.Height, child.Name)
+ if (child.parent != nil) {
+ if (Config.DebugNode) {
+ log.Println("\t\t\tparent =",child.parent.id)
+ }
+ } else {
+ log.Println("\t\t\tno parent")
+ panic("no parent")
+ }
+ if (dump == true) {
+ child.Dump()
}
+ if (Config.DebugNode) {
+ if (child.children == nil) {
+ log.Println("\t\t", child.id, "has no children")
+ } else {
+ log.Println("\t\t\tHas children:", child.children)
+ }
+ }
+ listChildrenParent = n
+ listChildrenDepth += 1
+ child.ListChildren(dump)
+ listChildrenDepth -= 1
+ }
+ return
+}
+
+// The parent Node needs to be the raw Window
+// The 'stuff' Node needs to be the contents of the tab
+//
+// This function should make a new node with the parent and
+// the 'stuff' Node as a child
+func (n *Node) AddTabNode(title string, b *GuiBox) *Node {
+ var newNode *Node
+ parent := n
+
+ newNode = parent.makeNode(title, 444, 400 + Config.counter)
+ newNode.uiTab = parent.uiTab
+ newNode.box = b
+
+ if (Config.DebugNode) {
+ fmt.Println("")
+ log.Println("parent:")
+ parent.Dump()
+
+ fmt.Println("")
+ log.Println("newNode:")
+ newNode.Dump()
+ }
+
+ if (newNode.uiTab == nil) {
+ log.Println("wit/gui/ AddTabNode() Something went wrong tab == nil")
+ // TODO: try to find the tab or window and make them if need be
+ return newNode
+ }
+ newNode.uiTab.Append(title, b.UiBox)
+
+ return newNode
+}
+
+func (n *Node) AddTab(title string, uiC *ui.Box) *Node {
+ parent := n
+ log.Println("gui.Node.AddTab() START name =", title)
+ if parent.uiWindow == nil {
+ parent.Dump()
+ log.Println("gui.Node.AddTab() ERROR ui.Window == nil")
+ return nil
}
- return nil
+ if parent.box == nil {
+ parent.Dump()
+ panic("gui.AddTab() ERROR box == nil")
+ }
+ if parent.uiTab == nil {
+ inittab := ui.NewTab() // no, not that 'inittab'
+ parent.uiWindow.SetChild(inittab)
+ parent.uiWindow.SetMargined(true)
+ parent.uiTab = inittab
+
+ // parent.Dump()
+ // panic("gui.AddTab() ERROR uiTab == nil")
+ }
+
+ tab := parent.uiTab
+ parent.uiWindow.SetMargined(true)
+
+ if (uiC == nil) {
+ hbox := ui.NewHorizontalBox()
+ hbox.SetPadded(true)
+ uiC = hbox
+ }
+ tab.Append(title, uiC)
+
+ newNode := parent.makeNode(title, 555, 600 + Config.counter)
+ newNode.uiTab = tab
+ newNode.uiBox = uiC
+ // panic("gui.AddTab() after makeNode()")
+ tabSetMargined(newNode.uiTab)
+ return newNode
}
diff --git a/structs.go b/structs.go
index ad3307b..c15f4b7 100644
--- a/structs.go
+++ b/structs.go
@@ -19,11 +19,20 @@ var Data GuiData
var Config GuiConfig
type GuiConfig struct {
+ Title string
Width int
Height int
- Debug bool
- DebugTable bool
- Exit func(*GuiWindow)
+ Exit func(*Node)
+
+ Debug bool
+ DebugNode bool
+ DebugTabs bool
+ DebugTable bool
+ DebugWindow bool
+
+ depth int
+ counter int // used to make unique ID's
+ prefix string
}
type GuiData struct {
@@ -35,7 +44,10 @@ type GuiData struct {
AllEntries []*GuiEntry
WindowMap map[string]*GuiWindow
- // Windows []*GuiWindow
+ // Store access to everything via binary tree's
+ NodeMap map[string]*Node
+ NodeArray []*Node
+ NodeSlice []*Node
// A map of all buttons everywhere on all
// windows, all tabs, across all goroutines
@@ -45,7 +57,6 @@ type GuiData struct {
// andlabs/ui & andlabs/libui work
AllButtons []*GuiButton
buttonMap map[*ui.Button]*GuiButton
- Nodes *Node
}
type GuiTab struct {
@@ -87,11 +98,20 @@ type GuiWindow struct {
EntryMap map[string]*GuiEntry
Area *GuiArea
+ node *Node
+
// andlabs/ui abstraction mapping
UiWindow *ui.Window
UiTab *ui.Tab // if this != nil, the window is 'tabbed'
}
+func (w *GuiWindow) Dump() {
+ log.Println("gui.GuiWindow.Dump() Name = ", w.Name)
+ log.Println("gui.GuiWindow.Dump() node = ", w.node)
+ log.Println("gui.GuiWindow.Dump() Width = ", w.Width)
+ log.Println("gui.GuiWindow.Dump() Height = ", w.Height)
+}
+
// GuiBox is any type of ui.Hbox or ui.Vbox
// There can be lots of these for each GuiWindow
type GuiBox struct {
@@ -99,121 +119,62 @@ type GuiBox struct {
Axis int // does it add items to the X or Y axis
Window *GuiWindow // the parent Window
+ node *Node
+
// andlabs/ui abstraction mapping
UiBox *ui.Box
}
-func (s GuiBox) SetTitle(title string) {
+func (b *GuiBox) Dump() {
+ log.Println("gui.GuiBox.Dump() Name = ", b.Name)
+ log.Println("gui.GuiBox.Dump() Axis = ", b.Axis)
+ log.Println("gui.GuiBox.Dump() GuiWindow = ", b.Window)
+ log.Println("gui.GuiBox.Dump() node = ", b.node)
+ log.Println("gui.GuiBox.Dump() UiBox = ", b.UiBox)
+}
+
+func (b *GuiBox) SetTitle(title string) {
log.Println("DID IT!", title)
- if s.Window == nil {
+ if b.Window == nil {
return
}
- if s.Window.UiWindow == nil {
+ if b.Window.UiWindow == nil {
return
}
- s.Window.UiWindow.SetTitle(title)
+ b.Window.UiWindow.SetTitle(title)
return
}
-func (s GuiBox) Append(child ui.Control, x bool) {
- if s.UiBox == nil {
- return
+func (w *GuiWindow) SetNode(n *Node) {
+ if (w.node != nil) {
+ w.Dump()
+ panic("gui.SetNode() Error not nil")
}
- s.UiBox.Append(child, x)
-}
-
-/*
-func (w GuiWindow) InitWindow(title string) *GuiBox {
- if w.UiWindow == nil {
- log.Println("gui.InitBox() THIS SHOULD NEVER HAPPEN. Window doesn't exist", w)
- return nil
+ w.node = n
+ if (w.node == nil) {
+ w.Dump()
+ panic("gui.SetNode() node == nil")
}
- tab := ui.NewTab()
- w.UiWindow.SetChild(tab)
- w.UiWindow.SetMargined(true)
-
- tab.Append(title, InitBlankWindow())
- tab.SetMargined(0, true)
-
- w.UiTab = tab
- return nil
}
-*/
-func (s GuiBox) InitTab(title string, custom func() ui.Control) *ui.Tab {
- if s.Window == nil {
- return nil
+func (b *GuiBox) SetNode(n *Node) {
+ if (b.node != nil) {
+ b.Dump()
+ panic("gui.SetNode() Error not nil")
}
- if s.Window.UiWindow == nil {
- return nil
+ b.node = n
+ if (b.node == nil) {
+ b.Dump()
+ panic("gui.SetNode() node == nil")
}
-
- window := s.Window.UiWindow
- tab := ui.NewTab()
- window.SetChild(tab)
- window.SetMargined(true)
-
- tab.Append(title, custom())
- tab.SetMargined(0, true)
- // tab.SetMargined(1, true)
-
- s.Window.UiTab = tab
- return tab
}
-func (s GuiBox) AddTab(title string, custom ui.Control) *ui.Tab {
- if s.Window == nil {
- return nil
- }
- if s.Window.UiTab == nil {
- return nil
- }
-
- tab := s.Window.UiTab
-
- tab.Append(title, custom)
- return tab
-}
-
-func (s GuiBox) AddTab2(title string, custom ui.Control) *ui.Tab {
- if s.Window == nil {
- return nil
- }
- if s.Window.UiTab == nil {
- return nil
- }
-
- tab := s.Window.UiTab
- tab.Append(title, custom)
- return tab
-}
-
-func (s GuiBox) AddBoxTab(title string) *GuiBox {
- uiTab := s.AddTab2(title, InitBlankWindow())
- tabSetMargined(uiTab)
-
- var box *GuiBox
- box = HardBox(s.Window, Xaxis, "jcarrAddBoxTab")
- box.Window.UiTab = uiTab
- return box
-}
-
-func (s GuiBox) AddDemoTab(title string) {
- uiTab := s.AddTab(title, makeWindowTemplate())
- tabSetMargined(uiTab)
-}
-
-func (s GuiBox) AddDebugTab(title string) {
- uiTab := s.AddTab(title, makeWindowDebug())
- tabSetMargined(uiTab)
-}
-
-func tabSetMargined(tab *ui.Tab) {
- c := tab.NumPages()
- for i := 0; i < c; i++ {
- log.Println("tabSetMargined() i =", i)
- // tab.SetMargined(i, true)
+func (b *GuiBox) Append(child ui.Control, x bool) {
+ if b.UiBox == nil {
+ panic("GuiBox.Append() can't work. UiBox == nil")
+ return
}
+ b.UiBox.Append(child, x)
}
// Note: every mouse click is handled
diff --git a/table.go b/table.go
index 87e69b2..92ae871 100644
--- a/table.go
+++ b/table.go
@@ -98,12 +98,12 @@ func InitColumns(mh *TableData, parts []TableColumnData) {
}
func AddTableTab(gw *GuiWindow, name string, rowcount int, parts []TableColumnData) *TableData {
- box := InitWindow(gw, name, Yaxis)
-
- return AddTableBox(box, name, rowcount, parts)
+ node := NewWindow()
+ b := node.box
+ return b.AddTableBox(name, rowcount, parts)
}
-func AddTableBox(box *GuiBox, name string, rowcount int, parts []TableColumnData) *TableData {
+func (b *GuiBox) AddTableBox(name string, rowcount int, parts []TableColumnData) *TableData {
mh := new(TableData)
mh.RowCount = rowcount
@@ -142,9 +142,9 @@ func AddTableBox(box *GuiBox, name string, rowcount int, parts []TableColumnData
// is this needed?
// gw.BoxMap[name] = box
- mh.Box = box
+ mh.Box = b
- box.UiBox.Append(table, true)
+ b.UiBox.Append(table, true)
return mh
}
diff --git a/tableCallbacks.go b/tableCallbacks.go
index 966f173..6eefd8d 100644
--- a/tableCallbacks.go
+++ b/tableCallbacks.go
@@ -30,7 +30,8 @@ func (mh *TableData) ColumnTypes(m *ui.TableModel) []ui.TableValue {
}
// TODO: Figure out why this is being called 1000 times a second (10 times for each row & column)
-// Nevermind this TODO. Who gives a shit. This is a really smart way to treat the OS toolkits
+//
+// Nevermind that TODO. Who gives a shit. This is a really smart way to treat the OS toolkits
func (mh *TableData) CellValue(m *ui.TableModel, row, column int) ui.TableValue {
if (Config.DebugTable) {
log.Println("CellValue() row, column =", row, column)
diff --git a/window.go b/window.go
index 2b615b5..403638e 100644
--- a/window.go
+++ b/window.go
@@ -2,40 +2,13 @@ package gui
import (
"log"
+ "fmt"
"strconv"
- "time"
"github.com/andlabs/ui"
-
- // import "regexp"
-
_ "github.com/andlabs/ui/winmanifest"
)
-func initUI(name string, callback func(*GuiBox) *GuiBox) {
- ui.Main(func() {
- log.Println("gui.initUI() inside ui.Main()")
-
- box := InitWindow(nil, "StartNewWindow"+name, 0)
- box = callback(box)
- window := box.Window
- log.Println("StartNewWindow() box =", box)
-
- window.UiWindow.Show()
- })
-}
-
-func StartNewWindow(bg bool, name string, axis int, callback func(*GuiBox) *GuiBox) {
- log.Println("StartNewWindow() ui.Main() Create a new window")
-
- if bg {
- go initUI(name, callback)
- time.Sleep(500 * time.Millisecond) // this might make it more stable on windows?
- } else {
- initUI(name, callback)
- }
-}
-
func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) {
ui.MsgBox(gw.UiWindow, msg1, msg2)
}
@@ -44,71 +17,6 @@ func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) {
ui.MsgBoxError(gw.UiWindow, msg1, msg2)
}
-//
-// This creates a new 'window' (which is just a tab in the window)
-// This is this way because on Linux you can have more than one
-// actual window but that does not appear to work on the MacOS or Windows
-//
-func InitWindow(gw *GuiWindow, name string, axis int) *GuiBox {
- log.Println("InitGuiWindow() START")
-
- var box *GuiBox
- if gw == nil {
- box = mapWindow(nil, name, Config.Height, Config.Width)
- } else {
- box = mapWindow(gw.UiWindow, name, Config.Height, Config.Width)
- }
-
- // box.Window = &newGuiWindow
- newGuiWindow := box.Window
-
- // This is the first window. One must create it here
- if gw == nil {
- log.Println("initWindow() ADDING ui.NewWindow()")
- newGuiWindow.UiWindow = ui.NewWindow(name, int(newGuiWindow.Height), int(newGuiWindow.Width), true)
- newGuiWindow.UiWindow.SetBorderless(false)
-
- // newGuiWindow.UiWindow.SetTitle("test")
- newGuiWindow.UiWindow.OnClosing(func(*ui.Window) bool {
- log.Println("initTabWindow() OnClosing() THIS WINDOW IS CLOSING newGuiWindow=", newGuiWindow)
- // newGuiWindow.UiWindow.Destroy()
- if Config.Exit == nil {
- ui.Quit()
- } else {
- // allow a custom exit function
- Config.Exit(newGuiWindow)
- }
- return true
- })
-
- newGuiWindow.UiTab = ui.NewTab()
- newGuiWindow.UiWindow.SetChild(newGuiWindow.UiTab)
- newGuiWindow.UiWindow.SetMargined(true)
- tmp := 0
- newGuiWindow.TabNumber = &tmp
- } else {
- newGuiWindow.UiWindow = gw.UiWindow
- newGuiWindow.UiTab = gw.UiTab
- }
-
- newGuiWindow.BoxMap = make(map[string]*GuiBox)
- newGuiWindow.EntryMap = make(map[string]*GuiEntry)
- // Data.Windows = append(Data.Windows, &newGuiWindow)
-
- if newGuiWindow.UiTab == nil {
- tabnum := 0
- newGuiWindow.TabNumber = &tabnum
- } else {
- tabnum := newGuiWindow.UiTab.NumPages()
- newGuiWindow.TabNumber = &tabnum
- }
-
- Data.WindowMap[newGuiWindow.Name] = newGuiWindow
-
- log.Println("InitGuiWindow() END *GuiWindow =", newGuiWindow)
- return box
-}
-
func DeleteWindow(name string) {
log.Println("gui.DeleteWindow() START name =", name)
window := Data.WindowMap[name]
@@ -144,57 +52,102 @@ func DeleteWindow(name string) {
}
}
-func CreateWindow(title string, tabname string, x int, y int, custom func() ui.Control) *GuiBox {
- box := CreateBlankWindow(title, x, y)
- box.InitTab(title, custom)
- return box
-}
+func makeNode(parent *Node, title string, x int, y int) *Node {
+ var node Node
+ node.Name = title
+ node.Width = x
+ node.Height = y
-func CreateBlankWindow(title string, x int, y int) *GuiBox {
- box := mapWindow(nil, title, x, y)
- log.Println("gui.CreateBlankWindow() title = box.Name =", box.Name)
+ id := Config.prefix + strconv.Itoa(Config.counter)
+ Config.counter += 1
+ node.id = id
- window := ui.NewWindow(box.Name, x, y, false)
- window.SetBorderless(false)
- window.OnClosing(func(*ui.Window) bool {
- log.Println("createWindow().OnClosing()", box.Name)
- return true
- })
- ui.OnShouldQuit(func() bool {
- log.Println("createWindow().Destroy()", box.Name)
- window.Destroy()
- return true
- })
+ // panic("gui.makeNode() START")
+ if (parent == nil) {
+ if (Data.NodeMap[title] != nil) {
+ log.Println("Duplicate window name =", title)
+ // TODO: just change the 'title' to something unique
+ panic(fmt.Sprintf("Duplicate window name = %s\n", title))
+ return nil
+ }
+ // panic("gui.makeNode() before NodeMap()")
+ Data.NodeMap[title] = &node
+ Data.NodeArray = append(Data.NodeArray, &node)
+ Data.NodeSlice = append(Data.NodeSlice, &node)
+ // panic("gui.makeNode() after NodeMap()")
+ return &node
+ } else {
+ // panic("gui.makeNode() before Append()")
+ parent.Append(&node)
+ // panic("gui.makeNode() after Append()")
+ }
+ node.parent = parent
+ return &node
+}
- window.SetMargined(true)
- window.Show()
+func (parent *Node) makeNode(title string, x int, y int) *Node {
+ var node Node
+ node.Name = title
+ node.Width = x
+ node.Height = y
- box.Window.UiWindow = window
- return box
+ id := Config.prefix + strconv.Itoa(Config.counter)
+ Config.counter += 1
+ node.id = id
+
+ parent.Append(&node)
+ node.parent = parent
+ return &node
}
-func InitBlankWindow() ui.Control {
- hbox := ui.NewHorizontalBox()
- hbox.SetPadded(true)
+func (n *Node) AddNode(title string) *Node {
+ var node Node
+ node.Name = title
+ node.Width = n.Width
+ node.Height = n.Height
- return hbox
+ id := Config.prefix + strconv.Itoa(Config.counter)
+ Config.counter += 1
+ node.id = id
+
+ n.Append(&node)
+ node.parent = n
+ return &node
}
-var master = 0
+func (n *Node) uiNewWindow(title string, x int, y int) {
+ w := ui.NewWindow(title, x, y, false)
+ w.SetBorderless(false)
+ f := Config.Exit
+ w.OnClosing(func(*ui.Window) bool {
+ if (Config.Debug) {
+ log.Println("ui.Window().OnClosing()")
+ }
+ if (f != nil) {
+ f(n)
+ }
+ return true
+ })
+ w.SetMargined(true)
+ w.Show()
+ n.uiWindow = w
+ // w.node = &node
+ return
+}
-func mapWindow(window *ui.Window, title string, x int, y int) *GuiBox {
+func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Node {
log.Println("gui.WindowMap START title =", title)
if Data.WindowMap[title] != nil {
log.Println("Data.WindowMap[title] already exists title =", title)
- master = master + 1
- title = title + " jcarr " + strconv.Itoa(master)
+ title = title + Config.prefix + strconv.Itoa(Config.counter)
+ Config.counter += 1
}
if Data.WindowMap[title] != nil {
log.Println("Data.WindowMap[title] already exists title =", title)
panic("Data.WindowMap[newGuiWindow.Name] already exists")
return nil
}
- log.Println("gui.WindowMap START title =", title)
+
var newGuiWindow GuiWindow
newGuiWindow.Width = x
newGuiWindow.Height = y
@@ -210,30 +163,47 @@ func mapWindow(window *ui.Window, title string, x int, y int) *GuiBox {
box.Window = &newGuiWindow
box.Name = title
+ node := makeNode(parent, title, x, y)
+ node.box = &box
+ node.uiWindow = window
+ box.node = node
+
newGuiWindow.BoxMap["jcarrInitTest"] = &box
- return &box
+ return node
}
-func NewWindow(title string, x int, y int) *GuiBox {
- box := mapWindow(nil, title, x, y)
+// This routine creates a blank window with a Title and size (W x H)
+//
+// This routine can not have any arguements due to the nature of how
+// it can be passed via the 'andlabs/ui' queue which, because it is
+// cross platform, must pass UI changes into the OS threads (that is
+// my guess).
+func NewWindow() *Node {
+ title := Config.Title
+ w := Config.Width
+ h := Config.Height
+
+ var n *Node
+ n = mapWindow(nil, nil, title, w, h)
+ box := n.box
log.Println("gui.NewWindow() title = box.Name =", box.Name)
- window := ui.NewWindow(box.Name, x, y, false)
- window.SetBorderless(false)
- window.OnClosing(func(*ui.Window) bool {
- log.Println("createWindow().OnClosing()", box.Name)
- return true
- })
+ n.uiNewWindow(box.Name, w, h)
+ window := n.uiWindow
+
+ f := Config.Exit
ui.OnShouldQuit(func() bool {
- log.Println("createWindow().Destroy()", box.Name)
- window.Destroy()
+ log.Println("createWindow().Destroy() on node.Name =", n.Name)
+ if (f != nil) {
+ f(n)
+ }
return true
})
- window.SetMargined(true)
- window.Show()
-
box.Window.UiWindow = window
- return box
+ if(n.uiWindow == nil) {
+ panic("node.uiWindow == nil. This should never happen")
+ }
+ return n
}