Refactor to 'gui/toolkit/'

* add a example cmds/consolemouse
       uses a console button to launch the andlabs/ui
    * fix wrong return value in toolkit/NewLabel()
    * redirect STDIN output to a file
    * wonderful fix of Window() exit
    * finally remove the ancient stupid variables x & y
    * phase out struct 'box' and use 'node' instead
    * better names for things: use NewFoo() and NewBar()
This commit is contained in:
Jeff Carr 2022-10-19 13:23:22 -05:00
parent a482e34efa
commit 6286635049
36 changed files with 1124 additions and 480 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.swp *.swp
cmds/gui-demo/gui-demo cmds/gui-demo/gui-demo
cmds/helloworld/helloworld cmds/helloworld/helloworld
cmds/consolemouse/consolemouse

View File

@ -9,7 +9,10 @@ update:
git pull git pull
go get -v -t -u ./... go get -v -t -u ./...
examples: examples-gui-demo examples-helloworld examples: examples-consolemouse examples-helloworld examples-gui-demo
examples-consolemouse:
make -C cmds/consolemouse
examples-helloworld: examples-helloworld:
make -C cmds/helloworld make -C cmds/helloworld
@ -18,4 +21,4 @@ examples-gui-demo:
make -C cmds/gui-demo make -C cmds/gui-demo
doc: doc:
godoc -v GO111MODULE="off" godoc -v

20
box.go
View File

