Massive refactor to use go plugins. This is neat.
update README.md set xterm title. make os.Exit() default on window close add a toolkit.Widget to the node structure remove 'Greeter' symbol mapping scheme removed the testing greeter code plugins: attempt to load plugins in a sensible order andlabs/ui: working andlabs/ui plugin (andlabs2) buttons work in andlabs plugin TODO: re-implement non-plugin version for Windows mswindows doesn't support go plugins yet gocui: put the gocui console so file in the binary does a full init of gocui plugin Button() and Group() working very well with gogui cleanly exit gocui technically you can load two toolkits at the same time kinda both working at the same time. esoteric two working plugins at the same time give up working on two gui's at the same time this is fun, but _not interesting wow. this actually works. NewButton() from both toolkits examples: all the examples run again remove early helloplugin example buttonplugin example cmd code buttonplugin runs and ldd is minimum Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
06237c36fa
commit
8221522ba8
22
Makefile
22
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
|
||||
|
|
|
@ -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.
|
||||
The next step is to allow this to work against go-gtk and go-qt.
|
||||
|
||||
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.
|
||||
|
||||
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 [Init](/main.go#L41)
|
||||
|
||||
`func LoadPlugin(name string) *plugin.Plugin`
|
||||
`func Init()`
|
||||
|
||||
### func [LookupJcarrButton](/plugin.go#L98)
|
||||
### func [LoadToolkit](/plugin.go#L50)
|
||||
|
||||
`func LookupJcarrButton()`
|
||||
`func LoadToolkit(name string) bool`
|
||||
|
||||
### func [Main](/main.go#L38)
|
||||
loads and initializes a toolkit (andlabs/ui, gocui, etc)
|
||||
|
||||
### func [Main](/main.go#L86)
|
||||
|
||||
`func Main(f func())`
|
||||
|
||||
### func [Queue](/main.go#L51)
|
||||
This should not pass a function
|
||||
|
||||
`func Queue(f func())`
|
||||
|
||||
Other goroutines must use this to access the GUI
|
||||
|
||||
You can not acess / process the GUI thread directly from
|
||||
other goroutines. This is due to the nature of how
|
||||
Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
|
||||
For example: gui.Queue(NewWindow())
|
||||
|
||||
### func [RunGreet](/plugin.go#L88)
|
||||
|
||||
`func RunGreet()`
|
||||
|
||||
### 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
|
||||
|
||||
### 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 [Greeter](/plugin.go#L17)
|
||||
|
||||
`type Greeter interface { ... }`
|
||||
|
||||
TODO: could a protobuf work here?
|
||||
|
||||
### 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 Widget struct { ... }`
|
||||
`type Symbol any`
|
||||
|
||||
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?)
|
||||
## Sub Packages
|
||||
|
||||
* [toolkit](./toolkit)
|
||||
|
||||
---
|
||||
Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)
|
||||
|
|
180
README.md
180
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
|
||||
* 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
|
||||
|
@ -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 [GetDebug](/structs.go#L25)
|
||||
|
||||
`func DebugTab()`
|
||||
`func GetDebug() bool`
|
||||
|
||||
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 [DemoToolkitWindow](/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](/window-demo.go#L10)
|
||||
|
||||
`func DemoWindow()`
|
||||
|
||||
This creates a window that shows how this package works
|
||||
|
||||
### func [GetDebugToolkit](/structs.go#L28)
|
||||
### func [GetDebugToolkit](/structs.go#L37)
|
||||
|
||||
`func GetDebugToolkit() bool`
|
||||
|
||||
### func [GolangDebugWindow](/window-golang-debug.go#L20)
|
||||
|
||||
`func GolangDebugWindow()`
|
||||
|
||||
### func [IndentPrintln](/structs.go#L199)
|
||||
### func [IndentPrintln](/structs.go#L188)
|
||||
|
||||
`func IndentPrintln(a ...interface{})`
|
||||
|
||||
### func [Main](/main.go#L31)
|
||||
### func [Init](/main.go#L41)
|
||||
|
||||
`func Init()`
|
||||
|
||||
### func [LoadToolkit](/plugin.go#L37)
|
||||
|
||||
`func LoadToolkit(name string)`
|
||||
|
||||
loads and initializes a toolkit (andlabs/ui, gocui, etc)
|
||||
|
||||
### 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()
|
||||
### type [Symbol](/plugin.go#L17)
|
||||
|
||||
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.
|
||||
`type Symbol any`
|
||||
|
||||
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.
|
||||
## Sub Packages
|
||||
|
||||
```golang
|
||||
package main
|
||||
* [need-to-redo](./need-to-redo)
|
||||
|
||||
import (
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
You get a window
|
||||
```
|
||||
|
||||
### type [Widget](/structs.go#L74)
|
||||
|
||||
`type Widget int`
|
||||
* [toolkit](./toolkit)
|
||||
|
||||
---
|
||||
Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)
|
||||
|
|
35
button.go
35
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")
|
||||
}
|
||||
}
|
||||
newNode.custom = custom
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
return newNode
|
||||
}
|
||||
|
|
52
checkbox.go
52
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()
|
||||
*/
|
||||
|
||||
return c
|
||||
|
||||
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 newNode
|
||||
}
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -2,4 +2,5 @@ run: build
|
|||
./debug
|
||||
|
||||
build:
|
||||
go build
|
||||
# go build
|
||||
GO111MODULE="off" go build
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
gui.Init()
|
||||
gui.Main(helloworld)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
48
doc.go
48
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
|
||||
* 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.
|
||||
The next step is to allow this to work against go-gtk and go-qt.
|
||||
|
||||
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.
|
||||
|
||||
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]
|
||||
|
||||
|
||||
*/
|
||||
|
|
73
dropdown.go
73
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")
|
||||
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
|
||||
}
|
||||
} else {
|
||||
if (Config.Options.DebugChange) {
|
||||
log.Println("Running n.OnChanged(n)")
|
||||
}
|
||||
n.OnChanged(n)
|
||||
aplug.AddDropdownName(&n.Widget, name)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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) AddDropdown(name string) {
|
||||
n.toolkit.AddDropdown(name)
|
||||
}
|
||||
|
||||
func (n *Node) SetDropdown(i int) {
|
||||
n.toolkit.SetDropdown(i)
|
||||
}
|
||||
|
||||
func (n *Node) NewDropdown(text string) *Node {
|
||||
newNode := n.New(text)
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
33
group.go
33
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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
19
int.go
19
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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
111
main.go
111
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()
|
||||
}
|
||||
|
||||
// load the gocui plugin
|
||||
PlugGocli = LoadPlugin("../../toolkit/gocui.so")
|
||||
PlugGocliOk = false
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
|
13
node.go
13
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)
|
||||
|
|
307
plugin.go
307
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
|
||||
|
||||
// var gBut plugin.Symbol
|
||||
var jcarrBut plugin.Symbol
|
||||
var symGreeter plugin.Symbol
|
||||
var greeter Greeter
|
||||
var ok bool
|
||||
// loads and initializes a toolkit (andlabs/ui, gocui, etc)
|
||||
func LoadToolkit(name string) bool {
|
||||
var newPlug aplug
|
||||
|
||||
var typeToolkit plugin.Symbol
|
||||
var typeToolkitCast Greeter
|
||||
log.Println("gui.LoadToolkit() START")
|
||||
newPlug.LoadOk = false
|
||||
|
||||
func LoadPlugin(name string) *plugin.Plugin {
|
||||
scs := spew.ConfigState{MaxDepth: 1}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// load module
|
||||
// 1. open the so file to load the symbols
|
||||
plug, err := plugin.Open(name)
|
||||
log.Println("plug =")
|
||||
log.Println(scs.Sdump(plug))
|
||||
// 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")
|
||||
|
||||
allPlugins = append(allPlugins, &newPlug)
|
||||
|
||||
log.Println("gui.LoadToolkit() END", newPlug.name, filename)
|
||||
newPlug.LoadOk = true
|
||||
return true
|
||||
}
|
||||
|
||||
func loadFuncE(p *aplug, funcName string) func() {
|
||||
var newfunc func()
|
||||
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())
|
||||
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
|
||||
|
||||
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))
|
||||
if !ok {
|
||||
log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
|
||||
return nil
|
||||
}
|
||||
return newfunc
|
||||
}
|
||||
|
||||
func loadFuncS(p *aplug, funcName string) func(*toolkit.Widget, string) {
|
||||
var newfunc func(*toolkit.Widget, string)
|
||||
var ok bool
|
||||
var test plugin.Symbol
|
||||
|
||||
test, err = p.plug.Lookup(funcName)
|
||||
if err != nil {
|
||||
log.Println("DID NOT FIND: name =", test, "err =", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
newfunc, ok = test.(func(*toolkit.Widget, string))
|
||||
if !ok {
|
||||
log.Println("function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
|
||||
return nil
|
||||
}
|
||||
return newfunc
|
||||
}
|
||||
|
||||
func loadFunc2(p *aplug, funcName string) func(*toolkit.Widget, *toolkit.Widget) {
|
||||
var newfunc func(*toolkit.Widget, *toolkit.Widget)
|
||||
var ok bool
|
||||
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
|
||||
}
|
||||
return newfunc
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
test, err = p.plug.Lookup(funcName)
|
||||
if err != nil {
|
||||
log.Println("DID NOT FIND: name =", test, "err =", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
|
||||
filename = "/usr/share/wit/gui/" + name
|
||||
p.plug = loadfile(filename)
|
||||
if (p.plug != nil) {
|
||||
p.filename = filename
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
symGreeter, err = plug.Lookup("Greeter")
|
||||
log.Println("symGreater", symGreeter)
|
||||
log.Println(scs.Sdump(symGreeter))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 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))
|
||||
if !ok {
|
||||
log.Println("unexpected type from module symbol")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
/*
|
||||
typeToolkitCast, ok = typeToolkit.(Greeter)
|
||||
if !ok {
|
||||
log.Println("unexpected cast of Toolkit to Greeter")
|
||||
os.Exit(1)
|
||||
}
|
||||
*/
|
||||
return plug
|
||||
}
|
||||
|
||||
func RunGreet() {
|
||||
log.Println("gui.RunGreet() START")
|
||||
if (greeter == nil) {
|
||||
log.Println("wit/gui gocui plugin didn't load")
|
||||
return
|
||||
}
|
||||
PlugGocliOk = true
|
||||
greeter.Greet()
|
||||
}
|
||||
|
||||
func LookupJcarrButton() {
|
||||
log.Println("lookupJcarrButton() START")
|
||||
|
||||
if (greeter == nil) {
|
||||
log.Println("wit/gui gocui plugin didn't load")
|
||||
return
|
||||
}
|
||||
greeter.JcarrButton()
|
||||
}
|
||||
|
||||
func GocuiAddButton(name string) {
|
||||
log.Println("GocuiAddButton() START", name)
|
||||
|
||||
if (greeter == nil) {
|
||||
log.Println("wit/gui gocui plugin didn't load")
|
||||
return
|
||||
}
|
||||
greeter.AddButton(name)
|
||||
}
|
||||
|
|
35
slider.go
35
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
|
||||
newNode := n.New(name)
|
||||
newNode.Widget.Name = name
|
||||
newNode.Widget.X = x
|
||||
newNode.Widget.Y = y
|
||||
|
||||
log.Println("toolkit.NewSlider() START", name)
|
||||
|
||||
n.verify()
|
||||
|
||||
// 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)
|
||||
newNode.Widget.Custom = func() {
|
||||
log.Println("even newer clicker() name in NewSlider", newNode.Widget)
|
||||
}
|
||||
sNode.toolkit = newT
|
||||
sNode.Dump()
|
||||
// panic("checking Custom()")
|
||||
|
||||
return 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)
|
||||
}
|
||||
|
||||
return newNode
|
||||
}
|
||||
|
|
34
spinner.go
34
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
|
||||
newNode := n.New(name)
|
||||
newNode.Widget.Name = name
|
||||
newNode.Widget.X = x
|
||||
newNode.Widget.Y = y
|
||||
|
||||
log.Println("toolkit.NewSpinner() START", name)
|
||||
|
||||
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()
|
||||
|
||||
newT.Custom = func () {
|
||||
commonCallback(sNode)
|
||||
newNode.Widget.Custom = func() {
|
||||
log.Println("even newer clicker() name in NewSpinner", newNode.Widget)
|
||||
}
|
||||
|
||||
return 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 newNode
|
||||
}
|
||||
|
|
77
structs.go
77
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 {
|
||||
|
|
23
tab.go
23
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
|
||||
}
|
||||
|
|
52
textbox.go
52
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
|
||||
newNode := n.New(name)
|
||||
|
||||
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)
|
||||
|
||||
c.toolkit = newt
|
||||
c.custom = n.custom
|
||||
|
||||
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")
|
||||
}
|
||||
newNode.Widget.Custom = func() {
|
||||
log.Println("even newer clicker() name in NewTextBox", newNode.Widget)
|
||||
}
|
||||
|
||||
return c
|
||||
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 newNode
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
all: plugin
|
||||
|
||||
plugin:
|
||||
GO111MODULE="off" go build -buildmode=plugin -o ../andlabs2.so
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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()
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,3 +6,6 @@ build:
|
|||
|
||||
plugin:
|
||||
GO111MODULE="off" go build -buildmode=plugin -o ../gocui.so
|
||||
|
||||
objdump:
|
||||
objdump -t ../gocui.so |less
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
log.Panicln(err)
|
||||
}
|
||||
if err := newView(g); err != nil {
|
||||
if err := initKeybindings(baseGui); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
addButton("hello")
|
||||
addButton("world")
|
||||
addButton("foo")
|
||||
viewWidget = make(map[*gocui.View]*toolkit.Widget)
|
||||
stringWidget = make(map[string]*toolkit.Widget)
|
||||
|
||||
addGroup("blank")
|
||||
addButton("bar")
|
||||
addButton("bar none")
|
||||
addButton("bar going")
|
||||
|
||||
addGroup("te")
|
||||
addButton("world 2")
|
||||
addButton("foo 2")
|
||||
|
||||
if err := baseGui.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
|
||||
log.Panicln(err)
|
||||
}
|
||||
ch = make(chan func())
|
||||
}
|
||||
|
||||
func ToolkitMain() {
|
||||
func Queue(f func()) {
|
||||
log.Println("QUEUEEEEE")
|
||||
f()
|
||||
}
|
||||
|
||||
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) {
|
|
@ -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
|
||||
}
|
||||
*/
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/awesome-gocui/gocui"
|
||||
// "git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
||||
func newView(g *gocui.Gui) error {
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
all: plugin
|
||||
ldd ../hello.so
|
||||
|
||||
build:
|
||||
GO111MODULE="off" go build
|
||||
|
||||
plugin:
|
||||
GO111MODULE="off" go build -buildmode=plugin -o ../hello.so
|
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
/*
|
|
@ -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)
|
||||
}
|
||||
}
|
59
window.go
59
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
|
||||
}
|
||||
StandardExit(n)
|
||||
}
|
||||
n.toolkit = t
|
||||
return n
|
||||
|
||||
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
|
||||
}
|
||||
aplug.NewWindow(&newNode.Widget)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue