cleanup of the example commands. more plugin work
add a button in two plugins at the same time! added a button in andlabs/ui & gocui attempt a common widget struct between wit/gui & the plugins start handling missing plugins rename Makefile command examples remote examples used for testing filename improvements golang src code uses lowercase and _ in filenames fix crash when button click function == nil fix wrong name 'gocli' -> 'gocui' keep fighting with goreadme generated README.md Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
c43a684857
commit
06237c36fa
|
@ -1,12 +1,10 @@
|
|||
*.swp
|
||||
|
||||
# ignore compiled plugins
|
||||
toolkit/*.so
|
||||
|
||||
cmds/buttonplugin/buttonplugin
|
||||
cmds/console-ui-helloworld/console-ui-helloworld
|
||||
cmds/debug/debug
|
||||
cmds/helloworld/helloworld
|
||||
cmds/textbox/textbox
|
||||
cmds/gui-demo/gui-demo
|
||||
cmds/consolemouse/consolemouse
|
||||
cmds/console-hello-world/console-hello-world
|
||||
cmds/gocli-as-plugin/gocli-as-plugin
|
||||
cmds/buttonAsPlugin/buttonAsPlugin
|
||||
|
||||
tookit/gocui/gocli
|
||||
|
||||
toolkit/*.so
|
||||
|
|
28
Makefile
28
Makefile
|
@ -2,7 +2,7 @@
|
|||
|
||||
all: README.md
|
||||
@echo
|
||||
@echo "make examples # will run all the examples"
|
||||
@echo "make cmds # will run all the cmds"
|
||||
@echo "make update # full git update"
|
||||
@echo
|
||||
make -C cmds/helloworld
|
||||
|
@ -12,16 +12,22 @@ update:
|
|||
git pull
|
||||
go get -v -t -u ./...
|
||||
|
||||
examples: examples-consolemouse examples-helloworld examples-gui-demo
|
||||
cmds: cmds-buttonplugin cmds-console-ui-helloworld cmds-debug cmds-helloworld cmds-textbox
|
||||
|
||||
examples-consolemouse:
|
||||
make -C cmds/consolemouse
|
||||
cmds-buttonplugin:
|
||||
make -C cmds/buttonplugin
|
||||
|
||||
examples-helloworld:
|
||||
cmds-console-ui-helloworld:
|
||||
make -C cmds/console-ui-helloworld
|
||||
|
||||
cmds-helloworld:
|
||||
make -C cmds/helloworld
|
||||
|
||||
examples-gui-demo:
|
||||
make -C cmds/gui-demo
|
||||
cmds-debug:
|
||||
make -C cmds/debug
|
||||
|
||||
cmds-textbox:
|
||||
make -C cmds/textbox
|
||||
|
||||
# sync repo to the github backup
|
||||
github:
|
||||
|
@ -34,7 +40,11 @@ doc:
|
|||
|
||||
# GO111MODULE=on go install github.com/posener/goreadme/cmd/goreadme@latest (worked Oct 20 2022)
|
||||
README.md: doc.go
|
||||
goreadme -factories -types -functions -variabless > README.md
|
||||
goreadme -factories -types -functions -variabless > README-goreadme.md
|
||||
|
||||
clean:
|
||||
rm -f toolkit/*.so
|
||||
|
||||
plugins:
|
||||
GO111MODULE="off" go build -buildmode=plugin -o toolkit/gocli.so toolkit/gocli/greeter.go
|
||||
# GO111MODULE="off" go build -buildmode=plugin -o toolkit/test.so toolkit/gocui/*.go
|
||||
make -C toolkit/gocui
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
# 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:
|
||||
|
||||
Definitions:
|
||||
|
||||
```go
|
||||
* Toolkit: the underlying library (MacOS gui, Windows gui, gtk, qt, etc)
|
||||
* Node: A binary tree of all the underlying GUI toolkit elements
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
This section demonstrates how to quickly get started with spew. See the
|
||||
sections below for further details on formatting and configuration options.
|
||||
|
||||
```go
|
||||
// This creates a simple hello world window
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
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.Main(helloworld)
|
||||
}
|
||||
|
||||
// This initializes the first window and 2 tabs
|
||||
func helloworld() {
|
||||
gui.Config.Title = "Hello World golang wit/gui Window"
|
||||
gui.Config.Width = 640
|
||||
gui.Config.Height = 480
|
||||
|
||||
window := gui.NewWindow()
|
||||
addTab(window, "A Simple Tab Demo")
|
||||
addTab(window, "A Second Tab")
|
||||
}
|
||||
|
||||
func addTab(w *gui.Node, title string) {
|
||||
tab := w.NewTab(title)
|
||||
|
||||
group := tab.NewGroup("foo bar")
|
||||
group.NewButton("hello", func() {
|
||||
log.Println("world")
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Debian Build
|
||||
|
||||
This worked on debian sid on 2022/10/20
|
||||
I didn't record the dependances needed
|
||||
|
||||
```go
|
||||
GO111MODULE="off" go get -v -t -u git.wit.org/wit/gui
|
||||
cd ~/go/src/git.wit.org/wit/gui/cmds/helloworld/
|
||||
GO111MODULE="off" go build -v -x
|
||||
[./helloworld](./helloworld)
|
||||
```
|
||||
|
||||
## Toolkits
|
||||
|
||||
* Andlabs - [https://github.com/andlabs/ui](https://github.com/andlabs/ui)
|
||||
* gocui - [https://github.com/awesome-gocui/gocui](https://github.com/awesome-gocui/gocui)
|
||||
|
||||
The goal is to design something that will work with more than one.
|
||||
|
||||
Right now, this abstraction is built on top of the go package 'andlabs/ui'
|
||||
which does the cross platform support.
|
||||
The next step is to intent is to allow this to work directly against GTK and QT.
|
||||
|
||||
It should be able to 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'
|
||||
|
||||
## References
|
||||
|
||||
Useful links and other
|
||||
external things
|
||||
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)
|
||||
|
||||
```go
|
||||
* [Wikipedia Graphical widget]
|
||||
* [Github mirror]
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
```golang
|
||||
var PlugGocli *plugin.Plugin
|
||||
```
|
||||
|
||||
```golang
|
||||
var PlugGocliOk bool
|
||||
```
|
||||
|
||||
```golang
|
||||
var PlugHello *plugin.Plugin
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
### func [DebugTab](/example_window_debug.go#L26)
|
||||
|
||||
`func DebugTab()`
|
||||
|
||||
this function is used by the examples to add a tab
|
||||
dynamically to the bugWin node
|
||||
TODO: make this smarter once this uses toolkit/
|
||||
|
||||
### func [DebugWindow](/example_window_debug.go#L14)
|
||||
|
||||
`func DebugWindow()`
|
||||
|
||||
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() bool`
|
||||
|
||||
### func [GetDebugToolkit](/structs.go#L36)
|
||||
|
||||
`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(a ...interface{})`
|
||||
|
||||
### func [LoadPlugin](/plugin.go#L36)
|
||||
|
||||
`func LoadPlugin(name string) *plugin.Plugin`
|
||||
|
||||
### func [LookupJcarrButton](/plugin.go#L98)
|
||||
|
||||
`func LookupJcarrButton()`
|
||||
|
||||
### func [Main](/main.go#L38)
|
||||
|
||||
`func Main(f func())`
|
||||
|
||||
### func [Queue](/main.go#L51)
|
||||
|
||||
`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(s bool)`
|
||||
|
||||
### func [SetDebugToolkit](/structs.go#L40)
|
||||
|
||||
`func SetDebugToolkit(s bool)`
|
||||
|
||||
### func [ShowDebugValues](/structs.go#L44)
|
||||
|
||||
`func ShowDebugValues()`
|
||||
|
||||
### func [StandardClose](/main.go#L57)
|
||||
|
||||
`func StandardClose(n *Node)`
|
||||
|
||||
The window is destroyed but the application does not quit
|
||||
|
||||
### func [StandardExit](/main.go#L65)
|
||||
|
||||
`func StandardExit(n *Node)`
|
||||
|
||||
The window is destroyed but the application does not quit
|
||||
|
||||
## Types
|
||||
|
||||
### type [Greeter](/plugin.go#L17)
|
||||
|
||||
`type Greeter interface { ... }`
|
||||
|
||||
TODO: could a protobuf work here?
|
||||
|
||||
### type [GuiConfig](/structs.go#L67)
|
||||
|
||||
`type GuiConfig struct { ... }`
|
||||
|
||||
#### Variables
|
||||
|
||||
```golang
|
||||
var Config GuiConfig
|
||||
```
|
||||
|
||||
### type [GuiOptions](/structs.go#L56)
|
||||
|
||||
`type GuiOptions struct { ... }`
|
||||
|
||||
This struct can be used with go-arg
|
||||
|
||||
### type [Node](/structs.go#L117)
|
||||
|
||||
`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(title string) *Node`
|
||||
|
||||
#### func [NewWindow](/window.go#L15)
|
||||
|
||||
`func NewWindow() *Node`
|
||||
|
||||
This routine creates a blank window with a Title and size (W x H)
|
||||
|
||||
This routine can not have any arguements due to the nature of how
|
||||
it can be passed via the 'andlabs/ui' queue which, because it is
|
||||
cross platform, must pass UI changes into the OS threads (that is
|
||||
my guess).
|
||||
|
||||
This example demonstrates how to create a NewWindow()
|
||||
|
||||
Interacting with a GUI in a cross platform fashion adds some
|
||||
unusual problems. To obvuscate those, andlabs/ui starts a
|
||||
goroutine that interacts with the native gui toolkits
|
||||
on the Linux, MacOS, Windows, etc.
|
||||
|
||||
Because of this oddity, to initialize a new window, the
|
||||
function is not passed any arguements and instead passes
|
||||
the information via the Config type.
|
||||
|
||||
```golang
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
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](/widget.go#L12)
|
||||
|
||||
`type Widget struct { ... }`
|
||||
|
||||
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?)
|
||||
|
||||
---
|
||||
Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)
|
13
README.md
13
README.md
|
@ -8,21 +8,17 @@ and principles for how this package should generally work:
|
|||
|
||||
Definitions:
|
||||
|
||||
```go
|
||||
* Toolkit: the underlying library (MacOS gui, Windows gui, gtk, qt, etc)
|
||||
* Node: A binary tree of all the underlying GUI toolkit elements
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
@ -113,13 +109,8 @@ Useful links and other
|
|||
external things
|
||||
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)
|
||||
|
||||
```go
|
||||
* [Wikipedia Graphical widget]
|
||||
* [Github mirror]
|
||||
```
|
||||
* [Wikipedia Graphical widget](https://en.wikipedia.org/wiki/Graphical_widget)
|
||||
* [Github mirror](https://github.com/witorg/gui)
|
||||
|
||||
## Functions
|
||||
|
||||
|
|
23
button.go
23
button.go
|
@ -4,21 +4,34 @@ import "log"
|
|||
|
||||
func (n *Node) NewButton(name string, custom func()) *Node {
|
||||
if (n.toolkit == nil) {
|
||||
log.Println("gui.Node.AppendButton() filed node.toolkit == nil")
|
||||
panic("gui.Node.AppendButton() filed node.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.AppendButton() Button Clicked. Running custom() from outside toolkit START")
|
||||
log.Println("gui.Newutton() Button Clicked. Running custom() from outside toolkit START")
|
||||
}
|
||||
if (custom != nil) {
|
||||
custom()
|
||||
} else {
|
||||
log.Println("wit/gui No callback function is defined for button name =", name)
|
||||
}
|
||||
custom()
|
||||
if (Config.Options.Debug) {
|
||||
log.Println("gui.AppendButton() Button Clicked. Running custom() from outside toolkit END")
|
||||
log.Println("gui.NewButton() Button Clicked. Running custom() from outside toolkit END")
|
||||
}
|
||||
}
|
||||
newNode.custom = custom
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
run: build
|
||||
./buttonAsPlugin >/tmp/buttonAsPlugin.log 2>&1
|
||||
|
||||
build-release:
|
||||
go get -v -u -x .
|
||||
go build
|
||||
./buttonAsPlugin
|
||||
|
||||
build:
|
||||
GO111MODULE="off" go get -v -x .
|
||||
GO111MODULE="off" go build
|
||||
|
||||
update:
|
||||
GO111MODULE="off" go get -v -u -x .
|
|
@ -1,11 +1,10 @@
|
|||
run: build
|
||||
./console-hello-world
|
||||
reset
|
||||
ldd ./console-hello-world
|
||||
./buttonplugin >/tmp/buttonplugin.log 2>&1
|
||||
|
||||
build-release:
|
||||
go get -v -u -x .
|
||||
go build
|
||||
./buttonplugin
|
||||
|
||||
build:
|
||||
GO111MODULE="off" go get -v -x .
|
|
@ -3,19 +3,19 @@ package main
|
|||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// go loadPlugin(plugHello, "../../toolkit/hello.so")
|
||||
|
||||
// this doesn't seem to work
|
||||
captureSTDOUT()
|
||||
|
||||
// go loadPlugin("../../toolkit/gocli.so")
|
||||
gui.Main(buttonWindow)
|
||||
}
|
||||
|
||||
var counter int = 10
|
||||
|
||||
// This creates a window
|
||||
func buttonWindow() {
|
||||
var w, g *gui.Node
|
||||
|
@ -30,13 +30,6 @@ func buttonWindow() {
|
|||
log.Println("world")
|
||||
})
|
||||
|
||||
/*
|
||||
g.NewButton("LoadPlugin()", func () {
|
||||
log.Println("world")
|
||||
gui.LoadPlugin("../../toolkit/gocli.so")
|
||||
})
|
||||
*/
|
||||
|
||||
g.NewButton("RunGreet()", func () {
|
||||
log.Println("world")
|
||||
go gui.RunGreet()
|
||||
|
@ -47,8 +40,10 @@ func buttonWindow() {
|
|||
gui.LookupJcarrButton()
|
||||
})
|
||||
|
||||
g.NewButton("gui.GocuiAddButton()", func () {
|
||||
log.Println("gui.GocuiAddButton()")
|
||||
gui.GocuiAddButton("new foobar")
|
||||
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)
|
||||
})
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
run: build
|
||||
./consolemouse
|
||||
./console-ui-helloworld
|
||||
reset
|
||||
ldd ./console-ui-helloworld
|
||||
|
||||
build-release:
|
||||
go get -v -u -x .
|
|
@ -51,17 +51,9 @@ func main() {
|
|||
}
|
||||
|
||||
addButton("hello")
|
||||
addButton("world")
|
||||
addButton("foo")
|
||||
|
||||
addGroup("blank")
|
||||
addButton("bar")
|
||||
addButton("bar none")
|
||||
addButton("bar going")
|
||||
|
||||
addGroup("te")
|
||||
addButton("world 2")
|
||||
addButton("foo 2")
|
||||
addButton("world")
|
||||
|
||||
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
|
||||
log.Panicln(err)
|
|
@ -1,51 +0,0 @@
|
|||
// This creates a simple hello world window
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
import toolkit "git.wit.org/wit/gui/toolkit/gocui"
|
||||
|
||||
func configureGogui() {
|
||||
toolkit.Init()
|
||||
toolkit.OnExit(mycallback)
|
||||
}
|
||||
|
||||
func startGogui() {
|
||||
toolkit.StartConsoleMouse()
|
||||
}
|
||||
|
||||
func mycallback(name string) {
|
||||
log.Println("run andlabs here? name =", name)
|
||||
if (name == "andlabs") {
|
||||
go gui.Main(initGUI)
|
||||
}
|
||||
if (name == "something") {
|
||||
log.Println("add something to do here")
|
||||
}
|
||||
if (name == "DemoToolkitWindow") {
|
||||
gui.Queue( func () {
|
||||
gui.DemoToolkitWindow()
|
||||
})
|
||||
}
|
||||
if (name == "addDemoTab") {
|
||||
gui.Queue( func () {
|
||||
addDemoTab(w, "A Tab from gocui")
|
||||
})
|
||||
}
|
||||
if (name == "DebugWindow") {
|
||||
log.Println("Opening a Debug Window via the gui.Queue()")
|
||||
gui.Config.Width = 800
|
||||
gui.Config.Height = 300
|
||||
gui.Config.Exit = myExit
|
||||
gui.Queue(gui.DebugWindow)
|
||||
time.Sleep(1 * time.Second)
|
||||
gui.Queue(gui.DebugTab)
|
||||
}
|
||||
if (name == "exit") {
|
||||
myExit(nil)
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
// This creates a simple hello world window
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"log"
|
||||
// "time"
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
import toolkit "git.wit.org/wit/gui/toolkit/gocui"
|
||||
|
||||
var w *gui.Node
|
||||
|
||||
func main() {
|
||||
go gui.Main(initGUI)
|
||||
|
||||
configureGogui()
|
||||
startGogui()
|
||||
}
|
||||
|
||||
// This initializes the first window
|
||||
func initGUI() {
|
||||
gui.Config.Title = "Hello World golang wit/gui Window"
|
||||
gui.Config.Width = 640
|
||||
gui.Config.Height = 480
|
||||
gui.Config.Exit = myExit
|
||||
|
||||
w = gui.NewWindow()
|
||||
w.Dump()
|
||||
addDemoTab(w, "A Simple Tab Demo")
|
||||
addDemoTab(w, "A Second Tab")
|
||||
}
|
||||
|
||||
func addDemoTab(w *gui.Node, title string) {
|
||||
var newNode, g *gui.Node
|
||||
|
||||
newNode = w.NewTab(title)
|
||||
|
||||
g = newNode.NewGroup("group 1")
|
||||
|
||||
dd := g.NewDropdown("demoCombo2")
|
||||
dd.AddDropdown("more 1")
|
||||
dd.AddDropdown("less 2")
|
||||
dd.AddDropdown("foo 3")
|
||||
}
|
||||
|
||||
func myExit(n *gui.Node) {
|
||||
log.Println("You can Do exit() things here")
|
||||
toolkit.Exit()
|
||||
os.Exit(0)
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
run: build
|
||||
./gui-demo
|
||||
./debug
|
||||
|
||||
build:
|
||||
go build
|
|
@ -0,0 +1,20 @@
|
|||
// A simple helloworld window
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
// This creates a window
|
||||
func helloworld() {
|
||||
var w *gui.Node
|
||||
gui.Config.Title = "helloworld golang wit/gui window"
|
||||
gui.Config.Width = 400
|
||||
gui.Config.Height = 100
|
||||
|
||||
w = gui.NewWindow()
|
||||
w.NewButton("hello", func () {
|
||||
log.Println("world")
|
||||
})
|
||||
}
|
|
@ -17,16 +17,12 @@ import (
|
|||
func main() {
|
||||
log.Println("Starting my Control Panel")
|
||||
|
||||
go gui.Main(initGUI)
|
||||
go gui.Main(helloworld)
|
||||
// go gui.DemoToolkitWindow()
|
||||
|
||||
watchGUI()
|
||||
}
|
||||
|
||||
// This initializes the first window
|
||||
func initGUI() {
|
||||
gui.DemoToolkitWindow()
|
||||
}
|
||||
|
||||
// This demonstrates how to properly interact with the GUI
|
||||
// You can not involke the GUI from external goroutines in most cases.
|
||||
func watchGUI() {
|
|
@ -1,14 +0,0 @@
|
|||
run: build
|
||||
./gocli-as-plugin
|
||||
# ldd ./gocli-as-plugin
|
||||
|
||||
build-release:
|
||||
go get -v -u -x .
|
||||
go build
|
||||
|
||||
build:
|
||||
GO111MODULE="off" go get -v -x .
|
||||
GO111MODULE="off" go build
|
||||
|
||||
update:
|
||||
GO111MODULE="off" go get -v -u -x .
|
|
@ -1,35 +0,0 @@
|
|||
// This creates a simple hello world window
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"os"
|
||||
arg "github.com/alexflint/go-arg"
|
||||
)
|
||||
|
||||
|
||||
var args struct {
|
||||
Foo string
|
||||
Bar bool
|
||||
User string `arg:"env:USER"`
|
||||
Demo bool `help:"run a demo"`
|
||||
}
|
||||
|
||||
var f *os.File
|
||||
var err error
|
||||
|
||||
func init() {
|
||||
arg.MustParse(&args)
|
||||
fmt.Println(args.Foo, args.Bar, args.User)
|
||||
|
||||
f, err = os.OpenFile("/tmp/guilogfile", os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
log.Fatalf("error opening file: %v", err)
|
||||
}
|
||||
// hmm. is there a trick here or must this be in main()
|
||||
// defer f.Close()
|
||||
|
||||
log.SetOutput(f)
|
||||
log.Println("This is a test log entry")
|
||||
}
|
|
@ -1,59 +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 (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"plugin"
|
||||
// "github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
type Greeter interface {
|
||||
Greet()
|
||||
}
|
||||
|
||||
var plugGocli *plugin.Plugin
|
||||
var plugHello *plugin.Plugin
|
||||
|
||||
func main() {
|
||||
log.Println("attempt plugin")
|
||||
|
||||
go loadPlugin(plugHello, "../../toolkit/hello.so")
|
||||
loadPlugin(plugGocli, "../../toolkit/gocli.so")
|
||||
}
|
||||
|
||||
func loadPlugin(plug *plugin.Plugin, name string) {
|
||||
// load module
|
||||
// 1. open the so file to load the symbols
|
||||
plug, err = plugin.Open(name)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 2. look up a symbol (an exported function or variable)
|
||||
// in this case, variable Greeter
|
||||
symGreeter, err := plug.Lookup("Greeter")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
log.Println("symGreater", symGreeter)
|
||||
|
||||
// 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)
|
||||
if !ok {
|
||||
log.Println("unexpected type from module symbol")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 4. use the module
|
||||
greeter.Greet()
|
||||
}
|
3
doc.go
3
doc.go
|
@ -73,6 +73,9 @@ I didn't record the dependances needed
|
|||
|
||||
Toolkits
|
||||
|
||||
* Andlabs - https://github.com/andlabs/ui
|
||||
* gocui - https://github.com/awesome-gocui/gocui
|
||||
|
||||
The goal is to design something that will work with more than one.
|
||||
|
||||
Right now, this abstraction is built on top of the go package 'andlabs/ui'
|
||||
|
|
5
main.go
5
main.go
|
@ -30,8 +30,9 @@ func init() {
|
|||
Config.master.Dump()
|
||||
}
|
||||
|
||||
// load the gocli plugin
|
||||
PlugGocli = LoadPlugin("../../toolkit/gocli.so")
|
||||
// load the gocui plugin
|
||||
PlugGocli = LoadPlugin("../../toolkit/gocui.so")
|
||||
PlugGocliOk = false
|
||||
}
|
||||
|
||||
func Main(f func()) {
|
||||
|
|
30
plugin.go
30
plugin.go
|
@ -1,5 +1,10 @@
|
|||
package gui
|
||||
|
||||
// This is based off of the excellent example and documentation here:
|
||||
// https://github.com/vladimirvivien/go-plugin-example
|
||||
// There truly are great people in this world.
|
||||
// It's a pleasure to be here with all of you
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
@ -8,6 +13,7 @@ import (
|
|||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
// TODO: could a protobuf work here?
|
||||
type Greeter interface {
|
||||
Greet()
|
||||
JcarrButton()
|
||||
|
@ -15,6 +21,7 @@ type Greeter interface {
|
|||
}
|
||||
|
||||
var PlugGocli *plugin.Plugin
|
||||
var PlugGocliOk bool
|
||||
var PlugHello *plugin.Plugin
|
||||
|
||||
// var gBut plugin.Symbol
|
||||
|
@ -23,6 +30,9 @@ var symGreeter plugin.Symbol
|
|||
var greeter Greeter
|
||||
var ok bool
|
||||
|
||||
var typeToolkit plugin.Symbol
|
||||
var typeToolkitCast Greeter
|
||||
|
||||
func LoadPlugin(name string) *plugin.Plugin {
|
||||
scs := spew.ConfigState{MaxDepth: 1}
|
||||
|
||||
|
@ -33,12 +43,19 @@ func LoadPlugin(name string) *plugin.Plugin {
|
|||
log.Println(scs.Sdump(plug))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
||||
PlugGocli = plug
|
||||
|
||||
// 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))
|
||||
|
@ -57,6 +74,14 @@ func LoadPlugin(name string) *plugin.Plugin {
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -66,6 +91,7 @@ func RunGreet() {
|
|||
log.Println("wit/gui gocui plugin didn't load")
|
||||
return
|
||||
}
|
||||
PlugGocliOk = true
|
||||
greeter.Greet()
|
||||
}
|
||||
|
||||
|
|
29
structs.go
29
structs.go
|
@ -82,35 +82,6 @@ type GuiConfig struct {
|
|||
prefix string
|
||||
}
|
||||
|
||||
type Widget int
|
||||
|
||||
// https://ieftimov.com/post/golang-datastructures-trees/
|
||||
const (
|
||||
Unknown Widget = iota
|
||||
Window
|
||||
Tab
|
||||
Frame
|
||||
Dropbox
|
||||
Spinner
|
||||
Label
|
||||
)
|
||||
|
||||
func (s Widget) String() string {
|
||||
switch s {
|
||||
case Window:
|
||||
return "Window"
|
||||
case Tab:
|
||||
return "Tab"
|
||||
case Frame:
|
||||
return "Frame"
|
||||
case Label:
|
||||
return "Label"
|
||||
case Dropbox:
|
||||
return "Dropbox"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// The Node is simply the name and the size of whatever GUI element exists
|
||||
type Node struct {
|
||||
id int
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
all: plugin
|
||||
ldd ../gocli.so
|
||||
ldd ../gocui.so
|
||||
|
||||
build:
|
||||
GO111MODULE="off" go build
|
||||
|
||||
plugin:
|
||||
GO111MODULE="off" go build -buildmode=plugin -o ../gocli.so
|
||||
GO111MODULE="off" go build -buildmode=plugin -o ../gocui.so
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
func (w *Widget) AddButton() {
|
||||
// func (g greeting) AddButton() {
|
||||
log.Println("gui.gocui.AddButton()", w.Name)
|
||||
addButton2(w.Name, w.Event)
|
||||
}
|
||||
|
||||
func addButton2(name string, e func(*Widget) *Widget) {
|
||||
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
|
||||
}
|
|
@ -1,28 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/awesome-gocui/gocui"
|
||||
// "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() {
|
||||
fmt.Println("Hello Universe")
|
||||
log.Println("Hello Universe")
|
||||
Init()
|
||||
// ToolkitMain()
|
||||
}
|
||||
|
||||
func (g greeting) JcarrButton() {
|
||||
fmt.Println("Hello GreetButton meet Universe")
|
||||
log.Println("Hello GreetButton meet Universe")
|
||||
addButton("Greet foo")
|
||||
addButton("Greet foo 2")
|
||||
}
|
||||
|
@ -39,6 +48,7 @@ func (g greeting) AddButton(name string) {
|
|||
addButton(name)
|
||||
}
|
||||
|
||||
/*
|
||||
func addButton(name string) error {
|
||||
t := len(name)
|
||||
v, err := baseGui.SetView(name, currentX, currentY, currentX+t+3, currentY+2, 0)
|
||||
|
@ -66,3 +76,4 @@ func addButton(name string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
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,57 @@
|
|||
package gui
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
/*
|
||||
type Widget int
|
||||
|
||||
// https://ieftimov.com/post/golang-datastructures-trees/
|
||||
const (
|
||||
Unknown Widget = iota
|
||||
Window
|
||||
Tab
|
||||
Frame
|
||||
Dropbox
|
||||
Spinner
|
||||
Label
|
||||
)
|
||||
|
||||
func (s Widget) String() string {
|
||||
switch s {
|
||||
case Window:
|
||||
return "Window"
|
||||
case Tab:
|
||||
return "Tab"
|
||||
case Frame:
|
||||
return "Frame"
|
||||
case Label:
|
||||
return "Label"
|
||||
case Dropbox:
|
||||
return "Dropbox"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue