Compare commits

...

9 Commits

Author SHA1 Message Date
Jeff Carr 3f7cca35f3 TODO: make the docs correct at pkg.go.dev
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 22:57:28 -06:00
Jeff Carr 60ede602fc go mod tidy for toolkit move
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 20:34:10 -06:00
Jeff Carr 49f8029a5f complete the move to 'go.wit.com/log'
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 18:54:08 -06:00
Jeff Carr 0a20b22a6c move to go.wit.com/log !!!
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 18:15:54 -06:00
Jeff Carr 3f42ba1882 move learning code to gui/debugger
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 13:53:43 -06:00
Jeff Carr 0090da64fc move the debian packaging to gui/toolkits
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 13:52:05 -06:00
Jeff Carr a08bbaf04f all debug stuff moved to 'go.wit.com/gui/debugger'
I finally was able to clean out all the debugging
    code and make a clean, new GO debugger. It's quite
    nice I think. Well, it's useful to me at any rate.

    2024 New Years wish: someone contributes code to improve it

Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-03 13:37:03 -06:00
Jeff Carr d8f1107387 fix doc paths to go.wit.com
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-01 17:47:23 -06:00
Jeff Carr e9a0ee35c9 correct path to go.wit.com/gui/gui
Signed-off-by: Jeff Carr <jcarr@wit.com>
2024-01-01 16:45:55 -06:00
42 changed files with 265 additions and 1849 deletions

14
.gitignore vendored
View File

@ -1,15 +1 @@
*.swp *.swp
# ignore compiled plugins
*.so
examples/buttons/buttons
examples/console-ui-helloworld/console-ui-helloworld
examples/helloworld/helloworld
# protobuf compiled files
protobuf/*.pb.go
# temporary files when building debian packages
/*.deb
/files

View File

@ -37,11 +37,6 @@ update:
git pull git pull
go get -v -t -u ./... go get -v -t -u ./...
deb:
cd debian && make
dpkg-deb -c go-wit-gui*.deb
-wit mirrors
examples: \ examples: \
all \ all \
examples-helloworld \ examples-helloworld \
@ -58,10 +53,15 @@ examples-buttons:
examples-console-ui-helloworld: examples-console-ui-helloworld:
make -C examples/console-ui-helloworld make -C examples/console-ui-helloworld
git.wit.org:
git push witgui master
git push witgui devel
git push witgui jcarr
git push witgui --tags
# sync repo to the github backup # sync repo to the github backup
# git remote add github git@github.com:witorg/gui.git # git remote add github git@github.com:wit-go/gui.git
# git remote add github2 git@github.com:wit-go/gui.git github: git.wit.org
github:
git push origin master git push origin master
git push origin devel git push origin devel
git push origin --tags git push origin --tags
@ -82,7 +82,6 @@ goget:
clean: clean:
rm -f toolkit/*.so rm -f toolkit/*.so
cd debian && make clean
plugins: plugins-gocui plugins-andlabs plugins: plugins-gocui plugins-andlabs

View File

@ -38,32 +38,21 @@ package main
import ( import (
"log" "log"
"git.wit.org/wit/gui" "go.wit.com/wit/gui/gui"
) )
var window *gui.Node // This is the beginning of the binary tree of widgets var myGui *gui.Node // This is your gui object
// go will sit here until the window exits // go will sit here until the window exits
func main() { func main() {
gui.Init() myGui = gui.Init()
gui.Main(helloworld)
} }
// This initializes the first window and 2 tabs // This initializes the first window and 2 tabs
func helloworld() { func helloworld() {
gui.Config.Title = "Hello World golang wit/gui Window" window := myGui.NewWindow()
gui.Config.Width = 640
gui.Config.Height = 480
window := gui.NewWindow() group := window.NewGroup("foo bar")
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() { group.NewButton("hello", func() {
log.Println("world") log.Println("world")
}) })
@ -94,7 +83,7 @@ Useful links and other
external things which might be useful external things which might be useful
* Wikipedia Graphical widget - [https://en.wikipedia.org/wiki/Graphical_widget](https://en.wikipedia.org/wiki/Graphical_widget) * 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) * Github mirror - [https://github.com/wit-go/gui](https://github.com/wit-go/gui)
* Federated git pull - [https://github.com/forgefed/forgefed](https://github.com/forgefed/forgefed) * Federated git pull - [https://github.com/forgefed/forgefed](https://github.com/forgefed/forgefed)
* GO Style Guide - [https://google.github.io/styleguide/go/index](https://google.github.io/styleguide/go/index) * GO Style Guide - [https://google.github.io/styleguide/go/index](https://google.github.io/styleguide/go/index)

59
args.go
View File

@ -3,34 +3,63 @@ package gui
import ( import (
arg "github.com/alexflint/go-arg" arg "github.com/alexflint/go-arg"
newlog "go.wit.com/log" "go.wit.com/log"
) )
var INFO log.LogFlag
var GUI log.LogFlag
var NODE log.LogFlag
var PLUG log.LogFlag
var CHANGE log.LogFlag
var argGui ArgsGui var argGui ArgsGui
// This struct can be used with the go-arg package // This struct can be used with the go-arg package
type ArgsGui struct { type ArgsGui struct {
GuiDebug bool `arg:"--gui-debug" help:"open the GUI debugger"`
GuiPlugin string `arg:"--gui" help:"Use this gui toolkit [andlabs,gocui,nocui]"` GuiPlugin string `arg:"--gui" help:"Use this gui toolkit [andlabs,gocui,nocui]"`
GuiVerbose bool `arg:"--gui-verbose" help:"enable all logging"` GuiVerbose bool `arg:"--gui-verbose" help:"enable all logging"`
} }
func init() {
arg.Register(&argGui)
newlog.Register("gui", "debugGui", &debugGui)
for _, s := range newlog.ListFlags() {
newlog.Info("go.wit.org/gui ListFlags() returned:", s)
}
}
// returns the toolkit // returns the toolkit
func ArgToolkit() string { func ArgToolkit() string {
return argGui.GuiPlugin return argGui.GuiPlugin
} }
// returns true if --gui-debug was passed from the command line func init() {
func ArgDebug() bool { arg.Register(&argGui)
return argGui.GuiDebug
INFO.B = false
INFO.Name = "INFO"
INFO.Subsystem = "gui"
INFO.Desc = "Enable log.Info()"
INFO.Register()
GUI.B = false
GUI.Name = "GUI"
GUI.Subsystem = "gui"
GUI.Desc = "basic GUI debugging"
GUI.Register()
NODE.B = false
NODE.Name = "NODE"
NODE.Subsystem = "gui"
NODE.Desc = "basic NODE debugging"
NODE.Register()
PLUG.B = false
PLUG.Name = "PLUG"
PLUG.Subsystem = "gui"
PLUG.Desc = "basic PLUG debugging"
PLUG.Register()
CHANGE.B = false
CHANGE.Name = "CHANGE"
CHANGE.Subsystem = "gui"
CHANGE.Desc = "user changed something"
CHANGE.Register()
for _, s := range log.ListFlags() {
log.Info("go.wit.com/gui/gui ListFlags() returned:", s)
}
} }

2
box.go
View File

@ -1,7 +1,7 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/gui/toolkits"
) )
func (parent *Node) NewBox(name string, b bool) *Node { func (parent *Node) NewBox(name string, b bool) *Node {

View File

@ -1,6 +1,6 @@
package gui package gui
import "go.wit.com/gui/gui/toolkit" import "go.wit.com/gui/toolkits"
func (parent *Node) NewButton(name string, custom func()) *Node { func (parent *Node) NewButton(name string, custom func()) *Node {
newNode := parent.newNode(name, toolkit.Button) newNode := parent.newNode(name, toolkit.Button)

122
chan.go
View File

@ -1,122 +0,0 @@
package gui
// channel communication to the plugins
// https://github.com/sourcegraph/conc
// https://www.reddit.com/r/golang/comments/11x1oek/hello_gophers_show_me_your_concurrent_code/
import (
// "regexp"
// "go.wit.com/gui/toolkit"
"sync"
"runtime"
"github.com/sourcegraph/conc"
"github.com/sourcegraph/conc/stream"
"github.com/sourcegraph/conc/panics"
)
// this should never exit
// TODO: clean up all this poorly named code
func makeConc() {
var wg conc.WaitGroup
defer wg.Wait()
startTheThing(&wg)
log(debugError, "panic?")
sleep(2)
log(debugError, "panic? after sleep(5)")
}
func startTheThing(wg *conc.WaitGroup) {
f := func() {
log(debugError, "startTheThing() == about to panic now")
panic("test conc.WaitGroup")
}
wg.Go(func() {
ExampleCatcher(f)
})
}
func ExampleCatcher(f func()) {
var pc panics.Catcher
i := 0
pc.Try(func() { i += 1 })
pc.Try(f)
pc.Try(func() { i += 1 })
recovered := pc.Recovered()
log(debugError, "panic.Recovered():", recovered.Value.(string))
frames := runtime.CallersFrames(recovered.Callers)
for {
frame, more := frames.Next()
log(debugError, "\t", frame.Function)
if !more {
break
}
}
}
func mapStream(
in chan int,
out chan int,
f func(int) int,
) {
tasks := make(chan func())
taskResults := make(chan chan int)
// Worker goroutines
var workerWg sync.WaitGroup
for i := 0; i < 10; i++ {
workerWg.Add(1)
go func() {
defer workerWg.Done()
for task := range tasks {
task()
}
}()
}
// Ordered reader goroutines
var readerWg sync.WaitGroup
readerWg.Add(1)
go func() {
defer readerWg.Done()
for result := range taskResults {
item := <-result
out <- item
}
}()
// Feed the workers with tasks
for elem := range in {
resultCh := make(chan int, 1)
taskResults <- resultCh
tasks <- func() {
resultCh <- f(elem)
}
}
// We've exhausted input.
// Wait for everything to finish
close(tasks)
workerWg.Wait()
close(taskResults)
readerWg.Wait()
}
func mapStream2(
in chan int,
out chan int,
f func(int) int,
) {
s := stream.New().WithMaxGoroutines(10)
for elem := range in {
elem := elem
s.Go(func() stream.Callback {
res := f(elem)
return func() { out <- res }
})
}
s.Wait()
}

View File

@ -1,6 +1,6 @@
package gui package gui
import "go.wit.com/gui/gui/toolkit" import "go.wit.com/gui/toolkits"
func (n *Node) Checked() bool { func (n *Node) Checked() bool {
return n.B return n.B

View File

@ -4,8 +4,9 @@ package gui
import ( import (
"regexp" "regexp"
"go.wit.com/gui/gui/toolkit" "errors"
newlog "go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
// functions for handling text related GUI elements // functions for handling text related GUI elements
@ -35,7 +36,7 @@ func (n *Node) Disable() *Node {
} }
func (n *Node) Add(str string) { func (n *Node) Add(str string) {
newlog.Log(debugGui, "gui.Add() value =", str) log.Log(GUI, "gui.Add() value =", str)
n.S = str n.S = str
@ -44,7 +45,7 @@ func (n *Node) Add(str string) {
} }
func (n *Node) AddText(str string) { func (n *Node) AddText(str string) {
newlog.Log(debugChange, "AddText() value =", str) log.Log(CHANGE, "AddText() value =", str)
n.Text = str n.Text = str
n.S = str n.S = str
@ -54,7 +55,7 @@ func (n *Node) AddText(str string) {
} }
func (n *Node) SetText(text string) *Node { func (n *Node) SetText(text string) *Node {
newlog.Log(debugChange, "SetText() value =", text) log.Log(CHANGE, "SetText() value =", text)
n.Text = text n.Text = text
n.S = text n.S = text
@ -67,11 +68,11 @@ func (n *Node) SetText(text string) *Node {
func (n *Node) SetNext(w int, h int) { func (n *Node) SetNext(w int, h int) {
n.NextW = w n.NextW = w
n.NextH = h n.NextH = h
newlog.Log(debugNow, "SetNext() w,h =", n.NextW, n.NextH) log.Info("SetNext() w,h =", n.NextW, n.NextH)
} }
func (n *Node) Set(val any) { func (n *Node) Set(val any) {
newlog.Log(debugChange, "Set() value =", val) log.Log(CHANGE, "Set() value =", val)
switch v := val.(type) { switch v := val.(type) {
case bool: case bool:
@ -82,7 +83,7 @@ func (n *Node) Set(val any) {
case int: case int:
n.I = val.(int) n.I = val.(int)
default: default:
newlog.Log(debugError, "Set() unknown type =", v) log.Error(errors.New("Set() unknown type"), "v =", v)
} }
a := newAction(n, toolkit.Set) a := newAction(n, toolkit.Set)
@ -98,11 +99,17 @@ func (n *Node) AppendText(str string) {
sendAction(a) sendAction(a)
} }
// THESE TWO FUNCTIONS ARE TERRIBLY NAMED AND NEED TO BE FIXED
// 5 seconds worth of ideas:
// Value() ?
// Progname() Reference() ?
// should get the value of the node
func (n *Node) GetText() string { func (n *Node) GetText() string {
if (n.S != n.Text) { if (n.S != n.Text) {
newlog.Warn("GetText() is screwed up. TODO: fix this dumb crap") log.Warn("GetText() is screwed up. TODO: fix this dumb crap")
stuff := newlog.ListFlags() stuff := log.ListFlags()
newlog.Warn("ListFlags() =", stuff) log.Warn("ListFlags() =", stuff)
} }
if (n.S != "") { if (n.S != "") {
return n.S return n.S
@ -110,13 +117,21 @@ func (n *Node) GetText() string {
return n.Text return n.Text
} }
// should get the value of the node
// myButton = myGroup.NewButton("hit ball", nil).SetName("HIT")
// myButton.GetName() should return "HIT"
// n = Find("HIT") should return myButton
func (n *Node) GetName() string {
return n.Name
}
/* /*
// string handling examples that might be helpful for normalizeInt() // string handling examples that might be helpful for normalizeInt()
isAlpha := regexp.MustCompile(`^[A-Za-z]+$`).MatchString isAlpha := regexp.MustCompile(`^[A-Za-z]+$`).MatchString
for _, username := range []string{"userone", "user2", "user-three"} { for _, username := range []string{"userone", "user2", "user-three"} {
if !isAlpha(username) { if !isAlpha(username) {
newlog.Log(debugGui, "%q is not valid\n", username) log.Log(GUI, "%q is not valid\n", username)
} }
} }
@ -136,11 +151,11 @@ func normalizeInt(s string) string {
// reg, err := regexp.Compile("[^a-zA-Z0-9]+") // reg, err := regexp.Compile("[^a-zA-Z0-9]+")
reg, err := regexp.Compile("[^0-9]+") reg, err := regexp.Compile("[^0-9]+")
if err != nil { if err != nil {
newlog.Log(debugGui, "normalizeInt() regexp.Compile() ERROR =", err) log.Log(GUI, "normalizeInt() regexp.Compile() ERROR =", err)
return s return s
} }
clean := reg.ReplaceAllString(s, "") clean := reg.ReplaceAllString(s, "")
newlog.Log(debugGui, "normalizeInt() s =", clean) log.Log(GUI, "normalizeInt() s =", clean)
return clean return clean
} }
@ -148,9 +163,9 @@ func commonCallback(n *Node) {
// TODO: make all of this common code to all the widgets // TODO: make all of this common code to all the widgets
// This might be common everywhere finally (2023/03/01) // This might be common everywhere finally (2023/03/01)
if (n.Custom == nil) { if (n.Custom == nil) {
newlog.Log(debugChange, "Not Running n.Custom(n) == nil") log.Log(CHANGE, "Not Running n.Custom(n) == nil")
} else { } else {
newlog.Log(debugChange, "Running n.Custom(n)") log.Log(CHANGE, "Running n.Custom(n)")
n.Custom() n.Custom()
} }
} }
@ -192,7 +207,7 @@ func (n *Node) Expand() *Node {
// myFunnyWindow = myGui.NewWindow("Hello").Standard().SetText("Hola") // myFunnyWindow = myGui.NewWindow("Hello").Standard().SetText("Hola")
func (n *Node) Window(title string) *Node { func (n *Node) Window(title string) *Node {
newlog.Log(debugError, "Window()", n) log.Warn("Window()", n)
return n.NewWindow(title) return n.NewWindow(title)
} }
@ -200,12 +215,12 @@ func (n *Node) Window(title string) *Node {
// should be the default way // should be the default way
/* /*
func (n *Node) Standard() *Node { func (n *Node) Standard() *Node {
newlog.Log(debugInfo, "Standard() not implemented yet") log.Warn("Standard() not implemented yet")
return n return n
} }
func (n *Node) SetMargin() *Node { func (n *Node) SetMargin() *Node {
newlog.Log(debugError, "DoMargin() not implemented yet") log.Warn("DoMargin() not implemented yet")
return n return n
} }
*/ */

49
debian/Makefile vendored
View File

@ -1,49 +0,0 @@
# GITVERSION=$(shell git rev-parse FETCH_HEAD)
VERSION=$(shell git describe --tags $(git rev-list --tags --max-count=1) | sed 's/^v//')
BASENAME=go-wit-gui
all: help deb
help:
@echo
@echo "make deb # attempt to build the .deb package using dpkg"
@echo
deb: clean extract DEBIAN build
clean:
rm -rf ../files
rm -f ../*.deb
rm -f ../*.tar.xz data.tar.xz
rm -rf DEBIAN
extract:
mkdir -p ../files/usr/lib/go-gui
cp ../toolkit/*.so ../files/usr/lib/go-gui/
cp ../README.md ../files/usr/lib/go-gui/
cp ../cmds/textbox/textbox ../files/usr/lib/go-gui/textbox-demo
# makes the DEBIAN/ directory
DEBIAN:
mkdir -p DEBIAN
# make the md5sum file
cd ../files/ && find -type f -exec md5sum '{}' \; |sort -k2 >../md5sums
mv ../md5sums DEBIAN/
# make the control there
mkdir -p DEBIAN
cp control DEBIAN/
echo Version: ${VERSION} >>DEBIAN/control
cp postinst DEBIAN
build:
mv DEBIAN ../files/
cd .. && dpkg-deb --build files ${BASENAME}_${VERSION}_amd64.deb
@echo
@echo '#######################'
cd .. && dpkg-deb --info ${BASENAME}_${VERSION}_amd64.deb
@echo '#######################'
@echo

1
debian/compat vendored
View File

@ -1 +0,0 @@
10

9
debian/control vendored
View File

@ -1,9 +0,0 @@
Source: go-wit-gui
Build-Depends: golang
Package: go-wit-gui
Maintainer: Jeff Carr <jcarr@wit.com>
Architecture: amd64
Depends:
Recommends: libgtk-3-0
Description: a abstraction layer for Go visual elements (GTK, QT, etc)
Package gui implements a abstraction layer for Go visual elements.

25
debian/index.html vendored
View File

@ -1,25 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>go.wit.com/gui</title>
<meta name="go-import" content="go.wit.com/gui git https://github.com/wit-go/gui">
<meta name="go-source" content="go.wit.com/gui https://github.com/wit-go/gui https://github.com/wit-go/gui/tree/master{/dir} https://github.com/wit-go/gui/blob/master{/dir}/{file}#L{line}">
<style>
* { font-family: sans-serif; }
body { margin-top: 0; }
.content { display: inline-block; }
code { display: block; font-family: monospace; font-size: 1em; background-color: #d5d5d5; padding: 1em; margin-bottom: 16px; }
ul { margin-top: 16px; margin-bottom: 16px; }
</style>
</head>
<body>
<div class="content">
<h2>go.wit.com/gui</h2>
<code>go get -v go.wit.com/gui</code>
<code>import "go.wit.com/gui"</code>
Home: <a href="https://godoc.org/go.wit.com/gui">https://godoc.org/go.wit.com/gui</a><br/>
Source: <a href="https://github.com/wit-go/gui">https://github.com/wit-go/gui</a><br/>
</div>
</body>
</html>

1
debian/postinst vendored
View File

@ -1 +0,0 @@
#!/bin/sh

133
debug.go
View File

@ -1,101 +1,24 @@
package gui package gui
// Lots of debugging things: // old debugging things. probably deprecate
// everything should be moved to "go.wit.com/gui/debugger"
// A function dump out the binary tree // A function dump out the binary tree
import ( import (
"errors"
"strconv" "strconv"
"go.wit.com/gui/gui/toolkit"
)
// various debugging flags "go.wit.com/log"
var debugNow bool = true // useful for active development "go.wit.com/gui/toolkits"
var debugGui bool = false )
var debugError bool = true
var debugDump bool = false
var debugNode bool = false
var debugTabs bool = false
var debugFlags bool = false
var debugChange bool = false // shows user events like mouse and keyboard
var debugPlugin bool = false
var debugAction bool = false
// for printing out the binary tree // for printing out the binary tree
var listChildrenParent *Node var listChildrenParent *Node
var listChildrenDepth int = 0 var listChildrenDepth int = 0
var defaultPadding = " " var defaultPadding = " "
func SetDebug (s bool) {
debugGui = s
debugTabs = s
logNow = s
logInfo = s
logWarn = s
logError = s
logVerbose = s
SetFlag("Node", s)
SetFlag("Tabs", s)
SetFlag("Dump", s)
SetFlag("Flags", s)
SetFlag("Plugin", s)
SetFlag("Change", s)
SetFlag("Error", s)
// This flag is only for the internal toolkit debugging
SetFlag("Toolkit", s)
}
func SetFlag (s string, b bool) {
switch s {
case "Toolkit":
// This flag is only for internal toolkit debugging
case "Tabs":
debugTabs = b
case "Node":
debugNode = b
case "Dump":
debugDump = b
case "Error":
debugError = b
case "Change":
debugChange = b
case "Flags":
debugFlags = b
case "Plugin":
debugPlugin = b
case "Show":
// ShowDebugValues() // print them here?
default:
log(debugGui, "Can't set unknown flag", s)
}
a := new(toolkit.Action)
a.ActionType = toolkit.Set
a.WidgetType = toolkit.Flag
a.S = s
a.B = b
sendAction(a)
}
func ShowDebugValues() {
// The order here should match the order in the GUI
// TODO: get the order from the node binary tree
log(true, "Debug =", debugGui)
log(true, "DebugError =", debugError)
log(true, "DebugChange =", debugChange)
log(true, "DebugDump =", debugDump)
log(true, "DebugTabs =", debugTabs)
log(true, "DebugPlugin =", debugPlugin)
log(true, "DebugNode =", debugNode)
SetFlag("Show", true)
}
func (n *Node) Dump() { func (n *Node) Dump() {
b := true b := true
// log("Dump() dump =", b)
Indent(b, "NODE DUMP START") Indent(b, "NODE DUMP START")
Indent(b, "id = ", n.id) Indent(b, "id = ", n.id)
Indent(b, "Name = ", n.Name) Indent(b, "Name = ", n.Name)
@ -129,7 +52,7 @@ func (n *Node) dumpWidget(b bool) string {
var info, d string var info, d string
if (n == nil) { if (n == nil) {
log(debugError, "dumpWidget() node == nil") log.Error(errors.New("dumpWidget() node == nil"))
return "" return ""
} }
info = n.WidgetType.String() info = n.WidgetType.String()
@ -144,6 +67,10 @@ func (n *Node) dumpWidget(b bool) string {
return tabs + d return tabs + d
} }
func (n *Node) Children() []*Node {
return n.children
}
// func (n *Node) ListChildren(dump bool, dropdown *Node, mapNodes map[string]*Node) { // func (n *Node) ListChildren(dump bool, dropdown *Node, mapNodes map[string]*Node) {
func (n *Node) ListChildren(dump bool) { func (n *Node) ListChildren(dump bool) {
if (n == nil) { if (n == nil) {
@ -155,32 +82,32 @@ func (n *Node) ListChildren(dump bool) {
if (n.parent == nil) { if (n.parent == nil) {
return return
} }
log(debugNode, "\t\t\tparent =",n.parent.id) log.Log(NODE, "\t\t\tparent =",n.parent.id)
if (listChildrenParent != nil) { if (listChildrenParent != nil) {
log(debugNode, "\t\t\tlistChildrenParent =",listChildrenParent.id) log.Log(NODE, "\t\t\tlistChildrenParent =",listChildrenParent.id)
if (listChildrenParent.id != n.parent.id) { if (listChildrenParent.id != n.parent.id) {
log(true, "parent =",n.parent.id, n.parent.Name) log.Log(true, "parent =",n.parent.id, n.parent.Name)
log(true, "listChildrenParent =",listChildrenParent.id, listChildrenParent.Name) log.Log(true, "listChildrenParent =",listChildrenParent.id, listChildrenParent.Name)
log(true, listChildrenParent.id, "!=", n.parent.id) log.Log(true, listChildrenParent.id, "!=", n.parent.id)
exit("parent.child does not match child.parent") log.Exit("parent.child does not match child.parent")
} }
} }
log(debugNode, "\t\t", n.id, "has no children") log.Log(NODE, "\t\t", n.id, "has no children")
return return
} }
for _, child := range n.children { for _, child := range n.children {
if (child.parent != nil) { if (child.parent != nil) {
log(debugNode, "\t\t\tparent =",child.parent.id) log.Log(NODE, "\t\t\tparent =",child.parent.id)
} else { } else {
log(debugGui, "\t\t\tno parent") log.Log(GUI, "\t\t\tno parent")
// memory corruption? non-threadsafe access? // memory corruption? non-threadsafe access?
// can all binary tree changes to Node.parent & Node.child be forced into a singular goroutine? // can all binary tree changes to Node.parent & Node.child be forced into a singular goroutine?
panic("something is wrong with the wit golang gui logic and the binary tree is broken. child has no parent") panic("something is wrong with the wit golang gui logic and the binary tree is broken. child has no parent")
} }
if (child.children == nil) { if (child.children == nil) {
log(debugNode, "\t\t", child.id, "has no children") log.Log(NODE, "\t\t", child.id, "has no children")
} else { } else {
log(debugNode, "\t\t\tHas children:", child.children) log.Log(NODE, "\t\t\tHas children:", child.children)
} }
listChildrenParent = n listChildrenParent = n
listChildrenDepth += 1 listChildrenDepth += 1
@ -190,3 +117,19 @@ func (n *Node) ListChildren(dump bool) {
} }
return return
} }
// b bool, print if true
func logindent(b bool, depth int, format string, a ...any) {
var tabs string
for i := 0; i < depth; i++ {
tabs = tabs + format
}
// newFormat := tabs + strconv.Itoa(depth) + " " + format
newFormat := tabs + format
// array prepend(). Why isn't this a standard function. It should be:
// a.prepend(debugGui, newFormat)
a = append([]any{b, newFormat}, a...)
log.Log(b, a...)
}

View File

@ -1,118 +0,0 @@
package gui
import (
newlog "go.wit.com/log"
)
type LogSettings struct {
ready bool
hidden bool
err error
name string
parent *Node // should be the root of the 'gui' package binary tree
window *Node // our window for displaying the log package settings
group *Node //
grid *Node //
checkbox *Node
label *Node
}
func (ls *LogSettings) Set(b bool) {
newlog.Set(ls.name, b)
ls.checkbox.Set(b)
}
func (p *Node) NewLogFlag(name string) *LogSettings {
ls := new(LogSettings)
ls.parent = p
ls.ready = false
ls.name = name
ls.checkbox = p.NewCheckbox(name)
ls.label = p.NewLabel("Enable log." + name)
ls.checkbox.Set(newlog.Get(name))
ls.checkbox.Custom = func() {
newlog.Set(name, ls.checkbox.B)
}
return ls
}
// Let's you toggle on and off the various types of debugging output
// These checkboxes should be in the same order as the are printed
func (n *Node) DebugFlags() {
var w, g *Node
logGadgets := make(map[string]*LogSettings)
// Either:
// make a new window
// make a new tab in the existing window
if (n.UseTabs()) {
w = me.rootNode.NewWindow("Debug Flags")
w.Custom = w.StandardClose
w = w.NewBox("hBox", true)
} else {
w = n.NewTab("Flags")
}
g = w.NewGroup("Show").Pad()
g.NewButton("log.SetTmp()", func () {
newlog.SetTmp()
})
g.NewButton("log.All(true)", func () {
for _, lf := range logGadgets {
lf.Set(true)
}
newlog.All(true)
})
g.NewButton("log.All(false)", func () {
for _, lf := range logGadgets {
lf.Set(false)
}
newlog.All(false)
})
g.NewButton("Dump Flags", func () {
// ShowDebugValues()
newlog.ListFlags()
})
/*
g.NewButton("All On", func () {
SetDebug(true)
})
g.NewButton("All Off", func () {
SetDebug(false)
})
*/
g = w.NewGroup("List")
g = g.NewGrid("flags grid", 2, 2)
logGadgets["INFO"] = g.NewLogFlag("INFO")
logGadgets["WARN"] = g.NewLogFlag("WARN")
logGadgets["SPEW"] = g.NewLogFlag("SPEW")
logGadgets["ERROR"] = g.NewLogFlag("ERROR")
// generally useful debugging
cb1 := g.NewCheckbox("debug Gui")
g.NewLabel("like verbose=1")
cb1.Custom = func() {
debugGui = cb1.B
log(debugGui, "Custom() n.widget =", cb1.Name, cb1.B)
}
// turns on debugging inside the plugin toolkit
cb7 := g.NewCheckbox("debug Toolkit")
g.NewLabel("the plugin internals)")
cb7.Custom = func() {
// SetDebugToolkit(cb7.B)
SetFlag("Toolkit", cb7.B)
}
}

