From ed382bec55be25039e4dcf020d1512139855c9bb Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Wed, 9 Nov 2022 08:38:50 -0600 Subject: 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 --- .gitignore | 16 +- Makefile | 28 ++- README-goreadme.md | 335 ++++++++++++++++++++++++++++++ README.md | 13 +- button.go | 23 +- cmds/buttonAsPlugin/Makefile | 14 -- cmds/buttonAsPlugin/log.go | 64 ------ cmds/buttonAsPlugin/main.go | 54 ----- cmds/buttonplugin/Makefile | 14 ++ cmds/buttonplugin/log.go | 64 ++++++ cmds/buttonplugin/main.go | 49 +++++ cmds/console-hello-world/Makefile | 15 -- cmds/console-hello-world/keybindings.go | 130 ------------ cmds/console-hello-world/log.go | 35 ---- cmds/console-hello-world/main.go | 91 -------- cmds/console-hello-world/newJ.go | 46 ---- cmds/console-hello-world/views.go | 114 ---------- cmds/console-ui-helloworld/Makefile | 15 ++ cmds/console-ui-helloworld/keybindings.go | 130 ++++++++++++ cmds/console-ui-helloworld/log.go | 35 ++++ cmds/console-ui-helloworld/main.go | 83 ++++++++ cmds/console-ui-helloworld/newJ.go | 46 ++++ cmds/console-ui-helloworld/views.go | 114 ++++++++++ cmds/consolemouse/Makefile | 14 -- cmds/consolemouse/gocui.go | 51 ----- cmds/consolemouse/main.go | 52 ----- cmds/debug/Makefile | 5 + cmds/debug/helloworld.go | 20 ++ cmds/debug/main.go | 52 +++++ cmds/gocli-as-plugin/Makefile | 14 -- cmds/gocli-as-plugin/log.go | 35 ---- cmds/gocli-as-plugin/main.go | 59 ------ cmds/gui-demo/Makefile | 5 - cmds/gui-demo/main.go | 56 ----- doc.go | 3 + example_window_debug.go | 164 +++++++++++++++ example_window_demo.go | 20 ++ example_window_demo_toolkit.go | 45 ++++ example_window_golang_debug.go | 106 ++++++++++ main.go | 5 +- plugin.go | 30 ++- structs.go | 29 --- toolkit/gocui/Makefile | 4 +- toolkit/gocui/button.go | 48 +++++ toolkit/gocui/gocui | Bin 3409595 -> 0 bytes toolkit/gocui/greeter.go | 23 +- toolkit/gocui/widget.go | 26 +++ widget.go | 57 +++++ window-debug.go | 164 --------------- window-demo-toolkit.go | 45 ---- window-demo.go | 20 -- window-golang-debug.go | 106 ---------- 52 files changed, 1527 insertions(+), 1259 deletions(-) create mode 100644 README-goreadme.md delete mode 100644 cmds/buttonAsPlugin/Makefile delete mode 100644 cmds/buttonAsPlugin/log.go delete mode 100644 cmds/buttonAsPlugin/main.go create mode 100644 cmds/buttonplugin/Makefile create mode 100644 cmds/buttonplugin/log.go create mode 100644 cmds/buttonplugin/main.go delete mode 100644 cmds/console-hello-world/Makefile delete mode 100644 cmds/console-hello-world/keybindings.go delete mode 100644 cmds/console-hello-world/log.go delete mode 100644 cmds/console-hello-world/main.go delete mode 100644 cmds/console-hello-world/newJ.go delete mode 100644 cmds/console-hello-world/views.go create mode 100644 cmds/console-ui-helloworld/Makefile create mode 100644 cmds/console-ui-helloworld/keybindings.go create mode 100644 cmds/console-ui-helloworld/log.go create mode 100644 cmds/console-ui-helloworld/main.go create mode 100644 cmds/console-ui-helloworld/newJ.go create mode 100644 cmds/console-ui-helloworld/views.go delete mode 100644 cmds/consolemouse/Makefile delete mode 100644 cmds/consolemouse/gocui.go delete mode 100644 cmds/consolemouse/main.go create mode 100644 cmds/debug/Makefile create mode 100644 cmds/debug/helloworld.go create mode 100644 cmds/debug/main.go delete mode 100644 cmds/gocli-as-plugin/Makefile delete mode 100644 cmds/gocli-as-plugin/log.go delete mode 100644 cmds/gocli-as-plugin/main.go delete mode 100644 cmds/gui-demo/Makefile delete mode 100644 cmds/gui-demo/main.go create mode 100644 example_window_debug.go create mode 100644 example_window_demo.go create mode 100644 example_window_demo_toolkit.go create mode 100644 example_window_golang_debug.go create mode 100644 toolkit/gocui/button.go delete mode 100755 toolkit/gocui/gocui create mode 100644 toolkit/gocui/widget.go create mode 100644 widget.go delete mode 100644 window-debug.go delete mode 100644 window-demo-toolkit.go delete mode 100644 window-demo.go delete mode 100644 window-golang-debug.go diff --git a/.gitignore b/.gitignore index 47191be..6bda501 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,10 @@ *.swp -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 +# ignore compiled plugins toolkit/*.so + +cmds/buttonplugin/buttonplugin +cmds/console-ui-helloworld/console-ui-helloworld +cmds/debug/debug +cmds/helloworld/helloworld +cmds/textbox/textbox diff --git a/Makefile b/Makefile index 306800f..8cd82c7 100644 --- a/Makefile +++ b/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 diff --git a/README-goreadme.md b/README-goreadme.md new file mode 100644 index 0000000..2a0470c --- /dev/null +++ b/README-goreadme.md @@ -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) diff --git a/README.md b/README.md index 56358e0..77acae7 100644 --- a/README.md +++ b/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 diff --git a/button.go b/button.go index 1ce7327..7b01e1e 100644 --- a/button.go +++ b/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 diff --git a/cmds/buttonAsPlugin/Makefile b/cmds/buttonAsPlugin/Makefile deleted file mode 100644 index d9a67bf..0000000 --- a/cmds/buttonAsPlugin/Makefile +++ /dev/null @@ -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 . diff --git a/cmds/buttonAsPlugin/log.go b/cmds/buttonAsPlugin/log.go deleted file mode 100644 index 642ff7b..0000000 --- a/cmds/buttonAsPlugin/log.go +++ /dev/null @@ -1,64 +0,0 @@ -// This creates a simple hello world window -package main - -import ( - "log" - "fmt" - "os" - "io" - "time" - "bufio" - 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 f1 *os.File -var f2 *os.File -var err error - -func init() { - arg.MustParse(&args) - fmt.Println(args.Foo, args.Bar, args.User) - - f1, 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(f1) - log.Println("This is a test log entry") -} - -func captureSTDOUT() { - f2, _ = os.OpenFile("/tmp/my.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664) - multiWriter := io.MultiWriter(os.Stderr, f2) - rd, wr, err := os.Pipe() - if err != nil { - os.Exit(1) - } - - // overwrite os.Stdout - os.Stderr = wr - - go func() { - scanner := bufio.NewScanner(rd) - for scanner.Scan() { - stdoutLine := scanner.Text() - multiWriter.Write([]byte(stdoutLine + "\n")) - } - }() - - fmt.Println("foobar") - - // hacky sleep to ensure the go routine can write before program exits - time.Sleep(time.Second) -} diff --git a/cmds/buttonAsPlugin/main.go b/cmds/buttonAsPlugin/main.go deleted file mode 100644 index e26c75e..0000000 --- a/cmds/buttonAsPlugin/main.go +++ /dev/null @@ -1,54 +0,0 @@ -// This is a simple example -package main - -import ( - "log" - "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) -} - -// This creates a window -func buttonWindow() { - var w, g *gui.Node - gui.Config.Title = "Demo Plugin Window" - gui.Config.Width = 640 - gui.Config.Height = 480 - - w = gui.NewWindow() - g = w.NewGroup("buttonGroup") - - g.NewButton("hello", func () { - 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() - }) - - g.NewButton("gui.LookupJcarrButton()", func () { - log.Println("gui.LookupJcarrButton()") - gui.LookupJcarrButton() - }) - - g.NewButton("gui.GocuiAddButton()", func () { - log.Println("gui.GocuiAddButton()") - gui.GocuiAddButton("new foobar") - }) -} diff --git a/cmds/buttonplugin/Makefile b/cmds/buttonplugin/Makefile new file mode 100644 index 0000000..cf60369 --- /dev/null +++ b/cmds/buttonplugin/Makefile @@ -0,0 +1,14 @@ +run: build + ./buttonplugin >/tmp/buttonplugin.log 2>&1 + +build-release: + go get -v -u -x . + go build + ./buttonplugin + +build: + GO111MODULE="off" go get -v -x . + GO111MODULE="off" go build + +update: + GO111MODULE="off" go get -v -u -x . diff --git a/cmds/buttonplugin/log.go b/cmds/buttonplugin/log.go new file mode 100644 index 0000000..642ff7b --- /dev/null +++ b/cmds/buttonplugin/log.go @@ -0,0 +1,64 @@ +// This creates a simple hello world window +package main + +import ( + "log" + "fmt" + "os" + "io" + "time" + "bufio" + 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 f1 *os.File +var f2 *os.File +var err error + +func init() { + arg.MustParse(&args) + fmt.Println(args.Foo, args.Bar, args.User) + + f1, 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(f1) + log.Println("This is a test log entry") +} + +func captureSTDOUT() { + f2, _ = os.OpenFile("/tmp/my.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664) + multiWriter := io.MultiWriter(os.Stderr, f2) + rd, wr, err := os.Pipe() + if err != nil { + os.Exit(1) + } + + // overwrite os.Stdout + os.Stderr = wr + + go func() { + scanner := bufio.NewScanner(rd) + for scanner.Scan() { + stdoutLine := scanner.Text() + multiWriter.Write([]byte(stdoutLine + "\n")) + } + }() + + fmt.Println("foobar") + + // hacky sleep to ensure the go routine can write before program exits + time.Sleep(time.Second) +} diff --git a/cmds/buttonplugin/main.go b/cmds/buttonplugin/main.go new file mode 100644 index 0000000..cd4d770 --- /dev/null +++ b/cmds/buttonplugin/main.go @@ -0,0 +1,49 @@ +// This is a simple example +package main + +import ( + "log" + "strconv" + "git.wit.org/wit/gui" +) + +func main() { + // this doesn't seem to work + captureSTDOUT() + + gui.Main(buttonWindow) +} + +var counter int = 10 + +// This creates a window +func buttonWindow() { + var w, g *gui.Node + gui.Config.Title = "Demo Plugin Window" + gui.Config.Width = 640 + gui.Config.Height = 480 + + w = gui.NewWindow() + g = w.NewGroup("buttonGroup") + + g.NewButton("hello", func () { + log.Println("world") + }) + + g.NewButton("RunGreet()", func () { + log.Println("world") + go gui.RunGreet() + }) + + g.NewButton("gui.LookupJcarrButton()", func () { + log.Println("gui.LookupJcarrButton()") + gui.LookupJcarrButton() + }) + + 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) + }) +} diff --git a/cmds/console-hello-world/Makefile b/cmds/console-hello-world/Makefile deleted file mode 100644 index 9c3540d..0000000 --- a/cmds/console-hello-world/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -run: build - ./console-hello-world - reset - ldd ./console-hello-world - -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 . diff --git a/cmds/console-hello-world/keybindings.go b/cmds/console-hello-world/keybindings.go deleted file mode 100644 index fdac1ff..0000000 --- a/cmds/console-hello-world/keybindings.go +++ /dev/null @@ -1,130 +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" -) - -func initKeybindings(g *gocui.Gui) error { - log.Println("got to initKeybindings") - if err := g.SetKeybinding("", 'q', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return gocui.ErrQuit - }); err != nil { - return err - } - if err := g.SetKeybinding("", 'Q', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return gocui.ErrQuit - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return gocui.ErrQuit - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeySpace, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return newView(g) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyBackspace, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return delView(g) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyBackspace2, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return delView(g) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - log.Println("tab", v.Name()) - return nextView(g, true) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyArrowLeft, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return moveView(g, v, -delta, 0) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - return moveView(g, v, delta, 0) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - log.Println("down", v.Name()) - return moveView(g, v, 0, delta) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - log.Println("up", v.Name()) - return moveView(g, v, 0, -delta) - }); err != nil { - return err - } - if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - log.Println("enter", v.Name()) - return nil - }); err != nil { - return err - } - if err := g.SetKeybinding("", 't', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - _, err := g.SetViewOnTop(views[curView]) - return err - }); err != nil { - return err - } - if err := g.SetKeybinding("", 'b', gocui.ModNone, - func(g *gocui.Gui, v *gocui.View) error { - _, err := g.SetViewOnBottom(views[curView]) - return err - }); 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") -// g.SetView("help", 2, 2, 30, 15, 0); - g.SetCurrentView("help") -// moveView(g, tmp, 0, -delta) - if err := g.DeleteView("help"); err != nil { - panic(err) - } - return nil - }); err != nil { - return err - } - return nil -} diff --git a/cmds/console-hello-world/log.go b/cmds/console-hello-world/log.go deleted file mode 100644 index b05beaf..0000000 --- a/cmds/console-hello-world/log.go +++ /dev/null @@ -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") -} diff --git a/cmds/console-hello-world/main.go b/cmds/console-hello-world/main.go deleted file mode 100644 index dd360d5..0000000 --- a/cmds/console-hello-world/main.go +++ /dev/null @@ -1,91 +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" - - "github.com/awesome-gocui/gocui" -) - -const delta = 1 - -var ( - views = []string{} - curView = -1 - idxView = 0 - currentX = 5 - currentY = 2 - groupSize = 0 - baseGui *gocui.Gui -) - -var helpLabel *gocui.View - -func main() { - // setup log to write to a file -// logInit() - - g, err := gocui.NewGui(gocui.OutputNormal, true) - baseGui = g - if err != nil { - log.Panicln(err) - } - defer g.Close() - - g.Highlight = true - g.SelFgColor = gocui.ColorRed - g.SelFrameColor = gocui.ColorRed - - g.SetManagerFunc(layout) - - if err := initKeybindings(g); err != nil { - log.Panicln(err) - } - if err := newView(g); err != nil { - log.Panicln(err) - } - - addButton("hello") - addButton("world") - addButton("foo") - - addGroup("blank") - addButton("bar") - addButton("bar none") - addButton("bar going") - - addGroup("te") - addButton("world 2") - addButton("foo 2") - - if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { - log.Panicln(err) - } -} - -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) { - return err - } - fmt.Fprintln(helpLabel, "KEYBINDINGS") - fmt.Fprintln(helpLabel, "Enter: Click Button") - fmt.Fprintln(helpLabel, "Tab/Space: Switch Buttons") - fmt.Fprintln(helpLabel, "") - fmt.Fprintln(helpLabel, "h: Help") - fmt.Fprintln(helpLabel, "Backspace: Delete Button") - fmt.Fprintln(helpLabel, "Arrow keys: Move Button") - fmt.Fprintln(helpLabel, "t: Move Button to the top") - fmt.Fprintln(helpLabel, "b: Move Button to the button") - fmt.Fprintln(helpLabel, "Ctrl-C or Q: Exit") - } - return nil -} diff --git a/cmds/console-hello-world/newJ.go b/cmds/console-hello-world/newJ.go deleted file mode 100644 index 47c7439..0000000 --- a/cmds/console-hello-world/newJ.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The gocui Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "errors" - "fmt" - "log" - "strings" - - "github.com/awesome-gocui/gocui" -) - -var topX int = 2 -var bottomX int = 20 -var topY int = 2 -var bottomY int = 7 - -func newJ(g *gocui.Gui) error { - // maxX, maxY := g.Size() - name := fmt.Sprintf("jcarr %v test ", idxView) - v, err := g.SetView(name, topX, topY, bottomX, bottomY, 0) - if err == nil { - return err - } - if !errors.Is(err, gocui.ErrUnknownView) { - return err - } - - v.Wrap = true - fmt.Fprintln(v, name) - fmt.Fprintln(v, strings.Repeat("foo\n", 2)) - // fmt.Fprintln(v, strings.Repeat(name+" ", 30)) - log.Println("newJ added a new view", v.Name()) - - if _, err := g.SetCurrentView(name); err != nil { - return err - } - - views = append(views, name) - curView = len(views) - 1 - idxView += 1 - return nil -} diff --git a/cmds/console-hello-world/views.go b/cmds/console-hello-world/views.go deleted file mode 100644 index 50287c2..0000000 --- a/cmds/console-hello-world/views.go +++ /dev/null @@ -1,114 +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" -) - -func addGroup(name string) { - log.Println("addGroup()", name) - currentY = 2 - currentX += groupSize + 6 -} - -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 -} - -func newView(g *gocui.Gui) error { - maxX, maxY := g.Size() - name := fmt.Sprintf("v%v", idxView) - v, err := g.SetView(name, maxX/2-5, maxY/2-5, maxX/2+5, maxY/2+5, 0) - if err == nil { - return err - } - if !errors.Is(err, gocui.ErrUnknownView) { - return err - } - - v.Wrap = true - fmt.Fprintln(v, strings.Repeat(name+" ", 30)) - - if _, err := g.SetCurrentView(name); err != nil { - return err - } - - views = append(views, name) - curView = len(views) - 1 - idxView += 1 - return nil -} - -func delView(g *gocui.Gui) error { - if len(views) <= 1 { - return nil - } - - if err := g.DeleteView(views[curView]); err != nil { - return err - } - views = append(views[:curView], views[curView+1:]...) - - return nextView(g, false) -} - -func nextView(g *gocui.Gui, disableCurrent bool) error { - next := curView + 1 - if next > len(views)-1 { - next = 0 - } - - if _, err := g.SetCurrentView(views[next]); err != nil { - return err - } - - curView = next - return nil -} - -func moveView(g *gocui.Gui, v *gocui.View, dx, dy int) error { - name := v.Name() - x0, y0, x1, y1, err := g.ViewPosition(name) - if err != nil { - return err - } - log.Println(x0, y0, x1, y1) - if _, err := g.SetView(name, x0+dx, y0+dy, x1+dx, y1+dy, 0); err != nil { - return err - } - x0, y0, x1, y1, err = g.ViewPosition(name) - log.Println(x0, y0, x1, y1) - return nil -} diff --git a/cmds/console-ui-helloworld/Makefile b/cmds/console-ui-helloworld/Makefile new file mode 100644 index 0000000..f63c8a9 --- /dev/null +++ b/cmds/console-ui-helloworld/Makefile @@ -0,0 +1,15 @@ +run: build + ./console-ui-helloworld + reset + ldd ./console-ui-helloworld + +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 . diff --git a/cmds/console-ui-helloworld/keybindings.go b/cmds/console-ui-helloworld/keybindings.go new file mode 100644 index 0000000..fdac1ff --- /dev/null +++ b/cmds/console-ui-helloworld/keybindings.go @@ -0,0 +1,130 @@ +// 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" +) + +func initKeybindings(g *gocui.Gui) error { + log.Println("got to initKeybindings") + if err := g.SetKeybinding("", 'q', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return gocui.ErrQuit + }); err != nil { + return err + } + if err := g.SetKeybinding("", 'Q', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return gocui.ErrQuit + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return gocui.ErrQuit + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeySpace, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return newView(g) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyBackspace, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return delView(g) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyBackspace2, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return delView(g) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + log.Println("tab", v.Name()) + return nextView(g, true) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyArrowLeft, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return moveView(g, v, -delta, 0) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyArrowRight, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + return moveView(g, v, delta, 0) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + log.Println("down", v.Name()) + return moveView(g, v, 0, delta) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + log.Println("up", v.Name()) + return moveView(g, v, 0, -delta) + }); err != nil { + return err + } + if err := g.SetKeybinding("", gocui.KeyEnter, gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + log.Println("enter", v.Name()) + return nil + }); err != nil { + return err + } + if err := g.SetKeybinding("", 't', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + _, err := g.SetViewOnTop(views[curView]) + return err + }); err != nil { + return err + } + if err := g.SetKeybinding("", 'b', gocui.ModNone, + func(g *gocui.Gui, v *gocui.View) error { + _, err := g.SetViewOnBottom(views[curView]) + return err + }); 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") +// g.SetView("help", 2, 2, 30, 15, 0); + g.SetCurrentView("help") +// moveView(g, tmp, 0, -delta) + if err := g.DeleteView("help"); err != nil { + panic(err) + } + return nil + }); err != nil { + return err + } + return nil +} diff --git a/cmds/console-ui-helloworld/log.go b/cmds/console-ui-helloworld/log.go new file mode 100644 index 0000000..b05beaf --- /dev/null +++ b/cmds/console-ui-helloworld/log.go @@ -0,0 +1,35 @@ +// 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") +} diff --git a/cmds/console-ui-helloworld/main.go b/cmds/console-ui-helloworld/main.go new file mode 100644 index 0000000..d16b805 --- /dev/null +++ b/cmds/console-ui-helloworld/main.go @@ -0,0 +1,83 @@ +// 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" + + "github.com/awesome-gocui/gocui" +) + +const delta = 1 + +var ( + views = []string{} + curView = -1 + idxView = 0 + currentX = 5 + currentY = 2 + groupSize = 0 + baseGui *gocui.Gui +) + +var helpLabel *gocui.View + +func main() { + // setup log to write to a file +// logInit() + + g, err := gocui.NewGui(gocui.OutputNormal, true) + baseGui = g + if err != nil { + log.Panicln(err) + } + defer g.Close() + + g.Highlight = true + g.SelFgColor = gocui.ColorRed + g.SelFrameColor = gocui.ColorRed + + g.SetManagerFunc(layout) + + if err := initKeybindings(g); err != nil { + log.Panicln(err) + } + if err := newView(g); err != nil { + log.Panicln(err) + } + + addButton("hello") + + addGroup("blank") + addButton("world") + + if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) { + log.Panicln(err) + } +} + +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) { + return err + } + fmt.Fprintln(helpLabel, "KEYBINDINGS") + fmt.Fprintln(helpLabel, "Enter: Click Button") + fmt.Fprintln(helpLabel, "Tab/Space: Switch Buttons") + fmt.Fprintln(helpLabel, "") + fmt.Fprintln(helpLabel, "h: Help") + fmt.Fprintln(helpLabel, "Backspace: Delete Button") + fmt.Fprintln(helpLabel, "Arrow keys: Move Button") + fmt.Fprintln(helpLabel, "t: Move Button to the top") + fmt.Fprintln(helpLabel, "b: Move Button to the button") + fmt.Fprintln(helpLabel, "Ctrl-C or Q: Exit") + } + return nil +} diff --git a/cmds/console-ui-helloworld/newJ.go b/cmds/console-ui-helloworld/newJ.go new file mode 100644 index 0000000..47c7439 --- /dev/null +++ b/cmds/console-ui-helloworld/newJ.go @@ -0,0 +1,46 @@ +// 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 test ", idxView) + v, err := g.SetView(name, topX, topY, bottomX, bottomY, 0) + if err == nil { + return err + } + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + + v.Wrap = true + fmt.Fprintln(v, name) + fmt.Fprintln(v, strings.Repeat("foo\n", 2)) + // fmt.Fprintln(v, strings.Repeat(name+" ", 30)) + log.Println("newJ added a new view", v.Name()) + + if _, err := g.SetCurrentView(name); err != nil { + return err + } + + views = append(views, name) + curView = len(views) - 1 + idxView += 1 + return nil +} diff --git a/cmds/console-ui-helloworld/views.go b/cmds/console-ui-helloworld/views.go new file mode 100644 index 0000000..50287c2 --- /dev/null +++ b/cmds/console-ui-helloworld/views.go @@ -0,0 +1,114 @@ +// 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" +) + +func addGroup(name string) { + log.Println("addGroup()", name) + currentY = 2 + currentX += groupSize + 6 +} + +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 +} + +func newView(g *gocui.Gui) error { + maxX, maxY := g.Size() + name := fmt.Sprintf("v%v", idxView) + v, err := g.SetView(name, maxX/2-5, maxY/2-5, maxX/2+5, maxY/2+5, 0) + if err == nil { + return err + } + if !errors.Is(err, gocui.ErrUnknownView) { + return err + } + + v.Wrap = true + fmt.Fprintln(v, strings.Repeat(name+" ", 30)) + + if _, err := g.SetCurrentView(name); err != nil { + return err + } + + views = append(views, name) + curView = len(views) - 1 + idxView += 1 + return nil +} + +func delView(g *gocui.Gui) error { + if len(views) <= 1 { + return nil + } + + if err := g.DeleteView(views[curView]); err != nil { + return err + } + views = append(views[:curView], views[curView+1:]...) + + return nextView(g, false) +} + +func nextView(g *gocui.Gui, disableCurrent bool) error { + next := curView + 1 + if next > len(views)-1 { + next = 0 + } + + if _, err := g.SetCurrentView(views[next]); err != nil { + return err + } + + curView = next + return nil +} + +func moveView(g *gocui.Gui, v *gocui.View, dx, dy int) error { + name := v.Name() + x0, y0, x1, y1, err := g.ViewPosition(name) + if err != nil { + return err + } + log.Println(x0, y0, x1, y1) + if _, err := g.SetView(name, x0+dx, y0+dy, x1+dx, y1+dy, 0); err != nil { + return err + } + x0, y0, x1, y1, err = g.ViewPosition(name) + log.Println(x0, y0, x1, y1) + return nil +} diff --git a/cmds/consolemouse/Makefile b/cmds/consolemouse/Makefile deleted file mode 100644 index 7061e7e..0000000 --- a/cmds/consolemouse/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -run: build - ./consolemouse - reset - -build-release: - go get -v -u -x . - go build - -build: - GO111MODULE="off" go get -v -x . - GO111MODULE="off" go build - -update: - GO111MODULE="off" go get -v -u -x . diff --git a/cmds/consolemouse/gocui.go b/cmds/consolemouse/gocui.go deleted file mode 100644 index 7da888e..0000000 --- a/cmds/consolemouse/gocui.go +++ /dev/null @@ -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) - } -} diff --git a/cmds/consolemouse/main.go b/cmds/consolemouse/main.go deleted file mode 100644 index 3f4ce58..0000000 --- a/cmds/consolemouse/main.go +++ /dev/null @@ -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) -} diff --git a/cmds/debug/Makefile b/cmds/debug/Makefile new file mode 100644 index 0000000..25c994d --- /dev/null +++ b/cmds/debug/Makefile @@ -0,0 +1,5 @@ +run: build + ./debug + +build: + go build diff --git a/cmds/debug/helloworld.go b/cmds/debug/helloworld.go new file mode 100644 index 0000000..d0998bf --- /dev/null +++ b/cmds/debug/helloworld.go @@ -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") + }) +} diff --git a/cmds/debug/main.go b/cmds/debug/main.go new file mode 100644 index 0000000..5e3a350 --- /dev/null +++ b/cmds/debug/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "log" + "os" + "time" + + "git.wit.org/wit/gui" +) + +// This initializes the first window +// +// BUG: THIS PROGRAM DOESN'T EXIT PROPERLY (NOT REALLY A BUG) +// +// Then starts a goroutine to demonstrate how to +// inject things into the GUI +func main() { + log.Println("Starting my Control Panel") + + go gui.Main(helloworld) +// go gui.DemoToolkitWindow() + + watchGUI() +} + +// This demonstrates how to properly interact with the GUI +// You can not involke the GUI from external goroutines in most cases. +func watchGUI() { + var i = 1 + for { + log.Println("Waiting", i, "seconds") + i += 1 + time.Sleep(1 * time.Second) + if i == 2 { + 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) + } + } +} + +// TODO: myExit isn't getting used anymore +func myExit(n *gui.Node) { + log.Println() + log.Println("Entered myExit() on node.Name =", n.Name) + log.Println() + os.Exit(0) +} diff --git a/cmds/gocli-as-plugin/Makefile b/cmds/gocli-as-plugin/Makefile deleted file mode 100644 index 277d737..0000000 --- a/cmds/gocli-as-plugin/Makefile +++ /dev/null @@ -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 . diff --git a/cmds/gocli-as-plugin/log.go b/cmds/gocli-as-plugin/log.go deleted file mode 100644 index b05beaf..0000000 --- a/cmds/gocli-as-plugin/log.go +++ /dev/null @@ -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") -} diff --git a/cmds/gocli-as-plugin/main.go b/cmds/gocli-as-plugin/main.go deleted file mode 100644 index a9bd632..0000000 --- a/cmds/gocli-as-plugin/main.go +++ /dev/null @@ -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() -} diff --git a/cmds/gui-demo/Makefile b/cmds/gui-demo/Makefile deleted file mode 100644 index 41fdd10..0000000 --- a/cmds/gui-demo/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -run: build - ./gui-demo - -build: - go build diff --git a/cmds/gui-demo/main.go b/cmds/gui-demo/main.go deleted file mode 100644 index 54ad449..0000000 --- a/cmds/gui-demo/main.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "log" - "os" - "time" - - "git.wit.org/wit/gui" -) - -// This initializes the first window -// -// BUG: THIS PROGRAM DOESN'T EXIT PROPERLY (NOT REALLY A BUG) -// -// Then starts a goroutine to demonstrate how to -// inject things into the GUI -func main() { - log.Println("Starting my Control Panel") - - go gui.Main(initGUI) - - watchGUI() -} - -// This initializes the first window -func initGUI() { - gui.DemoToolkitWindow() -} - -// This demonstrates how to properly interact with the GUI -// You can not involke the GUI from external goroutines in most cases. -func watchGUI() { - var i = 1 - for { - log.Println("Waiting", i, "seconds") - i += 1 - time.Sleep(1 * time.Second) - if i == 2 { - 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) - } - } -} - -// TODO: myExit isn't getting used anymore -func myExit(n *gui.Node) { - log.Println() - log.Println("Entered myExit() on node.Name =", n.Name) - log.Println() - os.Exit(0) -} diff --git a/doc.go b/doc.go index 541cdc1..41e976f 100644 --- a/doc.go +++ b/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' diff --git a/example_window_debug.go b/example_window_debug.go new file mode 100644 index 0000000..00ccfec --- /dev/null +++ b/example_window_debug.go @@ -0,0 +1,164 @@ +package gui + +import ( + "log" +) + +var names = make([]string, 100) +var nodeNames = make([]string, 100) + +var bugWin *Node +/* + Creates a window helpful for debugging this package +*/ +func DebugWindow() { + Config.Title = "git.wit.org/wit/gui debug fixme" + Config.Width = 300 + Config.Height = 200 + Config.Exit = StandardClose + bugWin = NewWindow() + bugWin.DebugTab("WIT GUI Debug Tab") +} + +// 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 DebugTab() { + if (bugWin == nil) { + log.Println("Not sure what window to add this to? Use node.DebugTab() instead") + return; + } + bugWin.DebugTab("does this work?") +} + +var checkd, checkdn, checkdt, checkdtk *Node + +//////////////////////// debug flags ////////////////////////////////// +func debugFlags(n *Node) { + var df, checkd, checkdn, checkdd, changeCheckbox *Node + df = n.NewGroup("Debug Flags") + df.NewLabel("flags to control debugging output") + + checkd = df.NewCheckbox("Debug") + checkd.OnChanged = func(*Node) { + checkd.checked = checkd.toolkit.Checked() + Config.Options.Debug = checkd.checked + if (Config.Options.Debug) { + log.Println("Debug turned on") + } else { + log.Println("Debug turned off") + } + } + + checkdn = df.NewCheckbox("Debug Node") + checkdn.OnChanged = func(*Node) { + checkdn.checked = checkdn.toolkit.Checked() + Config.Options.DebugNode = checkdn.checked + } + + checkdd = df.NewCheckbox("Debug node.Dump()") + checkdd.OnChanged = func(*Node) { + Config.Options.DebugDump = checkdd.toolkit.Checked() + } + + changeCheckbox = df.NewCheckbox("Debug Change") + changeCheckbox.OnChanged = func(*Node) { + Config.Options.DebugChange = changeCheckbox.toolkit.Checked() + } + + df.NewButton("Dump Debug Flags", func () { + ShowDebugValues() + }) + +} + +func (n *Node) DebugTab(title string) *Node { + var newN, gog, g1, g2, g3, dd *Node + + // time.Sleep(1 * time.Second) + newN = n.NewTab(title) + newN.Dump() + +//////////////////////// main debug things ////////////////////////////////// + gog = newN.NewGroup("GOLANG") + gog.NewLabel("go language") + gog.NewButton("GO Language Debug", func () { + GolangDebugWindow() + }) + + gog.NewLabel("wit/gui package") + gog.NewButton("WIT/GUI Package Debug", func () { + Config.Width = 640 + Config.Height = 480 + Queue(DebugWindow) + }) + gog.NewButton("Demo wit/gui", func () { + DemoWindow() + }) + gog.NewButton("Demo toolkit andlabs/ui", func () { + DemoToolkitWindow() + }) + + debugFlags(newN) + +//////////////////////// window debugging things ////////////////////////////////// + g1 = newN.NewGroup("Current Windows") + dd = g1.NewDropdown("Window Dropdown") + log.Println("dd =", dd) + + var dump = false + for _, child := range Config.master.children { + log.Println("\t\t", child.id, child.Width, child.Height, child.Name) + if (child.parent != nil) { + log.Println("\t\t\tparent =",child.parent.id) + } else { + log.Println("\t\t\tno parent") + panic("no parent") + } + if (dump == true) { + child.Dump() + } + dd.AddDropdown(child.Name) + } + dd.SetDropdown(0) + + g2 = newN.NewGroup("Debug Window") + g2.NewButton("SetMargined(tab)", func () { + log.Println("\tSTART") + name := dd.GetText() + log.Println("\tENDed with", name) + // gw.UiTab.SetMargined(*gw.TabNumber, true) + }) + g2.NewButton("Hide(tab)", func () { + // gw.UiTab.Hide() + }) + g2.NewButton("Show(tab)", func () { + // gw.UiTab.Show() + }) + g2.NewButton("Delete(tab)", func () { + // gw.UiTab.Delete(*gw.TabNumber) + }) + g2.NewButton("change Title", func () { + // mainWindow.SetText("hello world") + }) + + ///////////////////////////////////////////////////// + g3 = newN.NewGroup("Node Debug") + + g3.NewButton("Node.Dump()", func () { + bugWin.Dump() + }) + g3.NewButton("Node.ListChildren(false)", func () { + bugWin.ListChildren(false) + }) + g3.NewButton("Node.ListChildren(true)", func () { + bugWin.ListChildren(true) + }) + g3.NewButton("AddDebugTab()", func () { + if (bugWin != nil) { + bugWin.DebugTab("added this DebugTab") + } + }) + + return newN +} diff --git a/example_window_demo.go b/example_window_demo.go new file mode 100644 index 0000000..c4e0374 --- /dev/null +++ b/example_window_demo.go @@ -0,0 +1,20 @@ +package gui + +import "log" +// import "time" +// import toolkit "git.wit.org/wit/gui/toolkit/andlabs" + +// +// This creates a window that shows how this package works +// +func DemoWindow() { + var w, t1 *Node + log.Println("DemoWindow() START") + + w = NewStandardWindow("Demo of WIT/GUI") + + t1 = w.DebugTab("WIT GUI Debug Tab t1") + t1.DebugTab("WIT GUI Debug Tab t2") + + log.Println("DemoWindow() END") +} diff --git a/example_window_demo_toolkit.go b/example_window_demo_toolkit.go new file mode 100644 index 0000000..0872448 --- /dev/null +++ b/example_window_demo_toolkit.go @@ -0,0 +1,45 @@ +package gui + +import "log" +// import "time" +// import toolkit "git.wit.org/wit/gui/toolkit/andlabs" + +func NewStandardWindow(title string) *Node { + log.Println("NewStandardWindow() creating", title) + + Config.Title = title + Config.Width = 640 + Config.Height = 480 + Config.Exit = StandardClose + return NewWindow() +} + +// +// This creates a window that shows how the toolkit works +// internally using it's raw unchanged code for the toolkit itself +// +// This is a way to test and see if the toolkit is working at all +// right now it shows the andlabs/ui/DemoNumbersPage() +// +func DemoToolkitWindow() { + var w *Node + + w = NewStandardWindow("Demo of the GUI Toolkit") + +// d = w.New("demo") + + w.toolkit.DemoNumbersPage() + /* + tk = w.Toolkit.DemoNumbersPage() + tk.OnChanged = func(t *toolkit.Toolkit) { + log.Println("toolkit.NewSlider() value =", t.Value()) + if (d.OnChanged != nil) { + log.Println("toolkit.Demo() running node.OnChanged") + d.OnChanged(d) + } + } + d.Toolkit = tk + */ + + log.Println("ToolkitDemoWindow() END") +} diff --git a/example_window_golang_debug.go b/example_window_golang_debug.go new file mode 100644 index 0000000..464ab09 --- /dev/null +++ b/example_window_golang_debug.go @@ -0,0 +1,106 @@ +package gui + +import "log" + +import ( + "os" + "runtime" + "runtime/debug" + "runtime/pprof" +) + +func GolangDebugWindow() { + var w, t *Node + + Config.Title = "Go Language Debug Window" + Config.Width = 400 + Config.Height = 400 + Config.Exit = StandardClose + w = NewWindow() + + t = w.NewTab("Debug Tab") + log.Println("debugWindow() START") + + + /////////////////////////////// Column DEBUG GOLANG ////////////////////// + g := t.NewGroup("GO Language") + + g.NewButton("runtime.Stack()", func () { + log.Println("\tSTART") + buf := make([]byte, 1<<16) + runtime.Stack(buf, true) + log.Printf("%s", buf) + log.Println("\tEND") + }) + g.NewButton("dumpModuleInfo()", func () { + log.Println("\tSTART") + dumpModuleInfo() + log.Println("\tEND") + }) + g.NewButton("debug.PrintStack()", func () { + log.Println("\tSTART") + debug.PrintStack() + log.Println("\tEND") + }) + g.NewButton("pprof.Lookup(goroutine)", func () { + log.Println("\tSTART") + pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) + log.Println("\tEND") + }) + g.NewButton("pprof.Lookup(heap)", func () { + log.Println("\tSTART") + pprof.Lookup("heap").WriteTo(os.Stdout, 1) + log.Println("\tEND") + }) + g.NewButton("pprof.Lookup(block)", func () { + log.Println("\tSTART") + pprof.Lookup("block").WriteTo(os.Stdout, 1) + log.Println("\tEND") + }) + g.NewButton("pprof.Lookup threadcreate", func () { + log.Println("\tSTART") + pprof.Lookup("threadcreate").WriteTo(os.Stdout, 1) + log.Println("\tEND") + }) + g.NewButton("runtime.ReadMemStats", func () { + var s runtime.MemStats + runtime.ReadMemStats(&s) + log.Printf("alloc: %v bytes\n", s.Alloc) + log.Printf("total-alloc: %v bytes\n", s.TotalAlloc) + log.Printf("sys: %v bytes\n", s.Sys) + log.Printf("lookups: %v\n", s.Lookups) + log.Printf("mallocs: %v\n", s.Mallocs) + log.Printf("frees: %v\n", s.Frees) + log.Printf("heap-alloc: %v bytes\n", s.HeapAlloc) + log.Printf("heap-sys: %v bytes\n", s.HeapSys) + log.Printf("heap-idle: %v bytes\n", s.HeapIdle) + log.Printf("heap-in-use: %v bytes\n", s.HeapInuse) + log.Printf("heap-released: %v bytes\n", s.HeapReleased) + log.Printf("heap-objects: %v\n", s.HeapObjects) + log.Printf("stack-in-use: %v bytes\n", s.StackInuse) + log.Printf("stack-sys: %v bytes\n", s.StackSys) + log.Printf("next-gc: when heap-alloc >= %v bytes\n", s.NextGC) + log.Printf("last-gc: %v ns\n", s.LastGC) + log.Printf("gc-pause: %v ns\n", s.PauseTotalNs) + log.Printf("num-gc: %v\n", s.NumGC) + log.Printf("enable-gc: %v\n", s.EnableGC) + log.Printf("debug-gc: %v\n", s.DebugGC) + }) +} + +func dumpModuleInfo() { + tmp, _ := debug.ReadBuildInfo() + if tmp == nil { + log.Println("This wasn't compiled with go module support") + return + } + log.Println("mod.Path = ", tmp.Path) + log.Println("mod.Main.Path = ", tmp.Main.Path) + log.Println("mod.Main.Version = ", tmp.Main.Version) + log.Println("mod.Main.Sum = ", tmp.Main.Sum) + for _, value := range tmp.Deps { + log.Println("\tmod.Path = ", value.Path) + log.Println("\tmod.Version = ", value.Version) + } +} + diff --git a/main.go b/main.go index e3e6609..21cbd02 100644 --- a/main.go +++ b/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()) { diff --git a/plugin.go b/plugin.go index 5c10e03..58e6dbe 100644 --- a/plugin.go +++ b/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() } diff --git a/structs.go b/structs.go index bf16758..22ec988 100644 --- a/structs.go +++ b/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 diff --git a/toolkit/gocui/Makefile b/toolkit/gocui/Makefile index 42798cc..27f23ed 100644 --- a/toolkit/gocui/Makefile +++ b/toolkit/gocui/Makefile @@ -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 diff --git a/toolkit/gocui/button.go b/toolkit/gocui/button.go new file mode 100644 index 0000000..8fb6e05 --- /dev/null +++ b/toolkit/gocui/button.go @@ -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 +} diff --git a/toolkit/gocui/gocui b/toolkit/gocui/gocui deleted file mode 100755 index 094619c..0000000 Binary files a/toolkit/gocui/gocui and /dev/null differ diff --git a/toolkit/gocui/greeter.go b/toolkit/gocui/greeter.go index de6ee68..e3094e5 100644 --- a/toolkit/gocui/greeter.go +++ b/toolkit/gocui/greeter.go @@ -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 } +*/ diff --git a/toolkit/gocui/widget.go b/toolkit/gocui/widget.go new file mode 100644 index 0000000..758ac38 --- /dev/null +++ b/toolkit/gocui/widget.go @@ -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) +} diff --git a/widget.go b/widget.go new file mode 100644 index 0000000..2d97f61 --- /dev/null +++ b/widget.go @@ -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" +} +*/ diff --git a/window-debug.go b/window-debug.go deleted file mode 100644 index 00ccfec..0000000 --- a/window-debug.go +++ /dev/null @@ -1,164 +0,0 @@ -package gui - -import ( - "log" -) - -var names = make([]string, 100) -var nodeNames = make([]string, 100) - -var bugWin *Node -/* - Creates a window helpful for debugging this package -*/ -func DebugWindow() { - Config.Title = "git.wit.org/wit/gui debug fixme" - Config.Width = 300 - Config.Height = 200 - Config.Exit = StandardClose - bugWin = NewWindow() - bugWin.DebugTab("WIT GUI Debug Tab") -} - -// 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 DebugTab() { - if (bugWin == nil) { - log.Println("Not sure what window to add this to? Use node.DebugTab() instead") - return; - } - bugWin.DebugTab("does this work?") -} - -var checkd, checkdn, checkdt, checkdtk *Node - -//////////////////////// debug flags ////////////////////////////////// -func debugFlags(n *Node) { - var df, checkd, checkdn, checkdd, changeCheckbox *Node - df = n.NewGroup("Debug Flags") - df.NewLabel("flags to control debugging output") - - checkd = df.NewCheckbox("Debug") - checkd.OnChanged = func(*Node) { - checkd.checked = checkd.toolkit.Checked() - Config.Options.Debug = checkd.checked - if (Config.Options.Debug) { - log.Println("Debug turned on") - } else { - log.Println("Debug turned off") - } - } - - checkdn = df.NewCheckbox("Debug Node") - checkdn.OnChanged = func(*Node) { - checkdn.checked = checkdn.toolkit.Checked() - Config.Options.DebugNode = checkdn.checked - } - - checkdd = df.NewCheckbox("Debug node.Dump()") - checkdd.OnChanged = func(*Node) { - Config.Options.DebugDump = checkdd.toolkit.Checked() - } - - changeCheckbox = df.NewCheckbox("Debug Change") - changeCheckbox.OnChanged = func(*Node) { - Config.Options.DebugChange = changeCheckbox.toolkit.Checked() - } - - df.NewButton("Dump Debug Flags", func () { - ShowDebugValues() - }) - -} - -func (n *Node) DebugTab(title string) *Node { - var newN, gog, g1, g2, g3, dd *Node - - // time.Sleep(1 * time.Second) - newN = n.NewTab(title) - newN.Dump() - -//////////////////////// main debug things ////////////////////////////////// - gog = newN.NewGroup("GOLANG") - gog.NewLabel("go language") - gog.NewButton("GO Language Debug", func () { - GolangDebugWindow() - }) - - gog.NewLabel("wit/gui package") - gog.NewButton("WIT/GUI Package Debug", func () { - Config.Width = 640 - Config.Height = 480 - Queue(DebugWindow) - }) - gog.NewButton("Demo wit/gui", func () { - DemoWindow() - }) - gog.NewButton("Demo toolkit andlabs/ui", func () { - DemoToolkitWindow() - }) - - debugFlags(newN) - -//////////////////////// window debugging things ////////////////////////////////// - g1 = newN.NewGroup("Current Windows") - dd = g1.NewDropdown("Window Dropdown") - log.Println("dd =", dd) - - var dump = false - for _, child := range Config.master.children { - log.Println("\t\t", child.id, child.Width, child.Height, child.Name) - if (child.parent != nil) { - log.Println("\t\t\tparent =",child.parent.id) - } else { - log.Println("\t\t\tno parent") - panic("no parent") - } - if (dump == true) { - child.Dump() - } - dd.AddDropdown(child.Name) - } - dd.SetDropdown(0) - - g2 = newN.NewGroup("Debug Window") - g2.NewButton("SetMargined(tab)", func () { - log.Println("\tSTART") - name := dd.GetText() - log.Println("\tENDed with", name) - // gw.UiTab.SetMargined(*gw.TabNumber, true) - }) - g2.NewButton("Hide(tab)", func () { - // gw.UiTab.Hide() - }) - g2.NewButton("Show(tab)", func () { - // gw.UiTab.Show() - }) - g2.NewButton("Delete(tab)", func () { - // gw.UiTab.Delete(*gw.TabNumber) - }) - g2.NewButton("change Title", func () { - // mainWindow.SetText("hello world") - }) - - ///////////////////////////////////////////////////// - g3 = newN.NewGroup("Node Debug") - - g3.NewButton("Node.Dump()", func () { - bugWin.Dump() - }) - g3.NewButton("Node.ListChildren(false)", func () { - bugWin.ListChildren(false) - }) - g3.NewButton("Node.ListChildren(true)", func () { - bugWin.ListChildren(true) - }) - g3.NewButton("AddDebugTab()", func () { - if (bugWin != nil) { - bugWin.DebugTab("added this DebugTab") - } - }) - - return newN -} diff --git a/window-demo-toolkit.go b/window-demo-toolkit.go deleted file mode 100644 index 0872448..0000000 --- a/window-demo-toolkit.go +++ /dev/null @@ -1,45 +0,0 @@ -package gui - -import "log" -// import "time" -// import toolkit "git.wit.org/wit/gui/toolkit/andlabs" - -func NewStandardWindow(title string) *Node { - log.Println("NewStandardWindow() creating", title) - - Config.Title = title - Config.Width = 640 - Config.Height = 480 - Config.Exit = StandardClose - return NewWindow() -} - -// -// This creates a window that shows how the toolkit works -// internally using it's raw unchanged code for the toolkit itself -// -// This is a way to test and see if the toolkit is working at all -// right now it shows the andlabs/ui/DemoNumbersPage() -// -func DemoToolkitWindow() { - var w *Node - - w = NewStandardWindow("Demo of the GUI Toolkit") - -// d = w.New("demo") - - w.toolkit.DemoNumbersPage() - /* - tk = w.Toolkit.DemoNumbersPage() - tk.OnChanged = func(t *toolkit.Toolkit) { - log.Println("toolkit.NewSlider() value =", t.Value()) - if (d.OnChanged != nil) { - log.Println("toolkit.Demo() running node.OnChanged") - d.OnChanged(d) - } - } - d.Toolkit = tk - */ - - log.Println("ToolkitDemoWindow() END") -} diff --git a/window-demo.go b/window-demo.go deleted file mode 100644 index c4e0374..0000000 --- a/window-demo.go +++ /dev/null @@ -1,20 +0,0 @@ -package gui - -import "log" -// import "time" -// import toolkit "git.wit.org/wit/gui/toolkit/andlabs" - -// -// This creates a window that shows how this package works -// -func DemoWindow() { - var w, t1 *Node - log.Println("DemoWindow() START") - - w = NewStandardWindow("Demo of WIT/GUI") - - t1 = w.DebugTab("WIT GUI Debug Tab t1") - t1.DebugTab("WIT GUI Debug Tab t2") - - log.Println("DemoWindow() END") -} diff --git a/window-golang-debug.go b/window-golang-debug.go deleted file mode 100644 index 464ab09..0000000 --- a/window-golang-debug.go +++ /dev/null @@ -1,106 +0,0 @@ -package gui - -import "log" - -import ( - "os" - "runtime" - "runtime/debug" - "runtime/pprof" -) - -func GolangDebugWindow() { - var w, t *Node - - Config.Title = "Go Language Debug Window" - Config.Width = 400 - Config.Height = 400 - Config.Exit = StandardClose - w = NewWindow() - - t = w.NewTab("Debug Tab") - log.Println("debugWindow() START") - - - /////////////////////////////// Column DEBUG GOLANG ////////////////////// - g := t.NewGroup("GO Language") - - g.NewButton("runtime.Stack()", func () { - log.Println("\tSTART") - buf := make([]byte, 1<<16) - runtime.Stack(buf, true) - log.Printf("%s", buf) - log.Println("\tEND") - }) - g.NewButton("dumpModuleInfo()", func () { - log.Println("\tSTART") - dumpModuleInfo() - log.Println("\tEND") - }) - g.NewButton("debug.PrintStack()", func () { - log.Println("\tSTART") - debug.PrintStack() - log.Println("\tEND") - }) - g.NewButton("pprof.Lookup(goroutine)", func () { - log.Println("\tSTART") - pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) - log.Println("\tEND") - }) - g.NewButton("pprof.Lookup(heap)", func () { - log.Println("\tSTART") - pprof.Lookup("heap").WriteTo(os.Stdout, 1) - log.Println("\tEND") - }) - g.NewButton("pprof.Lookup(block)", func () { - log.Println("\tSTART") - pprof.Lookup("block").WriteTo(os.Stdout, 1) - log.Println("\tEND") - }) - g.NewButton("pprof.Lookup threadcreate", func () { - log.Println("\tSTART") - pprof.Lookup("threadcreate").WriteTo(os.Stdout, 1) - log.Println("\tEND") - }) - g.NewButton("runtime.ReadMemStats", func () { - var s runtime.MemStats - runtime.ReadMemStats(&s) - log.Printf("alloc: %v bytes\n", s.Alloc) - log.Printf("total-alloc: %v bytes\n", s.TotalAlloc) - log.Printf("sys: %v bytes\n", s.Sys) - log.Printf("lookups: %v\n", s.Lookups) - log.Printf("mallocs: %v\n", s.Mallocs) - log.Printf("frees: %v\n", s.Frees) - log.Printf("heap-alloc: %v bytes\n", s.HeapAlloc) - log.Printf("heap-sys: %v bytes\n", s.HeapSys) - log.Printf("heap-idle: %v bytes\n", s.HeapIdle) - log.Printf("heap-in-use: %v bytes\n", s.HeapInuse) - log.Printf("heap-released: %v bytes\n", s.HeapReleased) - log.Printf("heap-objects: %v\n", s.HeapObjects) - log.Printf("stack-in-use: %v bytes\n", s.StackInuse) - log.Printf("stack-sys: %v bytes\n", s.StackSys) - log.Printf("next-gc: when heap-alloc >= %v bytes\n", s.NextGC) - log.Printf("last-gc: %v ns\n", s.LastGC) - log.Printf("gc-pause: %v ns\n", s.PauseTotalNs) - log.Printf("num-gc: %v\n", s.NumGC) - log.Printf("enable-gc: %v\n", s.EnableGC) - log.Printf("debug-gc: %v\n", s.DebugGC) - }) -} - -func dumpModuleInfo() { - tmp, _ := debug.ReadBuildInfo() - if tmp == nil { - log.Println("This wasn't compiled with go module support") - return - } - log.Println("mod.Path = ", tmp.Path) - log.Println("mod.Main.Path = ", tmp.Main.Path) - log.Println("mod.Main.Version = ", tmp.Main.Version) - log.Println("mod.Main.Sum = ", tmp.Main.Sum) - for _, value := range tmp.Deps { - log.Println("\tmod.Path = ", value.Path) - log.Println("\tmod.Version = ", value.Version) - } -} - -- cgit v1.2.3