summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile22
-rw-r--r--README-goreadme.md154
-rw-r--r--README.md174
-rw-r--r--button.go33
-rw-r--r--checkbox.go52
-rw-r--r--cmds/buttonplugin/Makefile9
-rw-r--r--cmds/buttonplugin/main.go77
-rw-r--r--cmds/console-ui-helloworld/keybindings.go2
-rw-r--r--cmds/debug/Makefile3
-rw-r--r--cmds/debug/main.go8
-rw-r--r--cmds/helloworld/main.go1
-rw-r--r--cmds/textbox/main.go24
-rw-r--r--common.go (renamed from text.go)45
-rw-r--r--doc.go48
-rw-r--r--dropdown.go69
-rw-r--r--example_window_debug.go23
-rw-r--r--example_window_demo.go10
-rw-r--r--example_window_demo_toolkit.go45
-rw-r--r--group.go33
-rw-r--r--int.go19
-rw-r--r--label.go20
-rw-r--r--main.go109
-rw-r--r--node.go13
-rw-r--r--plugin.go265
-rw-r--r--slider.go33
-rw-r--r--spinner.go32
-rw-r--r--structs.go77
-rw-r--r--tab.go23
-rw-r--r--textbox.go48
-rw-r--r--toolkit/andlabs2/Makefile4
-rw-r--r--toolkit/andlabs2/box.go66
-rw-r--r--toolkit/andlabs2/button.go67
-rw-r--r--toolkit/andlabs2/checkbox.go34
-rw-r--r--toolkit/andlabs2/common.go61
-rw-r--r--toolkit/andlabs2/demo.go92
-rw-r--r--toolkit/andlabs2/dropdown.go90
-rw-r--r--toolkit/andlabs2/group.go56
-rw-r--r--toolkit/andlabs2/label.go42
-rw-r--r--toolkit/andlabs2/main.go56
-rw-r--r--toolkit/andlabs2/plugin.go43
-rw-r--r--toolkit/andlabs2/slider.go48
-rw-r--r--toolkit/andlabs2/spinner.go30
-rw-r--r--toolkit/andlabs2/structs.go249
-rw-r--r--toolkit/andlabs2/tab.go147
-rw-r--r--toolkit/andlabs2/textbox.go70
-rw-r--r--toolkit/andlabs2/window.go78
-rw-r--r--toolkit/gocui/Makefile3
-rw-r--r--toolkit/gocui/button.go37
-rw-r--r--toolkit/gocui/gocui.go (renamed from toolkit/gocui/main.go)61
-rw-r--r--toolkit/gocui/greeter.go79
-rw-r--r--toolkit/gocui/group.go38
-rw-r--r--toolkit/gocui/keybindings.go24
-rw-r--r--toolkit/gocui/newJ.go46
-rw-r--r--toolkit/gocui/plugin.go28
-rw-r--r--toolkit/gocui/views.go1
-rw-r--r--toolkit/gocui/widget.go26
-rw-r--r--toolkit/gocui/window.go18
-rw-r--r--toolkit/hello/Makefile8
-rw-r--r--toolkit/hello/greeter.go23
-rw-r--r--toolkit/hello/main.go44
-rw-r--r--toolkit/widget.go (renamed from widget.go)20
-rw-r--r--watchdog.go23
-rw-r--r--window.go57
63 files changed, 2244 insertions, 996 deletions
diff --git a/Makefile b/Makefile
index 8cd82c7..7985c4a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,11 @@
all: README.md
@echo
- @echo "make cmds # will run all the cmds"
- @echo "make update # full git update"
+ @echo "make cmds # will run all the Example demos and commands"
+ @echo "make update # full git update of all the dependencies"
@echo
- make -C cmds/helloworld
+ #make -C cmds/helloworld
+ make plugins
# should update every go dependancy (?)
update:
@@ -33,6 +34,9 @@ cmds-textbox:
github:
git push origin master
git push github master
+ @echo
+ @echo check https://github.com/witorg/gui
+ @echo
doc:
GO111MODULE="off" godoc -v
@@ -45,6 +49,14 @@ README.md: doc.go
clean:
rm -f toolkit/*.so
-plugins:
- # GO111MODULE="off" go build -buildmode=plugin -o toolkit/test.so toolkit/gocui/*.go
+plugins: plugins-gocui plugins-andlabs2
+
+plugins-gocui:
make -C toolkit/gocui
+
+plugins-andlabs2:
+ cd toolkit/andlabs2/ && GO111MODULE="off" go build -buildmode=plugin -o ../andlabs2.so
+ # make -C toolkit/andlabs2
+
+objdump:
+ objdump -t toolkit/andlabs.so |less
diff --git a/README-goreadme.md b/README-goreadme.md
index 2a0470c..c48da62 100644
--- a/README-goreadme.md
+++ b/README-goreadme.md
@@ -1,33 +1,26 @@
# gui
-Package gui implements a abstraction layer for Go visual elements in
-a cross platform and library independent way. (hopefully this is will work)
-
-A quick overview of the features, some general design guidelines
-and principles for how this package should generally work:
+Package gui implements a abstraction layer for Go visual elements.
Definitions:
```go
-* Toolkit: the underlying library (MacOS gui, Windows gui, gtk, qt, etc)
-* Node: A binary tree of all the underlying GUI toolkit elements
+* Toolkit: the underlying GUI library (MacOS gui, Windows gui, gtk, qt, etc)
+* Node: A binary tree of all the underlying widgets
```
Principles:
```go
* 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
-* Try to use [Wikipedia Graphical widget] names
+* Widget names should try to match [Wikipedia Graphical widget]
+* When in doubt, search upward in the binary tree
+* It's ok to guess. Try to do something sensible.
```
-## Quick Start
-
-This section demonstrates how to quickly get started with spew. See the
-sections below for further details on formatting and configuration options.
+Quick Start
```go
// This creates a simple hello world window
@@ -42,6 +35,7 @@ var window *gui.Node // This is the beginning of the binary tree of widgets
// go will sit here until the window exits
func main() {
+ gui.Init()
gui.Main(helloworld)
}
@@ -78,37 +72,23 @@ GO111MODULE="off" go build -v -x
[./helloworld](./helloworld)
```
-## Toolkits
+Toolkits
-* Andlabs - [https://github.com/andlabs/ui](https://github.com/andlabs/ui)
+```go
+* andlabs - [https://github.com/andlabs/ui](https://github.com/andlabs/ui)
* gocui - [https://github.com/awesome-gocui/gocui](https://github.com/awesome-gocui/gocui)
+```
-The goal is to design something that will work with more than one.
-
-Right now, this abstraction is built on top of the go package 'andlabs/ui'
-which does the cross platform support.
-The next step is to intent is to allow this to work directly against GTK and QT.
+The next step is to allow this to work against go-gtk and go-qt.
-It should be able to add Fyne, WASM, native macos & windows, android and
+TODO: Add Fyne, WASM, native macos & windows, android and
hopefully also things like libSDL, faiface/pixel, slint
-## 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.
-
-## Debugging
-
-To dump variables with full newlines, indentation, type, and pointer
-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'
+-- quote from the minimalistic window manager 'evilwm'
## References
@@ -118,24 +98,12 @@ which might be useful
[Wikipedia Graphical widget]: [https://en.wikipedia.org/wiki/Graphical_widget](https://en.wikipedia.org/wiki/Graphical_widget)
[Github mirror]: [https://github.com/witorg/gui](https://github.com/witorg/gui)
+[Federated git pull]: [https://github.com/forgefed/forgefed](https://github.com/forgefed/forgefed)
```go
* [Wikipedia Graphical widget]
* [Github mirror]
-```
-
-## Variables
-
-```golang
-var PlugGocli *plugin.Plugin
-```
-
-```golang
-var PlugGocliOk bool
-```
-
-```golang
-var PlugHello *plugin.Plugin
+* [Federated git pull]
```
## Functions
@@ -154,102 +122,80 @@ TODO: make this smarter once this uses toolkit/
Creates a window helpful for debugging this package
-### func [DemoToolkitWindow](/example_window_demo_toolkit.go#L24)
-
-`func DemoToolkitWindow()`
-
-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 [DemoWindow](/example_window_demo.go#L10)
`func DemoWindow()`
This creates a window that shows how this package works
-### func [GetDebug](/structs.go#L24)
+### func [GetDebug](/structs.go#L25)
`func GetDebug() bool`
-### func [GetDebugToolkit](/structs.go#L36)
+### func [GetDebugToolkit](/structs.go#L37)
`func GetDebugToolkit() bool`
-### func [GocuiAddButton](/plugin.go#L108)
-
-`func GocuiAddButton(name string)`
-
### func [GolangDebugWindow](/example_window_golang_debug.go#L12)
`func GolangDebugWindow()`
-### func [IndentPrintln](/structs.go#L216)
+### func [IndentPrintln](/structs.go#L188)
`func IndentPrintln(a ...interface{})`
-### func [LoadPlugin](/plugin.go#L36)
-
-`func LoadPlugin(name string) *plugin.Plugin`
+### func [Init](/main.go#L41)
-### func [LookupJcarrButton](/plugin.go#L98)
+`func Init()`
-`func LookupJcarrButton()`
+### func [LoadToolkit](/plugin.go#L50)
-### func [Main](/main.go#L38)
+`func LoadToolkit(name string) bool`
-`func Main(f func())`
-
-### func [Queue](/main.go#L51)
-
-`func Queue(f func())`
+loads and initializes a toolkit (andlabs/ui, gocui, etc)
-Other goroutines must use this to access the GUI
+### func [Main](/main.go#L86)
-You can not acess / process the GUI thread directly from
-other goroutines. This is due to the nature of how
-Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
-For example: gui.Queue(NewWindow())
-
-### func [RunGreet](/plugin.go#L88)
+`func Main(f func())`
-`func RunGreet()`
+This should not pass a function
-### func [SetDebug](/structs.go#L28)
+### func [SetDebug](/structs.go#L29)
`func SetDebug(s bool)`
-### func [SetDebugToolkit](/structs.go#L40)
+### func [SetDebugToolkit](/structs.go#L41)
`func SetDebugToolkit(s bool)`
-### func [ShowDebugValues](/structs.go#L44)
+### func [ShowDebugValues](/structs.go#L45)
`func ShowDebugValues()`
-### func [StandardClose](/main.go#L57)
+### func [StandardClose](/main.go#L128)
`func StandardClose(n *Node)`
The window is destroyed but the application does not quit
-### func [StandardExit](/main.go#L65)
+### func [StandardExit](/main.go#L135)
`func StandardExit(n *Node)`
The window is destroyed but the application does not quit
-## Types
+### func [Watchdog](/watchdog.go#L16)
+
+`func Watchdog()`
-### type [Greeter](/plugin.go#L17)
+This program sits here.
+If you exit here, the whole thing will os.Exit()
-`type Greeter interface { ... }`
+This goroutine can be used like a watchdog timer
-TODO: could a protobuf work here?
+## Types
-### type [GuiConfig](/structs.go#L67)
+### type [GuiConfig](/structs.go#L68)
`type GuiConfig struct { ... }`
@@ -259,19 +205,19 @@ TODO: could a protobuf work here?
var Config GuiConfig
```
-### type [GuiOptions](/structs.go#L56)
+### type [GuiDebug](/structs.go#L56)
-`type GuiOptions struct { ... }`
+`type GuiDebug struct { ... }`
This struct can be used with go-arg
-### type [Node](/structs.go#L117)
+### type [Node](/structs.go#L87)
`type Node struct { ... }`
The Node is simply the name and the size of whatever GUI element exists
-#### func [NewStandardWindow](/example_window_demo_toolkit.go#L7)
+#### func [NewStandardWindow](/example_window_demo.go#L22)
`func NewStandardWindow(title string) *Node`
@@ -323,13 +269,13 @@ func main() {
You get a window
```
-### type [Widget](/widget.go#L12)
+### type [Symbol](/plugin.go#L17)
+
+`type Symbol any`
-`type Widget struct { ... }`
+## Sub Packages
-what names should be used? This is not part of [[Graphical Widget]]
-Event() seems like a good name.
-Could a protobuf be used here? (Can functions be passed?)
+* [toolkit](./toolkit)
---
Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)
diff --git a/README.md b/README.md
index 77acae7..844fee3 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,22 @@
# gui
-Package gui implements a abstraction layer for Go visual elements in
-a cross platform and library independent way. (hopefully this is will work)
-
-A quick overview of the features, some general design guidelines
-and principles for how this package should generally work:
+Package gui implements a abstraction layer for Go visual elements.
Definitions:
-* Toolkit: the underlying library (MacOS gui, Windows gui, gtk, qt, etc)
-* Node: A binary tree of all the underlying GUI toolkit elements
+* Toolkit: the underlying GUI library (MacOS gui, Windows gui, gtk, qt, etc)
+* Node: A binary tree of all the underlying widgets
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
-* Try to use [Wikipedia Graphical widget] names
-
-## Quick Start
+* Widget names should try to match [Wikipedia Graphical widget]
+* When in doubt, search upward in the binary tree
+* It's ok to guess. Try to do something sensible.
-This section demonstrates how to quickly get started with spew. See the
-sections below for further details on formatting and configuration options.
+Quick Start
```go
// This creates a simple hello world window
@@ -38,6 +31,7 @@ var window *gui.Node // This is the beginning of the binary tree of widgets
// go will sit here until the window exits
func main() {
+ gui.Init()
gui.Main(helloworld)
}
@@ -74,34 +68,21 @@ GO111MODULE="off" go build -v -x
[./helloworld](./helloworld)
```
-## Toolkits
+Toolkits
-The goal is to design something that will work with more than one.
+* andlabs - [https://github.com/andlabs/ui](https://github.com/andlabs/ui)
+* gocui - [https://github.com/awesome-gocui/gocui](https://github.com/awesome-gocui/gocui)
-Right now, this abstraction is built on top of the go package 'andlabs/ui'
-which does the cross platform support.
-The next step is to intent is to allow this to work directly against GTK and QT.
+The next step is to allow this to work against go-gtk and go-qt.
-It should be able to add Fyne, WASM, native macos & windows, android and
+TODO: Add Fyne, WASM, native macos & windows, android and
hopefully also things like libSDL, faiface/pixel, slint
-## 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.
-
-## Debugging
-
-To dump variables with full newlines, indentation, type, and pointer
-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'
+-- quote from the minimalistic window manager 'evilwm'
## References
@@ -111,56 +92,37 @@ which might be useful
* [Wikipedia Graphical widget](https://en.wikipedia.org/wiki/Graphical_widget)
* [Github mirror](https://github.com/witorg/gui)
+* [Federated git pull](https://github.com/forgefed/forgefed)
## Functions
-### func [DebugTab](/window-debug.go#L26)
-
-`func DebugTab()`
-
-this function is used by the examples to add a tab
-dynamically to the bugWin node
-TODO: make this smarter once this uses toolkit/
-
-### func [DebugWindow](/window-debug.go#L14)
-
-`func DebugWindow()`
-
-Creates a window helpful for debugging this package
+### func [GetDebug](/structs.go#L25)
-### func [DemoToolkitWindow](/window-demo-toolkit.go#L24)
+`func GetDebug() bool`
-`func DemoToolkitWindow()`
+### func [GetDebugToolkit](/structs.go#L37)
-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 [DemoWindow](/window-demo.go#L10)
-
-`func DemoWindow()`
+`func GetDebugToolkit() bool`
-This creates a window that shows how this package works
+### func [IndentPrintln](/structs.go#L188)
-### func [GetDebugToolkit](/structs.go#L28)
+`func IndentPrintln(a ...interface{})`
-`func GetDebugToolkit() bool`
+### func [Init](/main.go#L41)
-### func [GolangDebugWindow](/window-golang-debug.go#L20)
+`func Init()`
-`func GolangDebugWindow()`
+### func [LoadToolkit](/plugin.go#L37)
-### func [IndentPrintln](/structs.go#L199)
+`func LoadToolkit(name string)`
-`func IndentPrintln(a ...interface{})`
+loads and initializes a toolkit (andlabs/ui, gocui, etc)
-### func [Main](/main.go#L31)
+### func [Main](/main.go#L56)
`func Main(f func())`
-### func [Queue](/main.go#L42)
+### func [Queue](/main.go#L77)
`func Queue(f func())`
@@ -171,21 +133,42 @@ other goroutines. This is due to the nature of how
Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
For example: gui.Queue(NewWindow())
-### func [SetDebugToolkit](/structs.go#L24)
+### func [SetDebug](/structs.go#L29)
+
+`func SetDebug(s bool)`
+
+### func [SetDebugToolkit](/structs.go#L41)
`func SetDebugToolkit(s bool)`
-### func [ShowDebugValues](/structs.go#L32)
+### func [ShowDebugValues](/structs.go#L45)
`func ShowDebugValues()`
-### func [StandardClose](/window-golang-debug.go#L12)
+### func [StandardClose](/main.go#L83)
`func StandardClose(n *Node)`
+The window is destroyed but the application does not quit
+
+### func [StandardExit](/main.go#L90)
+
+`func StandardExit(n *Node)`
+
+The window is destroyed but the application does not quit
+
+### func [Watchdog](/watchdog.go#L16)
+
+`func Watchdog()`
+
+This program sits here.
+If you exit here, the whole thing will os.Exit()
+
+This goroutine can be used like a watchdog timer
+
## Types
-### type [GuiConfig](/structs.go#L56)
+### type [GuiConfig](/structs.go#L68)
`type GuiConfig struct { ... }`
@@ -195,20 +178,18 @@ For example: gui.Queue(NewWindow())
var Config GuiConfig
```
-### type [GuiOptions](/structs.go#L44)
+### type [GuiOptions](/structs.go#L56)
`type GuiOptions struct { ... }`
-### type [Node](/structs.go#L104)
+This struct can be used with go-arg
+
+### type [Node](/structs.go#L87)
`type Node struct { ... }`
The Node is simply the name and the size of whatever GUI element exists
-#### func [NewStandardWindow](/window-demo-toolkit.go#L7)
-
-`func NewStandardWindow(title string) *Node`
-
#### func [NewWindow](/window.go#L15)
`func NewWindow() *Node`
@@ -220,46 +201,15 @@ 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).
-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.
-
-```golang
-package main
-
-import (
- "git.wit.org/wit/gui"
-)
+### type [Symbol](/plugin.go#L17)
-func main() {
- // 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()
+`type Symbol any`
-}
-
-```
-
- Output:
-
-```
-You get a window
-```
+## Sub Packages
-### type [Widget](/structs.go#L74)
+* [need-to-redo](./need-to-redo)
-`type Widget int`
+* [toolkit](./toolkit)
---
Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)
diff --git a/button.go b/button.go
index 7b01e1e..c14988f 100644
--- a/button.go
+++ b/button.go
@@ -3,38 +3,25 @@ package gui
import "log"
func (n *Node) NewButton(name string, custom func()) *Node {
- if (n.toolkit == nil) {
- log.Println("gui.Node.NewButton() filed node.toolkit == nil")
- panic("gui.Node.NewButton() filed node.toolkit == nil")
- return n
- }
newNode := n.New(name)
- newNode.toolkit = n.toolkit.NewButton(name)
-
- log.Println("gui.Node.NewButton()", name)
- if (PlugGocliOk) {
- log.Println("wit/gui gocui is loaded", PlugGocliOk)
- greeter.AddButton(name)
- log.Println("GOT HERE PlugGocliOk TRUE")
- } else {
- log.Println("GOT HERE PlugGocliOk FALSE")
- }
- // TODO: this is still confusing and probably wrong. This needs to communicate through a channel
- newNode.toolkit.Custom = func() {
- if (Config.Options.Debug) {
- log.Println("gui.Newutton() Button Clicked. Running custom() from outside toolkit START")
- }
+ newNode.Widget.Custom = func() {
+ log.Println("even newer clicker() name", newNode.Widget)
if (custom != nil) {
custom()
} else {
log.Println("wit/gui No callback function is defined for button name =", name)
}
- if (Config.Options.Debug) {
- log.Println("gui.NewButton() Button Clicked. Running custom() from outside toolkit END")
+ }
+
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewButton() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewButton == nil) {
+ log.Println("\tgui.NewButton() aplug.NewButton = nil", aplug.name)
+ continue
}
+ aplug.NewButton(&n.Widget, &newNode.Widget)
}
- newNode.custom = custom
return newNode
}
diff --git a/checkbox.go b/checkbox.go
index 0284920..0aa6aeb 100644
--- a/checkbox.go
+++ b/checkbox.go
@@ -2,34 +2,13 @@ package gui
import "log"
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
-
-func (n *Node) verify() {
- if (n.toolkit == nil) {
- log.Println("gui/wit node.Verify(): toolkit == nil", n.Name)
- panic("gui/wit node.Verify(): toolkit == nil")
- }
-}
-
func (n *Node) Checked() bool {
n.Dump()
return n.checked
}
-func (n *Node) NewCheckbox(name string) *Node {
- var newt *toolkit.Toolkit
- var c *Node
-
- log.Println("toolkit.NewCheckbox() START", name)
-
- n.verify()
-
- // make a *Node with a *toolkit.Group
- c = n.New(name + " part1")
- newt = n.toolkit.NewCheckbox(name)
- newt.Name = name
- c.toolkit = newt
- c.custom = n.custom
+/*
+This was the old code
newt.Custom = func () {
println("AM IN CALLBACK. SETTING NODE.checked START")
if newt.Checked() {
@@ -42,7 +21,30 @@ func (n *Node) NewCheckbox(name string) *Node {
commonCallback(c)
println("AM IN CALLBACK. SETTING NODE.checked END")
}
- c.Dump()
+*/
+
+
+func (n *Node) NewCheckbox(name string) *Node {
+ newNode := n.New(name)
+ newNode.custom = n.custom
+
+ newNode.Widget.Custom = func() {
+ log.Println("even newer clicker() name", newNode.Widget)
+ if (n.custom != nil) {
+ n.custom()
+ } else {
+ log.Println("wit/gui No callback function is defined for button name =", name)
+ }
+ }
+
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewCheckbox() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewCheckbox == nil) {
+ log.Println("\tgui.NewCheckbox() aplug.NewCheckbox = nil", aplug.name)
+ continue
+ }
+ aplug.NewCheckbox(&n.Widget, &newNode.Widget)
+ }
- return c
+ return newNode
}
diff --git a/cmds/buttonplugin/Makefile b/cmds/buttonplugin/Makefile
index cf60369..faa8882 100644
--- a/cmds/buttonplugin/Makefile
+++ b/cmds/buttonplugin/Makefile
@@ -1,5 +1,14 @@
+# with andlabs plugin loaded:
+# PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
+# 180006 jcarr 20 0 1918460 41688 31152 S 0.7 0.3 0:00.27 buttonplugin
+
+# with gocui plugin loaded:
+# 180365 jcarr 20 0 1392668 24364 12596 S 2.0 0.2 0:00.09 buttonplugin
+#
+
run: build
./buttonplugin >/tmp/buttonplugin.log 2>&1
+ # ./buttonplugin
build-release:
go get -v -u -x .
diff --git a/cmds/buttonplugin/main.go b/cmds/buttonplugin/main.go
index cd4d770..c296280 100644
--- a/cmds/buttonplugin/main.go
+++ b/cmds/buttonplugin/main.go
@@ -2,48 +2,97 @@
package main
import (
+ "fmt"
"log"
+ "time"
"strconv"
"git.wit.org/wit/gui"
)
+var title string = "Demo Plugin Window"
+
func main() {
+ fmt.Println("\033]0;" + title + "\007")
+ // time.Sleep(5 * time.Second)
+ // var w *gui.Node
// this doesn't seem to work
captureSTDOUT()
- gui.Main(buttonWindow)
+ // gui.LoadToolkit("default")
+ // panic("WTF gocui not happening")
+ // gui.LoadToolkit("gocui")
+ gui.Init()
+
+ // buttonWindow()
+ go gui.Main(func () {
+ log.Println("START Main f()")
+ buttonWindow()
+ /*
+ log.Println("END NewWindow()")
+ log.Println("START NewGroup()")
+ g := w.NewGroup("new Group 22")
+ log.Println("END NewGroup()")
+ g.NewButton("asdjkl", func () {
+ log.Println("world")
+ })
+ */
+ log.Println("END Main f()")
+ // gui.StandardExit(nil)
+ })
+ log.Println("Main() END")
+ time.Sleep(1 * time.Second)
+ gui.Watchdog()
+ gui.StandardExit(nil)
}
-var counter int = 10
+var counter int = 5
// This creates a window
func buttonWindow() {
var w, g *gui.Node
- gui.Config.Title = "Demo Plugin Window"
+ gui.Config.Title = title
gui.Config.Width = 640
gui.Config.Height = 480
w = gui.NewWindow()
g = w.NewGroup("buttonGroup")
+ g.NewButton("NewButton()", func () {
+ log.Println("new foobar 2. Adding button 'foobar 3'")
+ name := "foobar " + strconv.Itoa(counter)
+ counter += 1
+ g.NewButton(name, func () {
+ log.Println("Got all the way to main() name =", name)
+ })
+ })
+
+ g.NewButton("NewGroup()", func () {
+ log.Println("new foobar 2. Adding button 'foobar 3'")
+ name := "neat " + strconv.Itoa(counter)
+ counter += 1
+ g.NewGroup(name)
+ })
+
g.NewButton("hello", func () {
log.Println("world")
})
- g.NewButton("RunGreet()", func () {
- log.Println("world")
- go gui.RunGreet()
+ g.NewButton("LoadToolkit(andlabs2)", func () {
+ gui.LoadToolkit("andlabs2")
})
- g.NewButton("gui.LookupJcarrButton()", func () {
- log.Println("gui.LookupJcarrButton()")
- gui.LookupJcarrButton()
+ g.NewButton("LoadToolkit(gocui)", func () {
+ gui.LoadToolkit("gocui")
})
- g.NewButton("new foobar 2", func () {
- log.Println("new foobar 2. Adding button 'foobar 3'")
- name := "foobar " + strconv.Itoa(counter)
- counter += 1
- g.NewButton(name, nil)
+ g.NewButton("Init()", func () {
+ gui.Init()
+ })
+
+ g.NewButton("Main()", func () {
+ go gui.Main(func () {
+ w := gui.NewWindow()
+ w.NewGroup("buttonGroup")
+ })
})
}
diff --git a/cmds/console-ui-helloworld/keybindings.go b/cmds/console-ui-helloworld/keybindings.go
index fdac1ff..8c4623b 100644
--- a/cmds/console-ui-helloworld/keybindings.go
+++ b/cmds/console-ui-helloworld/keybindings.go
@@ -115,7 +115,7 @@ func initKeybindings(g *gocui.Gui) error {
func(g *gocui.Gui, v *gocui.View) error {
log.Println("help", v.Name())
tmp, _ := g.SetViewOnTop("help")
- log.Println("help 2", tmp.Name(), "blah")
+ log.Println("help 2", tmp.Name())
// g.SetView("help", 2, 2, 30, 15, 0);
g.SetCurrentView("help")
// moveView(g, tmp, 0, -delta)
diff --git a/cmds/debug/Makefile b/cmds/debug/Makefile
index 25c994d..5f979cc 100644
--- a/cmds/debug/Makefile
+++ b/cmds/debug/Makefile
@@ -2,4 +2,5 @@ run: build
./debug
build:
- go build
+ # go build
+ GO111MODULE="off" go build
diff --git a/cmds/debug/main.go b/cmds/debug/main.go
index 5e3a350..c0df70b 100644
--- a/cmds/debug/main.go
+++ b/cmds/debug/main.go
@@ -17,7 +17,9 @@ import (
func main() {
log.Println("Starting my Control Panel")
- go gui.Main(helloworld)
+ gui.Init()
+// go gui.Main(helloworld)
+ go gui.Main(gui.DebugWindow)
// go gui.DemoToolkitWindow()
watchGUI()
@@ -36,9 +38,9 @@ func watchGUI() {
gui.Config.Width = 800
gui.Config.Height = 300
gui.Config.Exit = myExit
- gui.Queue(gui.DebugWindow)
+ // gui.DebugWindow()
time.Sleep(1 * time.Second)
- gui.Queue(gui.DebugTab)
+ // gui.DebugTab()
}
}
}
diff --git a/cmds/helloworld/main.go b/cmds/helloworld/main.go
index 552ecb5..43aa08c 100644
--- a/cmds/helloworld/main.go
+++ b/cmds/helloworld/main.go
@@ -7,6 +7,7 @@ import (
)
func main() {
+ gui.Init()
gui.Main(helloworld)
}
diff --git a/cmds/textbox/main.go b/cmds/textbox/main.go
index faf8b86..b545d08 100644
--- a/cmds/textbox/main.go
+++ b/cmds/textbox/main.go
@@ -21,7 +21,7 @@ var args struct {
Foo string
Bar bool
LogOptions
- gui.GuiOptions
+ gui.GuiDebug
}
@@ -29,11 +29,13 @@ func main() {
arg.MustParse(&args)
fmt.Println(args.Foo, args.Bar, args.User)
- gui.Config.Options.Debug = args.Debug
- gui.Config.Options.DebugChange = args.DebugChange
- gui.Config.Options.DebugDump = args.DebugDump
- gui.Config.Options.DebugNode = args.DebugNode
- gui.Config.Options.DebugTabs = args.DebugTabs
+ gui.Config.Debug.Debug = args.Debug
+ /*
+ gui.Config.Debug.Change = args.DebugChange
+ gui.Config.Debug.Dump = args.DebugDump
+ gui.Config.Debug.Node = args.DebugNode
+ gui.Config.Debug.Tabs = args.DebugTabs
+ */
/*
f, err := os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
@@ -46,6 +48,7 @@ func main() {
log.Println("This is a test log entry")
*/
+ gui.Init()
gui.Main(initGUI)
}
@@ -62,6 +65,8 @@ func initGUI() {
addDemoTab(w, "A Simple Tab Demo")
addDemoTab(w, "A Second Tab")
+ /*
+ TODO: add these back
if (args.GuiDemo) {
gui.DemoToolkitWindow()
}
@@ -69,6 +74,7 @@ func initGUI() {
if (args.GuiDebug) {
gui.DebugWindow()
}
+ */
}
func addDemoTab(window *gui.Node, title string) {
@@ -80,9 +86,9 @@ func addDemoTab(window *gui.Node, title string) {
g = newNode.NewGroup("group 1")
dd := g.NewDropdown("demoCombo2")
- dd.AddDropdown("more 1")
- dd.AddDropdown("more 2")
- dd.AddDropdown("more 3")
+ dd.AddDropdownName("more 1")
+ dd.AddDropdownName("more 2")
+ dd.AddDropdownName("more 3")
dd.OnChanged = func(*gui.Node) {
s := dd.GetText()
tb.SetText("hello world " + args.User + "\n" + s)
diff --git a/text.go b/common.go
index 9603bff..27b96bd 100644
--- a/text.go
+++ b/common.go
@@ -6,30 +6,16 @@ import "regexp"
// 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(str string) bool {
- if (Config.Options.DebugChange) {
+ if (Config.Debug.Change) {
log.Println("gui.SetText() value =", str)
}
- if (n.toolkit == nil) {
- return false
- }
- return n.toolkit.SetText(str)
+ return true
}
func (n *Node) GetText() string {
- return n.toolkit.GetText()
+ return "not implemented"
}
/*
@@ -65,3 +51,28 @@ func normalizeInt(s string) string {
log.Println("normalizeInt() s =", clean)
return clean
}
+
+func commonCallback(n *Node) {
+ // TODO: make all of this common code to all the widgets
+ if (n.OnChanged == nil) {
+ if (Config.Debug.Change) {
+ log.Println("Not Running n.OnChanged(n) == nil")
+ }
+ } else {
+ if (Config.Debug.Change) {
+ log.Println("Running n.OnChanged(n)")
+ }
+ n.OnChanged(n)
+ }
+
+ if (n.custom == nil) {
+ if (Config.Debug.Change) {
+ log.Println("Not Running n.custom(n) == nil")
+ }
+ } else {
+ if (Config.Debug.Change) {
+ log.Println("Running n.custom()")
+ }
+ n.custom()
+ }
+}
diff --git a/doc.go b/doc.go
index 41e976f..344ba79 100644
--- a/doc.go
+++ b/doc.go
@@ -1,30 +1,23 @@
/*
-Package gui implements a abstraction layer for Go visual elements in
-a cross platform and library independent way. (hopefully this is will work)
-
-A quick overview of the features, some general design guidelines
-and principles for how this package should generally work:
+Package gui implements a abstraction layer for Go visual elements.
Definitions:
- * Toolkit: the underlying library (MacOS gui, Windows gui, gtk, qt, etc)
- * Node: A binary tree of all the underlying GUI toolkit elements
+ * Toolkit: the underlying GUI library (MacOS gui, Windows gui, gtk, qt, etc)
+ * Node: A binary tree of all the underlying widgets
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
- * Try to use [Wikipedia Graphical widget] names
+ * Widget names should try to match [Wikipedia Graphical widget]
+ * When in doubt, search upward in the binary tree
+ * It's ok to guess. Try to do something sensible.
Quick Start
-This section demonstrates how to quickly get started with spew. See the
-sections below for further details on formatting and configuration options.
-
// This creates a simple hello world window
package main
@@ -37,6 +30,7 @@ sections below for further details on formatting and configuration options.
// go will sit here until the window exits
func main() {
+ gui.Init()
gui.Main(helloworld)
}
@@ -73,35 +67,19 @@ I didn't record the dependances needed
Toolkits
-* Andlabs - https://github.com/andlabs/ui
-* gocui - https://github.com/awesome-gocui/gocui
-
-The goal is to design something that will work with more than one.
+ * andlabs - https://github.com/andlabs/ui
+ * gocui - https://github.com/awesome-gocui/gocui
-Right now, this abstraction is built on top of the go package 'andlabs/ui'
-which does the cross platform support.
-The next step is to intent is to allow this to work directly against GTK and QT.
+The next step is to allow this to work against go-gtk and go-qt.
-It should be able to add Fyne, WASM, native macos & windows, android and
+TODO: Add Fyne, WASM, native macos & windows, android and
hopefully also things like libSDL, faiface/pixel, slint
-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.
-
-Debugging
-
-To dump variables with full newlines, indentation, type, and pointer
-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'
+-- quote from the minimalistic window manager 'evilwm'
References
@@ -111,9 +89,11 @@ which might be useful
[Wikipedia Graphical widget]: https://en.wikipedia.org/wiki/Graphical_widget
[Github mirror]: https://github.com/witorg/gui
+[Federated git pull]: https://github.com/forgefed/forgefed
* [Wikipedia Graphical widget]
* [Github mirror]
+ * [Federated git pull]
*/
diff --git a/dropdown.go b/dropdown.go
index 583ea25..f500c55 100644
--- a/dropdown.go
+++ b/dropdown.go
@@ -2,61 +2,30 @@ package gui
import "log"
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
-
-func commonCallback(n *Node) {
- // TODO: make all of this common code to all the widgets
- if (n.OnChanged == nil) {
- if (Config.Options.DebugChange) {
- log.Println("Not Running n.OnChanged(n) == nil")
- }
- } else {
- if (Config.Options.DebugChange) {
- log.Println("Running n.OnChanged(n)")
+func (n *Node) AddDropdownName(name string) {
+ for _, aplug := range allPlugins {
+ log.Println("gui.AddDropdownName() aplug =", aplug.name, "name =", name)
+ if (aplug.AddDropdownName == nil) {
+ log.Println("\tgui.AddDropdownName() aplug.NewDropdown = nil", aplug.name)
+ continue
}
- n.OnChanged(n)
- }
-
- if (n.custom == nil) {
- if (Config.Options.DebugChange) {
- log.Println("Not Running n.custom(n) == nil")
- }
- } else {
- if (Config.Options.DebugChange) {
- log.Println("Running n.custom()")
- }
- n.custom()
+ aplug.AddDropdownName(&n.Widget, name)
}
}
-func (n *Node) NewDropdown(name string) *Node {
- var newT *toolkit.Toolkit
- var sNode *Node
-
- if (Config.Options.Debug) {
- log.Println("toolkit.NewDropdown() START", name)
- }
-
- n.verify()
-
- sNode = n.New(name + " part1")
- newT = n.toolkit.NewDropdown(name)
- newT.Name = name
- sNode.custom = n.custom
- newT.Custom = func () {
- commonCallback(sNode)
- }
- sNode.toolkit = newT
- sNode.Dump()
- // panic("checking Custom()")
-
- return sNode
+func (n *Node) SetDropdown(i int) {
}
-func (n *Node) AddDropdown(name string) {
- n.toolkit.AddDropdown(name)
-}
+func (n *Node) NewDropdown(text string) *Node {
+ newNode := n.New(text)
-func (n *Node) SetDropdown(i int) {
- n.toolkit.SetDropdown(i)
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewDropdown() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewDropdown == nil) {
+ log.Println("\tgui.NewDropdown() aplug.NewDropdown = nil", aplug.name)
+ continue
+ }
+ aplug.NewDropdown(&n.Widget, &newNode.Widget)
+ }
+ return newNode
}
diff --git a/example_window_debug.go b/example_window_debug.go
index 00ccfec..0c6503e 100644
--- a/example_window_debug.go
+++ b/example_window_debug.go
@@ -41,9 +41,9 @@ func debugFlags(n *Node) {
checkd = df.NewCheckbox("Debug")
checkd.OnChanged = func(*Node) {
- checkd.checked = checkd.toolkit.Checked()
- Config.Options.Debug = checkd.checked
- if (Config.Options.Debug) {
+ // checkd.checked = checkd.toolkit.Checked()
+ Config.Debug.Debug = true
+ if (Config.Debug.Debug) {
log.Println("Debug turned on")
} else {
log.Println("Debug turned off")
@@ -52,18 +52,17 @@ func debugFlags(n *Node) {
checkdn = df.NewCheckbox("Debug Node")
checkdn.OnChanged = func(*Node) {
- checkdn.checked = checkdn.toolkit.Checked()
- Config.Options.DebugNode = checkdn.checked
+ Config.Debug.Node = true
}
checkdd = df.NewCheckbox("Debug node.Dump()")
checkdd.OnChanged = func(*Node) {
- Config.Options.DebugDump = checkdd.toolkit.Checked()
+ Config.Debug.Dump = true
}
changeCheckbox = df.NewCheckbox("Debug Change")
changeCheckbox.OnChanged = func(*Node) {
- Config.Options.DebugChange = changeCheckbox.toolkit.Checked()
+ Config.Debug.Change = true
}
df.NewButton("Dump Debug Flags", func () {
@@ -83,20 +82,20 @@ func (n *Node) DebugTab(title string) *Node {
gog = newN.NewGroup("GOLANG")
gog.NewLabel("go language")
gog.NewButton("GO Language Debug", func () {
- GolangDebugWindow()
+ // GolangDebugWindow()
})
gog.NewLabel("wit/gui package")
gog.NewButton("WIT/GUI Package Debug", func () {
Config.Width = 640
Config.Height = 480
- Queue(DebugWindow)
+ // Queue(DebugWindow)
})
gog.NewButton("Demo wit/gui", func () {
- DemoWindow()
+ // DemoWindow()
})
gog.NewButton("Demo toolkit andlabs/ui", func () {
- DemoToolkitWindow()
+ // DemoToolkitWindow()
})
debugFlags(newN)
@@ -118,7 +117,7 @@ func (n *Node) DebugTab(title string) *Node {
if (dump == true) {
child.Dump()
}
- dd.AddDropdown(child.Name)
+ dd.AddDropdownName(child.Name)
}
dd.SetDropdown(0)
diff --git a/example_window_demo.go b/example_window_demo.go
index c4e0374..be07496 100644
--- a/example_window_demo.go
+++ b/example_window_demo.go
@@ -18,3 +18,13 @@ func DemoWindow() {
log.Println("DemoWindow() END")
}
+
+func NewStandardWindow(title string) *Node {
+ log.Println("NewStandardWindow() creating", title)
+
+ Config.Title = title
+ Config.Width = 640
+ Config.Height = 480
+ Config.Exit = StandardClose
+ return NewWindow()
+}
diff --git a/example_window_demo_toolkit.go b/example_window_demo_toolkit.go
deleted file mode 100644
index 0872448..0000000
--- a/example_window_demo_toolkit.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package gui
-
-import "log"
-// import "time"
-// import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
-
-func NewStandardWindow(title string) *Node {
- log.Println("NewStandardWindow() creating", title)
-
- Config.Title = title
- Config.Width = 640
- Config.Height = 480
- Config.Exit = StandardClose
- return NewWindow()
-}
-
-//
-// 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 *Node
-
- w = NewStandardWindow("Demo of the GUI Toolkit")
-
-// d = w.New("demo")
-
- w.toolkit.DemoNumbersPage()
- /*
- tk = w.Toolkit.DemoNumbersPage()
- tk.OnChanged = func(t *toolkit.Toolkit) {
- log.Println("toolkit.NewSlider() value =", t.Value())
- if (d.OnChanged != nil) {
- log.Println("toolkit.Demo() running node.OnChanged")
- d.OnChanged(d)
- }
- }
- d.Toolkit = tk
- */
-
- log.Println("ToolkitDemoWindow() END")
-}
diff --git a/group.go b/group.go
index 7e60b23..d82e99a 100644
--- a/group.go
+++ b/group.go
@@ -2,30 +2,41 @@ package gui
import "log"
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+// import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+// import newtoolkit "git.wit.org/wit/gui/toolkit"
// TODO: which name is better. AddGroup or NewGroup ?
// first reaction is NewGroup
func (n *Node) NewGroup(name string) *Node {
- var newT *toolkit.Toolkit
- var gNode *Node
+// var newT *toolkit.Toolkit
+ var newNode *Node
if (GetDebug()) {
log.Println("toolkit.NewGroup() START", name)
}
- if (n.toolkit == nil) {
- log.Println("toolkit.NewGroup() toolkit == nil")
- panic("toolkit should never be nil")
+// if (n.toolkit == nil) {
+// log.Println("toolkit.NewGroup() toolkit == nil")
+// panic("toolkit should never be nil")
+// }
+
+ newNode = n.New(name)
+
+ log.Println("gui.Node.NewGroup()", name)
+ for _, aplug := range allPlugins {
+ log.Println("gui.Node.NewGroup() toolkit plugin =", aplug.name)
+ if (aplug.NewGroup == nil) {
+ continue
+ }
+ aplug.NewGroup(&n.Widget, &newNode.Widget)
}
// make a *Node with a *toolkit.Group
- gNode = n.New(name)
- newT = n.toolkit.NewGroup(name)
- gNode.toolkit = newT
- gNode.Dump()
+ // newT = n.toolkit.NewGroup(name)
+ // newNode.toolkit = newT
+ // newNode.Dump()
- return gNode
+ return newNode
}
/*
diff --git a/int.go b/int.go
index 34e22e7..da27092 100644
--- a/int.go
+++ b/int.go
@@ -4,8 +4,6 @@ import "log"
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
@@ -16,18 +14,14 @@ import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
Is it "has to go" or "should go"? Probably it makes sense to strictly inforce it. No "callback" functions. IPC only (go channels)
*/
func (n *Node) Int() int {
- if (toolkit.DebugToolkit) {
+ if (Config.Debug.Toolkit) {
log.Println("gui.Node.Int() for node name =", n.Name)
scs := spew.ConfigState{MaxDepth: 1}
scs.Dump(n)
}
- if (n.toolkit == nil) {
- log.Println("gui.Node.Int() for toolkit struct = nil")
- return 0
- }
-
- i := n.toolkit.Value()
+ // i := n.toolkit.Value()
+ i := 3333
return i
}
@@ -38,11 +32,6 @@ func (n *Node) Value() 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)
+ // n.toolkit.SetValue(i)
}
diff --git a/label.go b/label.go
new file mode 100644
index 0000000..6542a68
--- /dev/null
+++ b/label.go
@@ -0,0 +1,20 @@
+package gui
+
+import "log"
+// import "errors"
+// import "regexp"
+
+func (n *Node) NewLabel(text string) *Node {
+ newNode := n.New(text)
+
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewLabel() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewLabel == nil) {
+ log.Println("\tgui.NewLabel() aplug.NewLabel = nil", aplug.name)
+ continue
+ }
+ aplug.NewLabel(&n.Widget, &newNode.Widget)
+ }
+
+ return newNode
+}
diff --git a/main.go b/main.go
index 21cbd02..ae22dc6 100644
--- a/main.go
+++ b/main.go
@@ -3,22 +3,29 @@ package gui
import (
"log"
"os"
+ "embed"
)
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+// Windows doesn't support plugins. How can I keep andlabs and only compile it on windows?
+// https://forum.heroiclabs.com/t/setting-up-goland-to-compile-plugins-on-windows/594/5
+// import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
const Xaxis = 0 // stack things horizontally
const Yaxis = 1 // stack things vertically
+// may this plugin work when all other plugins fail
+//go:embed toolkit/gocui.so
+var res embed.FS
+
func init() {
log.Println("gui.init() has been run")
Config.counter = 0
Config.prefix = "wit"
- // Config.Options.Debug = true
- // Config.Options.DebugNode = true
- // Config.Options.DebugTabs = true
+ // Config.Debug.Debug = true
+ // Config.Debug.Node = true
+ // Config.Debug.Tabs = true
title := "guiBinaryTree"
w := 640
@@ -26,45 +33,117 @@ func init() {
// Populates the top of the binary tree
Config.master = addNode(title, w, h)
- if (Config.Options.Debug) {
+ if (Config.Debug.Debug) {
Config.master.Dump()
}
+}
+
+func Init() {
+ var initBAD bool = true
+
+ if (Config.Debug.Debug) {
+ log.Println("Starting gui.Init()")
+ }
+ for _, aplug := range allPlugins {
+ log.Println("gui.LoadToolkit() already loaded toolkit plugin =", aplug.name)
+ initBAD = false
+ }
+
+ // the program didn't specify a plugin. Try to load one
+ // TODO: detect the OS & user preferences to load the best one
+ if (initBAD) {
+ if (LoadToolkit("andlabs2")) {
+ initBAD = false
+ }
+ }
+
+ // andlabs2 gui failed. fall back to the terminal gui (should be compiled into the binary)
+ if (initBAD) {
+ if (LoadToolkit("gocui")) {
+ initBAD = false
+ }
+ }
- // load the gocui plugin
- PlugGocli = LoadPlugin("../../toolkit/gocui.so")
- PlugGocliOk = false
+ // locate the shared library file
+ // panic("WTF Init()")
+ for _, aplug := range allPlugins {
+ log.Println("gui.Node.Init() toolkit plugin =", aplug.name)
+ if (aplug.InitOk) {
+ log.Println("gui.Node.Init() Already Ran Init()", aplug.name)
+ continue
+ }
+ if (aplug.Init == nil) {
+ log.Println("gui.Node.Main() Init == nil", aplug.name)
+ continue
+ }
+ aplug.InitOk = true
+ aplug.Init()
+ }
+ // StandardExit(nil)
}
+// This should not pass a function
func Main(f func()) {
- if (Config.Options.Debug) {
+ if (Config.Debug.Debug) {
log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
}
- toolkit.Main(f)
+ for _, aplug := range allPlugins {
+ log.Println("gui.Node.NewButton() toolkit plugin =", aplug.name)
+ if (aplug.MainOk) {
+ log.Println("gui.Node.Main() Already Ran Main()", aplug.name)
+ continue
+ }
+ if (aplug.Main == nil) {
+ log.Println("gui.Node.Main() Main == nil", aplug.name)
+ continue
+ }
+ aplug.MainOk = true
+ aplug.Main(f)
+ // f()
+ }
+ // toolkit.Main(f)
}
+// This should never be exposed(?)
+
// Other goroutines must use this to access the GUI
//
// You can not acess / process the GUI thread directly from
// other goroutines. This is due to the nature of how
// Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
// For example: gui.Queue(NewWindow())
-func Queue(f func()) {
+func queue(f func()) {
log.Println("Sending function to gui.Main() (using gtk via andlabs/ui)")
- toolkit.Queue(f)
+ // toolkit.Queue(f)
+ for _, aplug := range allPlugins {
+ log.Println("gui.Node.NewButton() toolkit plugin =", aplug.name)
+ if (aplug.Queue == nil) {
+ continue
+ }
+ aplug.Queue(f)
+ }
}
// The window is destroyed but the application does not quit
func StandardClose(n *Node) {
- if (Config.Options.Debug) {
+ if (Config.Debug.Debug) {
log.Println("wit/gui Standard Window Close. name =", n.Name)
}
}
-
// The window is destroyed but the application does not quit
func StandardExit(n *Node) {
- if (Config.Options.Debug) {
+ if (Config.Debug.Debug) {
log.Println("wit/gui Standard Window Exit. running os.Exit()")
}
+
+ log.Println("gui.Node.StandardExit() attempt to exit each toolkit plugin")
+ for i, aplug := range allPlugins {
+ log.Println("gui.Node.NewButton()", i, aplug)
+ if (aplug.Quit != nil) {
+ aplug.Quit()
+ }
+ }
+
os.Exit(0)
}
diff --git a/node.go b/node.go
index 57ad65d..c4641f5 100644
--- a/node.go
+++ b/node.go
@@ -1,5 +1,7 @@
package gui
+// import "git.wit.org/wit/gui/toolkit"
+
/*
generic function to create a new node on the binary tree
*/
@@ -16,11 +18,16 @@ func (n *Node) New(title string) *Node {
/*
raw create function for a new node struct
*/
-func addNode(title string, w int, h int) *Node {
+func addNode(title string, width int, height int) *Node {
var n Node
+
n.Name = title
- n.Width = w
- n.Height = h
+ n.Width = width
+ n.Height = height
+
+ n.Widget.Name = title
+ n.Widget.Width = width
+ n.Widget.Height = height
// no longer a string
// id := Config.prefix + strconv.Itoa(Config.counter)
diff --git a/plugin.go b/plugin.go
index 58e6dbe..e13f751 100644
--- a/plugin.go
+++ b/plugin.go
@@ -8,109 +8,234 @@ package gui
import (
"log"
"os"
-
"plugin"
- "github.com/davecgh/go-spew/spew"
+
+ "git.wit.org/wit/gui/toolkit"
)
-// TODO: could a protobuf work here?
-type Greeter interface {
- Greet()
- JcarrButton()
- AddButton(string)
+var err error
+type Symbol any
+
+type aplug struct {
+ // Ok bool
+ name string
+ filename string
+ plug *plugin.Plugin
+ sym *plugin.Symbol
+ LoadOk bool
+ InitOk bool
+ MainOk bool
+
+ Init func()
+ Main func(func ())
+ Queue func(func ())
+ Quit func()
+ NewWindow func(*toolkit.Widget)
+ NewButton func(*toolkit.Widget, *toolkit.Widget)
+ NewGroup func(*toolkit.Widget, *toolkit.Widget)
+ NewCheckbox func(*toolkit.Widget, *toolkit.Widget)
+ NewTab func(*toolkit.Widget, *toolkit.Widget)
+ NewLabel func(*toolkit.Widget, *toolkit.Widget)
+ NewTextbox func(*toolkit.Widget, *toolkit.Widget)
+ NewSlider func(*toolkit.Widget, *toolkit.Widget)
+ NewSpinner func(*toolkit.Widget, *toolkit.Widget)
+
+ NewDropdown func(*toolkit.Widget, *toolkit.Widget)
+ AddDropdownName func(*toolkit.Widget, string)
}
-var PlugGocli *plugin.Plugin
-var PlugGocliOk bool
-var PlugHello *plugin.Plugin
+var allPlugins []*aplug
+
+// loads and initializes a toolkit (andlabs/ui, gocui, etc)
+func LoadToolkit(name string) bool {
+ var newPlug aplug
+
+ log.Println("gui.LoadToolkit() START")
+ newPlug.LoadOk = false
+
+ for _, aplug := range allPlugins {
+ log.Println("gui.LoadToolkit() already loaded toolkit plugin =", aplug.name)
+ if (aplug.name == name) {
+ log.Println("gui.LoadToolkit() SKIPPING")
+ return true
+ }
+ }
+
+ // locate the shared library file
+ filename := name + ".so"
+ loadPlugin(&newPlug, filename)
+ if (newPlug.plug == nil) {
+ return false
+ }
+ // newPlug.Ok = true
+ newPlug.name = name
+
+ // map all the functions
+ newPlug.Init = loadFuncE(&newPlug, "Init")
+ newPlug.Quit = loadFuncE(&newPlug, "Quit")
+
+ // this should be laodFuncE()
+ newPlug.Main = loadFuncF(&newPlug, "Main")
+ newPlug.Queue = loadFuncF(&newPlug, "Queue")
+
+ newPlug.NewWindow = loadFunc1(&newPlug, "NewWindow")
+
+ newPlug.NewButton = loadFunc2(&newPlug, "NewButton")
+ newPlug.NewGroup = loadFunc2(&newPlug, "NewGroup")
+ newPlug.NewCheckbox = loadFunc2(&newPlug, "NewCheckbox")
+ newPlug.NewTab = loadFunc2(&newPlug, "NewTab")
+ newPlug.NewLabel = loadFunc2(&newPlug, "NewLabel")
+ newPlug.NewTextbox = loadFunc2(&newPlug, "NewTextbox")
+ newPlug.NewSlider = loadFunc2(&newPlug, "NewSlider")
+ newPlug.NewSpinner = loadFunc2(&newPlug, "NewSpinner")
+
+ newPlug.NewDropdown = loadFunc2(&newPlug, "NewDropdown")
+ newPlug.AddDropdownName = loadFuncS(&newPlug, "AddDropdownName")
-// var gBut plugin.Symbol
-var jcarrBut plugin.Symbol
-var symGreeter plugin.Symbol
-var greeter Greeter
-var ok bool
+ allPlugins = append(allPlugins, &newPlug)
-var typeToolkit plugin.Symbol
-var typeToolkitCast Greeter
+ log.Println("gui.LoadToolkit() END", newPlug.name, filename)
+ newPlug.LoadOk = true
+ return true
+}
-func LoadPlugin(name string) *plugin.Plugin {
- scs := spew.ConfigState{MaxDepth: 1}
+func loadFuncE(p *aplug, funcName string) func() {
+ var newfunc func()
+ var ok bool
+ var test plugin.Symbol
- // load module
- // 1. open the so file to load the symbols
- plug, err := plugin.Open(name)
- log.Println("plug =")
- log.Println(scs.Sdump(plug))
+ test, err = p.plug.Lookup(funcName)
if err != nil {
- log.Println(err)
+ log.Println("DID NOT FIND: name =", test, "err =", err)
return nil
}
- // 2. look up a symbol (an exported function or variable)
- // in this case, variable Greeter
- typeToolkit, err = plug.Lookup("Toolkit")
- log.Println("plugin.Toolkit", typeToolkit)
- log.Println(scs.Sdump(typeToolkit))
- if err != nil {
- log.Println(err)
- os.Exit(1)
+ newfunc, ok = test.(func())
+ if !ok {
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
+ return newfunc
+}
+
+func loadFunc1(p *aplug, funcName string) func(*toolkit.Widget) {
+ var newfunc func(*toolkit.Widget)
+ var ok bool
+ var test plugin.Symbol
- symGreeter, err = plug.Lookup("Greeter")
- log.Println("symGreater", symGreeter)
- log.Println(scs.Sdump(symGreeter))
+ test, err = p.plug.Lookup(funcName)
if err != nil {
- log.Println(err)
- os.Exit(1)
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
}
- // 3. Assert that loaded symbol is of a desired type
- // in this case interface type Greeter (defined above)
- // var greeter Greeter
- greeter, ok = symGreeter.(Greeter)
- log.Println("greeter", symGreeter)
- log.Println(scs.Sdump(greeter))
+ newfunc, ok = test.(func(*toolkit.Widget))
if !ok {
- log.Println("unexpected type from module symbol")
- os.Exit(1)
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
+ return newfunc
+}
- /*
- typeToolkitCast, ok = typeToolkit.(Greeter)
+func loadFuncS(p *aplug, funcName string) func(*toolkit.Widget, string) {
+ var newfunc func(*toolkit.Widget, string)
+ var ok bool
+ var test plugin.Symbol
+
+ test, err = p.plug.Lookup(funcName)
+ if err != nil {
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
+ }
+
+ newfunc, ok = test.(func(*toolkit.Widget, string))
if !ok {
- log.Println("unexpected cast of Toolkit to Greeter")
- os.Exit(1)
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
- */
- return plug
+ return newfunc
}
-func RunGreet() {
- log.Println("gui.RunGreet() START")
- if (greeter == nil) {
- log.Println("wit/gui gocui plugin didn't load")
- return
+func loadFunc2(p *aplug, funcName string) func(*toolkit.Widget, *toolkit.Widget) {
+ var newfunc func(*toolkit.Widget, *toolkit.Widget)
+ var ok bool
+ var test plugin.Symbol
+
+ test, err = p.plug.Lookup(funcName)
+ if err != nil {
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
+ }
+
+ newfunc, ok = test.(func(*toolkit.Widget, *toolkit.Widget))
+ if !ok {
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
}
- PlugGocliOk = true
- greeter.Greet()
+ return newfunc
}
-func LookupJcarrButton() {
- log.Println("lookupJcarrButton() START")
+// This is probably dangerous and should never be done
+// executing arbitrary functions will cause them to run inside the goroutine that
+// the GUI toolkit itself is running in. TODO: move to channels here
+func loadFuncF(p *aplug, funcName string) func(func ()) {
+ var newfunc func(func ())
+ var ok bool
+ var test plugin.Symbol
- if (greeter == nil) {
- log.Println("wit/gui gocui plugin didn't load")
- return
+ test, err = p.plug.Lookup(funcName)
+ if err != nil {
+ log.Println("DID NOT FIND: name =", test, "err =", err)
+ return nil
}
- greeter.JcarrButton()
+
+ newfunc, ok = test.(func(func ()))
+ if !ok {
+ log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
+ return nil
+ }
+ return newfunc
}
-func GocuiAddButton(name string) {
- log.Println("GocuiAddButton() START", name)
+func loadPlugin(p *aplug, name string) {
+ var filename string
+
+ // attempt to write out the file from the internal resource
+ internalName := "toolkit/" + name
+ soFile, err := res.ReadFile(internalName)
+ if (err != nil) {
+ log.Println(err)
+ } else {
+ err = os.WriteFile("/tmp/wit/" + name, soFile, 0644)
+ if (err != nil) {
+ log.Println(err)
+ }
+ }
+
+ filename = "/tmp/wit/" + name
+ p.plug = loadfile(filename)
+ if (p.plug != nil) {
+ p.filename = filename
+ return
+ }
- if (greeter == nil) {
- log.Println("wit/gui gocui plugin didn't load")
+ filename = "/usr/share/wit/gui/" + name
+ p.plug = loadfile(filename)
+ if (p.plug != nil) {
+ p.filename = filename
return
}
- greeter.AddButton(name)
+ return
+}
+
+// load module
+// 1. open the shared object file to load the symbols
+func loadfile(filename string) *plugin.Plugin {
+ plug, err := plugin.Open(filename)
+ log.Println("plug =", plug)
+ if err != nil {
+ log.Println(err)
+ return nil
+ }
+ return plug
}
diff --git a/slider.go b/slider.go
index a50ee9a..abc1357 100644
--- a/slider.go
+++ b/slider.go
@@ -2,27 +2,24 @@ package gui
import "log"
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
-
func (n *Node) NewSlider(name string, x int, y int) *Node {
- var newT *toolkit.Toolkit
- var sNode *Node
-
- log.Println("toolkit.NewSlider() START", name)
+ newNode := n.New(name)
+ newNode.Widget.Name = name
+ newNode.Widget.X = x
+ newNode.Widget.Y = y
- n.verify()
+ newNode.Widget.Custom = func() {
+ log.Println("even newer clicker() name in NewSlider", newNode.Widget)
+ }
- // make a *Node with a *toolkit.Group
- sNode = n.New(name + " part1")
- newT = n.toolkit.NewSlider(name, x, y)
- newT.Name = name
- sNode.custom = n.custom
- newT.Custom = func () {
- commonCallback(sNode)
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewSlider() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewSlider == nil) {
+ log.Println("\tgui.NewSlider() aplug.NewSlider = nil", aplug.name)
+ continue
+ }
+ aplug.NewSlider(&n.Widget, &newNode.Widget)
}
- sNode.toolkit = newT
- sNode.Dump()
- // panic("checking Custom()")
- return sNode
+ return newNode
}
diff --git a/spinner.go b/spinner.go
index 617da34..565ee56 100644
--- a/spinner.go
+++ b/spinner.go
@@ -2,26 +2,24 @@ package gui
import "log"
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
-
func (n *Node) NewSpinner(name string, x int, y int) *Node {
- var newT *toolkit.Toolkit
- var sNode *Node
-
- log.Println("toolkit.NewSpinner() START", name)
+ newNode := n.New(name)
+ newNode.Widget.Name = name
+ newNode.Widget.X = x
+ newNode.Widget.Y = y
- n.verify()
-
- // make a *Node with a *toolkit.Group
- sNode = n.New(name + " part1")
- newT = n.toolkit.NewSpinner(name, x, y)
- newT.Name = name
- sNode.toolkit = newT
- // sNode.Dump()
+ newNode.Widget.Custom = func() {
+ log.Println("even newer clicker() name in NewSpinner", newNode.Widget)
+ }
- newT.Custom = func () {
- commonCallback(sNode)
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewSpinner() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewSpinner == nil) {
+ log.Println("\tgui.NewSpinner() aplug.NewSpinner = nil", aplug.name)
+ continue
+ }
+ aplug.NewSpinner(&n.Widget, &newNode.Widget)
}
- return sNode
+ return newNode
}
diff --git a/structs.go b/structs.go
index 22ec988..af0947f 100644
--- a/structs.go
+++ b/structs.go
@@ -5,7 +5,8 @@ import (
"reflect"
)
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+// import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+import newtoolkit "git.wit.org/wit/gui/toolkit"
//
// All GUI Data Structures and functions that are external
@@ -22,46 +23,46 @@ import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
var Config GuiConfig
func GetDebug () bool {
- return Config.Options.Debug
+ return Config.Debug.Debug
}
func SetDebug (s bool) {
- Config.Options.Debug = s
+ Config.Debug.Debug = s
// also set these
- Config.Options.DebugDump = s
- Config.Options.DebugNode = s
- toolkit.DebugToolkit = s
+ Config.Debug.Dump = s
+ Config.Debug.Node = s
+ // toolkit.DebugToolkit = s
}
func GetDebugToolkit () bool {
- return toolkit.DebugToolkit
+ return Config.Debug.Toolkit
}
func SetDebugToolkit (s bool) {
- toolkit.DebugToolkit = s
+ Config.Debug.Toolkit = s
}
func ShowDebugValues() {
- log.Println("\t wit/gui Debug =", Config.Options.Debug)
- log.Println("\t wit/gui DebugDump =", Config.Options.DebugDump)
- log.Println("\t wit/gui DebugNode =", Config.Options.DebugNode)
- log.Println("\t wit/gui DebugTabs =", Config.Options.DebugTabs)
- log.Println("\t wit/gui DebugPlugin =", Config.Options.DebugPlugin)
- log.Println("\t wit/gui DebugChange =", Config.Options.DebugChange)
-
- log.Println("\t wit/gui DebugToolkit =", toolkit.DebugToolkit)
+ log.Println("\t wit/gui Debug =", Config.Debug.Debug)
+ log.Println("\t wit/gui DebugDump =", Config.Debug.Dump)
+ log.Println("\t wit/gui DebugNode =", Config.Debug.Node)
+ log.Println("\t wit/gui DebugTabs =", Config.Debug.Tabs)
+ log.Println("\t wit/gui DebugPlugin =", Config.Debug.Plugin)
+ log.Println("\t wit/gui DebugChange =", Config.Debug.Change)
+ log.Println("\t wit/gui DebugToolkit =", Config.Debug.Toolkit)
}
// This struct can be used with go-arg
-type GuiOptions struct {
+type GuiDebug struct {
// These are global debugging settings
// TODO: move to a standard logging system
- Debug bool
- DebugDump bool
- DebugNode bool
- DebugTabs bool
- DebugPlugin bool
- DebugChange bool `help:"debug mouse clicks and keyboard input"`
+ Debug bool
+ Dump bool
+ Node bool
+ Tabs bool
+ Plugin bool
+ Change bool `help:"debug mouse clicks and keyboard input"`
+ Toolkit bool `help:"debug toolkit"`
}
type GuiConfig struct {
@@ -74,7 +75,7 @@ type GuiConfig struct {
Height int
Exit func(*Node)
- Options GuiOptions
+ Debug GuiDebug
// hacks
depth int
@@ -86,10 +87,13 @@ type GuiConfig struct {
type Node struct {
id int
+ // deprecate these and use toolkit.Widget
Name string
Width int
Height int
+ Widget newtoolkit.Widget
+
// this function is run when there are mouse or keyboard events
OnChanged func(*Node)
@@ -98,13 +102,12 @@ type Node struct {
children []*Node
// hmm. how do you handle this when the toolkits are plugins?
- toolkit *toolkit.Toolkit
+ // toolkit *toolkit.Toolkit
// things that may not really be needed (?)
custom func()
checked bool
text string
-
}
func (n *Node) Parent() *Node {
@@ -116,7 +119,7 @@ func (n *Node) Window() *Node {
}
func (n *Node) Dump() {
- if ! Config.Options.DebugDump {
+ if ! Config.Debug.Dump {
return
}
IndentPrintln("NODE DUMP START")
@@ -141,10 +144,10 @@ func (n *Node) Dump() {
IndentPrintln("OnChanged = ", n.OnChanged)
}
IndentPrintln("text = ", reflect.ValueOf(n.text).Kind(), n.text)
- if (n.toolkit != nil) {
- IndentPrintln("toolkit = ", reflect.ValueOf(n.toolkit).Kind())
- n.toolkit.Dump()
- }
+// if (n.toolkit != nil) {
+// IndentPrintln("toolkit = ", reflect.ValueOf(n.toolkit).Kind())
+// n.toolkit.Dump()
+// }
// if (n.id == nil) {
// // Node structs should never have a nil id.
// // I probably shouldn't panic here, but this is just to check the sanity of
@@ -163,7 +166,7 @@ func (n *Node) SetName(name string) {
func (n *Node) Append(child *Node) {
n.children = append(n.children, child)
- if (Config.Options.Debug) {
+ if (Config.Debug.Debug) {
log.Println("child node:")
child.Dump()
log.Println("parent node:")
@@ -206,11 +209,11 @@ func (n *Node) ListChildren(dump bool) {
if len(n.children) == 0 {
if (n.parent == nil) {
} else {
- if (Config.Options.DebugNode) {
+ if (Config.Debug.Node) {
log.Println("\t\t\tparent =",n.parent.id)
}
if (listChildrenParent != nil) {
- if (Config.Options.DebugNode) {
+ if (Config.Debug.Node) {
log.Println("\t\t\tlistChildrenParent =",listChildrenParent.id)
}
if (listChildrenParent.id != n.parent.id) {
@@ -219,7 +222,7 @@ func (n *Node) ListChildren(dump bool) {
}
}
}
- if (Config.Options.DebugNode) {
+ if (Config.Debug.Node) {
log.Println("\t\t", n.id, "has no children")
}
return
@@ -227,7 +230,7 @@ func (n *Node) ListChildren(dump bool) {
for _, child := range n.children {
// log.Println("\t\t", child.id, child.Width, child.Height, child.Name)
if (child.parent != nil) {
- if (Config.Options.DebugNode) {
+ if (Config.Debug.Node) {
log.Println("\t\t\tparent =",child.parent.id)
}
} else {
@@ -237,7 +240,7 @@ func (n *Node) ListChildren(dump bool) {
if (dump == true) {
child.Dump()
}
- if (Config.Options.DebugNode) {
+ if (Config.Debug.Node) {
if (child.children == nil) {
log.Println("\t\t", child.id, "has no children")
} else {
diff --git a/tab.go b/tab.go
index bade55f..083e42f 100644
--- a/tab.go
+++ b/tab.go
@@ -7,20 +7,17 @@ import (
// This function should make a new node with the parent and
// the 'tab' as a child
-func (n *Node) NewTab(title string) *Node {
- log.Println("gui.Node.NewTab() START name =", title)
+func (n *Node) NewTab(text string) *Node {
+ newNode := n.New(text)
- // TODO: standardize these checks somewhere
- if (n.toolkit == nil) {
- n.Dump()
- panic("NewTab() failed. toolkit == nil")
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewTab() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewTab == nil) {
+ log.Println("\tgui.NewTab() aplug.NewTab = nil", aplug.name)
+ continue
+ }
+ aplug.NewTab(&n.Widget, &newNode.Widget)
}
- log.Println("Make new node")
- newN := n.New(title)
- log.Println("New tab to window")
- t := n.toolkit.AddTab(title)
- newN.toolkit = t
- n.Append(newN)
- return newN
+ return newNode
}
diff --git a/textbox.go b/textbox.go
index 94f0d9e..639631d 100644
--- a/textbox.go
+++ b/textbox.go
@@ -2,47 +2,21 @@ package gui
import "log"
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
-
func (n *Node) NewTextbox(name string) *Node {
- var newt *toolkit.Toolkit
- var c *Node
-
- log.Println("toolkit.NewTextbox() START", name)
-
- n.verify()
-
- // make a new Node and a new toolbox struct
- c = n.New(name)
- newt = n.toolkit.NewTextbox(name)
+ newNode := n.New(name)
- c.toolkit = newt
- c.custom = n.custom
+ newNode.Widget.Custom = func() {
+ log.Println("even newer clicker() name in NewTextBox", newNode.Widget)
+ }
- newt.Name = name
- // newt.Custom = func () {
- newt.OnChanged = func (*toolkit.Toolkit) {
- if (Config.Options.DebugChange) {
- log.Println("AM IN CALLBACK. SETTING NODE.checked START")
- c.Dump()
- c.toolkit.Dump()
- }
- c.text = c.toolkit.GetText()
- if (c.OnChanged == nil) {
- if (Config.Options.DebugChange) {
- log.Println("this is println?")
- }
- } else {
- if (Config.Options.DebugChange) {
- log.Println("this is println? running c.OnChanged() here")
- }
- c.OnChanged(n)
- }
- if (Config.Options.DebugChange) {
- log.Println("n.toolkit.GetText() =", c.text)
- log.Println("AM IN CALLBACK. SETTING NODE.checked END")
+ for _, aplug := range allPlugins {
+ log.Println("gui.NewTextbox() aplug =", aplug.name, "name =", newNode.Widget.Name)
+ if (aplug.NewTextbox == nil) {
+ log.Println("\tgui.NewTextbox() aplug.NewTextbox = nil", aplug.name)
+ continue
}
+ aplug.NewTextbox(&n.Widget, &newNode.Widget)
}
- return c
+ return newNode
}
diff --git a/toolkit/andlabs2/Makefile b/toolkit/andlabs2/Makefile
new file mode 100644
index 0000000..54cf7f5
--- /dev/null
+++ b/toolkit/andlabs2/Makefile
@@ -0,0 +1,4 @@
+all: plugin
+
+plugin:
+ GO111MODULE="off" go build -buildmode=plugin -o ../andlabs2.so
diff --git a/toolkit/andlabs2/box.go b/toolkit/andlabs2/box.go
new file mode 100644
index 0000000..bb9945e
--- /dev/null
+++ b/toolkit/andlabs2/box.go
@@ -0,0 +1,66 @@
+package main
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+// create a new box
+func (t *andlabsT) GetBox() *ui.Box {
+ return t.uiBox
+}
+
+// create a new box
+func (t *andlabsT) NewBox() *andlabsT {
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewBox() START create default")
+ }
+ t.Dump()
+ if (t.uiGroup != nil) {
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() is a Group")
+ }
+ var newTK andlabsT
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(padded)
+ t.uiGroup.SetChild(vbox)
+ newTK.uiBox = vbox
+
+ return &newTK
+ }
+ if (t.uiBox != nil) {
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() is a Box")
+ }
+ var newTK andlabsT
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(padded)
+ t.uiBox.Append(vbox, stretchy)
+ newTK.uiBox = vbox
+ newTK.Name = t.Name
+
+ return &newTK
+ }
+ if (t.uiWindow != nil) {
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() is a Window")
+ }
+ var newT andlabsT
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(padded)
+ t.uiWindow.SetChild(vbox)
+ newT.uiBox = vbox
+ newT.Name = t.Name
+
+ // panic("WTF")
+ return &newT
+ }
+ if (DebugToolkit) {
+ log.Println("\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box")
+ }
+ t.Dump()
+ return nil
+}
diff --git a/toolkit/andlabs2/button.go b/toolkit/andlabs2/button.go
new file mode 100644
index 0000000..bd80683
--- /dev/null
+++ b/toolkit/andlabs2/button.go
@@ -0,0 +1,67 @@
+package main
+
+import "log"
+// import "os"
+
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "git.wit.org/wit/gui/toolkit"
+func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) {
+ var t, newt *andlabsT
+ var b *ui.Button
+ log.Println("gui.andlabs.NewButton()", w.Name)
+
+ t = mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewButton() toolkit struct == nil. name=", parentW.Name, w.Name)
+ return
+ }
+
+ if t.broken() {
+ return
+ }
+ newt = new(andlabsT)
+
+ b = ui.NewButton(w.Name)
+ newt.uiButton = b
+
+ b.OnClicked(func(*ui.Button) {
+ if (DebugToolkit) {
+ log.Println("TODO: IN TOOLKIT GOROUTINE. SHOULD LEAVE HERE VIA channels. button name =", w.Name)
+ log.Println("FOUND WIDGET!", w)
+ }
+ if (w.Custom != nil) {
+ w.Custom()
+ return
+ }
+ if (w.Event != nil) {
+ w.Event(w)
+ return
+ }
+ t.Dump()
+ newt.Dump()
+ if (DebugToolkit) {
+ log.Println("TODO: LEFT TOOLKIT GOROUTINE WITH NOTHING TO DO button name =", w.Name)
+ }
+ })
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewButton() about to append to Box parent t:", w.Name)
+ t.Dump()
+ log.Println("gui.Toolbox.NewButton() about to append to Box new t:", w.Name)
+ newt.Dump()
+ }
+ if (t.uiBox != nil) {
+ t.uiBox.Append(b, stretchy)
+ } else if (t.uiWindow != nil) {
+ t.uiWindow.SetChild(b)
+ } else {
+ log.Println("ERROR: wit/gui andlabs couldn't place this button in a box or a window")
+ log.Println("ERROR: wit/gui andlabs couldn't place this button in a box or a window")
+ return
+ }
+
+ mapWidgetsToolkits(w, newt)
+}
diff --git a/toolkit/andlabs2/checkbox.go b/toolkit/andlabs2/checkbox.go
new file mode 100644
index 0000000..b4b1524
--- /dev/null
+++ b/toolkit/andlabs2/checkbox.go
@@ -0,0 +1,34 @@
+package main
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t andlabsT) NewCheckbox(name string) *andlabsT {
+ log.Println("gui.Toolkit.NewCheckbox()", name)
+ var newt andlabsT
+
+ if t.broken() {
+ return nil
+ }
+
+ c := ui.NewCheckbox(name)
+ newt.uiCheckbox = c
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(c, stretchy)
+
+ c.OnToggled(func(spin *ui.Checkbox) {
+ newt.commonChange("Checkbox")
+ })
+
+ return &newt
+}
+
+func (t andlabsT) Checked() bool {
+ if t.broken() {
+ return false
+ }
+
+ return t.uiCheckbox.Checked()
+}
diff --git a/toolkit/andlabs2/common.go b/toolkit/andlabs2/common.go
new file mode 100644
index 0000000..fc6cbe8
--- /dev/null
+++ b/toolkit/andlabs2/common.go
@@ -0,0 +1,61 @@
+package main
+
+import "log"
+
+func init() {
+ if (DebugToolkit) {
+ log.Println("gui/toolkit init() Setting defaultBehavior = true")
+ }
+ setDefaultBehavior(true)
+}
+
+func (t andlabsT) commonChange(widget string) {
+ s := t.String()
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.ui.OnChanged() =", s)
+ }
+ if (t.OnChanged != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.OnChanged() trying to run toolkit.OnChanged() entered val =", s)
+ }
+ t.OnChanged(&t)
+ return
+ }
+ if (t.Custom != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.OnChanged() Running toolkit.Custom()")
+ t.Dump()
+ }
+ t.Custom()
+ return
+ }
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.OnChanged() ENDED without finding any callback")
+ }
+}
+
+// does some sanity checks on the internal structs of the binary tree
+// TODO: probably this should not panic unless it's running in devel mode (?)
+func (t *andlabsT) broken() bool {
+ if (t.uiBox == nil) {
+ if (t.uiWindow != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.UiBox == nil. This is an empty window. Try to add a box")
+ }
+ t.NewBox()
+ return false
+ }
+ log.Println("gui.Toolkit.UiBox == nil. I can't add a widget without a place to put it")
+ // log.Println("probably could just make a box here?")
+ // corruption or something horrible?
+ panic("wit/gui toolkit/andlabs func broken() invalid goroutine access into this toolkit?")
+ panic("wit/gui toolkit/andlabs func broken() this probably should not cause the app to panic here (?)")
+ return true
+ }
+ if (t.uiWindow == nil) {
+ log.Println("gui.Toolkit.UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)")
+ forceDump(t)
+ return false
+ }
+ return false
+}
diff --git a/toolkit/andlabs2/demo.go b/toolkit/andlabs2/demo.go
new file mode 100644
index 0000000..0781f88
--- /dev/null
+++ b/toolkit/andlabs2/demo.go
@@ -0,0 +1,92 @@
+package main
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+/*
+ This is a code example taken directly from the toolkit andlabs/ui
+
+ This code is here to double check that the toolkit itself still works
+ the same way. This is intended as a sanity check.
+*/
+
+func BlankWindow(w *ui.Window) *ui.Box {
+ hbox := ui.NewHorizontalBox()
+ hbox.SetPadded(true)
+ w.SetChild(hbox)
+ return hbox
+}
+
+func (t *andlabsT) DemoNumbersPage() {
+ var w *ui.Window
+
+ log.Println("Starting wit/gui toolkit andlabs/ui DemoNumbersPage()")
+
+ w = t.uiWindow
+ t.uiBox = makeNumbersPage()
+ t.uiBox.SetPadded(true)
+ w.SetChild(t.uiBox)
+ w.SetTitle("Internal demo of andlabs/ui toolkit")
+}
+
+func makeNumbersPage() *ui.Box {
+ hbox := ui.NewHorizontalBox()
+ hbox.SetPadded(true)
+
+ group := ui.NewGroup("Numbers")
+ group.SetMargined(true)
+ hbox.Append(group, true)
+
+ vbox := ui.NewVerticalBox()
+ vbox.SetPadded(true)
+ group.SetChild(vbox)
+
+ spinbox := ui.NewSpinbox(0, 100)
+ slider := ui.NewSlider(0, 100)
+ pbar := ui.NewProgressBar()
+ spinbox.OnChanged(func(*ui.Spinbox) {
+ slider.SetValue(spinbox.Value())
+ pbar.SetValue(spinbox.Value())
+ })
+ slider.OnChanged(func(*ui.Slider) {
+ spinbox.SetValue(slider.Value())
+ pbar.SetValue(slider.Value())
+ })
+ vbox.Append(spinbox, false)
+ vbox.Append(slider, false)
+ vbox.Append(pbar, false)
+
+ ip := ui.NewProgressBar()
+ ip.SetValue(-1)
+ vbox.Append(ip, false)
+
+ group = ui.NewGroup("Lists")
+ group.SetMargined(true)
+ hbox.Append(group, true)
+
+ vbox = ui.NewVerticalBox()
+ vbox.SetPadded(true)
+ group.SetChild(vbox)
+
+ cbox := ui.NewCombobox()
+ cbox.Append("Combobox Item 1")
+ cbox.Append("Combobox Item 2")
+ cbox.Append("Combobox Item 3")
+ vbox.Append(cbox, false)
+
+ ecbox := ui.NewEditableCombobox()
+ ecbox.Append("Editable Item 1")
+ ecbox.Append("Editable Item 2")
+ ecbox.Append("Editable Item 3")
+ vbox.Append(ecbox, false)
+
+ rb := ui.NewRadioButtons()
+ rb.Append("Radio Button 1")
+ rb.Append("Radio Button 2")
+ rb.Append("Radio Button 3")
+ vbox.Append(rb, false)
+
+ return hbox
+}
diff --git a/toolkit/andlabs2/dropdown.go b/toolkit/andlabs2/dropdown.go
new file mode 100644
index 0000000..1e1886a
--- /dev/null
+++ b/toolkit/andlabs2/dropdown.go
@@ -0,0 +1,90 @@
+package main
+
+import "log"
+// import "time"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "git.wit.org/wit/gui/toolkit"
+
+func (t *andlabsT) NewDropdown(title string) *andlabsT {
+ // make new node here
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewDropdownCombobox()", title)
+ }
+ var newt andlabsT
+
+ if t.broken() {
+ return nil
+ }
+
+ s := ui.NewCombobox()
+ newt.uiCombobox = s
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(s, stretchy)
+
+ // initialize the index
+ newt.c = 0
+ newt.val = make(map[int]string)
+
+ s.OnSelected(func(spin *ui.Combobox) {
+ i := spin.Selected()
+ if (newt.val == nil) {
+ log.Println("make map didn't work")
+ newt.text = "error"
+ }
+ newt.text = newt.val[i]
+ newt.commonChange("Dropdown")
+ })
+
+ return &newt
+}
+
+func (t *andlabsT) AddDropdownName(title string) {
+ t.uiCombobox.Append(title)
+ if (t.val == nil) {
+ log.Println("make map didn't work")
+ return
+ }
+ t.val[t.c] = title
+ t.c = t.c + 1
+}
+
+func (t andlabsT) SetDropdown(i int) {
+ t.uiCombobox.SetSelected(i)
+}
+
+func NewDropdown(parentW *toolkit.Widget, w *toolkit.Widget) {
+ log.Println("gui.andlabs.NewDropdown()", w.Name)
+
+ t := mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewDropdown() toolkit struct == nil. name=", parentW.Name, w.Name)
+ listMap()
+ }
+ newt := t.NewDropdown(w.Name)
+ mapWidgetsToolkits(w, newt)
+}
+
+func AddDropdownName(w *toolkit.Widget, s string) {
+ log.Println("gui.andlabs.AddDropdownName()", w.Name, "add:", s)
+
+ t := mapToolkits[w]
+ if (t == nil) {
+ log.Println("go.andlabs.AddDropdownName() toolkit struct == nil. name=", w.Name, s)
+ listMap()
+ }
+ t.AddDropdownName(s)
+}
+
+func SetDropdown(w *toolkit.Widget, i int) {
+ log.Println("gui.andlabs.SetDropdown()", i)
+
+ t := mapToolkits[w]
+ if (t == nil) {
+ log.Println("go.andlabs.SetDropdown() toolkit struct == nil. name=", w.Name, i)
+ listMap()
+ }
+ t.SetDropdown(i)
+}
diff --git a/toolkit/andlabs2/group.go b/toolkit/andlabs2/group.go
new file mode 100644
index 0000000..39f740b
--- /dev/null
+++ b/toolkit/andlabs2/group.go
@@ -0,0 +1,56 @@
+package main
+
+import "log"
+import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "git.wit.org/wit/gui/toolkit"
+
+func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) {
+ log.Println("gui.andlabs.NewGroup()", w.Name)
+
+ t := mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewGroup() toolkit struct == nil. name=", parentW.Name, w.Name)
+ listMap()
+ }
+ newt := t.NewGroup(w.Name)
+ mapWidgetsToolkits(w, newt)
+}
+
+// make new Group here
+func (t andlabsT) NewGroup(title string) *andlabsT {
+ var newt andlabsT
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewGroup() create", title)
+ }
+ g := ui.NewGroup(title)
+ g.SetMargined(margin)
+
+ if (t.uiBox != nil) {
+ t.uiBox.Append(g, stretchy)
+ } else if (t.uiWindow != nil) {
+ t.uiWindow.SetChild(g)
+ } else {
+ log.Println("gui.ToolboxNode.NewGroup() 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)
+ }
+
+ hbox := ui.NewVerticalBox()
+ hbox.SetPadded(padded)
+ g.SetChild(hbox)
+
+ newt.uiGroup = g
+ newt.uiBox = hbox
+ newt.uiWindow = t.uiWindow
+ newt.Name = title
+
+ t.Dump()
+ newt.Dump()
+ // panic("toolkit.NewGroup")
+ return &newt
+}
diff --git a/toolkit/andlabs2/label.go b/toolkit/andlabs2/label.go
new file mode 100644
index 0000000..c5a6896
--- /dev/null
+++ b/toolkit/andlabs2/label.go
@@ -0,0 +1,42 @@
+package main
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "git.wit.org/wit/gui/toolkit"
+
+func NewLabel(parentW *toolkit.Widget, w *toolkit.Widget) {
+ var t, newt *andlabsT
+ log.Println("gui.andlabs.NewButton()", w.Name)
+
+ t = mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewButton() toolkit struct == nil. name=", parentW.Name, w.Name)
+ return
+ }
+
+ if t.broken() {
+ return
+ }
+ newt = new(andlabsT)
+
+ newt.uiLabel = ui.NewLabel(w.Name)
+ newt.uiBox = t.uiBox
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewButton() about to append to Box parent t:", w.Name)
+ t.Dump()
+ log.Println("gui.Toolbox.NewButton() about to append to Box new t:", w.Name)
+ newt.Dump()
+ }
+ if (t.uiBox != nil) {
+ t.uiBox.Append(newt.uiLabel, false)
+ } else {
+ log.Println("ERROR: wit/gui andlabs couldn't place this label in a box")
+ return
+ }
+
+ mapWidgetsToolkits(w, newt)
+}
diff --git a/toolkit/andlabs2/main.go b/toolkit/andlabs2/main.go
new file mode 100644
index 0000000..8a28710
--- /dev/null
+++ b/toolkit/andlabs2/main.go
@@ -0,0 +1,56 @@
+package main
+
+import (
+ "log"
+// "time"
+
+ "git.wit.org/wit/gui/toolkit"
+
+ "github.com/andlabs/ui"
+ // the _ means we only need this for the init()
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func Main(f func()) {
+ if (DebugToolkit) {
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ }
+ ui.Main( func() {
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ log.Println("Starting gui.Main() (using gtk via andlabs/ui)")
+ // time.Sleep(1 * time.Second)
+ // NewWindow2("helloworld2", 200, 100)
+ f()
+ })
+}
+
+// Other goroutines must use this to access the GUI
+//
+// You can not acess / process the GUI thread directly from
+// other goroutines. This is due to the nature of how
+// Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
+//
+// For example: Queue(NewWindow())
+//
+func Queue(f func()) {
+ if (DebugToolkit) {
+ log.Println("Sending function to ui.QueueMain() (using gtk via andlabs/ui)")
+ }
+ ui.QueueMain(f)
+}
+
+func Init() {
+ log.Println("should Init() here")
+
+ mapWidgets = make(map[*andlabsT]*toolkit.Widget)
+ mapToolkits = make(map[*toolkit.Widget]*andlabsT)
+}
+
+func Quit() {
+ log.Println("should Quit() here")
+ // myExit(nil)
+}
diff --git a/toolkit/andlabs2/plugin.go b/toolkit/andlabs2/plugin.go
new file mode 100644
index 0000000..f78e95e
--- /dev/null
+++ b/toolkit/andlabs2/plugin.go
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "log"
+
+ "git.wit.org/wit/gui/toolkit"
+)
+
+// This is a map between the widgets in wit/gui and the internal structures of gocui
+
+var mapWidgets map[*andlabsT]*toolkit.Widget
+var mapToolkits map[*toolkit.Widget]*andlabsT
+
+// This lists out the know mappings
+func listMap() {
+ log.Println("listMap() HERE")
+ log.Println("listMap() HERE")
+ log.Println("listMap() HERE mapWidgets()")
+ for t, w := range mapWidgets {
+ log.Println("andlabs =", t.Name, "widget =", w.Name)
+ }
+ log.Println("listMap() HERE mapToolkits()")
+ for w, t := range mapToolkits {
+ log.Println("andlabs =", t, "widget =", w.Name)
+ forceDump(t)
+ }
+}
+
+func mapWidgetsToolkits(w *toolkit.Widget, t *andlabsT) {
+ if (mapToolkits[w] == nil) {
+ mapToolkits[w] = t
+ } else {
+ log.Println("WTF: mapToolkits already installed")
+ panic("WTF")
+ }
+
+ if (mapWidgets[t] == nil) {
+ mapWidgets[t] = w
+ } else {
+ log.Println("WTF: mapWidgets already installed")
+ panic("WTF")
+ }
+}
diff --git a/toolkit/andlabs2/slider.go b/toolkit/andlabs2/slider.go
new file mode 100644
index 0000000..f9ff0f3
--- /dev/null
+++ b/toolkit/andlabs2/slider.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+ "log"
+ "os"
+
+ "git.wit.org/wit/gui/toolkit"
+
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+)
+
+func (t andlabsT) NewSlider(title string, x int, y int) *andlabsT {
+ // make new node here
+ log.Println("gui.Toolkit.NewSpinbox()", x, y)
+ var newt andlabsT
+
+ if (t.uiBox == nil) {
+ log.Println("gui.ToolkitNode.NewGroup() 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
+ }
+
+ s := ui.NewSlider(x, y)
+ newt.uiSlider = s
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(s, stretchy)
+
+ s.OnChanged(func(spin *ui.Slider) {
+ newt.commonChange("Slider")
+ })
+
+ return &newt
+}
+
+func NewSlider(parentW *toolkit.Widget, w *toolkit.Widget) {
+ var newt *andlabsT
+ log.Println("gui.andlabs.NewTab()", w.Name)
+
+ t := mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name)
+ return
+ }
+ newt = t.NewSlider(w.Name, w.X, w.Y)
+ mapWidgetsToolkits(w, newt)
+}
diff --git a/toolkit/andlabs2/spinner.go b/toolkit/andlabs2/spinner.go
new file mode 100644
index 0000000..6505b48
--- /dev/null
+++ b/toolkit/andlabs2/spinner.go
@@ -0,0 +1,30 @@
+package main
+
+import "log"
+import "os"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t andlabsT) NewSpinner(title string, x int, y int) *andlabsT {
+ // make new node here
+ log.Println("gui.Toolkit.NewSpinner()", x, y)
+ var newt andlabsT
+
+ if (t.uiBox == nil) {
+ log.Println("gui.ToolkitNode.NewSpinner() node.UiBox == nil. I can't add a range UI element without a place to put it")
+ os.Exit(0)
+ return nil
+ }
+
+ s := ui.NewSpinbox(x, y)
+ newt.uiSpinbox = s
+ newt.uiBox = t.uiBox
+ t.uiBox.Append(s, stretchy)
+
+ s.OnChanged(func(s *ui.Spinbox) {
+ newt.commonChange("Spinner")
+ })
+
+ return &newt
+}
diff --git a/toolkit/andlabs2/structs.go b/toolkit/andlabs2/structs.go
new file mode 100644
index 0000000..2f3fa72
--- /dev/null
+++ b/toolkit/andlabs2/structs.go
@@ -0,0 +1,249 @@
+package main
+
+import "log"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+import "github.com/davecgh/go-spew/spew"
+
+var defaultBehavior bool = true
+
+var bookshelf bool // do you want things arranged in the box like a bookshelf or a stack?
+var canvas bool // if set to true, the windows are a raw canvas
+var menubar bool // for windows
+var stretchy bool // expand things like buttons to the maximum size
+var padded bool // add space between things like buttons
+var margin bool // add space around the frames of windows
+
+var DebugToolkit bool
+
+func setDefaultBehavior(s bool) {
+ defaultBehavior = s
+ if (defaultBehavior) {
+ if (DebugToolkit) {
+ log.Println("Setting this toolkit to use the default behavior.")
+ log.Println("This is the 'guessing' part as defined by the wit/gui 'Principles'. Refer to the docs.")
+ }
+ stretchy = false
+ padded = true
+ menubar = true
+ margin = true
+ canvas = false
+ bookshelf = true // 99% of the time, things make a vertical stack of objects
+
+ DebugToolkit = false
+ } else {
+ log.Println("This toolkit is set to ignore the default behavior.")
+ }
+}
+
+func SetDebugToolkit (s bool) {
+ DebugToolkit = s
+}
+
+func GetDebugToolkit () bool {
+ return DebugToolkit
+}
+
+// stores the raw toolkit internals
+type andlabsT struct {
+ id string
+
+ Name string
+ Width int
+ Height int
+
+ OnChanged func(*andlabsT)
+ OnExit func(*andlabsT)
+
+ Custom func()
+
+ uiBox *ui.Box
+ uiBox2 *ui.Box // temporary hack while implementing tabs
+ uiButton *ui.Button
+ uiControl *ui.Control
+ uiCombobox *ui.Combobox
+ uiCheckbox *ui.Checkbox
+ uiEntry *ui.Entry
+ uiMultilineEntry *ui.MultilineEntry
+ uiGroup *ui.Group
+ uiLabel *ui.Label
+ uiSlider *ui.Slider
+ uiSpinbox *ui.Spinbox
+ uiTab *ui.Tab
+ uiText *ui.EditableCombobox
+ uiWindow *ui.Window
+ UiWindowBad *ui.Window
+
+ // used as a counter to work around limitations of widgets like combobox
+ // this is probably fucked up and in many ways wrong because of unsafe goroutine threading
+ // but it's working for now due to the need for need for a correct interaction layer betten toolkits
+ c int
+ val map[int]string
+ text string
+}
+
+func (t *andlabsT) String() string {
+ return t.GetText()
+}
+
+func forceDump(t *andlabsT) {
+ tmp := DebugToolkit
+ DebugToolkit = true
+ t.Dump()
+ DebugToolkit = tmp
+}
+
+func (t *andlabsT) GetText() string {
+ t.Dump()
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Text() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t.uiEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiEntry.Text())
+ }
+ return t.uiEntry.Text()
+ }
+ if (t.uiMultilineEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiMultilineEntry.Text())
+ }
+ text := t.uiMultilineEntry.Text()
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() text =", text)
+ }
+ t.text = text
+ return text
+ }
+ if (t.uiCombobox != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.GetText() =", t.text)
+ }
+ return t.text
+ }
+ return ""
+}
+
+func (t *andlabsT) SetText(s string) bool {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Text() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t.uiEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiEntry.Text)
+ }
+ t.uiEntry.SetText(s)
+ return true
+ }
+ if (t.uiMultilineEntry != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiMultilineEntry.Text)
+ }
+ t.uiMultilineEntry.SetText(s)
+ return true
+ }
+ return false
+}
+
+func sanity(t *andlabsT) 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 *andlabsT) 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 *andlabsT) Value() int {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() Enter")
+ scs := spew.ConfigState{MaxDepth: 1}
+ scs.Dump(t)
+ }
+ if (t == nil) {
+ log.Println("gui.Toolkit.Value() can not get value t == nil")
+ return 0
+ }
+ if (t.uiSlider != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiSlider.Value)
+ }
+ return t.uiSlider.Value()
+ }
+ if (t.uiSpinbox != nil) {
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.Value() =", t.uiSpinbox.Value)
+ }
+ return t.uiSpinbox.Value()
+ }
+ log.Println("gui.Toolkit.Value() Could not find a ui element to get a value from")
+ return 0
+}
+
+func (t *andlabsT) Dump() {
+ if ! DebugToolkit {
+ return
+ }
+ log.Println("gui.Toolkit.Dump() Name = ", 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.uiCombobox != nil) {
+ log.Println("gui.Toolkit.Dump() uiCombobox =", t.uiCombobox)
+ }
+ 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.uiEntry != nil) {
+ log.Println("gui.Toolkit.Dump() uiEntry =", t.uiEntry)
+ }
+ if (t.uiMultilineEntry != nil) {
+ log.Println("gui.Toolkit.Dump() uiMultilineEntry =", t.uiMultilineEntry)
+ }
+ if (t.uiSlider != nil) {
+ log.Println("gui.Toolkit.Dump() uiSlider =", t.uiSlider)
+ }
+ if (t.uiCheckbox != nil) {
+ log.Println("gui.Toolkit.Dump() uiCheckbox =", t.uiCheckbox)
+ }
+ if (t.OnExit != nil) {
+ log.Println("gui.Toolkit.Dump() OnExit =", t.OnExit)
+ }
+ if (t.Custom != nil) {
+ log.Println("gui.Toolkit.Dump() Custom =", t.Custom)
+ }
+ log.Println("gui.Toolkit.Dump() c =", t.c)
+ log.Println("gui.Toolkit.Dump() val =", t.val)
+ log.Println("gui.Toolkit.Dump() text =", t.text)
+}
diff --git a/toolkit/andlabs2/tab.go b/toolkit/andlabs2/tab.go
new file mode 100644
index 0000000..0556fb9
--- /dev/null
+++ b/toolkit/andlabs2/tab.go
@@ -0,0 +1,147 @@
+package main
+
+import (
+ "log"
+ "time"
+
+ "git.wit.org/wit/gui/toolkit"
+
+ "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 *andlabsT) newTab(name string) *andlabsT {
+ // var w *ui.Window
+ var newt *andlabsT
+
+ log.Println("gui.toolkit.AddTab() sleep 3")
+
+ if (t.uiWindow == nil) {
+ log.Println("gui.Toolkit.UiWindow == nil. I can't add a toolbar without window")
+ return nil
+ }
+
+ if (t.uiTab == nil) {
+ // this means you have to make a new tab
+ log.Println("gui.toolkit.NewTab() GOOD. This should be the first tab:", name)
+ newt = newTab(t.uiWindow, name)
+ t.uiTab = newt.uiTab
+ } else {
+ // this means you have to append a tab
+ log.Println("gui.toolkit.NewTab() GOOD. This should be an additional tab:", name)
+ newt = t.appendTab(name)
+ }
+
+ newt.Name = name
+
+ if (DebugToolkit) {
+ log.Println("t:")
+ t.Dump()
+ log.Println("newt:")
+ newt.Dump()
+ }
+
+ return newt
+}
+
+// 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++ {
+ if (DebugToolkit) {
+ log.Println("SetMargined", i, margin)
+ }
+ tab.SetMargined(i, margin)
+ }
+}
+
+func newTab(w *ui.Window, name string) *andlabsT {
+ var t andlabsT
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.NewTab() ADD", name)
+ }
+
+ if (w == nil) {
+ log.Println("gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window")
+ log.Println("gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window")
+ log.Println("gui.toolkit.NewTab() node.UiWindow == nil. I can't add a tab without a window")
+ time.Sleep(1 * time.Second)
+ return nil
+ }
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.AddTab() START name =", name)
+ }
+ tab := ui.NewTab()
+ w.SetMargined(margin)
+
+ hbox := ui.NewHorizontalBox() // this makes everything go along the horizon
+ hbox.SetPadded(padded)
+ tab.Append(name, hbox)
+ tabSetMargined(tab) // TODO: run this in the right place(?)
+ w.SetChild(tab)
+
+ t.uiWindow = w
+ t.uiTab = tab
+ t.uiBox = hbox
+ return &t
+}
+
+func (t *andlabsT) appendTab(name string) *andlabsT {
+ var newT andlabsT
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.NewTab() ADD", name)
+ }
+
+ if (t.uiTab == nil) {
+ log.Println("gui.Toolkit.UiWindow == nil. I can't add a widget without a place to put it")
+ panic("should never have happened. wit/gui/toolkit has ui.Tab == nil")
+ }
+ if (DebugToolkit) {
+ log.Println("gui.toolkit.AddTab() START name =", name)
+ }
+
+ var hbox *ui.Box
+ if (defaultBehavior) {
+ hbox = ui.NewHorizontalBox()
+ } else {
+ if (bookshelf) {
+ hbox = ui.NewHorizontalBox()
+ } else {
+ hbox = ui.NewVerticalBox()
+ }
+ }
+ hbox.SetPadded(padded)
+ t.uiTab.Append(name, hbox)
+
+ newT.uiWindow = t.uiWindow
+ newT.uiTab = t.uiTab
+ newT.uiBox = hbox
+ return &newT
+}
+
+func NewTab(parentW *toolkit.Widget, w *toolkit.Widget) {
+ var newt *andlabsT
+ log.Println("gui.andlabs.NewTab()", w.Name)
+
+ t := mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewTab() toolkit struct == nil. name=", parentW.Name, w.Name)
+ return
+ }
+ newt = t.newTab(w.Name)
+ mapWidgetsToolkits(w, newt)
+}
diff --git a/toolkit/andlabs2/textbox.go b/toolkit/andlabs2/textbox.go
new file mode 100644
index 0000000..c7a9390
--- /dev/null
+++ b/toolkit/andlabs2/textbox.go
@@ -0,0 +1,70 @@
+package main
+
+import "log"
+
+import "git.wit.org/wit/gui/toolkit"
+
+import "github.com/andlabs/ui"
+import _ "github.com/andlabs/ui/winmanifest"
+
+func (t andlabsT) NewTextbox(name string) *andlabsT {
+ var newt andlabsT
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolkit.NewTextbox()", name)
+ }
+ if t.broken() {
+ return nil
+ }
+
+ c := ui.NewNonWrappingMultilineEntry()
+ newt.uiMultilineEntry = c
+
+ newt.uiBox = t.uiBox
+ newt.Name = name
+ if (defaultBehavior) {
+ t.uiBox.Append(c, true)
+ } else {
+ t.uiBox.Append(c, stretchy)
+ }
+
+ c.OnChanged(func(spin *ui.MultilineEntry) {
+ newt.commonChange("Textbox")
+ })
+
+ return &newt
+}
+
+func NewTextbox(parentW *toolkit.Widget, w *toolkit.Widget) {
+ var t, newt *andlabsT
+ log.Println("gui.andlabs.NewTextbox()", w.Name)
+
+ t = mapToolkits[parentW]
+ if (t == nil) {
+ log.Println("go.andlabs.NewTextbox() toolkit struct == nil. name=", parentW.Name, w.Name)
+ return
+ }
+
+ if t.broken() {
+ return
+ }
+ newt = new(andlabsT)
+
+ newt.uiLabel = ui.NewLabel(w.Name)
+ newt.uiBox = t.uiBox
+
+ if (DebugToolkit) {
+ log.Println("gui.Toolbox.NewTextbox() about to append to Box parent t:", w.Name)
+ t.Dump()
+ log.Println("gui.Toolbox.NewTextbox() about to append to Box new t:", w.Name)
+ newt.Dump()
+ }
+ if (t.uiBox != nil) {
+ t.uiBox.Append(newt.uiLabel, false)
+ } else {
+ log.Println("ERROR: wit/gui andlabs couldn't place this Textbox in a box")
+ return
+ }
+
+ mapWidgetsToolkits(w, newt)
+}
diff --git a/toolkit/andlabs2/window.go b/toolkit/andlabs2/window.go
new file mode 100644
index 0000000..b360cb8
--- /dev/null
+++ b/toolkit/andlabs2/window.go
@@ -0,0 +1,78 @@
+package main
+
+import (
+ "log"
+
+ "github.com/andlabs/ui"
+ _ "github.com/andlabs/ui/winmanifest"
+
+ "git.wit.org/wit/gui/toolkit"
+)
+
+func (t *andlabsT) MessageWindow(msg1 string, msg2 string) {
+ ui.MsgBox(t.uiWindow, msg1, msg2)
+}
+
+func (t *andlabsT) ErrorWindow(msg1 string, msg2 string) {
+ ui.MsgBoxError(t.uiWindow, msg1, msg2)
+}
+
+func NewWindow(w *toolkit.Widget) {
+ var t *andlabsT
+
+ if (DebugToolkit) {
+ log.Println("toolkit NewWindow", w.Name, w.Width, w.Height)
+ }
+
+ if (w == nil) {
+ log.Println("wit/gui plugin error. widget == nil")
+ return
+ }
+ t = new(andlabsT)
+ // t = NewWindow2(w.Name, w.Width, w.Height)
+
+// func NewWindow2(title string, x int, y int) *andlabsT {
+ // menubar bool is if the OS defined border on the window should be used
+ win := ui.NewWindow(w.Name, w.Width, w.Height, menubar)
+ win.SetBorderless(canvas)
+ win.SetMargined(margin)
+ win.OnClosing(func(*ui.Window) bool {
+ if (DebugToolkit) {
+ log.Println("ui.Window().OnExit() SHOULD ATTEMPT CALLBACK here")
+ t.Dump()
+ }
+ if (w.Custom != nil) {
+ w.Custom()
+ return true
+ }
+ if (w.Event != nil) {
+ w.Event(w)
+ return true
+ }
+ if (DebugToolkit) {
+ log.Println("andlabs.ui.Window().OnClosing() was not defined")
+ }
+ return false
+ })
+ win.Show()
+ t.uiWindow = win
+ t.UiWindowBad = win // deprecate this as soon as possible
+ t.Name = w.Name
+
+ mapWidgetsToolkits(w, t)
+ return
+}
+
+func (t *andlabsT) SetWindowTitle(title string) {
+ if (DebugToolkit) {
+ log.Println("toolkit NewWindow", t.Name, "title", title)
+ }
+ win := t.uiWindow
+ if (win != nil) {
+ win.SetTitle(title)
+ } else {
+ if (DebugToolkit) {
+ log.Println("Setting the window title", title)
+ }
+ }
+}
diff --git a/toolkit/gocui/Makefile b/toolkit/gocui/Makefile
index 27f23ed..597b2b2 100644
--- a/toolkit/gocui/Makefile
+++ b/toolkit/gocui/Makefile
@@ -6,3 +6,6 @@ build:
plugin:
GO111MODULE="off" go build -buildmode=plugin -o ../gocui.so
+
+objdump:
+ objdump -t ../gocui.so |less
diff --git a/toolkit/gocui/button.go b/toolkit/gocui/button.go
index 8fb6e05..5b41c48 100644
--- a/toolkit/gocui/button.go
+++ b/toolkit/gocui/button.go
@@ -7,42 +7,49 @@ import (
"strings"
"github.com/awesome-gocui/gocui"
+ "git.wit.org/wit/gui/toolkit"
)
-func (w *Widget) AddButton() {
-// func (g greeting) AddButton() {
+func NewButton(parentW *toolkit.Widget, w *toolkit.Widget) {
log.Println("gui.gocui.AddButton()", w.Name)
- addButton2(w.Name, w.Event)
+ addButton(w.Name)
+ // viewWidget[v] = w
+ stringWidget[w.Name] = w
+ listMap()
}
-func addButton2(name string, e func(*Widget) *Widget) {
- addButton(name)
-}
-
-func addButton(name string) error {
+func addButton(name string) *gocui.View {
t := len(name)
+ if (baseGui == nil) {
+ panic("WTF")
+ }
v, err := baseGui.SetView(name, currentX, currentY, currentX+t+3, currentY+2, 0)
if err == nil {
- return err
+ log.Println("wit/gui internal plugin error", err)
+ return nil
}
if !errors.Is(err, gocui.ErrUnknownView) {
- return err
+ log.Println("wit/gui internal plugin error", err)
+ return nil
}
v.Wrap = true
fmt.Fprintln(v, " " + name)
fmt.Fprintln(v, strings.Repeat("foo\n", 2))
- if _, err := baseGui.SetCurrentView(name); err != nil {
- return err
+ currentView, err := baseGui.SetCurrentView(name)
+ if err != nil {
+ log.Println("wit/gui internal plugin error", err)
+ return nil
}
+ log.Println("wit/gui addbutton() current view name =", currentView.Name())
views = append(views, name)
curView = len(views) - 1
idxView += 1
currentY += 3
- if (groupSize < len(views)) {
- groupSize = len(views)
+ if (groupSize < len(name)) {
+ groupSize = len(name)
}
- return nil
+ return currentView
}
diff --git a/toolkit/gocui/main.go b/toolkit/gocui/gocui.go
index 314f5be..d614387 100644
--- a/toolkit/gocui/main.go
+++ b/toolkit/gocui/gocui.go
@@ -8,6 +8,9 @@ import (
"errors"
"fmt"
"log"
+ "os"
+
+ "git.wit.org/wit/gui/toolkit"
"github.com/awesome-gocui/gocui"
)
@@ -22,61 +25,57 @@ var (
currentY = 2
groupSize = 0
baseGui *gocui.Gui
+ helpLabel *gocui.View
+ err error
+ ch chan(func ())
)
-var helpLabel *gocui.View
-
func Init() {
- // setup log to write to a file
-// logInit()
-
- g, err := gocui.NewGui(gocui.OutputNormal, true)
- baseGui = g
+ baseGui, err = gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
log.Panicln(err)
}
- defer g.Close()
- g.Highlight = true
- g.SelFgColor = gocui.ColorRed
- g.SelFrameColor = gocui.ColorRed
+ baseGui.Highlight = true
+ baseGui.SelFgColor = gocui.ColorRed
+ baseGui.SelFrameColor = gocui.ColorRed
- g.SetManagerFunc(layout)
+ baseGui.SetManagerFunc(layout)
- if err := initKeybindings(g); err != nil {
+ if err := initKeybindings(baseGui); err != nil {
log.Panicln(err)
}
- if err := newView(g); err != nil {
- log.Panicln(err)
- }
-
- addButton("hello")
- addButton("world")
- addButton("foo")
- addGroup("blank")
- addButton("bar")
- addButton("bar none")
- addButton("bar going")
+ viewWidget = make(map[*gocui.View]*toolkit.Widget)
+ stringWidget = make(map[string]*toolkit.Widget)
- addGroup("te")
- addButton("world 2")
- addButton("foo 2")
+ ch = make(chan func())
+}
- if err := baseGui.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
- log.Panicln(err)
- }
+func Queue(f func()) {
+ log.Println("QUEUEEEEE")
+ f()
}
-func ToolkitMain() {
+func Main(f func()) {
+ if (baseGui == nil) {
+ panic("WTF Main()")
+ }
+ defer baseGui.Close()
+ // log.Println("ADDDDDDDD BUTTTTTTTTTON")
+ // addButton("test 3")
+ f()
if err := baseGui.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
log.Panicln(err)
}
+ baseGui.Close()
+ os.Exit(0)
}
func layout(g *gocui.Gui) error {
var err error
maxX, _ := g.Size()
+
helpLabel, err = g.SetView("help", maxX-32, 0, maxX-1, 11, 0)
if err != nil {
if !errors.Is(err, gocui.ErrUnknownView) {
diff --git a/toolkit/gocui/greeter.go b/toolkit/gocui/greeter.go
deleted file mode 100644
index e3094e5..0000000
--- a/toolkit/gocui/greeter.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package main
-
-import (
- "log"
-
- // "errors"
- // "fmt"
- // "strings"
- // "github.com/awesome-gocui/gocui"
-)
-
-type greeting string
-
-// stores the raw toolkit internals
-type toolkit struct {
- id string
- Name string
-
- OnChanged func(toolkit)
-}
-
-// this is exported
-var Greeter greeting
-var Toolkit toolkit
-
-// func main() {
-func (g greeting) Greet() {
- log.Println("Hello Universe")
- Init()
- // ToolkitMain()
-}
-
-func (g greeting) JcarrButton() {
- log.Println("Hello GreetButton meet Universe")
- addButton("Greet foo")
- addButton("Greet foo 2")
-}
-
-func addGroup(name string) {
- log.Println("addGroup()", name)
- currentY = 2
- currentX += groupSize + 6
-}
-
-func (g greeting) AddButton(name string) {
-// func (g greeting) AddButton() {
- log.Println("gui.gocui.AddButton()", name)
- addButton(name)
-}
-
-/*
-func addButton(name string) error {
- t := len(name)
- v, err := baseGui.SetView(name, currentX, currentY, currentX+t+3, currentY+2, 0)
- if err == nil {
- return err
- }
- if !errors.Is(err, gocui.ErrUnknownView) {
- return err
- }
-
- v.Wrap = true
- fmt.Fprintln(v, " " + name)
- fmt.Fprintln(v, strings.Repeat("foo\n", 2))
-
- if _, err := baseGui.SetCurrentView(name); err != nil {
- return err
- }
-
- views = append(views, name)
- curView = len(views) - 1
- idxView += 1
- currentY += 3
- if (groupSize < len(views)) {
- groupSize = len(views)
- }
- return nil
-}
-*/
diff --git a/toolkit/gocui/group.go b/toolkit/gocui/group.go
new file mode 100644
index 0000000..7cea346
--- /dev/null
+++ b/toolkit/gocui/group.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+ "log"
+
+ "git.wit.org/wit/gui/toolkit"
+)
+
+func NewGroup(parentW *toolkit.Widget, w *toolkit.Widget) {
+ if (parentW == nil) {
+ log.Println("wit/gui plugin error. parent widget == nil")
+ return
+ }
+ if (w == nil) {
+ log.Println("wit/gui plugin error. widget == nil")
+ return
+ }
+ if (w.Name == "") {
+ w.Name = parentW.Name
+ }
+ if (w.Name == "") {
+ w.Name = "nil newGroup"
+ }
+ log.Println("gui.gocui.AddGroup", w.Name)
+ addGroup(w.Name)
+ stringWidget[w.Name] = w
+}
+
+func addGroup(name string) {
+ log.Println("addGroup() START name =", name)
+ log.Println("addGroup() START groupSize =", groupSize, "currentY =", currentY, "currentX =", currentX)
+
+ currentY = 2
+ currentX += groupSize + 5
+ groupSize = 0
+
+ log.Println("addGroup() START, RESET Y = 3, RESET X = ", currentX)
+}
diff --git a/toolkit/gocui/keybindings.go b/toolkit/gocui/keybindings.go
index fdac1ff..69def39 100644
--- a/toolkit/gocui/keybindings.go
+++ b/toolkit/gocui/keybindings.go
@@ -11,6 +11,7 @@ import (
// "strings"
"github.com/awesome-gocui/gocui"
+ "git.wit.org/wit/gui/toolkit"
)
func initKeybindings(g *gocui.Gui) error {
@@ -87,6 +88,21 @@ func initKeybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
log.Println("enter", v.Name())
+ var w *toolkit.Widget
+ w = stringWidget[v.Name()]
+ if (w == nil) {
+ log.Println("COULD NOT FIND WIDGET", v.Name())
+ } else {
+ log.Println("FOUND WIDGET!", w)
+ if (w.Custom != nil) {
+ w.Custom()
+ return nil
+ }
+ if (w.Event != nil) {
+ w.Event(w)
+ return nil
+ }
+ }
return nil
}); err != nil {
return err
@@ -105,17 +121,11 @@ func initKeybindings(g *gocui.Gui) error {
}); err != nil {
return err
}
- if err := g.SetKeybinding("", 'j', gocui.ModNone,
- func(g *gocui.Gui, v *gocui.View) error {
- return newJ(g)
- }); err != nil {
- return err
- }
if err := g.SetKeybinding("", 'h', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
log.Println("help", v.Name())
tmp, _ := g.SetViewOnTop("help")
- log.Println("help 2", tmp.Name(), "blah")
+ log.Println("help 2", tmp.Name())
// g.SetView("help", 2, 2, 30, 15, 0);
g.SetCurrentView("help")
// moveView(g, tmp, 0, -delta)
diff --git a/toolkit/gocui/newJ.go b/toolkit/gocui/newJ.go
deleted file mode 100644
index 3e04cd3..0000000
--- a/toolkit/gocui/newJ.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The gocui Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "errors"
- "fmt"
- "log"
- "strings"
-
- "github.com/awesome-gocui/gocui"
-)
-
-var topX int = 2
-var bottomX int = 20
-var topY int = 2
-var bottomY int = 7
-
-func newJ(g *gocui.Gui) error {
- // maxX, maxY := g.Size()
- name := fmt.Sprintf("jcarr %v foo ", idxView)
- v, err := g.SetView(name, topX, topY, bottomX, bottomY, 0)
- if err == nil {
- return err
- }
- if !errors.Is(err, gocui.ErrUnknownView) {
- return err
- }
-
- v.Wrap = true
- fmt.Fprintln(v, name)
- fmt.Fprintln(v, strings.Repeat("foo\n", 2))
- // fmt.Fprintln(v, strings.Repeat(name+" ", 30))
- log.Println("newJ added a new view", v.Name())
-
- if _, err := g.SetCurrentView(name); err != nil {
- return err
- }
-
- views = append(views, name)
- curView = len(views) - 1
- idxView += 1
- return nil
-}
diff --git a/toolkit/gocui/plugin.go b/toolkit/gocui/plugin.go
new file mode 100644
index 0000000..5be26f3
--- /dev/null
+++ b/toolkit/gocui/plugin.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "log"
+
+ "git.wit.org/wit/gui/toolkit"
+
+ "github.com/awesome-gocui/gocui"
+)
+
+// This is a map between the widgets in wit/gui and the internal structures of gocui
+var viewWidget map[*gocui.View]*toolkit.Widget
+var stringWidget map[string]*toolkit.Widget
+
+func Quit() {
+ baseGui.Close()
+}
+
+// This lists out the know mappings
+func listMap() {
+ for v, w := range viewWidget {
+ log.Println("view =", v.Name, "widget name =", w.Name)
+ }
+ for s, w := range stringWidget {
+ log.Println("string =", s, "widget =", w)
+ }
+}
+
diff --git a/toolkit/gocui/views.go b/toolkit/gocui/views.go
index 6c9c65d..defe2b2 100644
--- a/toolkit/gocui/views.go
+++ b/toolkit/gocui/views.go
@@ -11,6 +11,7 @@ import (
"strings"
"github.com/awesome-gocui/gocui"
+ // "git.wit.org/wit/gui/toolkit"
)
func newView(g *gocui.Gui) error {
diff --git a/toolkit/gocui/widget.go b/toolkit/gocui/widget.go
deleted file mode 100644
index 758ac38..0000000
--- a/toolkit/gocui/widget.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package main
-
-// passes information between the toolkit library (plugin)
-
-// All Toolkit interactions should be done via a channel or Queue()
-
-// This is the only thing that is passed between the toolkit plugin
-
-// what names should be used? This is not part of [[Graphical Widget]]
-// Event() seems like a good name.
-// Could a protobuf be used here? (Can functions be passed?)
-type Widget struct {
- i int
- s string
-
- Name string
- Width int
- Height int
-
- Event func(*Widget) *Widget
-
- // Probably deprecate these
- OnChanged func(*Widget)
- Custom func(*Widget)
- OnExit func(*Widget)
-}
diff --git a/toolkit/gocui/window.go b/toolkit/gocui/window.go
new file mode 100644
index 0000000..b2d241d
--- /dev/null
+++ b/toolkit/gocui/window.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+ "log"
+
+ "git.wit.org/wit/gui/toolkit"
+)
+
+func NewWindow(w *toolkit.Widget) {
+ if (w == nil) {
+ log.Println("wit/gui plugin error. widget == nil")
+ return
+ }
+ if (w.Name == "") {
+ w.Name = "nil newWindow"
+ }
+ log.Println("gui.gocui.AddWindow", w.Name)
+}
diff --git a/toolkit/hello/Makefile b/toolkit/hello/Makefile
deleted file mode 100644
index 8271843..0000000
--- a/toolkit/hello/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-all: plugin
- ldd ../hello.so
-
-build:
- GO111MODULE="off" go build
-
-plugin:
- GO111MODULE="off" go build -buildmode=plugin -o ../hello.so
diff --git a/toolkit/hello/greeter.go b/toolkit/hello/greeter.go
deleted file mode 100644
index 1eb3307..0000000
--- a/toolkit/hello/greeter.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package main
-
-import (
-// "errors"
- "fmt"
-// "log"
-// "strings"
-
-// "github.com/awesome-gocui/gocui"
-)
-
-type greeting string
-
-
-// func main() {
-func (g greeting) Greet() {
- fmt.Println("Hello Universe")
- Init()
- // ToolkitMain()
-}
-
-// this is exported
-var Greeter greeting
diff --git a/toolkit/hello/main.go b/toolkit/hello/main.go
deleted file mode 100644
index 3a72d1f..0000000
--- a/toolkit/hello/main.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// This creates a simple hello world window
-package main
-
-import (
- "os"
- "log"
- "git.wit.org/wit/gui"
-)
-
-func Init() {
- gui.Main(myGUI)
-}
-
-// This initializes the first window
-func myGUI() {
- var w *gui.Node
- gui.Config.Title = "Hello World golang wit/gui Window"
- gui.Config.Width = 640
- gui.Config.Height = 480
- gui.Config.Exit = myExit
-
- w = gui.NewWindow()
- addHelloWorld(w, "A Simple Tab")
-}
-
-func addHelloWorld(window *gui.Node, title string) {
- var newNode, g, tb *gui.Node
-
- newNode = window.NewTab(title)
-
- g = newNode.NewGroup("hello")
- tb = g.NewTextbox("hello world box") // when debugging, this string will be used
- tb.OnChanged = func(*gui.Node) {
- s := tb.GetText()
- log.Println("text box =", s)
- }
- tb.SetText("world")
-}
-
-func myExit(n *gui.Node) {
- log.Println("exit() here")
- os.Exit(0)
-}
-
diff --git a/widget.go b/toolkit/widget.go
index 2d97f61..9003546 100644
--- a/widget.go
+++ b/toolkit/widget.go
@@ -1,4 +1,4 @@
-package gui
+package toolkit
// passes information between the toolkit library (plugin)
@@ -16,13 +16,25 @@ type Widget struct {
Name string
Width int
Height int
+ X int
+ Y int
+ Custom func()
Event func(*Widget) *Widget
// Probably deprecate these
- OnChanged func(*Widget)
- Custom func(*Widget)
- OnExit func(*Widget)
+// OnChanged func(*Widget)
+// Custom func(*Widget)
+// OnExit func(*Widget)
+}
+
+type Blah struct {
+ i int
+ s string
+
+ Name string
+ Width int
+ Height int
}
/*
diff --git a/watchdog.go b/watchdog.go
new file mode 100644
index 0000000..29ac21a
--- /dev/null
+++ b/watchdog.go
@@ -0,0 +1,23 @@
+package gui
+
+import (
+ "log"
+ "time"
+)
+
+var watchtime time.Duration = 100 // in tenths of seconds
+
+/*
+ This program sits here.
+ If you exit here, the whole thing will os.Exit()
+
+ This goroutine can be used like a watchdog timer
+*/
+func Watchdog() {
+ var i = 1
+ for {
+ log.Println("watchdog timer is alive. give me something to do.", i, "debug =", Config.Debug.Debug)
+ i += 1
+ time.Sleep(watchtime * time.Second / 10)
+ }
+}
diff --git a/window.go b/window.go
index 06db292..99e5880 100644
--- a/window.go
+++ b/window.go
@@ -4,7 +4,7 @@ import (
"log"
)
-import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
+//import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
// This routine creates a blank window with a Title and size (W x H)
//
@@ -13,33 +13,46 @@ import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
// cross platform, must pass UI changes into the OS threads (that is
// my guess).
func NewWindow() *Node {
- var n *Node
- var t *toolkit.Toolkit
+ var newNode *Node
+// var t *toolkit.Toolkit
title := Config.Title
- w := Config.Width
- h := Config.Height
- // f := Config.Exit
-
// Windows are created off of the master node of the Binary Tree
- n = Config.master.New(title)
+ newNode = Config.master.New(title)
- n.OnChanged = Config.Exit
+ newNode.Widget.Name = title
+ newNode.Widget.Width = Config.Width
+ newNode.Widget.Height = Config.Height
- t = toolkit.NewWindow(title, w, h)
- t.Custom = func () {
- if (Config.Options.Debug) {
- log.Println("Got to wit/gui Window Close START user defined close()")
+ if (Config.Exit != nil) {
+ newNode.custom = func() {
+ Config.Exit(newNode)
}
- if (n.OnChanged != nil) {
- if (Config.Options.Debug) {
- log.Println("Got to wit/gui Window Close SKIP node.custom() == nil")
- }
- n.OnChanged(n)
- return
+ }
+
+ if (newNode.custom == nil) {
+ newNode.custom = func () {StandardExit(newNode)}
+ }
+
+ newNode.Widget.Custom = newNode.custom
+
+ log.Println("gui.Node.Window()", title)
+
+ // t = toolkit.NewWindow(title, w, h)
+ // n.toolkit = t
+
+ for _, aplug := range allPlugins {
+ log.Println("gui.Node.NewWindow() toolkit plugin =", aplug.name)
+ if (aplug.NewWindow == nil) {
+ log.Println("gui.Node.NewWindow() is nil")
+ continue
}
- StandardExit(n)
+ aplug.NewWindow(&newNode.Widget)
}
- n.toolkit = t
- return n
+
+ // TODO: this is still confusing and probably wrong. This needs to communicate through a channel
+ // newNode.toolkit = n.toolkit.NewButton(name)
+ // newNode.toolkit.Custom = newNode.Widget.Custom
+
+ return newNode
}