View File

@ -1,97 +0,0 @@
// https://www.digitalocean.com/community/tutorials/how-to-run-multiple-functions-concurrently-in-go
// who came up with the idea of making community tutorials. that was a good idea!
package gui
import (
"fmt"
"sync"
)
var debugWG *sync.WaitGroup
var debugNumberChan chan int
func (n *Node) DebugGoChannels() {
var w, g *Node
w = n.NewWindow("Debug GO Channels")
w.Custom = w.StandardClose
g = w.NewGroup("Channel stuff")
// var debugWG sync.WaitGroup
g.NewButton("init()", func () {
if (debugNumberChan == nil) {
log(true, "making debugNumberChan channel")
debugNumberChan = make(chan int)
} else {
log(true, "debugNumberChan already made")
}
debugWG = new(sync.WaitGroup)
})
g.NewButton("go printInt(x) (read x values off the channel)", func () {
debugWG.Add(1)
go printInt(2, "routine1")
debugWG.Add(1)
go printInt(2, "routine2")
})
g.NewButton("sendNumber(2) (chan <- 2, 4)", func () {
debugWG.Add(1)
debugWG.Add(1)
go sendNumber(2)
go sendNumber(4)
})
g.NewButton("sendNumber(1) (chan <- 7)", func () {
debugWG.Add(1)
go sendNumber(7)
})
g.NewButton("send 4 numbers (chan <- int)", func () {
log(true, "generateNumbers(4)")
go generateNumbers(4)
})
g.NewButton("debugWG.Done()", func () {
log(true, "ran debugWG.Done()")
debugWG.Done()
})
g.NewButton("close chan", func () {
log(true, "close() on", debugNumberChan)
close(debugNumberChan)
})
g.NewButton("print", func () {
log(true, "waitgroup counter is ?")
})
}
func sendNumber(i int) {
log(true, "START debugNumberChan <-", i, " (sending", i, "to channel)")
debugNumberChan <- i
debugWG.Wait()
log(true, "END debugNumberChan sendNumber() done", i)
}
func generateNumbers(total int) {
fmt.Printf("START generateNumbers()\n")
for idx := 1; idx <= total; idx++ {
log(true, "ran debugNumberChan <= idx where idx =", idx)
fmt.Printf("S generateNumbers() sending %d to channel\n", idx)
debugNumberChan <- idx
// res, err := (<-r)()
fmt.Printf("E generateNumbers() sending %d to channel\n", idx)
}
debugWG.Wait()
fmt.Printf("END generateNumbers()\n")
}
// i equals the number of times to read values from the channel
func printInt(i int, name string) {
tmp := 1
log(true, "START printInt", name, "read debugNumberChan()")
for num := range debugNumberChan {
log(true, "printInt()",name, "read", num, "from channel")
debugWG.Done()
if (tmp == i) {
return
}
tmp += 1
}
fmt.Printf("END printInt()", name, "read debugNumberChan\n")
}

View File

@ -1,171 +0,0 @@
package gui
import (
"fmt"
"bytes"
// "os"
"runtime"
"runtime/debug"
"runtime/pprof"
)
func (n *Node) DebugGolangWindow() {
var w, g, og, outputTextbox *Node
w = n.NewWindow("GO")
w.Custom = w.StandardClose
g = w.NewGroup("Language Internals")
g.NewButton("ReadModuleInfo()", func () {
tmp, _ := debug.ReadBuildInfo()
outputTextbox.SetText(tmp.String())
})
g.NewButton("runtime.NumGoroutine()", func () {
buf := new(bytes.Buffer)
pprof.Lookup("goroutine").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
outputTextbox.AppendText(fmt.Sprintln("runtime.NumGoroutine() = ", runtime.NumGoroutine()))
})
g.NewButton("pprof.Lookup(heap)", func () {
buf := new(bytes.Buffer)
pprof.Lookup("heap").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("debug.PrintStack(current)", func () {
outputTextbox.SetText(string(debug.Stack()))
})
g.NewButton("pprof.Lookup(goroutine)", func () {
buf := new(bytes.Buffer)
pprof.Lookup("goroutine").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("pprof.Lookup(block)", func () {
buf := new(bytes.Buffer)
pprof.Lookup("block").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("pprof.Lookup threadcreate", func () {
buf := new(bytes.Buffer)
pprof.Lookup("threadcreate").WriteTo(buf, 1)
outputTextbox.SetText(buf.String())
})
g.NewButton("runtime.ReadMemStats()", func () {
outputTextbox.SetText(runtimeReadMemStats())
})
g.NewButton("debug.FreeOSMemory()", func () {
var out string = "Before debug.FreeOSMemory():\n\n"
out += runtimeReadMemStats()
debug.FreeOSMemory()
out += "\n\nAfter debug.FreeOSMemory():\n\n"
out += runtimeReadMemStats()
outputTextbox.SetText(out)
})
g.NewButton("debug.ReadGCStats()", func () {
var tmp debug.GCStats
var out string
debug.ReadGCStats(&tmp)
log(true, tmp)
out += fmt.Sprintln("LastGC:", tmp.LastGC, "// time.Time time of last collection")
out += fmt.Sprintln("NumGC:", tmp.NumGC, "// number of garbage collections")
out += fmt.Sprintln("PauseTotal:", tmp.PauseTotal, "// total pause for all collections")
out += fmt.Sprintln("Pause:", tmp.Pause, "// []time.Duration pause history, most recent first")
out += fmt.Sprintln("PauseEnd:", tmp.Pause, "// []time.Time pause history, most recent first")
out += fmt.Sprintln("PauseQuantiles:", tmp.PauseQuantiles, "// []time.Duration")
outputTextbox.SetText(out)
})
g.NewButton("debug.SetTraceback('all')", func () {
debug.SetTraceback("all")
})
g.NewButton("panic()", func () {
panic("test")
})
g = w.NewGroup("TODO: finish these")
// g.NewLabel("TODO:")
g.NewButton("runtime.Stack(true)", func () {
// TODO: https://stackoverflow.com/questions/61127053/how-to-list-all-the-running-goroutines-in-a-go-program
// func Stack(buf []byte, all bool) int
})
g.NewButton("debug.SetMemoryLimit(int)", func () {
// TODO:
//debug.SetMemoryLimit(1024 * 1024 * 100)
})
g.NewButton("debug.SetMaxStack(int bytes)", func () {
// default is apparently 1GB
})
g.NewButton("debug.SetMaxThreads(int)", func () {
// default is apparently 10,000
})
g.NewButton("debug.SetTraceback('all')", func () {
debug.SetTraceback("all")
})
// deprecated (probably) by String() implementation within golang
g.NewButton("dumpModuleInfo() (deprecate)", func () {
outputTextbox.SetText(dumpModuleInfo())
})
og = w.NewGroup("output")
outputTextbox = og.NewTextbox("outputBox")
outputTextbox.Custom = func () {
log(true, "custom TextBox() for golang output a =", outputTextbox.S, outputTextbox.id)
}
}
func runtimeReadMemStats() string {
var s runtime.MemStats
var out string
runtime.ReadMemStats(&s)
out += fmt.Sprintln("alloc:", s.Alloc, "bytes")
out += fmt.Sprintln("total-alloc:", s.TotalAlloc, "bytes")
out += fmt.Sprintln("sys:", s.Sys, "bytes")
out += fmt.Sprintln("lookups:", s.Lookups)
out += fmt.Sprintln("mallocs:", s.Mallocs)
out += fmt.Sprintln("frees:", s.Frees)
out += fmt.Sprintln("heap-alloc:", s.HeapAlloc, "bytes")
out += fmt.Sprintln("heap-sys:", s.HeapSys, "bytes")
out += fmt.Sprintln("heap-idle:", s.HeapIdle,"bytes")
out += fmt.Sprintln("heap-in-use:", s.HeapInuse, "bytes")
out += fmt.Sprintln("heap-released:", s.HeapReleased, "bytes")
out += fmt.Sprintln("heap-objects:", s.HeapObjects)
out += fmt.Sprintln("stack-in-use:", s.StackInuse, "bytes")
out += fmt.Sprintln("stack-sys", s.StackSys, "bytes")
out += fmt.Sprintln("next-gc: when heap-alloc >=", s.NextGC, "bytes")
out += fmt.Sprintln("last-gc:", s.LastGC, "ns")
out += fmt.Sprintln("gc-pause:", s.PauseTotalNs, "ns")
out += fmt.Sprintln("num-gc:", s.NumGC)
out += fmt.Sprintln("enable-gc:", s.EnableGC)
out += fmt.Sprintln("debug-gc:", s.DebugGC)
return out
}
func dumpModuleInfo() string {
var out string
tmp, _ := debug.ReadBuildInfo()
if tmp == nil {
out += fmt.Sprintln("This wasn't compiled with go module support")
return ""
}
out += fmt.Sprintln("mod.Path = ", tmp.Path)
out += fmt.Sprintln("mod.Main.Path = ", tmp.Main.Path)
out += fmt.Sprintln("mod.Main.Version = ", tmp.Main.Version)
out += fmt.Sprintln("mod.Main.Sum = ", tmp.Main.Sum)
for _, value := range tmp.Deps {
out += fmt.Sprintln("\tmod.Path = ", value.Path)
out += fmt.Sprintln("\tmod.Version = ", value.Version)
}
return out
}

View File

@ -1,302 +0,0 @@
package gui
import (
"strconv"
"go.wit.com/gui/gui/toolkit"
)
// global var for checking to see if this
// window/tab for debugging a widget exists
// check the binary tree instead (?) for a window called "Widgets" (bad idea)
var bugWidget *Node
// the widget all these actions are run against
var activeWidget *Node
// for testing move, this is the node things are put on
var activeJunk *Node
// the label where the user can see which widget is active
var activeLabel *Node
var activeLabelType *Node
var activeLabelNewName *Node
var activeLabelNewType *Node
var activeLabelNewX *Node
var activeLabelNewY *Node
var activeLabelNewB *Node
// tmp junk
var debugGrid *Node
var debugGridLabel *Node
var debugWidgetBut1, debugWidgetBut2 *Node
func setActiveWidget(w *Node) {
if (w == nil) {
log(debugError, "setActiveWidget() was sent nil !!!")
return
}
activeWidget = w
log(true, "The Widget is set to", w.id, w.Name)
if (activeLabel == nil) {
// the debug window doesn't exist yet so you can't display the change
// TODO: make a fake binary tree for this(?)
return
}
title := "ID =" + strconv.Itoa(w.id) + " " + w.Name
activeLabel.SetText(title)
activeLabelType.SetText("widget.Type = " + w.WidgetType.String())
return
}
func DebugWidgetWindow(w *Node) {
if (bugWidget != nil) {
// this window was already created. Just change the widget we are working against
setActiveWidget(w)
return
}
// Either:
// make a new window
// make a new tab in the existing window
if (me.rootNode.UseTabs()) {
bugWidget = me.rootNode.NewWindow("Widgets")
bugWidget.Custom = bugWidget.StandardClose
} else {
bugWidget = bugWin.NewTab("Widgets")
}
g := bugWidget.NewGroup("widget:")
g2 := g.NewGroup("widget:")
activeLabel = g2.NewLabel("undef")
g2 = g.NewGroup("type:")
activeLabelType = g2.NewLabel("undef")
g2 = g.NewGroup("New name:")
activeLabelNewName = g2.NewCombobox("newthing")
activeLabelNewName.AddText("penguin")
activeLabelNewName.AddText("snow")
activeLabelNewName.AddText("GO")
activeLabelNewName.AddText("debian")
activeLabelNewName.AddText("RiscV")
g2 = g.NewGroup("At X:")
activeLabelNewX = g2.NewSpinner("tmp spinner", -1, 100)
g2 = g.NewGroup("At Y:")
activeLabelNewY = g2.NewSpinner("tmp spinner", -1, 100)
g2 = g.NewGroup("bool B:")
activeLabelNewB = g2.NewCheckbox("tmp bool")
// common things that should work against each widget
g = bugWidget.NewGroup("common things")
g.NewButton("Enable()", func () {
activeWidget.Enable()
})
g.NewButton("Disable()", func () {
activeWidget.Disable()
})
g.NewButton("Show()", func () {
activeWidget.Show()
})
g.NewButton("Hide()", func () {
activeWidget.Hide()
})
g.NewButton("Dump()", func () {
activeWidget.Dump()
})
g = bugWidget.NewGroup("add things")
g.debugAddWidgetButton()
g.NewLabel("experiments:")
g.debugAddWidgetButtons()
g = bugWidget.NewGroup("change things")
g.NewButton("AddText()", func () {
activeWidget.S = activeLabelNewName.S
a := newAction(activeWidget, toolkit.AddText)
sendAction(a)
})
g.NewButton("SetText()", func () {
activeWidget.S = activeLabelNewName.S
a := newAction(activeWidget, toolkit.SetText)
sendAction(a)
})
g.NewButton("Margin()", func () {
a := newAction(activeWidget, toolkit.Margin)
sendAction(a)
})
g.NewButton("Unmargin()", func () {
a := newAction(activeWidget, toolkit.Unmargin)
sendAction(a)
})
g.NewButton("Pad()", func () {
a := newAction(activeWidget, toolkit.Pad)
sendAction(a)
})
g.NewButton("Unpad()", func () {
a := newAction(activeWidget, toolkit.Unpad)
sendAction(a)
})
g.NewButton("Move(junk)", func () {
a := newAction(activeWidget, toolkit.Move)
sendAction(a)
})
g.NewButton("Delete()", func () {
a := newAction(activeWidget, toolkit.Delete)
sendAction(a)
})
g = bugWidget.NewGroup("not working?")
activeJunk = bugWidget.NewGroup("junk:")
activeJunk.NewLabel("test junk")
if (activeWidget == nil) {
setActiveWidget(me.rootNode)
}
}
func (n *Node) debugAddWidgetButtons() {
n.NewButton("Dropdown", func () {
a := activeWidget.NewDropdown("tmp dropdown")
a.AddText("this is better than tcl/tk")
a.AddText("make something for tim for qflow")
a.AddText("and for riscv")
a.Custom = func () {
log(true, "custom dropdown() a =", a.Name, a.S, "id=", a.id)
}
})
n.NewButton("Combobox", func () {
a := activeWidget.NewCombobox("tmp combobox")
a.AddText("mirrors.wit.com")
a.AddText("go.wit.com")
a.Custom = func () {
log(true, "custom combobox() a =", a.Name, a.S, "id=", a.id)
}
})
n.NewButton("Grid", func () {
// Grid numbering by (X,Y)
// -----------------------------
// -- (1,1) -- (2,1) -- (3,1) --
// -- (1,2) -- (2,1) -- (3,1) --
// -----------------------------
// SetDebug(true)
debugGrid = activeWidget.NewGrid("tmp grid", 2, 3)
debugGridLabel = debugGrid.NewLabel("mirrors.wit.com")
/*
debugGrid.SetNext(0,1)
debugGrid.NewLabel("foo (0,1)")
debugGrid.SetNext(1,1)
debugGrid.NewLabel("foo (1,1)")
debugGrid.SetNext(2,1)
debugGrid.NewLabel("foo (2,1)")
*/
// SetDebug(false)
DebugWidgetWindow(debugGrid)
})
n.NewButton("Image", func () {
activeWidget.NewImage("image")
})
n.NewButton("Box(horizontal)", func () {
a := activeWidget.NewBox("hBox", true)
a.NewLabel("hBox")
a.NewLabel("hBox 2")
})
n.NewButton("Box(vertical)", func () {
a := activeWidget.NewBox("vBox", false)
a.NewLabel("vBox")
a.NewLabel("vBox 2")
})
}
func (n *Node) debugAddWidgetButton() {
activeLabelNewType = n.NewDropdown("tmp dropdown")
activeLabelNewType.AddText("Window")
activeLabelNewType.AddText("Tab")
activeLabelNewType.AddText("Frame")
activeLabelNewType.AddText("Grid")
activeLabelNewType.AddText("Group")
activeLabelNewType.AddText("Box")
activeLabelNewType.AddText("Button")
activeLabelNewType.AddText("Checkbox")
activeLabelNewType.AddText("Dropdown")
activeLabelNewType.AddText("Combobox")
activeLabelNewType.AddText("Label")
activeLabelNewType.AddText("Textbox")
activeLabelNewType.AddText("Slider")
activeLabelNewType.AddText("Spinner")
activeLabelNewType.AddText("Image")
activeLabelNewType.AddText("Area")
activeLabelNewType.AddText("Form")
activeLabelNewType.AddText("Font")
activeLabelNewType.AddText("Color")
activeLabelNewType.AddText("Dialog")
n.NewButton("Add", func () {
name := activeLabelNewName.S
newX := activeLabelNewX.I
newY := activeLabelNewY.I
newB := activeLabelNewB.B
if (newY == -1) {
name = name + " (" + strconv.Itoa(activeWidget.NextW) + "," + strconv.Itoa(activeWidget.NextH) + ")"
} else {
activeWidget.SetNext(newX, newY)
name = name + " (" + strconv.Itoa(newX) + "," + strconv.Itoa(newY) + ")"
}
log(true, "New Name =", name)
log(true, "New Type =", activeLabelNewType.S)
log(true, "New X =", newX)
log(true, "New Y =", newY)
log(true, "activeWidget.NextW =", activeWidget.NextW)
log(true, "activeWidget.NextH =", activeWidget.NextH)
log(debugNow, "Add() size (X,Y)", activeWidget.X, activeWidget.Y, "put next thing at (W,H) =", activeWidget.NextW, activeWidget.NextH)
activeWidget.Dump()
// activeWidget.X = newX
// activeWidget.Y = newY
switch activeLabelNewType.S {
case "Grid":
activeWidget.NewGrid(name, newX, newY)
case "Group":
activeWidget.NewGroup(name)
case "Box":
activeWidget.NewBox(name, newB)
case "Button":
var n *Node
n = activeWidget.NewButton(name, func () {
log(true, "got to button", name, n.id)
})
case "Checkbox":
a := activeWidget.NewCheckbox(name)
a.Custom = func () {
log(true, "custom checkox func a=", a.B, "id=", a.id)
}
case "Dropdown":
a := activeWidget.NewDropdown(name)
a.AddText(name + " yay")
a.AddText(name + " haha")
a.Custom = func () {
log(true, "WTF a=", a.B, "id=", a.id)
}
case "Combobox":
a := activeWidget.NewCombobox(name)
a.AddText(name + " foo")
a.AddText(name + " bar")
case "Label":
activeWidget.NewLabel(name)
case "Textbox":
activeWidget.NewTextbox(name)
case "Slider":
activeWidget.NewSlider(name, newX, newY)
case "Spinner":
activeWidget.NewSpinner(name, newX, newY)
default:
log(debugError, "make what type?")
}
})
}

View File

@ -1,185 +0,0 @@
package gui
import (
newlog "go.wit.com/log"
)
// TODO: move all this shit into somewhere not global
// main debugging window
var bugWin *Node
var mapWindows map[string]*Node
var checkd, checkdn, checkdt, checkdtk, lb1, lb2 *Node
var myButton *Node
/*
Creates a window helpful for debugging this package
*/
func (n *Node) DebugWindow() {
newlog.Warn("Don't use DebugWindow() directly anymore")
DebugWindow() // todo, remove the non-binary tree access
}
func DebugWindow() {
bugWin = me.rootNode.NewWindow("go.wit.com/gui debug window").DebugTab("Debug Tab")
bugWin.Custom = bugWin.StandardClose
if ArgDebug() {
newlog.SetTmp()
bugWin.DebugFlags()
}
}
// should the debugging windows be new windows or tabs
// var makeTabs bool = true
func (n *Node) UseTabs() bool {
return me.makeTabs
}
func (n *Node) SetTabs(b bool) {
me.makeTabs = b
}
func (n *Node) DebugTab(title string) *Node {
var newN, gog, g1 *Node
// var logSettings *gadgets.LogSettings
// time.Sleep(1 * time.Second)
newN = n.NewTab(title)
//////////////////////// main debug things //////////////////////////////////
gog = newN.NewGroup("Debugging Windows:")
// generally useful debugging
cb := gog.NewCheckbox("Seperate windows")
cb.Custom = func() {
log(debugGui, "Custom() n.widget =", cb.Name, cb.B)
n.SetTabs(cb.B)
}
cb.Set(false)
n.SetTabs(false)
gog.NewButton("logging", func () {
bugWin.DebugFlags()
})
gog.NewButton("Debug Widgets", func () {
DebugWidgetWindow(newN)
})
gog.NewButton("GO Language Internals", func () {
bugWin.DebugGolangWindow()
})
gog.NewButton("GO Channels debug", func () {
bugWin.DebugGoChannels()
})
gog.NewLabel("Force Quit:")
gog.NewButton("os.Exit()", func () {
exit()
})
//////////////////////// window debugging things //////////////////////////////////
g1 = newN.NewGroup("list things")
g1.NewButton("List toolkits", func () {
dropdownWindow(g1)
me.rootNode.ListToolkits()
})
g1.NewButton("List Windows", func () {
dropdownWindow(g1)
})
g1.NewButton("List Window Widgets", func () {
dropdownWindowWidgets(g1)
})
g2 := newN.NewGroup("more things")
g2.NewButton("Node.ListChildren(true)", func () {
if (activeWidget == nil) {
activeWidget = me.rootNode
}
activeWidget.ListChildren(true)
})
g2.NewButton("test conc", func () {
makeConc()
})
g2.NewButton("List Plugins", func () {
for _, aplug := range allPlugins {
log(true, "Loaded plugin:", aplug.name, aplug.filename)
}
})
g2.NewButton("load toolkit 'gocui'", func () {
me.rootNode.LoadToolkit("gocui")
})
g2.NewButton("load toolkit 'andlabs'", func () {
me.rootNode.LoadToolkit("andlabs")
})
return newN
}
func dropdownWindow(p *Node) {
var mapWindows map[string]*Node
mapWindows = make(map[string]*Node)
dd := p.NewDropdown("Window Dropdown")
dd.Custom = func() {
name := dd.S
activeWidget = mapWindows[name]
setActiveWidget(activeWidget)
log(true, "The Window was set to", name)
}
log(debugGui, "dd =", dd)
if (activeWidget == nil) {
// the debug window doesn't exist yet so you can't display the change
// TODO: make a fake binary tree for this(?)
return
}
// var last = ""
for _, child := range me.rootNode.children {
log(logInfo, "\t\t", child.id, child.Name)
dd.AddDropdownName(child.Name)
// last = child.Name
mapWindows[child.Name] = child
if (activeWidget == nil) {
activeWidget = child
}
}
// dd.SetDropdownName(last)
}
func dropdownWindowWidgets(p *Node) {
var mapWindows map[string]*Node
mapWindows = make(map[string]*Node)
dd := p.NewDropdown("Window Widgets Dropdown")
dd.Custom = func() {
name := dd.S
activeWidget = mapWindows[name]
setActiveWidget(activeWidget)
}
log(debugGui, "dd =", dd)
// log("dumpWidget() ", b, listChildrenDepth, defaultPadding, n.id, info)
var addDropdowns func (*Node)
addDropdowns = func (n *Node) {
s := n.dumpWidget(true)
dd.AddDropdownName(s)
mapWindows[s] = n
for _, child := range n.children {
listChildrenDepth += 1
addDropdowns(child)
listChildrenDepth -= 1
}
}
// list everything in the binary tree
addDropdowns(me.rootNode)
}

View File

@ -6,7 +6,7 @@ package gui
// since it is the same. confusing names? maybe... // since it is the same. confusing names? maybe...
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/gui/toolkits"
) )
// add a new entry to the dropdown name // add a new entry to the dropdown name

10
go.mod
View File

@ -1,16 +1,14 @@
module go.wit.com/gui module go.wit.com/gui/gui
go 1.21.4 go 1.21.4
require ( require (
github.com/alexflint/go-arg v1.4.3 github.com/alexflint/go-arg v1.4.3
github.com/sourcegraph/conc v0.3.0 go.wit.com/gui/toolkits v0.4.1
go.wit.com/log v0.0.0-20240101060000-bf41970f7793 go.wit.com/log v0.3.1
) )
require ( require (
github.com/alexflint/go-scalar v1.1.0 // indirect github.com/alexflint/go-scalar v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect go.wit.com/spew v0.0.0-20240101141411-c7b8e91573c9 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
) )

21
go.sum
View File

@ -7,21 +7,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= go.wit.com/gui/toolkits v0.4.1 h1:Kw9gTAajHwQShuK8MOj8UizGPeY5hOtDfvAxYpDXjUw=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= go.wit.com/gui/toolkits v0.4.1/go.mod h1:f2QuC3z15/JxNnwujyFkgvkYjBS1fy0ni+QQ9idZnWQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.wit.com/log v0.3.1 h1:UXtgJ4dwyWL0Yv4mw6gQnlmrIQU/zz6nClCB7NGKBQs=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.wit.com/log v0.3.1/go.mod h1:GmsggfsKrqdZdAj26fEOlcTz6qEIazbV33uyuuktvB8=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.wit.com/spew v0.0.0-20240101141411-c7b8e91573c9 h1:UEX2EzLQPzLTfy/kUFQD7OXtvKn8wk/+jpDOkbl4ff4=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.wit.com/spew v0.0.0-20240101141411-c7b8e91573c9/go.mod h1:qBpgJXThMMT15vym7/E4Ur9y8oOo2nP7t2RP52QHUNw=
go.wit.com/log v0.0.0-20240101060000-bf41970f7793 h1:kLs+rU96k6b48DqpkO4n3yDZ8hjiVnYjzPSEHU+93aY=
go.wit.com/log v0.0.0-20240101060000-bf41970f7793/go.mod h1:uXgfF8oPx5KYhtNZel6gsFYPMr9+z6sav5lSws1mN6A=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,7 +1,8 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
// Grid numbering examples (H) or (W,H) // Grid numbering examples (H) or (W,H)
@ -73,7 +74,7 @@ func (n *Node) At(w int, h int) *Node {
n.gridIncrement() n.gridIncrement()
if (n.NextW != w) || (n.NextH != h) { if (n.NextW != w) || (n.NextH != h) {
log(logError, "At() (W,H)", w, h, " was moved to avoid a collision (W,H) =", n.NextW, n.NextH) log.Warn("At() (W,H)", w, h, " was moved to avoid a collision (W,H) =", n.NextW, n.NextH)
} }
return n return n
} }

View File

@ -1,7 +1,7 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/gui/toolkits"
) )
// TODO: make a "Group" a "Grid" ? // TODO: make a "Group" a "Grid" ?

View File

@ -1,7 +1,7 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/gui/toolkits"
) )
func (parent *Node) NewImage(name string) *Node { func (parent *Node) NewImage(name string) *Node {

View File

@ -1,7 +1,7 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/gui/toolkits"
) )
func (parent *Node) NewLabel(text string) *Node { func (parent *Node) NewLabel(text string) *Node {

43
log.go
View File

@ -1,43 +0,0 @@
package gui
import (
witlog "go.wit.com/log"
)
// various debugging flags
var logNow bool = true // useful for active development
var logError bool = true
var logWarn bool = false
var logInfo bool = false
var logVerbose bool = false
// var log interface{}
func log(b bool, a ...any) {
// witlog.Where = "wit/gui"
witlog.Log(b, a...)
}
func sleep(a ...any) {
witlog.Sleep(a...)
}
func exit(a ...any) {
witlog.Exit(a...)
}
// b bool, print if true
func logindent(b bool, depth int, format string, a ...any) {
var tabs string
for i := 0; i < depth; i++ {
tabs = tabs + format
}
// newFormat := tabs + strconv.Itoa(depth) + " " + format
newFormat := tabs + format
// array prepend(). Why isn't this a standard function. It should be:
// a.prepend(debugGui, newFormat)
a = append([]any{b, newFormat}, a...)
witlog.Log(b, a...)
}

View File

@ -1,148 +0,0 @@
package witlog
//
// version v1.2
//
// I like things to be easy.
//
// this means all the log settings are in one place. it should allow
// things to be over-ridden externally to the library
// but still allow command line --args to pass debugging settings
//
// I also have a generic sleep() and exit() in here because it's simple
//
// Usage:
//
// log("something", foo, bar)
// var DEBUG bool = true
// log(DEBUG, "something else", someOtherVariable) # if DEBUG == false, return doing nothing
//
import (
"io"
"os"
"runtime"
"runtime/pprof"
golog "log"
"fmt"
"time"
"reflect"
// "net"
)
// various debugging flags
var LogNow bool = true // useful for active development
var LogError bool = true
var LogWarn bool = false
var LogInfo bool = false
var LogVerbose bool = false
var LogSleep bool = false
var LOGOFF bool = false // turn this off, all logging stops
var debugToolkit bool = false // does spew stuff?
var Where string = "gui/log"
var externalLog func(...any)
type Spewt struct {
a bool
}
/*
sleep() # you know what this does? sleeps for 1 second. yep. dump. easy.
sleep(.1) # you know what this does? yes, it sleeps for 1/10th of a second
*/
func Sleep(a ...any) {
if (a == nil) {
time.Sleep(time.Second)
return
}
Log(LogSleep, "sleep", a[0])
switch a[0].(type) {
case int:
time.Sleep(time.Duration(a[0].(int)) * time.Second)
case float64:
time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond)
default:
Log("sleep a[0], type = ", a[0], reflect.TypeOf(a[0]))
}
}
/*
exit() # yep. exits. I guess everything must be fine
exit(3) # I guess 3 it is then
exit("dont like apples") # ok. I'll make a note of that
*/
func Exit(a ...any) {
Log(LogError, "exit", a)
//if (a) {
// os.Exit(a)
//}
os.Exit(0)
}
/*
I've spent, am spending, too much time thinking about 'logging'. 'log', 'logrus', 'zap', whatever.
I'm not twitter. i don't give a fuck about how many nanoseconds it takes to log. Anyway, this
implementation is probably faster than all of those because you just set one bool to FALSE
and it all stops.
Sometimes I need to capture to stdout, sometimes stdout can't
work because it doesn't exist for the user. This whole thing is a PITA. Then it's spread
over 8 million references in every .go file. I'm tapping out and putting
it in one place. here it is. Also, this makes having debug levels really fucking easy.
You can define whatever level of logging you want from anywhere (command line) etc.
log() # doesn't do anything
log(stuff) # sends it to whatever log you define in a single place. here is the place
*/
func Log(a ...any) {
if (LOGOFF) {
return
}
if (a == nil) {
return
}
var tbool bool
if (reflect.TypeOf(a[0]) == reflect.TypeOf(tbool)) {
if (a[0] == false) {
return
}
a[0] = Where
}
golog.Println(a...)
if (externalLog == nil) {
// golog.Println(a...)
} else {
externalLog(fmt.Sprint(a...))
}
}
func loggo() {
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
golog.Println("runtime.NumGoroutine() = ", runtime.NumGoroutine())
}
func logindent(depth int, format string, a ...interface{}) {
var tabs string
for i := 0; i < depth; i++ {
tabs = tabs + format
}
// newFormat := tabs + strconv.Itoa(depth) + " " + format
newFormat := tabs + format
Log(debugToolkit, newFormat, a)
}
func SetOutput(w io.Writer) {
golog.SetOutput(w)
}
func SetToolkitOutput(newLog func(...any)) {
externalLog = newLog
}

View File

@ -1,13 +0,0 @@
package witlog
import (
)
//
// Attempt to switch logging to syslog on linux
//
// This struct can be used with the go-arg package
type LogArgs struct {
Log []string `arg:"--log" help:"Where to log [syslog,stdout]"`
}

87
main.go
View File

@ -2,8 +2,9 @@ package gui
import ( import (
"os" "os"
"time"
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
// TODO: make a fake 'plugin' channel of communication to andlabs for mswindows // TODO: make a fake 'plugin' channel of communication to andlabs for mswindows
@ -15,7 +16,7 @@ const Xaxis = 0 // stack things horizontally
const Yaxis = 1 // stack things vertically const Yaxis = 1 // stack things vertically
func init() { func init() {
log(true, "init() has been run") log.Log(true, "init() has been run")
me.counter = 0 me.counter = 0
me.prefix = "wit" me.prefix = "wit"
@ -36,28 +37,29 @@ func init() {
} }
func watchCallback() { func watchCallback() {
log(logInfo, "watchCallback() START") log.Info("watchCallback() START")
for { for {
log(logInfo, "watchCallback() restarted select for toolkit user events") log.Info("watchCallback() restarted select for toolkit user events")
select { select {
case a := <-me.guiChan: case a := <-me.guiChan:
if (a.ActionType == toolkit.UserQuit) { if (a.ActionType == toolkit.UserQuit) {
log(logInfo, "doUserEvent() User sent Quit()") log.Info("doUserEvent() User sent Quit()")
me.rootNode.doCustom() me.rootNode.doCustom()
exit("wit/gui toolkit.UserQuit") log.Exit("wit/gui toolkit.UserQuit")
break break
} }
if (a.ActionType == toolkit.EnableDebug) { if (a.ActionType == toolkit.EnableDebug) {
log(logInfo, "doUserEvent() Enable Debugging Window") log.Warn("doUserEvent() Enable Debugging Window")
DebugWindow() log.Warn("doUserEvent() TODO: not implemented")
// DebugWindow()
break break
} }
n := me.rootNode.FindId(a.WidgetId) n := me.rootNode.FindId(a.WidgetId)
if (n == nil) { if (n == nil) {
log(logError, "watchCallback() UNKNOWN widget id =", a.WidgetId, a.Name) log.Warn("watchCallback() UNKNOWN widget id =", a.WidgetId, a.Name)
} else { } else {
log(logInfo, "watchCallback() FOUND widget id =", n.id, n.Name) log.Info("watchCallback() FOUND widget id =", n.id, n.Name)
n.doUserEvent(a) n.doUserEvent(a)
} }
// this maybe a good idea? // this maybe a good idea?
@ -68,49 +70,49 @@ func watchCallback() {
} }
func (n *Node) doCustom() { func (n *Node) doCustom() {
log(logInfo, "doUserEvent() widget =", n.id, n.Name, n.WidgetType, n.B) log.Info("doUserEvent() widget =", n.id, n.Name, n.WidgetType, n.B)
if (n.Custom == nil) { if (n.Custom == nil) {
log(debugError, "Custom() = nil. SKIPPING") log.Warn("Custom() = nil. SKIPPING")
return return
} }
go n.Custom() go n.Custom()
} }
func (n *Node) doUserEvent(a toolkit.Action) { func (n *Node) doUserEvent(a toolkit.Action) {
log(logInfo, "doUserEvent() node =", n.id, n.Name) log.Info("doUserEvent() node =", n.id, n.Name)
switch n.WidgetType { switch n.WidgetType {
case toolkit.Checkbox: case toolkit.Checkbox:
n.B = a.B n.B = a.B
log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.B) log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.B)
n.doCustom() n.doCustom()
case toolkit.Button: case toolkit.Button:
log(logInfo, "doUserEvent() node =", n.id, n.Name, "button clicked") log.Info("doUserEvent() node =", n.id, n.Name, "button clicked")
n.doCustom() n.doCustom()
case toolkit.Combobox: case toolkit.Combobox:
n.S = a.S n.S = a.S
log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.S) log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.S)
n.doCustom() n.doCustom()
case toolkit.Dropdown: case toolkit.Dropdown:
n.S = a.S n.S = a.S
log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.S) log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.S)
n.doCustom() n.doCustom()
case toolkit.Textbox: case toolkit.Textbox:
n.S = a.S n.S = a.S
log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.S) log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.S)
n.doCustom() n.doCustom()
case toolkit.Spinner: case toolkit.Spinner:
n.I = a.I n.I = a.I
log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.I) log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.I)
n.doCustom() n.doCustom()
case toolkit.Slider: case toolkit.Slider:
n.I = a.I n.I = a.I
log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.I) log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.I)
n.doCustom() n.doCustom()
case toolkit.Window: case toolkit.Window:
log(logInfo, "doUserEvent() node =", n.id, n.Name, "window closed") log.Info("doUserEvent() node =", n.id, n.Name, "window closed")
n.doCustom() n.doCustom()
default: default:
log(logInfo, "doUserEvent() type =", n.WidgetType) log.Info("doUserEvent() type =", n.WidgetType)
} }
} }
@ -124,18 +126,15 @@ func New() *Node {
// try to load andlabs, if that doesn't work, fall back to the console // try to load andlabs, if that doesn't work, fall back to the console
func (n *Node) Default() *Node { func (n *Node) Default() *Node {
// start the GUI debugger if --gui-debug is true
checkDebug()
if (argGui.GuiPlugin != "") { if (argGui.GuiPlugin != "") {
log(logError, "New.Default() try toolkit =", argGui.GuiPlugin) log.Warn("New.Default() try toolkit =", argGui.GuiPlugin)
return n.LoadToolkit(argGui.GuiPlugin) return n.LoadToolkit(argGui.GuiPlugin)
} }
// if DISPLAY isn't set, return since gtk can't load // if DISPLAY isn't set, return since gtk can't load
// TODO: figure out how to check what to do in macos and mswindows // TODO: figure out how to check what to do in macos and mswindows
if (os.Getenv("DISPLAY") == "") { if (os.Getenv("DISPLAY") == "") {
if (n.LoadToolkit("gocui") == nil) { if (n.LoadToolkit("gocui") == nil) {
log(logError, "New() failed to load gocui") log.Warn("New() failed to load gocui")
} }
return n return n
} }
@ -146,39 +145,19 @@ func (n *Node) Default() *Node {
return n return n
} }
func checkDebug() {
if ! ArgDebug() {
return
}
f := func() {
log(debugGui, "wit/gui START DEBUG")
log(debugGui, "wit/gui START DEBUG")
log(debugGui, "wit/gui START DEBUG")
time.Sleep(2 * time.Second)
log(debugGui, "wit/gui START DEBUG")
log(debugGui, "wit/gui START DEBUG")
log(debugGui, "wit/gui START DEBUG")
DebugWindow()
log(debugGui, "wit/gui END DEBUG")
log(debugGui, "wit/gui END DEBUG")
log(debugGui, "wit/gui END DEBUG")
}
go f()
}
// The window is destroyed but the application does not quit // The window is destroyed but the application does not quit
func (n *Node) StandardClose() { func (n *Node) StandardClose() {
log(debugGui, "wit/gui Standard Window Close. name =", n.Name) log.Log(GUI, "wit/gui Standard Window Close. name =", n.Name)
log(debugGui, "wit/gui Standard Window Close. n.Custom exit =", n.Custom) log.Log(GUI, "wit/gui Standard Window Close. n.Custom exit =", n.Custom)
} }
// The window is destroyed and the application exits // The window is destroyed and the application exits
// TODO: properly exit the plugin since Quit() doesn't do it // TODO: properly exit the plugin since Quit() doesn't do it
func StandardExit() { func StandardExit() {
log(true, "wit/gui Standard Window Exit. running os.Exit()") log.Log(true, "wit/gui Standard Window Exit. running os.Exit()")
log(true, "StandardExit() attempt to exit each toolkit plugin") log.Log(true, "StandardExit() attempt to exit each toolkit plugin")
for i, plug := range allPlugins { for i, plug := range allPlugins {
log(true, "NewButton()", i, plug) log.Log(true, "NewButton()", i, plug)
} }
exit(0) log.Exit(0)
} }

13
node.go
View File

@ -1,6 +1,9 @@
package gui package gui
import "go.wit.com/gui/gui/toolkit" import (
"go.wit.com/log"
"go.wit.com/gui/toolkits"
)
/* /*
generic function to create a new node on the binary tree generic function to create a new node on the binary tree
@ -30,7 +33,7 @@ func addNode(title string) *Node {
n.Name = title n.Name = title
n.Text = title n.Text = title
n.id = me.counter n.id = me.counter
log(debugNode, "addNode = widget setid =", n.id) log.Log(NODE, "addNode = widget setid =", n.id)
me.counter += 1 me.counter += 1
return n return n
@ -42,12 +45,12 @@ func (n *Node) Parent() *Node {
func (n *Node) Delete(d *Node) { func (n *Node) Delete(d *Node) {
for i, child := range n.children { for i, child := range n.children {
log(debugNode, "\t", i, child.id, child.Name) log.Log(NODE, "\t", i, child.id, child.Name)
if (child.id == d.id) { if (child.id == d.id) {
log(debugNode, "\t\t Deleting this") log.Log(NODE, "\t\t Deleting this")
n.children = append(n.children[:i], n.children[i+1:]...) n.children = append(n.children[:i], n.children[i+1:]...)
return return
} }
} }
log(debugError, "did not find node to delete", d.id, d.Name) log.Warn("did not find node to delete", d.id, d.Name)
} }

View File

@ -10,7 +10,8 @@ import (
"embed" "embed"
"plugin" "plugin"
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
var err error var err error
@ -50,12 +51,12 @@ var allPlugins []*aplug
// loads and initializes a toolkit (andlabs/ui, gocui, etc) // loads and initializes a toolkit (andlabs/ui, gocui, etc)
// attempts to locate the .so file // attempts to locate the .so file
func initPlugin(name string) *aplug { func initPlugin(name string) *aplug {
log(logInfo, "initPlugin() START") log.Log(PLUG, "initPlugin() START")
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(debugGui, "initPlugin() already loaded toolkit plugin =", aplug.name) log.Log(PLUG, "initPlugin() already loaded toolkit plugin =", aplug.name)
if (aplug.name == name) { if (aplug.name == name) {
log(debugError, "initPlugin() SKIPPING", name, "as you can't load it twice") log.Warn("initPlugin() SKIPPING", name, "as you can't load it twice")
return nil return nil
} }
} }
@ -71,13 +72,13 @@ func getPluginChannel(p *aplug, funcName string) func() chan toolkit.Action {
test, err = p.plug.Lookup(funcName) test, err = p.plug.Lookup(funcName)
if err != nil { if err != nil {
log(debugGui, "DID NOT FIND: name =", test, "err =", err) log.Error(err, "DID NOT FIND: name =", test)
return nil return nil
} }
newfunc, ok = test.(func() chan toolkit.Action) newfunc, ok = test.(func() chan toolkit.Action)
if !ok { if !ok {
log(debugGui, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name) log.Log(PLUG, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
return nil return nil
} }
return newfunc return newfunc
@ -90,13 +91,13 @@ func sendCallback(p *aplug, funcName string) func(chan toolkit.Action) {
test, err = p.plug.Lookup(funcName) test, err = p.plug.Lookup(funcName)
if err != nil { if err != nil {
log(debugGui, "DID NOT FIND: name =", test, "err =", err) log.Error(err, "DID NOT FIND: name =", test)
return nil return nil
} }
newfunc, ok = test.(func(chan toolkit.Action)) newfunc, ok = test.(func(chan toolkit.Action))
if !ok { if !ok {
log(debugGui, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name) log.Log(PLUG, "function name =", funcName, "names didn't map correctly. Fix the plugin name =", p.name)
return nil return nil
} }
return newfunc return newfunc
@ -120,7 +121,7 @@ func searchPaths(name string) *aplug {
pfile, err = me.resFS.ReadFile(filename) pfile, err = me.resFS.ReadFile(filename)
if (err == nil) { if (err == nil) {
filename = "/tmp/" + name + ".so" filename = "/tmp/" + name + ".so"
log(logError, "write out file here", name, filename, len(pfile)) log.Error(err, "write out file here", name, filename, len(pfile))
f, _ := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600) f, _ := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600)
f.Write(pfile) f.Write(pfile)
f.Close() f.Close()
@ -129,11 +130,11 @@ func searchPaths(name string) *aplug {
return p return p
} }
} else { } else {
log(logError, filename, "was not embedded in the binary. Error:", err) log.Error(err, filename, "was not embedded in the binary")
} }
// attempt to write out the file from the internal resource // attempt to write out the file from the internal resource
filename = "toolkit/" + name + ".so" filename = "toolkits/" + name + ".so"
p := initToolkit(name, filename) p := initToolkit(name, filename)
if (p != nil) { if (p != nil) {
return p return p
@ -141,33 +142,23 @@ func searchPaths(name string) *aplug {
homeDir, err := os.UserHomeDir() homeDir, err := os.UserHomeDir()
if err != nil { if err != nil {
log(logError, "searchPaths() error. exiting here?") log.Error(err, "os.UserHomeDir() error. giving up")
} else { return nil
}
filename = homeDir + "/go/src/go.wit.com/gui/toolkits/" + name + ".so" filename = homeDir + "/go/src/go.wit.com/gui/toolkits/" + name + ".so"
p = initToolkit(name, filename) p = initToolkit(name, filename)
if (p != nil) { if (p != nil) {
return p return p
} }
}
homeDir, err = os.UserHomeDir() filename = "/usr/lib/go-gui/latest/" + name + ".so"
if err != nil {
log(logError, "searchPaths() error. exiting here?")
} else {
filename = homeDir + "/go/src/go.wit.com/toolkits/" + name + ".so"
p = initToolkit(name, filename)
if (p != nil) {
return p
}
}
filename = "/usr/lib/go-gui/" + name + ".so"
p = initToolkit(name, filename) p = initToolkit(name, filename)
if (p != nil) { if (p != nil) {
return p return p
} }
filename = "/usr/local/lib/" + name + ".so" filename = "/usr/local/lib/gui/toolkits/" + name + ".so"
p = initToolkit(name, filename) p = initToolkit(name, filename)
if (p != nil) { if (p != nil) {
return p return p
@ -180,18 +171,18 @@ func searchPaths(name string) *aplug {
func initToolkit(name string, filename string) *aplug { func initToolkit(name string, filename string) *aplug {
if _, err := os.Stat(filename); err != nil { if _, err := os.Stat(filename); err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
log(true, "missing plugin", name, "as filename", filename) log.Log(true, "missing plugin", name, "as filename", filename)
return nil return nil
} }
} }
log(true, "Found plugin", name, "as filename", filename) log.Log(true, "Found plugin", name, "as filename", filename)
plug, err := plugin.Open(filename) plug, err := plugin.Open(filename)
if err != nil { if err != nil {
log(debugError, "plugin FAILED =", filename, err) log.Error(err, "plugin FAILED =", filename)
return nil return nil
} }
log(debugPlugin, "initToolkit() loading plugin =", filename) log.Log(PLUG, "initToolkit() loading plugin =", filename)
var newPlug *aplug var newPlug *aplug
newPlug = new(aplug) newPlug = new(aplug)
@ -214,12 +205,12 @@ func initToolkit(name string, filename string) *aplug {
// set the communication to the plugins // set the communication to the plugins
newPlug.pluginChan = newPlug.PluginChannel() newPlug.pluginChan = newPlug.PluginChannel()
if (newPlug.pluginChan == nil) { if (newPlug.pluginChan == nil) {
log(debugError, "initToolkit() ERROR PluginChannel() returned nil for plugin:", newPlug.name, filename) log.Warn("initToolkit() ERROR PluginChannel() returned nil for plugin:", newPlug.name, filename)
return nil return nil
} }
newPlug.Callback(me.guiChan) newPlug.Callback(me.guiChan)
log(debugPlugin, "initToolkit() END", newPlug.name, filename) log.Log(PLUG, "initToolkit() END", newPlug.name, filename)
return newPlug return newPlug
} }
@ -255,16 +246,16 @@ func newAction(n *Node, atype toolkit.ActionType) *toolkit.Action {
// sends the action/event to each toolkit via a golang plugin channel // sends the action/event to each toolkit via a golang plugin channel
func sendAction(a *toolkit.Action) { func sendAction(a *toolkit.Action) {
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(debugPlugin, "Action() aplug =", aplug.name, "Action type=", a.ActionType) log.Log(PLUG, "Action() aplug =", aplug.name, "Action type=", a.ActionType)
if (aplug.pluginChan == nil) { if (aplug.pluginChan == nil) {
log(logInfo, "Action() retrieving the aplug.PluginChannel()", aplug.name) log.Info("Action() retrieving the aplug.PluginChannel()", aplug.name)
aplug.pluginChan = aplug.PluginChannel() aplug.pluginChan = aplug.PluginChannel()
log(logInfo, "Action() retrieved", aplug.pluginChan) log.Info("Action() retrieved", aplug.pluginChan)
} }
log(logInfo, "Action() SEND to pluginChan", aplug.name) log.Info("Action() SEND to pluginChan", aplug.name)
aplug.pluginChan <- *a aplug.pluginChan <- *a
// added during debugging. might be a good idea in general for a tactile experience // added during debugging. might be a good idea in general for a tactile experience
sleep(.02) // this delay makes it so SetText() works on initial widget creation log.Sleep(.02) // this delay makes it so SetText() works on initial widget creation
} }
} }
@ -275,15 +266,16 @@ func (n *Node) InitEmbed(resFS embed.FS) *Node {
func (n *Node) LoadToolkitEmbed(name string, b []byte) *Node { func (n *Node) LoadToolkitEmbed(name string, b []byte) *Node {
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(logInfo, "LoadToolkitEmbed() already loaded toolkit plugin =", aplug.name) log.Info("LoadToolkitEmbed() already loaded toolkit plugin =", aplug.name)
if (aplug.name == name) { if (aplug.name == name) {
log(logError, "LoadToolkitEmbed() SKIPPING", name, "as you can't load it twice") log.Warn("LoadToolkitEmbed() SKIPPING", name, "as you can't load it twice")
return n return n
} }
} }
f, err := os.CreateTemp("", "sample." + name + ".so") f, err := os.CreateTemp("", "sample." + name + ".so")
if (err != nil) { if (err != nil) {
log.Error(err, "LoadToolkitEmbed() SKIPPING", name, "as you can't load it twice")
return n return n
} }
defer os.Remove(f.Name()) defer os.Remove(f.Name())
@ -291,25 +283,25 @@ func (n *Node) LoadToolkitEmbed(name string, b []byte) *Node {
p := initToolkit(name, f.Name()) p := initToolkit(name, f.Name())
if (p == nil) { if (p == nil) {
log(logError, "LoadToolkitEmbed() embedded go file failed", name) log.Warn("LoadToolkitEmbed() embedded go file failed", name)
} }
return n return n
} }
func (n *Node) ListToolkits() { func (n *Node) ListToolkits() {
for _, aplug := range allPlugins { for _, aplug := range allPlugins {
log(logNow, "ListToolkits() already loaded toolkit plugin =", aplug.name) log.Log(PLUG, "ListToolkits() already loaded toolkit plugin =", aplug.name)
} }
} }
func (n *Node) LoadToolkit(name string) *Node { func (n *Node) LoadToolkit(name string) *Node {
log(logInfo, "LoadToolkit() START for name =", name) log.Log(PLUG, "LoadToolkit() START for name =", name)
plug := initPlugin(name) plug := initPlugin(name)
if (plug == nil) { if (plug == nil) {
return n return n
} }
log(logInfo, "LoadToolkit() sending InitToolkit action to the plugin channel") log.Log(PLUG, "LoadToolkit() sending InitToolkit action to the plugin channel")
var a toolkit.Action var a toolkit.Action
a.ActionType = toolkit.InitToolkit a.ActionType = toolkit.InitToolkit
plug.pluginChan <- a plug.pluginChan <- a
@ -317,16 +309,16 @@ func (n *Node) LoadToolkit(name string) *Node {
// TODO: find a new way to do this that is locking, safe and accurate // TODO: find a new way to do this that is locking, safe and accurate
me.rootNode.redraw(plug) me.rootNode.redraw(plug)
log(logInfo, "LoadToolkit() END for name =", name) log.Log(PLUG, "LoadToolkit() END for name =", name)
return n return n
} }
func (n *Node) CloseToolkit(name string) bool { func (n *Node) CloseToolkit(name string) bool {
log(logInfo, "CloseToolkit() for name =", name) log.Log(PLUG, "CloseToolkit() for name =", name)
for _, plug := range allPlugins { for _, plug := range allPlugins {
log(debugGui, "CloseToolkit() found", plug.name) log.Log(PLUG, "CloseToolkit() found", plug.name)
if (plug.name == name) { if (plug.name == name) {
log(debugNow, "CloseToolkit() sending close", name) log.Log(PLUG, "CloseToolkit() sending close", name)
var a toolkit.Action var a toolkit.Action
a.ActionType = toolkit.CloseToolkit a.ActionType = toolkit.CloseToolkit
plug.pluginChan <- a plug.pluginChan <- a

View File

@ -1,7 +1,8 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
// This recreates the whole GUI for a plugin // This recreates the whole GUI for a plugin
@ -20,7 +21,7 @@ func (n *Node) redraw(p *aplug) {
} }
func (n *Node) redo(plug *aplug) { func (n *Node) redo(plug *aplug) {
log(logNow, "redo()", plug.name, n.id, n.WidgetType, n.Name) log.Info("redo()", plug.name, n.id, n.WidgetType, n.Name)
var a *toolkit.Action var a *toolkit.Action
a = new(toolkit.Action) a = new(toolkit.Action)

View File

@ -1,14 +1,15 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
func (parent *Node) NewSlider(name string, x int, y int) *Node { func (parent *Node) NewSlider(name string, x int, y int) *Node {
newNode := parent.newNode(name, toolkit.Slider) newNode := parent.newNode(name, toolkit.Slider)
newNode.Custom = func() { newNode.Custom = func() {
log(debugGui, "even newer clicker() name in NewSlider name =", name) log.Log(GUI, "even newer clicker() name in NewSlider name =", name)
} }
newNode.X = x newNode.X = x

View File

@ -1,14 +1,15 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
func (parent *Node) NewSpinner(name string, x int, y int) *Node { func (parent *Node) NewSpinner(name string, x int, y int) *Node {
newNode := parent.newNode(name, toolkit.Spinner) newNode := parent.newNode(name, toolkit.Spinner)
newNode.Custom = func() { newNode.Custom = func() {
log(debugChange, "default NewSpinner() change", name) log.Info("default NewSpinner() change", name)
} }
newNode.X = x newNode.X = x

View File

@ -3,7 +3,7 @@ package gui
import ( import (
"sync" "sync"
"embed" "embed"
"go.wit.com/gui/gui/toolkit" "go.wit.com/gui/toolkits"
) )
// //

12
tab.go
View File

@ -1,7 +1,9 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
// This function should make a new node with the parent and // This function should make a new node with the parent and
@ -12,16 +14,16 @@ func (n *Node) NewTab(text string) *Node {
if (n.WidgetType != toolkit.Window) { if (n.WidgetType != toolkit.Window) {
// figure out what the actual window is // figure out what the actual window is
log(logError, "NewTab() is being requested on something that isn't a Window. node =", n) log.Warn("NewTab() is being requested on something that isn't a Window. node =", n)
if (n.parent == nil) { if (n.parent == nil) {
// TODO: find a window. any window. never give up. never die. // TODO: find a window. any window. never give up. never die.
log(logError, "NewTab() TODO: make a window here", n) log.Warn("NewTab() TODO: make a window here", n)
panic("NewTab did not get passed a window") panic("NewTab did not get passed a window")
} }
log(logError, "NewTab() parent =", n.parent) log.Warn("NewTab() parent =", n.parent)
if (n.parent.WidgetType == toolkit.Root) { if (n.parent.WidgetType == toolkit.Root) {
// also broken // also broken
log(logError, "NewTab() TODO: make or find a window here", n) log.Warn("NewTab() TODO: make or find a window here", n)
panic("NewTab() did not get passed a window") panic("NewTab() did not get passed a window")
} }
// go up the binary tree until we find a window widget to add a tab too // go up the binary tree until we find a window widget to add a tab too

View File

@ -1,14 +1,16 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
func (parent *Node) NewTextbox(name string) *Node { func (parent *Node) NewTextbox(name string) *Node {
newNode := parent.newNode(name, toolkit.Textbox) newNode := parent.newNode(name, toolkit.Textbox)
newNode.Custom = func() { newNode.Custom = func() {
log(debugGui, "NewTextbox changed =", name) log.Log(GUI, "NewTextbox changed =", name)
} }
a := newAction(newNode, toolkit.Add) a := newAction(newNode, toolkit.Add)
@ -22,7 +24,7 @@ func (parent *Node) NewEntryLine(name string) *Node {
newNode.X = 1 newNode.X = 1
newNode.Custom = func() { newNode.Custom = func() {
log(debugGui, "NewTextbox changed =", name) log.Log(GUI, "NewTextbox changed =", name)
} }
a := newAction(newNode, toolkit.Add) a := newAction(newNode, toolkit.Add)

View File

@ -1,204 +0,0 @@
package toolkit
// passes information between the toolkit library (plugin)
//
// 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.
// Event is used too much: web dev, cloud, etc
// I'm using "Action". Maybe it should really be
// "Interaction" as per wikipedia [[User interface]]
//
// TODO: convert this to a protobuf (?)
//
type WidgetType int // Button, Menu, Checkbox, etc.
type ActionType int // Add, SetText, Click, Hide, Append, Delete, etc
type Action struct {
ActionType ActionType
WidgetType WidgetType
WidgetId int
ParentId int
Text string // what is visable to the user
Name string // a name useful for programming
// This is how the values are passed back and forth
// values from things like checkboxes & dropdown's
B bool
I int
S string
// This is used for things like a slider(0,100)
X int
Y int
// This is for the grid size & widget position
W int
H int
AtW int
AtH int
// Put space around elements to improve look & feel
Margin bool
// Make widgets fill up the space available
Expand bool
A any // switch to this or deprecate this? pros/cons?
}
const (
Unknown WidgetType = iota
Root // the master 'root' node of the binary tree
Flag // used to send configuration values to plugins
Window // in certain gui's (ncurses), these are tabs
Tab // internally, this is a window
Frame // deprecate?
Grid // like drawers in a chest
Group // like the 'Appetizers' section on a menu
Box // a vertical or horizontal stack of widgets
Button
Checkbox // select 'on' or 'off'
Dropdown
Combobox // dropdown with edit=true
Label
Textbox // is this a Label with edit=true
Slider // like a progress bar
Spinner // like setting the oven temperature
Separator // TODO
Image // TODO
Area // TODO
Form // TODO
Font // TODO
Color // TODO
Dialog // TODO
Stdout // can be used to capture and display log output
)
const (
Add ActionType = iota
Delete
Get
Set
GetText
SetText
AddText
Show
Hide
Enable
Disable
Margin
Unmargin
Pad
Unpad
Append
Move
Dump
User // the user did something (mouse, keyboard, etc)
InitToolkit // initializes the toolkit
CloseToolkit // closes the toolkit
UserQuit // the user closed the GUI
EnableDebug // open the debugging window
)
func (s WidgetType) String() string {
switch s {
case Root:
return "Root"
case Flag:
return "Flag"
case Window:
return "Window"
case Tab:
return "Tab"
case Frame:
return "Frame"
case Grid:
return "Grid"
case Group:
return "Group"
case Box:
return "Box"
case Button:
return "Button"
case Checkbox:
return "Checkbox"
case Dropdown:
return "Dropdown"
case Combobox:
return "Combobox"
case Label:
return "Label"
case Textbox:
return "Textbox"
case Slider:
return "Slider"
case Spinner:
return "Spinner"
case Separator:
return "Separator"
case Image:
return "Image"
case Area:
return "Area"
case Form:
return "Form"
case Font:
return "Font"
case Color:
return "Color"
case Dialog:
return "Dialog"
case Stdout:
return "Stdout"
case Unknown:
return "Unknown"
}
return "WidgetType.String() Error"
}
func (s ActionType) String() string {
switch s {
case Add:
return "Add"
case Delete:
return "Delete"
case Get:
return "Get"
case Set:
return "Set"
case GetText:
return "GetText"
case SetText:
return "SetText"
case AddText:
return "AddText"
case Show:
return "Show"
case Hide:
return "Hide"
case Enable:
return "Enable"
case Disable:
return "Disable"
case Margin:
return "Margin"
case Unmargin:
return "Unmargin"
case Pad:
return "Pad"
case Unpad:
return "Unpad"
case Append:
return "Append"
case Move:
return "Move"
case Dump:
return "Dump"
}
return "ActionType.String() Error"
}

View File

@ -2,6 +2,8 @@ package gui
import ( import (
"time" "time"
"go.wit.com/log"
) )
var watchtime time.Duration = 100 // in tenths of seconds var watchtime time.Duration = 100 // in tenths of seconds
@ -16,43 +18,8 @@ var watchtime time.Duration = 100 // in tenths of seconds
func Watchdog() { func Watchdog() {
var i = 1 var i = 1
for { for {
log(logInfo, "gui.Watchdog() is alive. give me something to do.", i) log.Verbose("gui.Watchdog() is alive. give me something to do.", i)
if (me.rootNode == nil) {
log(logInfo, "me.rootNode == nil", i)
} else {
if (logVerbose) {
me.rootNode.ListChildren(true)
}
}
i += 1 i += 1
time.Sleep(watchtime * time.Second / 10) time.Sleep(watchtime * time.Second / 10)
} }
} }
// https://www.reddit.com/r/golang/comments/12em87q/how_to_run_periodic_tasks/
/*
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
done := make(chan bool)
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
for {
select {
case <-done:
fmt.Println("Done!")
return
case t := <-ticker.C:
fmt.Println("Current time: ", t)
}
}
}
*/

View File

@ -1,7 +1,8 @@
package gui package gui
import ( import (
"go.wit.com/gui/gui/toolkit" "go.wit.com/log"
"go.wit.com/gui/toolkits"
) )
// This routine creates a blank window with a Title and size (W x H) // This routine creates a blank window with a Title and size (W x H)
@ -13,7 +14,7 @@ func (parent *Node) NewWindow(title string) *Node {
newNode = parent.newNode(title, toolkit.Window) newNode = parent.newNode(title, toolkit.Window)
newNode.Custom = StandardExit newNode.Custom = StandardExit
log(logInfo, "NewWindow()", title) log.Info("NewWindow()", title)
a := newAction(newNode, toolkit.Add) a := newAction(newNode, toolkit.Add)
sendAction(a) sendAction(a)