start trying to make the tookits plugins

totally minimize helloworld demo
    try to make a button plugin example
    debug changes
    final changes before attempting to use a golang plugin
    actually running gocui as a plugin
    add gocli-as-plugin example
    try to convert the go-cui toolkit into a plugin
    doc updates
    make a minimal console gui

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2022-11-06 12:59:24 -06:00
parent 5417c8f477
commit 482c3ef8eb
37 changed files with 1237 additions and 101 deletions

7
.gitignore vendored
View File

@ -3,3 +3,10 @@ cmds/helloworld/helloworld
cmds/textbox/textbox cmds/textbox/textbox
cmds/gui-demo/gui-demo cmds/gui-demo/gui-demo
cmds/consolemouse/consolemouse 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

View File

@ -1,3 +1,5 @@
.PHONY: README.md
all: README.md all: README.md
@echo @echo
@echo "make examples # will run all the examples" @echo "make examples # will run all the examples"
@ -33,3 +35,6 @@ doc:
# GO111MODULE=on go install github.com/posener/goreadme/cmd/goreadme@latest (worked Oct 20 2022) # GO111MODULE=on go install github.com/posener/goreadme/cmd/goreadme@latest (worked Oct 20 2022)
README.md: doc.go README.md: doc.go
goreadme -factories -types -functions -variabless > README.md goreadme -factories -types -functions -variabless > README.md
plugins:
GO111MODULE="off" go build -buildmode=plugin -o toolkit/gocli.so toolkit/gocli/greeter.go

View File

@ -21,7 +21,7 @@ Principles:
* It's ok to guess. We will return something close. * It's ok to guess. We will return something close.
* Hide complexity internally here * Hide complexity internally here
* Isolate the GUI toolkit * Isolate the GUI toolkit
* Function names should follow [Wikipedia Graphical widget] * Try to use [Wikipedia Graphical widget] names
``` ```
## Quick Start ## Quick Start
@ -161,15 +161,15 @@ This creates a window that shows how this package works
`func GolangDebugWindow()` `func GolangDebugWindow()`
### func [IndentPrintln](/structs.go#L190) ### func [IndentPrintln](/structs.go#L199)
`func IndentPrintln(a ...interface{})` `func IndentPrintln(a ...interface{})`
### func [Main](/main.go#L34) ### func [Main](/main.go#L31)
`func Main(f func())` `func Main(f func())`
### func [Queue](/main.go#L45) ### func [Queue](/main.go#L42)
`func Queue(f func())` `func Queue(f func())`
@ -194,7 +194,7 @@ For example: gui.Queue(NewWindow())
## Types ## Types
### type [GuiConfig](/structs.go#L42) ### type [GuiConfig](/structs.go#L56)
`type GuiConfig struct { ... }` `type GuiConfig struct { ... }`
@ -204,7 +204,11 @@ For example: gui.Queue(NewWindow())
var Config GuiConfig var Config GuiConfig
``` ```
### type [Node](/structs.go#L97) ### type [GuiOptions](/structs.go#L44)
`type GuiOptions struct { ... }`
### type [Node](/structs.go#L104)
`type Node struct { ... }` `type Node struct { ... }`
@ -262,7 +266,7 @@ func main() {
You get a window You get a window
``` ```
### type [Widget](/structs.go#L67) ### type [Widget](/structs.go#L74)
`type Widget int` `type Widget int`

View File

@ -0,0 +1,14 @@
run: build
./buttonAsPlugin
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 .

View File

@ -0,0 +1,33 @@
// This is a simple example
package main
import (
"log"
"git.wit.org/wit/gui"
)
func main() {
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
// gui.Config.Exit = gui.StandardClose
// gui.SetDebug(true)
w = gui.NewWindow()
g = w.NewGroup("buttonGroup")
g.NewButton("hello", func () {
log.Println("world")
})
g.NewButton("foo", func () {
log.Println("bar")
})
}

View File

@ -0,0 +1,15 @@
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 .

View File

@ -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
}

View File

@ -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")
}

View File

@ -0,0 +1,91 @@
// 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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -0,0 +1,14 @@
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 .

View File

@ -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")
}

View File

@ -0,0 +1,59 @@
// 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()
}

View File

@ -1,44 +1,24 @@
// This creates a simple hello world window // This is a simple example
package main package main
import ( import (
"os"
"log" "log"
"git.wit.org/wit/gui" "git.wit.org/wit/gui"
) )
func main() { func main() {
gui.Main(myGUI) gui.Main(helloworld)
} }
// This initializes the first window // This creates a window
func myGUI() { func helloworld() {
var w *gui.Node var w *gui.Node
gui.Config.Title = "Hello World golang wit/gui Window" gui.Config.Title = "helloworld golang wit/gui window"
gui.Config.Width = 640 gui.Config.Width = 640
gui.Config.Height = 480 gui.Config.Height = 480
gui.Config.Exit = myExit
w = gui.NewWindow() w = gui.NewWindow()
addHelloWorld(w, "A Simple Tab") w.NewButton("hello", func () {
log.Println("world")
})
} }
func addHelloWorld(window *gui.Node, title string) {
var newNode, g, tb *gui.Node
newNode = window.NewTab(title)
g = newNode.NewGroup("hello")
tb = g.NewTextbox("hello world box") // when debugging, this string will be used
tb.OnChanged = func(*gui.Node) {
s := tb.GetText()
log.Println("text box =", s)
}
tb.SetText("world")
}
func myExit(n *gui.Node) {
log.Println("exit() here")
os.Exit(0)
}

3
doc.go
View File

@ -18,8 +18,7 @@ Principles:
* It's ok to guess. We will return something close. * It's ok to guess. We will return something close.
* Hide complexity internally here * Hide complexity internally here
* Isolate the GUI toolkit * Isolate the GUI toolkit
* Function names should follow [Wikipedia Graphical widget] * Try to use [Wikipedia Graphical widget] names
Quick Start Quick Start

40
main.go
View File

@ -2,33 +2,33 @@ package gui
import ( import (
"log" "log"
"os"
) )
import toolkit "git.wit.org/wit/gui/toolkit/andlabs" import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
const Xaxis = 0 // stack things horizontally
// the _ means we only need this for the init() const Yaxis = 1 // stack things vertically
const Xaxis = 0 // box that is horizontal
const Yaxis = 1 // box that is vertical
func init() { func init() {
log.Println("gui.init() has been run") log.Println("gui.init() has been run")
Config.counter = 0 Config.counter = 0
Config.prefix = "wit" Config.prefix = "wit"
Config.Options.DebugNode = false
Config.Options.DebugTabs = false
title := "master" // Config.Options.Debug = true
// Config.Options.DebugNode = true
// Config.Options.DebugTabs = true
title := "guiBinaryTree"
w := 640 w := 640
h := 480 h := 480
// f := StandardClose
// Populates the top of the binary tree
Config.master = addNode(title, w, h) Config.master = addNode(title, w, h)
// Config.master.custom = f if (Config.Options.Debug) {
Config.master.Dump()
Config.master.Dump() }
} }
func Main(f func()) { func Main(f func()) {
@ -46,3 +46,19 @@ func Queue(f func()) {
log.Println("Sending function to gui.Main() (using gtk via andlabs/ui)") log.Println("Sending function to gui.Main() (using gtk via andlabs/ui)")
toolkit.Queue(f) toolkit.Queue(f)
} }
// The window is destroyed but the application does not quit
func StandardClose(n *Node) {
if (Config.Options.Debug) {
log.Println("wit/gui Standard Window Close. name =", n.Name)
}
}
// The window is destroyed but the application does not quit
func StandardExit(n *Node) {
if (Config.Options.Debug) {
log.Println("wit/gui Standard Window Exit. running os.Exit()")
}
os.Exit(0)
}

10
node.go
View File

@ -1,8 +1,5 @@
package gui package gui
import "strconv"
// import "fmt"
/* /*
generic function to create a new node on the binary tree generic function to create a new node on the binary tree
*/ */
@ -25,9 +22,12 @@ func addNode(title string, w int, h int) *Node {
n.Width = w n.Width = w
n.Height = h n.Height = h
id := Config.prefix + strconv.Itoa(Config.counter) // no longer a string
// id := Config.prefix + strconv.Itoa(Config.counter)
// n.id = id
n.id = Config.counter
Config.counter += 1 Config.counter += 1
n.id = id
return &n return &n
} }

View File

@ -21,7 +21,15 @@ import toolkit "git.wit.org/wit/gui/toolkit/andlabs"
var Config GuiConfig var Config GuiConfig
func SetDebugToolkit (s bool) { func GetDebug () bool {
return Config.Options.Debug
}
func SetDebug (s bool) {
Config.Options.Debug = s
// also set these
Config.Options.DebugDump = s
Config.Options.DebugNode = s
toolkit.DebugToolkit = s toolkit.DebugToolkit = s
} }
@ -29,6 +37,10 @@ func GetDebugToolkit () bool {
return toolkit.DebugToolkit return toolkit.DebugToolkit
} }
func SetDebugToolkit (s bool) {
toolkit.DebugToolkit = s
}
func ShowDebugValues() { func ShowDebugValues() {
log.Println("\t wit/gui Debug =", Config.Options.Debug) log.Println("\t wit/gui Debug =", Config.Options.Debug)
log.Println("\t wit/gui DebugDump =", Config.Options.DebugDump) log.Println("\t wit/gui DebugDump =", Config.Options.DebugDump)
@ -102,23 +114,27 @@ func (s Widget) String() string {
// The Node is simply the name and the size of whatever GUI element exists // The Node is simply the name and the size of whatever GUI element exists
type Node struct { type Node struct {
id string id int
Name string Name string
Width int Width int
Height int Height int
// this function is run when there are mouse or keyboard events
OnChanged func(*Node)
parent *Node parent *Node
// TODO: make children a double linked list since some toolkits require order // TODO: make children a double linked list since some toolkits require order (?)
children []*Node children []*Node
// hmm. how do you handle this when the toolkits are plugins?
toolkit *toolkit.Toolkit
// things that may not really be needed (?) // things that may not really be needed (?)
custom func() custom func()
OnChanged func(*Node)
checked bool checked bool
text string text string
toolkit *toolkit.Toolkit
} }
func (n *Node) Parent() *Node { func (n *Node) Parent() *Node {
@ -159,12 +175,12 @@ func (n *Node) Dump() {
IndentPrintln("toolkit = ", reflect.ValueOf(n.toolkit).Kind()) IndentPrintln("toolkit = ", reflect.ValueOf(n.toolkit).Kind())
n.toolkit.Dump() n.toolkit.Dump()
} }
if (n.id == "") { // if (n.id == nil) {
// Node structs should never have a nil id. // // Node structs should never have a nil id.
// I probably shouldn't panic here, but this is just to check the sanity of // // I probably shouldn't panic here, but this is just to check the sanity of
// the gui package to make sure it's not exiting // // the gui package to make sure it's not exiting
panic("gui.Node.Dump() id == nil TODO: make a unigue id here in the golang gui library") // panic("gui.Node.Dump() id == nil TODO: make a unigue id here in the golang gui library")
} // }
IndentPrintln("NODE DUMP END") IndentPrintln("NODE DUMP END")
} }

View File

@ -37,6 +37,19 @@ func (t *Toolkit) NewBox() *Toolkit {
return &newTK return &newTK
} }
if (t.uiWindow != nil) {
log.Println("\tgui.Toolbox.NewBox() is a Window")
var newT Toolkit
vbox := ui.NewVerticalBox()
vbox.SetPadded(padded)
t.uiWindow.SetChild(vbox)
newT.uiBox = vbox
newT.Name = t.Name
// panic("WTF")
return &newT
}
log.Println("\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box") log.Println("\tgui.Toolbox.NewBox() FAILED. Couldn't figure out where to make a box")
t.Dump() t.Dump()
return nil return nil

View File

@ -1,7 +1,7 @@
package toolkit package toolkit
import "log" import "log"
import "os" // import "os"
import "github.com/andlabs/ui" import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest" import _ "github.com/andlabs/ui/winmanifest"
@ -11,15 +11,12 @@ func (t Toolkit) NewButton(name string) *Toolkit {
var newt Toolkit var newt Toolkit
var b *ui.Button var b *ui.Button
if (t.uiBox == nil) { if t.broken() {
log.Println("gui.ToolboxNode.NewButton() node.UiBox == nil. I can't add a range UI element without a place to put it")
log.Println("probably could just make a box here?")
os.Exit(0)
return nil return nil
} }
if (DebugToolkit) { if (DebugToolkit) {
log.Println("gui.Toolbox.NewGroup() create", name) log.Println("gui.Toolbox.NewButton() create", name)
} }
b = ui.NewButton(name) b = ui.NewButton(name)
newt.uiButton = b newt.uiButton = b
@ -40,6 +37,7 @@ func (t Toolkit) NewButton(name string) *Toolkit {
log.Println("wit/gui/toolkit NewButton() toolkit.Custom() START") log.Println("wit/gui/toolkit NewButton() toolkit.Custom() START")
} }
newt.Custom() newt.Custom()
return
if (DebugToolkit) { if (DebugToolkit) {
log.Println("wit/gui/toolkit NewButton() toolkit.Custom() END") log.Println("wit/gui/toolkit NewButton() toolkit.Custom() END")
} }
@ -53,14 +51,29 @@ func (t Toolkit) NewButton(name string) *Toolkit {
log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() START (IS THIS A BAD IDEA?)") log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() START (IS THIS A BAD IDEA?)")
} }
t.Custom() t.Custom()
return
if (DebugToolkit) { if (DebugToolkit) {
log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() END (IS THIS A BAD IDEA?)") log.Println("wit/gui/toolkit NewButton() running parent toolkit.Custom() END (IS THIS A BAD IDEA?)")
} }
} }
log.Println("TODO: LEFT TOOLKIT GOROUTINE button name =", name) log.Println("TODO: LEFT TOOLKIT GOROUTINE WITH NOTHING TO DO button name =", name)
}) })
t.uiBox.Append(b, stretchy) if (DebugToolkit) {
log.Println("gui.Toolbox.NewButton() about to append to Box parent t:", name)
t.Dump()
log.Println("gui.Toolbox.NewButton() about to append to Box new t:", name)
newt.Dump()
}
if (t.uiBox != nil) {
t.uiBox.Append(b, stretchy)
} else if (t.uiWindow != nil) {
t.uiWindow.SetChild(b)
} else {
log.Println("ERROR: wit/gui andlabs couldn't place this button in a box or a window")
log.Println("ERROR: wit/gui andlabs couldn't place this button in a box or a window")
return &t
}
return &newt return &newt
} }