@ -1,6 +1,7 @@
package gui package gui
import "log" import "log"
import "os"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
@ -15,7 +16,7 @@ func (n *Node) AddBox(axis int, name string) *Node {
} }
// make a new box & a new node // make a new box & a new node
newNode := n.makeNode(name, 111, 100 + Config.counter) newNode := n.New(name)
newNode.box = newBox newNode.box = newBox
Config.counter += 1 Config.counter += 1
@ -53,12 +54,21 @@ func VerticalBreak(box *GuiBox) {
} }
func (n *Node) AddComboBox(title string, s ...string) *Node { func (n *Node) AddComboBox(title string, s ...string) *Node {
box := n.uiBox if (n.Toolkit == nil) {
if (box == nil) { log.Println("AddComboBox.Toolkit is nil", title, s)
return n n.Dump()
os.Exit(0)
} }
if (n.uiBox == nil) {
log.Println("AddComboBox.uiBox is nil", title, s)
n.Toolkit.Dump()
n.uiBox = n.Toolkit.GetBox()
// os.Exit(0)
// return n
}
box := n.uiBox
newNode := n.AddNode(title) newNode := n.New(title)
ecbox := ui.NewEditableCombobox() ecbox := ui.NewEditableCombobox()
for id, name := range s { for id, name := range s {

View File

@ -1,7 +1,7 @@
package gui package gui
import "log" import "log"
import "reflect" // import "reflect"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
// import "github.com/davecgh/go-spew/spew" // import "github.com/davecgh/go-spew/spew"
@ -53,24 +53,33 @@ func guiButtonClick(button *GuiButton) {
} }
func (n *Node) AddButton(name string, custom func(*Node)) *Node { func (n *Node) AddButton(name string, custom func(*Node)) *Node {
if (n.uiBox == nil) { if (n.Toolkit == nil) {
log.Println("gui.Node.AppendButton() filed node.UiBox == nil") log.Println("gui.Node.AppendButton() filed node.Toolkit == nil")
panic("gui.Node.AppendButton() filed node.Toolkit == nil")
return n return n
} }
/*
button := ui.NewButton(name) button := ui.NewButton(name)
log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox)) log.Println("reflect.TypeOF(uiBox) =", reflect.TypeOf(n.uiBox))
log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button)) log.Println("reflect.TypeOF(uiButton) =", reflect.TypeOf(button))
n.uiBox.Append(button, false) n.uiBox.Append(button, false)
n.uiButton = button n.uiButton = button
*/
newNode := n.makeNode(name, 888, 888 + Config.counter) newNode := n.New(name)
newNode.uiButton = button newNode.Toolkit = n.Toolkit.NewButton(name)
newNode.Toolkit.Custom = func() {
log.Println("gui.AppendButton() Button Clicked. Running custom()")
custom(newNode)
}
newNode.custom = custom newNode.custom = custom
/*
button.OnClicked(func(*ui.Button) { button.OnClicked(func(*ui.Button) {
log.Println("gui.AppendButton() Button Clicked. Running custom()") log.Println("gui.AppendButton() Button Clicked. Running custom()")
custom(newNode) custom(newNode)
}) })
*/
// panic("AppendButton") // panic("AppendButton")
// time.Sleep(3 * time.Second) // time.Sleep(3 * time.Second)
return newNode return newNode
@ -106,6 +115,10 @@ func (n *Node) CreateButton(custom func(*GuiButton), name string, values interfa
return newNode return newNode
} }
func (n *Node) NewButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton {
return CreateButton(box, custom, name, values)
}
func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton { func CreateButton(box *GuiBox, custom func(*GuiButton), name string, values interface {}) *GuiButton {
newUiB := ui.NewButton(name) newUiB := ui.NewButton(name)
newUiB.OnClicked(defaultButtonClick) newUiB.OnClicked(defaultButtonClick)

View File

@ -0,0 +1,14 @@
run: build
./consolemouse
reset
build-release:
go get -v -u -x .
go build
build:
GO111MODULE="off" go get -v -x .
GO111MODULE="off" go build
update:
GO111MODULE="off" go get -v -u -x .

View File

@ -0,0 +1,51 @@
// This creates a simple hello world window
package main
import (
"log"
"time"
"git.wit.org/wit/gui"
)
import toolkit "git.wit.org/wit/gui/toolkit/gocui"
func configureGogui() {
toolkit.Init()
toolkit.OnExit(mycallback)
}
func startGogui() {
toolkit.StartConsoleMouse()
}
func mycallback(name string) {
log.Println("run andlabs here? name =", name)
if (name == "andlabs") {
go gui.Main(initGUI)
}
if (name == "something") {
log.Println("add something to do here")
}
if (name == "DemoToolkitWindow") {
gui.Queue( func () {
gui.DemoToolkitWindow()
})
}
if (name == "addDemoTab") {
gui.Queue( func () {
addDemoTab(w, "A Tab from gocui")
})
}
if (name == "DebugWindow") {
log.Println("Opening a Debug Window via the gui.Queue()")
gui.Config.Width = 800
gui.Config.Height = 300
gui.Config.Exit = myExit
gui.Queue(gui.DebugWindow)
time.Sleep(1 * time.Second)
gui.Queue(gui.DebugTab)
}
if (name == "exit") {
myExit(nil)
}
}

61
cmds/consolemouse/main.go Normal file
View File

@ -0,0 +1,61 @@
// This creates a simple hello world window
package main
import (
"os"
"log"
// "time"
"git.wit.org/wit/gui"
)
import toolkit "git.wit.org/wit/gui/toolkit/gocui"
var w *gui.Node
func main() {
go gui.Main(initGUI)
configureGogui()
startGogui()
}
// This initializes the first window
func initGUI() {
gui.Config.Title = "Hello World golang wit/gui Window"
gui.Config.Width = 640
gui.Config.Height = 480
gui.Config.Exit = myExit
w = gui.NewWindow()
w.Dump()
addDemoTab(w, "A Simple Tab Demo")
addDemoTab(w, "A Second Tab")
}
func addDemoTab(window *gui.Node, title string) {
var newNode, g *gui.Node
newNode = window.AddTab(title, nil)
log.Println("addDemoTab() newNode.Dump")
log.Println("addDemoTab() newNode.Dump")
log.Println("addDemoTab() newNode.Dump")
log.Println("addDemoTab() newNode.Dump")
newNode.Dump()
newNode.Toolkit.Dump()
g = newNode.NewGroup("group 1")
log.Println("addDemoTab() g.Dump")
log.Println("addDemoTab() g.Dump")
log.Println("addDemoTab() g.Dump")
log.Println("addDemoTab() g.Dump")
g.Dump()
g.Toolkit.Dump()
// myExit(nil)
g.AddComboBox("demoCombo2", "more 1", "more 2", "more 3")
}
func myExit(n *gui.Node) {
log.Println("You can Do exit() things here")
toolkit.Exit()
os.Exit(0)
}

View File

@ -22,7 +22,7 @@ func main() {
// This initializes the first window // This initializes the first window
func initGUI() { func initGUI() {
gui.ToolkitDemoWindow() gui.DemoToolkitWindow()
} }
// This demonstrates how to properly interact with the GUI // This demonstrates how to properly interact with the GUI
@ -33,24 +33,22 @@ func watchGUI() {
log.Println("Waiting", i, "seconds") log.Println("Waiting", i, "seconds")
i += 1 i += 1
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
if i == 4 { if i == 2 {
log.Println("Opening a Debug Window via the gui.Queue()") log.Println("Opening a Debug Window via the gui.Queue()")
gui.Config.Width = 800 gui.Config.Width = 800
gui.Config.Height = 300 gui.Config.Height = 300
gui.Config.Exit = myDebugExit gui.Config.Exit = myExit
gui.Queue(gui.DebugWindow) gui.Queue(gui.DebugWindow)
time.Sleep(1 * time.Second)
gui.Queue(gui.DebugTab)
} }
} }
} }
// TODO: myExit isn't getting used anymore
func myExit(n *gui.Node) { func myExit(n *gui.Node) {
log.Println() log.Println()
log.Println("Entered myExit() on node.Name =", n.Name) log.Println("Entered myExit() on node.Name =", n.Name)
log.Println() log.Println()
os.Exit(0) os.Exit(0)
} }
func myDebugExit(n *gui.Node) {
log.Println("Entered myDebugExit() on node.Name =", n.Name)
log.Println("Don't actually os.Exit()")
}

View File

@ -8,7 +8,6 @@ build-release:
build: build:
GO111MODULE="off" go get -v -x . GO111MODULE="off" go get -v -x .
GO111MODULE="off" go build GO111MODULE="off" go build
./helloworld
update: update:
GO111MODULE="off" go get -v -u -x . GO111MODULE="off" go get -v -u -x .

View File

@ -8,26 +8,51 @@ import (
) )
func main() { func main() {
f, err := os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
log.SetOutput(f)
log.Println("This is a test log entry")
gui.Main(initGUI) gui.Main(initGUI)
} }
// This initializes the first window // This initializes the first window
func initGUI() { func initGUI() {
var w *gui.Node
gui.Config.Title = "Hello World golang wit/gui Window" gui.Config.Title = "Hello World golang wit/gui Window"
gui.Config.Width = 640 gui.Config.Width = 640
gui.Config.Height = 480 gui.Config.Height = 480
gui.Config.Exit = myDefaultExit gui.Config.Exit = myDefaultExit
node1 := gui.NewWindow() w = gui.NewWindow()
addDemoTab(node1, "A Simple Tab Demo") w.Dump()
addDemoTab(node1, "A Second Tab") addDemoTab(w, "A Simple Tab Demo")
addDemoTab(w, "A Second Tab")
} }
func addDemoTab(n *gui.Node, title string) { func addDemoTab(window *gui.Node, title string) {
newNode := n.AddTab(title, nil) var newNode, g *gui.Node
g := newNode.NewGroup("group 1") newNode = window.AddTab(title, nil)
// g.Dump() log.Println("addDemoTab() newNode.Dump")
log.Println("addDemoTab() newNode.Dump")
log.Println("addDemoTab() newNode.Dump")
log.Println("addDemoTab() newNode.Dump")
newNode.Dump()
newNode.Toolkit.Dump()
g = newNode.NewGroup("group 1")
log.Println("addDemoTab() g.Dump")
log.Println("addDemoTab() g.Dump")
log.Println("addDemoTab() g.Dump")
log.Println("addDemoTab() g.Dump")
g.Dump()
g.Toolkit.Dump()
// os.Exit(0)
g.AddComboBox("demoCombo2", "more 1", "more 2", "more 3") g.AddComboBox("demoCombo2", "more 1", "more 2", "more 3")
} }

View File

@ -2,6 +2,8 @@ package gui
import ( import (
"log" "log"
// "time"
// "os"
"github.com/andlabs/ui" "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
@ -11,23 +13,31 @@ import (
var names = make([]string, 100) var names = make([]string, 100)
var nodeNames = make([]string, 100) var nodeNames = make([]string, 100)
var bugWin *Node
/*
Creates a window helpful for debugging this package
*/
func DebugWindow() { func DebugWindow() {
Config.Title = "git.wit.org/wit/gui debug" Config.Title = "git.wit.org/wit/gui debug fixme"
Config.Width = 640 Config.Width = 300
Config.Height = 480 Config.Height = 200
Config.Exit = StandardClose Config.Exit = StandardClose
node := NewWindow() bugWin = NewWindow()
node.DebugTab("WIT GUI Debug Tab") bugWin.DebugTab("does this also work?")
// node.DebugTab("WIT GUI Debug Tab")
} }
// TODO: remove this crap // TODO: remove this crap
// What does this actually do? // What does this actually do?
// It populates the nodeNames in a map. No, not a map, an array. // 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) // What is the difference again? (other than one being in order and a predefined length)
func addNodeName(c *ui.Combobox, s string, id string) { func addNodeNameBAD(c *ui.Combobox, s string, id string) {
c.Append(s) c.Append(s)
nodeNames[y] = id // nodeNames[y] = id
y = y + 1 // y = y + 1
log.Println("addNodeName:", s)
// time.Sleep(1 * time.Second)
// os.Exit(0)
} }
func makeWindowDebug() *ui.Box { func makeWindowDebug() *ui.Box {
@ -42,7 +52,7 @@ func makeWindowDebug() *ui.Box {
if (Config.Debug) { if (Config.Debug) {
log.Println("range Data.WindowMap() name =", name) log.Println("range Data.WindowMap() name =", name)
} }
addName(cbox, name) addNameBAD(cbox, name)
} }
cbox.SetSelected(0) cbox.SetSelected(0)
@ -83,8 +93,8 @@ func makeWindowDebug() *ui.Box {
} }
scs := spew.ConfigState{MaxDepth: 1} scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(gw) scs.Dump(gw)
log.Println("gui.DumpBoxes()\tWindow.UiTab =", gw.UiTab) log.Println("gui.dumpBoxes()\tWindow.UiTab =", gw.UiTab)
log.Println("gui.DumpBoxes()\tWindow.TabNumber =", *gw.TabNumber) log.Println("gui.dumpBoxes()\tWindow.TabNumber =", *gw.TabNumber)
gw.UiTab.SetMargined(*gw.TabNumber, true) gw.UiTab.SetMargined(*gw.TabNumber, true)
}) })
@ -141,17 +151,17 @@ func makeWindowDebug() *ui.Box {
dump3 := addButton(vbox, "Dump Windows") dump3 := addButton(vbox, "Dump Windows")
dump3.OnClicked(func(*ui.Button) { dump3.OnClicked(func(*ui.Button) {
DumpWindows() dumpWindows()
}) })
dump2 := addButton(vbox, "Dump Boxes") dump2 := addButton(vbox, "Dump Boxes")
dump2.OnClicked(func(*ui.Button) { dump2.OnClicked(func(*ui.Button) {
DumpBoxes() dumpBoxes()
}) })
dump1 := addButton(vbox, "Dump MAP") dump1 := addButton(vbox, "Dump MAP")
dump1.OnClicked(func(*ui.Button) { dump1.OnClicked(func(*ui.Button) {
DumpMap() dumpMap()
}) })
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -159,12 +169,15 @@ func makeWindowDebug() *ui.Box {
nodeCombo := ui.NewCombobox() nodeCombo := ui.NewCombobox()
for name, node := range Data.NodeMap { for name, node := range Data.NodeMap {
if (Config.Debug) { // if (Config.Debug) {
log.Println("range Data.NodeMap() name =", name) log.Println("range Data.NodeMap() name =", name)
} // }
tmp := node.id + " (" + name + ")" tmp := node.id + " (" + name + ")"
addNodeName(nodeCombo, tmp, node.id) addNodeNameBAD(nodeCombo, tmp, node.id)
} }
// scs := spew.ConfigState{MaxDepth: 1}
// scs.Dump(Data.NodeMap)
// os.Exit(0)
nodeCombo.SetSelected(0) nodeCombo.SetSelected(0)
nodeBox.Append(nodeCombo, false) nodeBox.Append(nodeCombo, false)
@ -245,14 +258,17 @@ func makeWindowDebug() *ui.Box {
} }
// TODO: remove this crap // TODO: remove this crap
var x int = 0 // var x int = 0
var y int = 0 // var y int = 0
// TODO: remove this crap // TODO: remove this crap
func addName(c *ui.Combobox, s string) { func addNameBAD(c *ui.Combobox, s string) {
c.Append(s) c.Append(s)
names[x] = s // names[x] = s
x = x + 1 // x = x + 1
log.Println("addName:", s)
// time.Sleep(1 * time.Second)
// os.Exit(0)
} }
func addGroup(b *ui.Box, name string) *ui.Box { func addGroup(b *ui.Box, name string) *ui.Box {
@ -300,7 +316,7 @@ func dumpBox(s string) {
if window.UiTab != nil { if window.UiTab != nil {
pages := window.UiTab.NumPages() pages := window.UiTab.NumPages()
log.Println("gui.DumpBoxes()\tWindow.UiTab.NumPages() =", pages) log.Println("gui.DumpBoxes()\tWindow.UiTab.NumPages() =", pages)
tabSetMargined(window.UiTab) // fixme: tabSetMargined(window.UiTab)
if Config.Debug { if Config.Debug {
scs := spew.ConfigState{MaxDepth: 2} scs := spew.ConfigState{MaxDepth: 2}
scs.Dump(window.UiTab) scs.Dump(window.UiTab)
@ -320,26 +336,22 @@ func addButton(box *ui.Box, name string) *ui.Button {
return button return button
} }
func (n *Node) DebugTab(title string) { func DebugTab() {
newNode := n.AddTab(title, makeWindowDebug()) bugWin.DebugTab("does this work?")
if (Config.DebugNode) {
newNode.Dump()
}
tabSetMargined(newNode.uiTab)
} }
// This sets _all_ the tabs to Margin = true func (n *Node) DebugTab(title string) *Node {
// var newN *Node
// TODO: do proper tab tracking (will be complicated). low priority var b *ui.Box
func tabSetMargined(tab *ui.Tab) { // var uiBox *ui.Box
if (Config.DebugTabs) {
log.Println("tabSetMargined() IGNORE THIS") // time.Sleep(1 * time.Second)
} newN = n.AddTabNew(title + " fix makeWindowDebug")
c := tab.NumPages() newN.Toolkit.Dump()
for i := 0; i < c; i++ { b = makeWindowDebug()
if (Config.DebugTabs) { newN.Toolkit.SetTabBox(b)
log.Println("tabSetMargined() i =", i) // FIXME: make sure this is getting run to add padding: tabSetMargined(newN.uiTab)
} // os.Exit(0)
tab.SetMargined(i, true)
} return newN
} }

View File

@ -15,14 +15,15 @@ import (
TODO: add configuration triggers on what to dump out TODO: add configuration triggers on what to dump out
TODO: allow this to be sent to /var/log, syslogd, systemd's journalctl, etc TODO: allow this to be sent to /var/log, syslogd, systemd's journalctl, etc
*/ */
func WatchGUI() { /*
func watchGUI() {
count := 0 count := 0
for { for {
if count > 20 { if count > 20 {
log.Println("Sleep() in watchGUI()") log.Println("Sleep() in watchGUI()")
if Config.Debug { if Config.Debug {
DumpBoxes() dumpBoxes()
} }
count = 0 count = 0
} }
@ -30,14 +31,15 @@ func WatchGUI() {
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
} }
} }
*/
func DumpWindows() { func dumpWindows() {
for name, _ := range Data.WindowMap { for name, _ := range Data.WindowMap {
log.Println("gui.DumpWindows() window =", name) log.Println("gui.DumpWindows() window =", name)
} }
} }
func DumpMap() { func dumpMap() {
for name, window := range Data.WindowMap { for name, window := range Data.WindowMap {
log.Println("gui.DumpBoxes() MAP: ", name) log.Println("gui.DumpBoxes() MAP: ", name)
log.Println("gui.DumpBoxes() BOXES:", name) log.Println("gui.DumpBoxes() BOXES:", name)
@ -47,7 +49,7 @@ func DumpMap() {
} }
} }
func DumpBoxes() { func dumpBoxes() {
for name, window := range Data.WindowMap { for name, window := range Data.WindowMap {
log.Println("gui.DumpBoxes() MAP: ", name) log.Println("gui.DumpBoxes() MAP: ", name)
if window.TabNumber == nil { if window.TabNumber == nil {

30
doc.go
View File

@ -1,13 +1,22 @@
/* /*
Package gui implements a abstraction layer for Go visual elements in Package gui implements a abstraction layer for Go visual elements in
a cross platform way. a cross platform and library independent way. (hopefully this is will work)
A quick overview of the features, some general design guidelines A quick overview of the features, some general design guidelines
and principles for how this package should generally work: and principles for how this package should generally work:
* GUI elements are stored in a tree of nodes Definitions:
* When in doubt, it's ok to guess. We will return something close.
* It tries to make your code simple * Toolkit: the underlying library (MacOS gui, Windows gui, gtk, qt, etc)
* Node: A binary tree of all the underlying GUI toolkit elements
Principles:
* Make code using this package simple to use
* When in doubt, search upward in the binary tree
* It's ok to guess. We will return something close.
* Hide complexity internally here
* Isolate the GUI toolkit
Quick Start Quick Start
@ -22,11 +31,11 @@ sections below for further details on formatting and configuration options.
) )
func main() { func main() {
gui.Main(initGUI) gui.Main(helloworld)
} }
// This initializes the first window // This initializes the first window
func initGUI() { func helloworld() {
gui.Config.Title = "Hello World golang wit/gui Window" gui.Config.Title = "Hello World golang wit/gui Window"
gui.Config.Width = 640 gui.Config.Width = 640
gui.Config.Height = 480 gui.Config.Height = 480
@ -42,7 +51,7 @@ sections below for further details on formatting and configuration options.
groupNode1.AddComboBox("demoCombo2", "more 1", "more 2", "more 3") groupNode1.AddComboBox("demoCombo2", "more 1", "more 2", "more 3")
} }
Toolkit Usage Toolkits (hopefully more than one will work)
Right now, this abstraction is built on top of the go package 'andlabs/ui' Right now, this abstraction is built on top of the go package 'andlabs/ui'
which does the cross platform support. which does the cross platform support.
@ -63,5 +72,12 @@ Debugging
To dump variables with full newlines, indentation, type, and pointer To dump variables with full newlines, indentation, type, and pointer
information this uses spew.Dump() information this uses spew.Dump()
Bugs
"The author's idea of friendly may differ to that of many other people."
-- manpage quote from the excellent minimalistic window manager 'evilwm'
*/ */
package gui package gui

View File

@ -1,62 +0,0 @@
package gui
import "log"
// import "fmt"
import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
import "github.com/davecgh/go-spew/spew"
// functions for handling text entry boxes
func NewLabel(box *GuiBox, text string) {
box.Append(ui.NewLabel(text), false)
}
func (n *Node) NewLabel(text string) *Node {
// make new node here
newNode := makeNode(n, text, 333, 334)
newNode.Dump()
t := toolkit.NewLabel(n.uiBox, text)
newNode.Toolkit = t
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(b.Window.EntryMap)
if (b.Window.EntryMap[name] == nil) {
log.Println("gui.GetText() ERROR box.Window.EntryMap[", name, "] == nil ")
return ""
}
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
}
if (n.uiWindow != nil) {
n.uiWindow.SetTitle(value)
return nil
}
return nil
}

View File

@ -4,60 +4,28 @@ import "log"
import toolkit "git.wit.org/wit/gui/toolkit/andlabs" import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
import "github.com/andlabs/ui" // TODO: which name is better. AddGroup or NewGroup ?
import _ "github.com/andlabs/ui/winmanifest" // first reaction is NewGroup
func (n *Node) NewGroup(name string) *Node { func (n *Node) NewGroup(name string) *Node {
var t *toolkit.Toolkit var newT *toolkit.Toolkit
var gNode, bNode *Node var gNode *Node
log.Println("toolkit.NewGroup() START", name) log.Println("toolkit.NewGroup() START", name)
if (n.Toolkit == nil) {
log.Println("toolkit.NewGroup() Toolkit == nil")
panic("Toolkit should never be nil")
}
// make a *Node with a *toolkit.Group // make a *Node with a *toolkit.Group
gNode = n.AddNode(name + " part1") gNode = n.New(name + " part1")
t = toolkit.NewGroup(n.uiBox, name) newT = n.Toolkit.NewGroup(name)
gNode.Toolkit = t gNode.Toolkit = newT
log.Println("################## gNode ####### ", name)
gNode.Dump() gNode.Dump()
// make a *Node with a *toolkit.Box return gNode
bNode = n.AddNode(name + " part2")
bNode.Toolkit = t.NewBox()
bNode.uiBox = bNode.Toolkit.GetBox()
bNode.Dump()
return bNode
} }
func (n *Node) AddGroup(title string) *Node { func (n *Node) AddGroup(title string) *Node {
return n.NewGroup(title) return n.NewGroup(title + "deprecated AddGroup")
} }
func (n *Node) AddGroupOld(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
}
/*
func (n *Node) NewGroup(title string) *Node {
group := ui.NewGroup(title)
group.SetMargined(true)
hbox.Append(group, true)
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
group.SetChild(vbox)
*/

30
int.go
View File

@ -4,13 +4,15 @@ import "log"
import "github.com/davecgh/go-spew/spew" import "github.com/davecgh/go-spew/spew"
// import toolkit "git.wit.org/wit/gui/toolkit/andlabs" /*
Get the int from the gui toolkit
because eventually this gui package should become it's own seperate go routine and never interact from the
gui subroutine back into the upstream application using the gui package
TODO: instead store the int in the Node structure? (this is probably a better idea)
// Get the int from the gui toolkit because technically every interaction with the toolkit has to go through the Queue() goroutine.
// TODO: instead store the int in the Node structure? (this is probably a better idea) Is it "has to go" or "should go"? Probably it makes sense to strictly inforce it. No "callback" functions. IPC only (go channels)
// because eventually this gui package should become it's own seperate go routine and never interact from the */
// gui subroutine back into the upstream application using the gui package
func (n *Node) Int() int { func (n *Node) Int() int {
if (Config.DebugToolkit) { if (Config.DebugToolkit) {
log.Println("gui.Node.Int() for node name =", n.Name) log.Println("gui.Node.Int() for node name =", n.Name)
@ -26,3 +28,19 @@ func (n *Node) Int() int {
i := n.Toolkit.Value() i := n.Toolkit.Value()
return i return i
} }
// which name to use?
func (n *Node) Value() int {
return n.Int()
}
func (n *Node) SetValue(i int) {
log.Println("gui.SetValue() START")
if (n.Toolkit == nil) {
log.Println("gui.Node.SetValue() for toolkit struct = nil")
panic("SetValue failed")
}
n.Dump()
n.Toolkit.Dump()
n.Toolkit.SetValue(i)
}

View File

@ -2,8 +2,6 @@ package gui
import ( import (
"log" "log"
"fmt"
// "reflect"
// "github.com/davecgh/go-spew/spew" // "github.com/davecgh/go-spew/spew"
@ -241,76 +239,3 @@ func (n *Node) ListChildren(dump bool) {
} }
return 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
}
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
}

40
node.go Normal file
View File

@ -0,0 +1,40 @@
package gui
import "strconv"
// import "fmt"
/*
generic function to create a new node on the binary tree
*/
func (n *Node) New(title string) *Node {
var newN *Node
newN = addNode(title, n.Width, n.Height)
n.Append(newN)
newN.parent = n
return newN
}
/*
raw create function for a new node struct
*/
func addNode(title string, w int, h int) *Node {
var n Node
n.Name = title
n.Width = w
n.Height = h
id := Config.prefix + strconv.Itoa(Config.counter)
Config.counter += 1
n.id = id
/*
if (Data.NodeMap[title] != nil) {
panic(fmt.Sprintf("Duplicate window name = %s\n", title))
} else {
Data.NodeMap[title] = &n
}
*/
return &n
}

View File

@ -5,20 +5,22 @@ import "log"
import toolkit "git.wit.org/wit/gui/toolkit/andlabs" import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
func (n *Node) NewSlider(name string, x int, y int) *Node { func (n *Node) NewSlider(name string, x int, y int) *Node {
// make new node here var newT *toolkit.Toolkit
log.Println("toolkit.NewSlider", x, y) var sNode *Node
newNode := n.makeNode(name, 767, 676 + Config.counter) log.Println("toolkit.NewSlider() START", name)
newNode.Name = name
t := toolkit.NewSlider(n.uiBox, name, x, y) if (n.Toolkit == nil) {
t.OnChanged = func(t *toolkit.Toolkit) { log.Println("toolkit.NewSlider() Toolkit == nil")
log.Println("toolkit.NewSlider() value =", t.Value()) panic("Toolkit should never be nil")
if (newNode.OnChanged != nil) {
newNode.OnChanged(newNode)
}
} }
newNode.Toolkit = t
return newNode // make a *Node with a *toolkit.Group
sNode = n.New(name + " part1")
newT = n.Toolkit.NewSlider(name, x, y)
newT.Name = name
sNode.Toolkit = newT
sNode.Dump()
return sNode
} }

View File

@ -8,8 +8,7 @@ func (n *Node) NewSpinbox(name string, x int, y int) *Node {
// make new node here // make new node here
log.Println("toolkit.NewSpinbox", x, y) log.Println("toolkit.NewSpinbox", x, y)
newNode := n.makeNode(name, 767, 676 + Config.counter) newNode := n.New(name)
newNode.Name = name
t := toolkit.NewSpinbox(n.uiBox, name, x, y) t := toolkit.NewSpinbox(n.uiBox, name, x, y)
t.OnChanged = func(t *toolkit.Toolkit) { t.OnChanged = func(t *toolkit.Toolkit) {

75
tab.go
View File

@ -2,39 +2,76 @@ package gui
import ( import (
"log" "log"
// "fmt" "os"
"github.com/andlabs/ui" "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
) )
// import toolkit "git.wit.org/wit/gui/toolkit/andlabs" // import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
func (n *Node) AddTabRaw(title string, uiC ui.Control) *Node { // This function should make a new node with the parent and
log.Println("gui.Node.AddTabRaw()") // the 'tab' as a child
tab := n.uiTab func (n *Node) NewTab(title string) *Node {
if (tab == nil) { log.Println("gui.Node.AddTab() START name =", title)
log.Println("gui.Node.AddTabRaw() FAIL tab == nil")
return n return n.AddTabNew(title)
}
func (n *Node) AddTabNew(title string) *Node {
log.Println("gui.Node.AddTab() START name =", title)
if (n.Toolkit == nil) {
log.Println("FUCK TOOLKIT nil uiWindow =", n.uiWindow)
log.Println("FUCK TOOLKIT nil uiTab =", n.uiTab)
log.Println("FUCK TOOLKIT nil Toolkit =", n.Toolkit)
// return n.AddTab(title) // need to make a toolkit here
n.Dump()
os.Exit(0)
} }
log.Println("Make new node")
newN := n.New(title)
log.Println("Add tab to window")
t := n.Toolkit.AddTab(title)
newN.Toolkit = t
n.Append(newN)
return newN
}
func (n *Node) AddTab(title string, uiC *ui.Box) *Node {
return n.AddTabNew(title)
}
/*
func (n *Node) AddTabBAD(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
}
if parent.uiTab == nil {
inittab := ui.NewTab() // no, not that 'inittab'
parent.uiWindow.SetChild(inittab)
parent.uiWindow.SetMargined(true)
parent.uiTab = inittab
}
tab := parent.uiTab
parent.uiWindow.SetMargined(true)
if (uiC == nil) { if (uiC == nil) {
// hbox := ui.NewHorizontalBox() hbox := ui.NewHorizontalBox()
// hbox.SetPadded(true) hbox.SetPadded(true)
// uiC = hbox uiC = hbox
log.Println("gui.Node.AddTabRaw() FAIL *ui.Control == nil")
return n
} }
tab.Append(title, uiC) tab.Append(title, uiC)
/* newNode := n.New(title)
newNode := parent.makeNode(title, 555, 600 + Config.counter)
newNode.uiTab = tab newNode.uiTab = tab
newNode.uiBox = uiC newNode.uiBox = uiC
// panic("gui.AddTab() after makeNode()") // tabSetMargined(newNode.uiTab)
tabSetMargined(newNode.uiTab) return newNode
*/
return n
} }
*/

40
text.go Normal file
View File

@ -0,0 +1,40 @@
package gui
import "log"
import "errors"
// import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
// functions for handling text related GUI elements
func (n *Node) NewLabel(text string) *Node {
// make new node here
newNode := n.New(text)
newNode.Dump()
t := n.Toolkit.NewLabel(text)
newNode.Toolkit = t
return newNode
}
func (n *Node) SetText(value string) error {
log.Println("gui.SetText() value =", value)
if (n.Toolkit != nil) {
n.Toolkit.SetText(value)
return nil
}
if (n.uiText != nil) {
n.uiText.SetText(value)
return nil
}
if (n.uiButton != nil) {
n.uiButton.SetText(value)
return nil
}
if (n.uiWindow != nil) {
n.uiWindow.SetTitle(value)
return nil
}
return errors.New("nothing found for gui.Node.SetText()")
}

49
toolkit/andlabs/box.go Normal file
View File

@ -0,0 +1,49 @@
package toolkit
import "log"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
// create a new box
func (t *Toolkit) GetBox() *ui.Box {
return t.uiBox
}
// create a new box
func (t *Toolkit) NewBox() *Toolkit {
log.Println("gui.Toolbox.NewBox() START create default")
t.Dump()
if (t.uiGroup != nil) {
log.Println("gui.Toolbox.NewBox() is a Group")
var newTK Toolkit
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
t.uiGroup.SetChild(vbox)
newTK.uiBox = vbox
return &newTK
}
if (t.uiBox != nil) {
log.Println("gui.Toolbox.NewBox() is a Box")
// return t
}
log.Println("gui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box")
t.Dump()
return nil
}
// Make a new box
func MakeBox(name string) *Toolkit {
var newt Toolkit
vbox := ui.NewVerticalBox()
vbox.SetPadded(border)
newt.uiBox = vbox
newt.Name = name
log.Println("gui.Toolbox.MakeBox() name =", name)
newt.Dump()
return &newt
}

50
toolkit/andlabs/button.go Normal file
View File

@ -0,0 +1,50 @@
package toolkit
import "log"
import "os"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
// make new Group here
func (t Toolkit) NewButton(name string) *Toolkit {
var newt Toolkit
var b *ui.Button
if (t.uiBox == nil) {
log.Println("gui.ToolboxNode.NewButton() node.UiBox == nil. I can't add a range UI element without a place to put it")
log.Println("probably could just make a box here?")
os.Exit(0)
return nil
}
log.Println("gui.Toolbox.NewGroup() create", name)
b = ui.NewButton(name)
newt.uiButton = b
b.OnClicked(func(*ui.Button) {
log.Println("TODO: IN TOOLKIT GOROUTINE. SHOULD LEAVE HERE VIA channels. button name =", name)
t.Dump()
newt.Dump()
log.Println("wit/gui/toolkit NewButton() Should do something here")
if (newt.Custom == nil) {
log.Println("wit/gui/toolkit NewButton() toolkit.Custom == nil")
} else {
log.Println("wit/gui/toolkit NewButton() toolkit.Custom() START")
newt.Custom()
log.Println("wit/gui/toolkit NewButton() toolkit.Custom() END")
}
if (t.Custom == nil) {
log.Println("wit/gui/toolkit NewButton() parent toolkit.Custom == nil")
} else {
log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() START (IS THIS A BAD IDEA?)")
t.Custom()
log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() END (IS THIS A BAD IDEA?)")
}
log.Println("TODO: LEFT TOOLKIT GOROUTINE button name =", name)
})
t.uiBox.Append(b, false)
return &newt
}

View File

@ -1,59 +1,37 @@
package toolkit package toolkit
import "log" import "log"
import "os"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
// make new Group here // make new Group here
func NewGroup(b *ui.Box, title string) *Toolkit { func (t Toolkit) NewGroup(title string) *Toolkit {
var t Toolkit var newt Toolkit
if (b == nil) { if (t.uiBox == nil) {
log.Println("gui.ToolboxNode.NewSpinbox() node.UiBox == nil. I can't add a range UI element without a place to put it") log.Println("gui.ToolboxNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
return &t log.Println("probably could just make a box here?")
os.Exit(0)
return nil
} }
log.Println("gui.Toolbox.NewGroup() create", title) log.Println("gui.Toolbox.NewGroup() create", title)
g := ui.NewGroup(title) g := ui.NewGroup(title)
g.SetMargined(true) g.SetMargined(true)
t.uiGroup = g t.uiBox.Append(g, streachy)
t.uiBox = b
t.uiBox.Append(g, false)
return &t hbox := ui.NewVerticalBox()
hbox.SetPadded(true)
g.SetChild(hbox)
newt.uiGroup = g
newt.uiBox = hbox
newt.Name = title
t.Dump()
newt.Dump()
// panic("toolkit.NewGroup")
return &newt
} }
// create a new box
func (t *Toolkit) GetBox() *ui.Box {
return t.uiBox
}
// create a new box
func (t *Toolkit) NewBox() *Toolkit {
log.Println("gui.Toolbox.NewBox() START create default")
if (t.uiGroup != nil) {
log.Println("gui.Toolbox.NewBox() is a Group")
var newTK Toolkit
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
t.uiGroup.SetChild(vbox)
newTK.uiBox = vbox
return &newTK
}
log.Println("gui.Toolbox.NewBox() FAILED")
return nil
}
/*
func (n *Node) NewGroup(title string) *Node {
group := ui.NewGroup(title)
group.SetMargined(true)
hbox.Append(group, true)
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
group.SetChild(vbox)
*/

View File

@ -1,23 +1,31 @@
package toolkit package toolkit
import "log" import "log"
import "os"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
func NewLabel(b *ui.Box, name string) *Toolkit { // func NewLabel(b *ui.Box, name string) *Toolkit {
func (t *Toolkit) NewLabel(name string) *Toolkit {
// make new node here // make new node here
log.Println("gui.Toolbox.NewLabel", name) log.Println("gui.Toolbox.NewLabel", name)
var t Toolkit
if (b == nil) { if (t.uiBox == nil) {
log.Println("gui.ToolboxNode.NewLabel() node.UiBox == nil. I can't add a range UI element without a place to put it") log.Println("gui.ToolboxNode.NewLabel() node.UiBox == nil. I can't add a range UI element without a place to put it")
return &t os.Exit(0)
return nil
} }
l := ui.NewLabel(name) var newt Toolkit
t.uiLabel = l newt.uiLabel = ui.NewLabel(name)
t.uiBox = b newt.uiBox = t.uiBox
t.uiBox.Append(l, false) t.uiBox.Append(newt.uiLabel, false)
log.Println("parent toolkit")
t.Dump()
log.Println("newt toolkit")
newt.Dump()
// panic("got here")
return &t return &newt
} }

View File

@ -1,38 +1,44 @@
package toolkit package toolkit
import "log" import "log"
import "os"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
import "github.com/davecgh/go-spew/spew" import "github.com/davecgh/go-spew/spew"
func NewSlider(b *ui.Box, name string, x int, y int) *Toolkit { // func NewSlider(b *ui.Box, name string *Toolkit {
func (t Toolkit) NewSlider(title string, x int, y int) *Toolkit {
// make new node here // make new node here
log.Println("gui.Toolbox.NewSpinbox()", x, y) log.Println("gui.Toolbox.NewSpinbox()", x, y)
var t Toolkit var newt Toolkit
if (b == nil) { if (t.uiBox == nil) {
log.Println("gui.ToolboxNode.NewSpinbox() node.UiBox == nil. I can't add a range UI element without a place to put it") log.Println("gui.ToolboxNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
return &t log.Println("probably could just make a box here?")
os.Exit(0)
return nil
} }
s := ui.NewSlider(x, y) s := ui.NewSlider(x, y)
t.uiSlider = s newt.uiSlider = s
t.uiBox = b newt.uiBox = t.uiBox
t.uiBox.Append(s, false) t.uiBox.Append(s, false)
s.OnChanged(func(spin *ui.Slider) { s.OnChanged(func(spin *ui.Slider) {
i := spin.Value() i := spin.Value()
log.Println("gui.Toolbox.ui.Slider.OnChanged() val =", i)
if (DebugToolkit) { if (DebugToolkit) {
log.Println("gui.Toolbox.ui.OnChanged() val =", i) log.Println("gui.Toolbox.ui.OnChanged() val =", i)
scs := spew.ConfigState{MaxDepth: 1} scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(t) scs.Dump(newt)
} }
if (t.OnChanged != nil) { if (t.OnChanged != nil) {
log.Println("gui.Toolbox.OnChanged() entered val =", i) log.Println("gui.Toolbox.OnChanged() entered val =", i)
t.OnChanged(&t) newt.OnChanged(&newt)
} }
}) })
return &t return &newt
} }

View File

@ -14,7 +14,7 @@ func NewSpinbox(b *ui.Box, name string, x int, y int) *Toolkit {
if (b == nil) { if (b == nil) {
log.Println("gui.ToolboxNode.NewSpinbox() node.UiBox == nil. I can't add a range UI element without a place to put it") log.Println("gui.ToolboxNode.NewSpinbox() node.UiBox == nil. I can't add a range UI element without a place to put it")
return &t return nil
} }
spin := ui.NewSpinbox(x, y) spin := ui.NewSpinbox(x, y)
t.uiSpinbox = spin t.uiSpinbox = spin

View File

@ -9,6 +9,10 @@ import "github.com/davecgh/go-spew/spew"
var DebugToolkit bool = false var DebugToolkit bool = false
var streachy = true
var border = true
// stores the raw toolkit internals // stores the raw toolkit internals
type Toolkit struct { type Toolkit struct {
id string id string
@ -18,8 +22,12 @@ type Toolkit struct {
Height int Height int
OnChanged func(*Toolkit) OnChanged func(*Toolkit)
OnExit func(*Toolkit)
Custom func()
uiBox *ui.Box uiBox *ui.Box
uiBox2 *ui.Box // temporary hack while implementing tabs
uiButton *ui.Button uiButton *ui.Button
uiControl *ui.Control uiControl *ui.Control
uiEntry *ui.Entry uiEntry *ui.Entry
@ -30,11 +38,7 @@ type Toolkit struct {
uiTab *ui.Tab uiTab *ui.Tab
uiText *ui.EditableCombobox uiText *ui.EditableCombobox
uiWindow *ui.Window uiWindow *ui.Window
} UiWindowBad *ui.Window
func (t *Toolkit) Dump() {
log.Println("gui.Toolkit.Dump() uiBox =", t.uiBox)
log.Println("gui.Toolkit.Dump() uiGroup =", t.uiGroup)
} }
func (t *Toolkit) GetText() string { func (t *Toolkit) GetText() string {
@ -68,6 +72,31 @@ func (t *Toolkit) SetText(s string) bool {
return false return false
} }
func sanity(t *Toolkit) bool {
if (DebugToolkit) {
log.Println("gui.Toolkit.Value() Enter")
scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(t)
}
if (t.uiEntry == nil) {
if (DebugToolkit) {
log.Println("gui.Toolkit.Value() =", t.uiEntry.Text)
}
return false
}
return true
}
func (t *Toolkit) SetValue(i int) bool {
log.Println("gui.Toolkit.SetValue() START")
if (sanity(t)) {
return false
}
t.Dump()
// panic("got to toolkit.SetValue")
return true
}
func (t *Toolkit) Value() int { func (t *Toolkit) Value() int {
if (DebugToolkit) { if (DebugToolkit) {
log.Println("gui.Toolkit.Value() Enter") log.Println("gui.Toolkit.Value() Enter")
@ -93,3 +122,28 @@ func (t *Toolkit) Value() int {
log.Println("gui.Toolkit.Value() Could not find a ui element to get a value from") log.Println("gui.Toolkit.Value() Could not find a ui element to get a value from")
return 0 return 0
} }
func (t *Toolkit) Dump() {
log.Println("gui.Toolkit.Dump()", t.Name, t.Width, t.Height)
if (t.uiBox != nil) {
log.Println("gui.Toolkit.Dump() uiBox =", t.uiBox)
}
if (t.uiButton != nil) {
log.Println("gui.Toolkit.Dump() uiButton =", t.uiButton)
}
if (t.uiWindow != nil) {
log.Println("gui.Toolkit.Dump() uiWindow =", t.uiWindow)
}
if (t.uiTab != nil) {
log.Println("gui.Toolkit.Dump() uiTab =", t.uiTab)
}
if (t.uiGroup != nil) {
log.Println("gui.Toolkit.Dump() uiGroup =", t.uiGroup)
}
if (t.uiSlider != nil) {
log.Println("gui.Toolkit.Dump() uiSlider =", t.uiSlider)
}
if (t.OnExit != nil) {
log.Println("gui.Toolkit.Dump() uiExit =", t.OnExit)
}
}

143
toolkit/andlabs/tab.go Normal file
View File

@ -0,0 +1,143 @@
package toolkit
import (
"log"
"time"
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
)
/*
This adds a tab
andlabs/ui is goofy in the sense that you have to determine
if the ui.Window already has a tab in it. If it does, then
you need to add this tab and not run SetChild() on the window
or instead it replaces the existing tab with the new one
I work around this by always sending a Toolkit that is a tab
once there is one. If you send a Window here, it will replace
any existing tabs rather than adding a new one
*/
func (t *Toolkit) AddTab(name string) *Toolkit {
var w *ui.Window
var newt *Toolkit
log.Println("gui.Toolbox.AddTab() sleep 3")
w = t.uiWindow
if (w == nil) {
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
return nil
}
if (t.uiTab == nil) {
// this means you have to make a new tab
log.Println("gui.Toolbox.NewTab() GOOD. This should be the first tab:", name)
newt = newTab(w, name)
t.uiTab = newt.uiTab
} else {
log.Println("gui.Toolbox.NewTab() GOOD. This should be an additional tab:", name)
newt = t.appendTab(name)
// this means you have to append a tab
}
log.Println("t:")
t.Dump()
log.Println("newt:")
newt.Dump()
return newt
}
func (t *Toolkit) SetTabBox(box *ui.Box) {
var tab *ui.Tab
log.Println("wit/gui/toolkit SetTabBox()")
t.Dump()
if (t.uiTab == nil) {
log.Println("wit/gui/toolkit SetTabBox() got uiTab == nil")
panic("fucknuts")
return
}
if (t.uiBox == nil) {
log.Println("wit/gui/toolkit SetTabBox() got uiBox == nil. Appending a new tab here")
tab = t.uiTab
tab.Append(t.Name, box)
tabSetMargined(tab)
return
} else {
log.Println("wit/gui/toolkit SetTabBox() got uiBox != nil. Appending the box to the existing box strechy = true")
t.uiBox.Append(box, true) // strechy == true
t.uiBox2 = box
// t.uiBox.Append(box, false) // strechy == false
return
}
}
// This sets _all_ the tabs to Margin = true
//
// TODO: do proper tab tracking (will be complicated). low priority
func tabSetMargined(tab *ui.Tab) {
c := tab.NumPages()
for i := 0; i < c; i++ {
tab.SetMargined(i, true)
}
}
func newTab(w *ui.Window, name string) *Toolkit {
log.Println("gui.Toolbox.NewTab() ADD", name)
var t Toolkit
if (w == nil) {
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
time.Sleep(1 * time.Second)
return nil
}
log.Println("gui.Toolbox.AddTab() START name =", name)
// time.Sleep(2 * time.Second)
tab := ui.NewTab()
w.SetMargined(true)
hbox := ui.NewHorizontalBox() // this makes everything go along the horizon
// hbox := ui.NewVerticalBox()
hbox.SetPadded(true)
tab.Append(name, hbox)
w.SetChild(tab)
t.uiWindow = w
t.uiTab = tab
t.uiBox = hbox
// tabSetMargined(newNode.uiTab)
return &t
}
func (t *Toolkit) appendTab(name string) *Toolkit {
log.Println("gui.Toolbox.NewTab() ADD", name)
var newT Toolkit
if (t.uiWindow == nil) {
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
log.Println("gui.Toolbox.NewTab() node.UiWindow == nil. I can't add a tab without a window")
time.Sleep(1 * time.Second)
return nil
}
log.Println("gui.Toolbox.AddTab() START name =", name)
hbox := ui.NewHorizontalBox() // this makes everything go along the horizon
// hbox := ui.NewVerticalBox()
hbox.SetPadded(true)
t.uiTab.Append(name, hbox)
// w.SetChild(tab)
newT.uiWindow = t.uiWindow
newT.uiTab = t.uiTab
newT.uiBox = hbox
// tabSetMargined(newNode.uiTab)
return &newT
}

45
toolkit/andlabs/window.go Normal file
View File

@ -0,0 +1,45 @@
package toolkit
import (
"log"
"os"
"github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest"
)
func (t *Toolkit) MessageWindow(msg1 string, msg2 string) {
ui.MsgBox(t.uiWindow, msg1, msg2)
}
func (t *Toolkit) ErrorWindow(msg1 string, msg2 string) {
ui.MsgBoxError(t.uiWindow, msg1, msg2)
}
func NewWindow(title string, x int, y int) *Toolkit {
var t Toolkit
log.Println("toolkit NewWindow", title, x, y)
w := ui.NewWindow(title, x, y, false)
w.SetBorderless(false)
w.OnClosing(func(*ui.Window) bool {
log.Println("ui.Window().OnExit() SHOULD ATTEMPT CALLBACK here")
t.Dump()
if (t.OnExit != nil) {
log.Println("ui.Window().OnExit() ATTEMPTING toolkit.OnExit CALLBACK")
t.OnExit(&t)
}
if (t.Custom != nil) {
log.Println("ui.Window().Custom() ATTEMPTING toolkit.Custom CALLBACK")
t.Custom()
}
log.Println("ui.Window().OnExit() Toolkit.OnExit is nil")
t.Dump()
os.Exit(0)
return true
})
w.SetMargined(true)
w.Show()
t.uiWindow = w
t.UiWindowBad = w // deprecate this as soon as possible
return &t
}

186
toolkit/gocui/mouse.go Normal file
View File

@ -0,0 +1,186 @@
// 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 toolkit
import (
"errors"
"fmt"
"log"
"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.Println("Found andlabs Running custom function for the mouse click")
Custom(name)
// panic("got andlabs")
}
func Init() {
log.Println("start Init()")
f, err := os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer f.Close()
log.SetOutput(f)
log.Println("This is a test log entry")
g, err = gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
log.Panicln(err)
}
g.Cursor = true
g.Mouse = true
g.SetManagerFunc(layout)
if err := keybindings(g); err != nil {
log.Panicln(err)
}
log.Println("exit Init()")
}
func StartConsoleMouse() {
defer g.Close()
log.Println("start Main()")
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
log.Panicln(err)
}
log.Println("exit Main()")
}
func layout(g *gocui.Gui) error {
if v, err := g.SetView("but1", 2, 2, 22, 17, 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")
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.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
}
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 {
if !errors.Is(err, gocui.ErrUnknownView) {
return err
}
mouseClick(l)
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")
return nil
}

View File

@ -13,14 +13,21 @@ func NewStandardWindow(title string) *Node {
Config.Exit = StandardClose Config.Exit = StandardClose
return NewWindow() return NewWindow()
} }
func ToolkitDemoWindow() {
//
// This creates a window that shows how the toolkit works
// internally using it's raw unchanged code for the toolkit itself
//
// This is a way to test and see if the toolkit is working at all
// right now it shows the andlabs/ui/DemoNumbersPage()
//
func DemoToolkitWindow() {
var w, d *Node var w, d *Node
var tk *toolkit.Toolkit var tk *toolkit.Toolkit
w = NewStandardWindow("Demo of the GUI Toolkit") w = NewStandardWindow("Demo of the GUI Toolkit")
d = w.makeNode("demo", 767, 676 + Config.counter) d = w.New("demo")
d.Name = "demo"
tk = toolkit.DemoNumbersPage(w.uiWindow) tk = toolkit.DemoNumbersPage(w.uiWindow)
tk.OnChanged = func(t *toolkit.Toolkit) { tk.OnChanged = func(t *toolkit.Toolkit) {

20
window-demo.go Normal file
View File

@ -0,0 +1,20 @@
package gui
import "log"
// import "time"
// import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
//
// This creates a window that shows how this package works
//
func DemoWindow() {
var w, t1 *Node
log.Println("DemoWindow() START")
w = NewStandardWindow("Demo of WIT/GUI")
t1 = w.DebugTab("WIT GUI Debug Tab t1")
t1.DebugTab("WIT GUI Debug Tab t2")
log.Println("DemoWindow() END")
}

View File

@ -26,12 +26,12 @@ func GolangDebugWindow() {
Config.Exit = StandardClose Config.Exit = StandardClose
w = NewWindow() w = NewWindow()
t = w.AddTab("Debug Tab", nil) t = w.NewTab("Debug Tab")
log.Println("debugWindow() START") log.Println("debugWindow() START")
/////////////////////////////// Column DEBUG GOLANG ////////////////////// /////////////////////////////// Column DEBUG GOLANG //////////////////////
g := t.NewGroup("GO Language") g := t.AddGroup("GO Language")
g.AddButton("runtime.Stack()", func (*Node) { g.AddButton("runtime.Stack()", func (*Node) {
log.Println("\tSTART") log.Println("\tSTART")

128
window.go
View File

@ -2,13 +2,15 @@ package gui
import ( import (
"log" "log"
"fmt"
"strconv" "strconv"
"github.com/andlabs/ui" // "github.com/andlabs/ui"
_ "github.com/andlabs/ui/winmanifest" // _ "github.com/andlabs/ui/winmanifest"
) )
import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
/*
func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) { func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) {
ui.MsgBox(gw.UiWindow, msg1, msg2) ui.MsgBox(gw.UiWindow, msg1, msg2)
} }
@ -16,6 +18,7 @@ func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) {
func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) { func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) {
ui.MsgBoxError(gw.UiWindow, msg1, msg2) ui.MsgBoxError(gw.UiWindow, msg1, msg2)
} }
*/
func DeleteWindow(name string) { func DeleteWindow(name string) {
log.Println("gui.DeleteWindow() START name =", name) log.Println("gui.DeleteWindow() START name =", name)
@ -58,96 +61,8 @@ func DeleteWindow(name string) {
} }
} }
/* // func mapWindowOld(parent *Node, window *ui.Window, title string, x int, y int) *Node {
generic function to create a newnode structure on the tree of nodes func mapWindow(title string, w int, h int) *Node {
If the parent is null, it tries to find out where it should go otherwise
it creates a new window or new tab depending on the toolkit or OS
*/
func makeNode(parent *Node, title string, x int, y int) *Node {
var node Node
node.Name = title
node.Width = x
node.Height = y
id := Config.prefix + strconv.Itoa(Config.counter)
Config.counter += 1
node.id = id
// 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
}
func (parent *Node) makeNode(title string, x int, y int) *Node {
var node Node
node.Name = title
node.Width = x
node.Height = y
id := Config.prefix + strconv.Itoa(Config.counter)
Config.counter += 1
node.id = id
parent.Append(&node)
node.parent = parent
return &node
}
func (n *Node) AddNode(title string) *Node {
var node Node
node.Name = title
node.Width = n.Width
node.Height = n.Height
id := Config.prefix + strconv.Itoa(Config.counter)
Config.counter += 1
node.id = id
n.Append(&node)
node.parent = n
return &node
}
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(parent *Node, window *ui.Window, title string, x int, y int) *Node {
log.Println("gui.WindowMap START title =", title) log.Println("gui.WindowMap START title =", title)
if Data.WindowMap[title] != nil { if Data.WindowMap[title] != nil {
log.Println("Data.WindowMap[title] already exists title =", title) log.Println("Data.WindowMap[title] already exists title =", title)
@ -161,10 +76,10 @@ func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Nod
} }
var newGuiWindow GuiWindow var newGuiWindow GuiWindow
newGuiWindow.Width = x newGuiWindow.Width = w
newGuiWindow.Height = y newGuiWindow.Height = h
newGuiWindow.Name = title newGuiWindow.Name = title
newGuiWindow.UiWindow = window // newGuiWindow.UiWindow = window
newGuiWindow.BoxMap = make(map[string]*GuiBox) newGuiWindow.BoxMap = make(map[string]*GuiBox)
newGuiWindow.EntryMap = make(map[string]*GuiEntry) newGuiWindow.EntryMap = make(map[string]*GuiEntry)
@ -175,9 +90,8 @@ func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Nod
box.Window = &newGuiWindow box.Window = &newGuiWindow
box.Name = title box.Name = title
node := makeNode(parent, title, x, y) node := addNode(title, w, h)
node.box = &box node.box = &box
node.uiWindow = window
box.node = node box.node = node
newGuiWindow.BoxMap["jcarrInitTest"] = &box newGuiWindow.BoxMap["jcarrInitTest"] = &box
@ -192,19 +106,30 @@ func mapWindow(parent *Node, window *ui.Window, title string, x int, y int) *Nod
// cross platform, must pass UI changes into the OS threads (that is // cross platform, must pass UI changes into the OS threads (that is
// my guess). // my guess).
func NewWindow() *Node { func NewWindow() *Node {
var n *Node
var t *toolkit.Toolkit
title := Config.Title title := Config.Title
w := Config.Width w := Config.Width
h := Config.Height h := Config.Height
f := Config.Exit f := Config.Exit
var n *Node n = mapWindow(title, w, h)
n = mapWindow(nil, nil, title, w, h) n.custom = f
box := n.box box := n.box
log.Println("gui.NewWindow() title = box.Name =", box.Name) log.Println("gui.NewWindow() title = box.Name =", box.Name)
n.uiNewWindow(box.Name, w, h) t = toolkit.NewWindow(title, w, h)
t.Custom = func () {
log.Println("GOT TO MY CUSTOM EXIT!!!! for window name:", box.Name)
f(n)
}
n.Toolkit = t
n.uiWindow = t.UiWindowBad // this is temporary
window := n.uiWindow window := n.uiWindow
/*
ui.OnShouldQuit(func() bool { ui.OnShouldQuit(func() bool {
log.Println("createWindow().Destroy() on node.Name =", n.Name) log.Println("createWindow().Destroy() on node.Name =", n.Name)
if (f != nil) { if (f != nil) {
@ -212,6 +137,7 @@ func NewWindow() *Node {
} }
return true return true
}) })
*/
box.Window.UiWindow = window box.Window.UiWindow = window
if(n.uiWindow == nil) { if(n.uiWindow == nil) {