View File

@ -2,9 +2,6 @@ package toolkit
import "log" import "log"
// import "github.com/andlabs/ui"
// import _ "github.com/andlabs/ui/winmanifest"
func init() { func init() {
log.Println("gui/toolkit init() Setting defaultBehavior = true") log.Println("gui/toolkit init() Setting defaultBehavior = true")
setDefaultBehavior(true) setDefaultBehavior(true)
@ -37,8 +34,13 @@ func (t Toolkit) commonChange(widget string) {
// does some sanity checks on the internal structs of the binary tree // does some sanity checks on the internal structs of the binary tree
// TODO: probably this should not panic unless it's running in devel mode (?) // TODO: probably this should not panic unless it's running in devel mode (?)
func (t Toolkit) broken() bool { func (t *Toolkit) broken() bool {
if (t.uiBox == nil) { if (t.uiBox == nil) {
if (t.uiWindow != nil) {
log.Println("gui.Toolkit.UiBox == nil. This is an empty window. Try to add a box")
t.NewBox()
return false
}
log.Println("gui.Toolkit.UiBox == nil. I can't add a widget without a place to put it") log.Println("gui.Toolkit.UiBox == nil. I can't add a widget without a place to put it")
// log.Println("probably could just make a box here?") // log.Println("probably could just make a box here?")
// corruption or something horrible? // corruption or something horrible?
@ -48,6 +50,7 @@ func (t Toolkit) broken() bool {
} }
if (t.uiWindow == nil) { if (t.uiWindow == nil) {
log.Println("gui.Toolkit.UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)") log.Println("gui.Toolkit.UiWindow == nil. I can't add a widget without a place to put it (IGNORING FOR NOW)")
forceDump(t)
return false return false
} }
return false return false

View File

@ -10,19 +10,21 @@ import _ "github.com/andlabs/ui/winmanifest"
func (t Toolkit) NewGroup(title string) *Toolkit { func (t Toolkit) NewGroup(title string) *Toolkit {
var newt Toolkit var newt Toolkit
if (t.uiBox == nil) {
log.Println("gui.ToolboxNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
log.Println("probably could just make a box here?")
os.Exit(0)
return nil
}
if (DebugToolkit) { if (DebugToolkit) {
log.Println("gui.Toolbox.NewGroup() create", title) log.Println("gui.Toolbox.NewGroup() create", title)
} }
g := ui.NewGroup(title) g := ui.NewGroup(title)
g.SetMargined(margin) g.SetMargined(margin)
t.uiBox.Append(g, stretchy)
if (t.uiBox != nil) {
t.uiBox.Append(g, stretchy)
} else if (t.uiWindow != nil) {
t.uiWindow.SetChild(g)
} else {
log.Println("gui.ToolboxNode.NewGroup() node.UiBox == nil. I can't add a range UI element without a place to put it")
log.Println("probably could just make a box here?")
os.Exit(0)
}
hbox := ui.NewVerticalBox() hbox := ui.NewVerticalBox()
hbox.SetPadded(padded) hbox.SetPadded(padded)
@ -30,6 +32,7 @@ func (t Toolkit) NewGroup(title string) *Toolkit {
newt.uiGroup = g newt.uiGroup = g
newt.uiBox = hbox newt.uiBox = hbox
newt.uiWindow = t.uiWindow
newt.Name = title newt.Name = title
t.Dump() t.Dump()

View File

@ -4,6 +4,7 @@ import (
"log" "log"
"github.com/andlabs/ui" "github.com/andlabs/ui"
// the _ means we only need this for the init()
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
) )

View File

@ -87,9 +87,10 @@ func (t *Toolkit) String() string {
} }
func forceDump(t *Toolkit) { func forceDump(t *Toolkit) {
tmp := DebugToolkit
DebugToolkit = true DebugToolkit = true
t.Dump() t.Dump()
DebugToolkit = false DebugToolkit = tmp
} }
func (t *Toolkit) GetText() string { func (t *Toolkit) GetText() string {

8
toolkit/gocui/Makefile Normal file
View File

@ -0,0 +1,8 @@
all: plugin
ldd ../gocli.so
build:
GO111MODULE="off" go build
plugin:
GO111MODULE="off" go build -buildmode=plugin -o ../gocli.so

57
toolkit/gocui/greeter.go Normal file
View File

@ -0,0 +1,57 @@
package main
import (
"errors"
"fmt"
"log"
"strings"
"github.com/awesome-gocui/gocui"
)
type greeting string
// func main() {
func (g greeting) Greet() {
fmt.Println("Hello Universe")
Init()
// ToolkitMain()
}
// this is exported
var Greeter greeting
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
}

View File

@ -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
}

97
toolkit/gocui/main.go Normal file
View File

@ -0,0 +1,97 @@
// 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 Init() {
// 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 := baseGui.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
log.Panicln(err)
}
}
func ToolkitMain() {
if err := baseGui.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
}

46
toolkit/gocui/newJ.go Normal file
View File

@ -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
}

80
toolkit/gocui/views.go Normal file
View File

@ -0,0 +1,80 @@
// 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 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
}

8
toolkit/hello/Makefile Normal file
View File

@ -0,0 +1,8 @@
all: plugin
ldd ../hello.so
build:
GO111MODULE="off" go build
plugin:
GO111MODULE="off" go build -buildmode=plugin -o ../hello.so

23
toolkit/hello/greeter.go Normal file
View File

@ -0,0 +1,23 @@
package main
import (
// "errors"
"fmt"
// "log"
// "strings"
// "github.com/awesome-gocui/gocui"
)
type greeting string
// func main() {
func (g greeting) Greet() {
fmt.Println("Hello Universe")
Init()
// ToolkitMain()
}
// this is exported
var Greeter greeting

44
toolkit/hello/main.go Normal file
View File

@ -0,0 +1,44 @@
// This creates a simple hello world window
package main
import (
"os"
"log"
"git.wit.org/wit/gui"
)
func Init() {
gui.Main(myGUI)
}
// This initializes the first window
func myGUI() {
var w *gui.Node
gui.Config.Title = "Hello World golang wit/gui Window"
gui.Config.Width = 640
gui.Config.Height = 480
gui.Config.Exit = myExit
w = gui.NewWindow()
addHelloWorld(w, "A Simple Tab")
}
func addHelloWorld(window *gui.Node, title string) {
var newNode, g, tb *gui.Node
newNode = window.NewTab(title)
g = newNode.NewGroup("hello")
tb = g.NewTextbox("hello world box") // when debugging, this string will be used
tb.OnChanged = func(*gui.Node) {
s := tb.GetText()
log.Println("text box =", s)
}
tb.SetText("world")
}
func myExit(n *gui.Node) {
log.Println("exit() here")
os.Exit(0)
}

View File

@ -9,14 +9,6 @@ import (
"runtime/pprof" "runtime/pprof"
) )
func StandardClose(n *Node) {
// origlog.Println("Should Exit Here")
// closed = true
log.Println("")
log.Println("STANDARD WINDOW CLOSE. Should not exit app.")
log.Println("")
}
func GolangDebugWindow() { func GolangDebugWindow() {
var w, t *Node var w, t *Node

View File

@ -23,19 +23,23 @@ func NewWindow() *Node {
// Windows are created off of the master node of the Binary Tree // Windows are created off of the master node of the Binary Tree
n = Config.master.New(title) n = Config.master.New(title)
// n.custom = f
n.OnChanged = Config.Exit
t = toolkit.NewWindow(title, w, h) t = toolkit.NewWindow(title, w, h)
t.Custom = func () { t.Custom = func () {
log.Println("Got to wit/gui Window Close START user defined close()") if (Config.Options.Debug) {
if (n.custom == nil) { log.Println("Got to wit/gui Window Close START user defined close()")
log.Println("Got to wit/gui Window Close SKIP node.custom() == nil") }
if (n.OnChanged != nil) {
if (Config.Options.Debug) {
log.Println("Got to wit/gui Window Close SKIP node.custom() == nil")
}
n.OnChanged(n)
return return
} }
n.custom() StandardExit(n)
log.Println("Got to wit/gui Window Close END user defined close()")
} }
n.toolkit = t n.toolkit = t
return n return n
} }