Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
|
391ed60415 | |
|
7af0ecf8f1 | |
|
844668dabd | |
|
ebeeed84b4 | |
|
732edc3faf | |
|
1e2fa2dce9 | |
|
25ed10c0ec | |
|
e2958fe561 |
18
Makefile
18
Makefile
|
@ -20,28 +20,14 @@ endif
|
|||
|
||||
redomod:
|
||||
rm -f go.*
|
||||
go mod init
|
||||
go mod tidy
|
||||
GO111MODULE= go mod init
|
||||
GO111MODULE= go mod tidy
|
||||
|
||||
# should update every go dependancy (?)
|
||||
update:
|
||||
git pull
|
||||
go get -v -t -u ./...
|
||||
|
||||
# sync repo to the github backup
|
||||
# git remote add github git@github.com:wit-go/gui.git
|
||||
github:
|
||||
git push origin master
|
||||
git push origin devel
|
||||
git push origin --tags
|
||||
git push github master
|
||||
git push github devel
|
||||
git push github --tags
|
||||
@echo
|
||||
@echo check https://git.wit.org/gui/gui
|
||||
@echo check https://github.com/wit-go/gui
|
||||
@echo
|
||||
|
||||
doc:
|
||||
godoc -v
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package gui
|
||||
|
||||
/*
|
||||
This is where the communication to the toolkit plugin happens.
|
||||
|
||||
We copy the current values from the widget node of the binary tree
|
||||
and send an "action" to the toolkit over a channel.
|
||||
|
||||
TODO: use protobuf
|
||||
*/
|
||||
|
||||
import (
|
||||
"go.wit.com/log"
|
||||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
// 2024/01/11 finally moving to type any. simplify to just 'value'
|
||||
// 2023/05/09 pretty clean
|
||||
// 2023/04/06 Queue() is also being used and channels are being used.
|
||||
func sendAction(n *Node, atype widget.ActionType) {
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
if n.hidden {
|
||||
return
|
||||
}
|
||||
|
||||
var a widget.Action
|
||||
a.ActionType = atype
|
||||
|
||||
// These should be "stable" at this point (2024/01/13)
|
||||
a.WidgetId = n.id
|
||||
a.ProgName = n.progname
|
||||
a.Value = n.value
|
||||
a.Direction = n.direction
|
||||
a.Strings = n.strings
|
||||
|
||||
// These should be improved/deprecated based on the gui/widget docs
|
||||
a.X = n.X
|
||||
a.Y = n.Y
|
||||
|
||||
a.AtW = n.AtW
|
||||
a.AtH = n.AtH
|
||||
|
||||
if (n.parent != nil) {
|
||||
a.ParentId = n.parent.id
|
||||
}
|
||||
a.WidgetType = n.WidgetType
|
||||
sendActionToPlugin(&a)
|
||||
}
|
||||
|
||||
// sends the action/event to each toolkit via a golang plugin channel
|
||||
func sendActionToPlugin(a *widget.Action) {
|
||||
for _, aplug := range allPlugins {
|
||||
log.Log(PLUG, "Action() aplug =", aplug.name, "Action type=", a.ActionType)
|
||||
if (aplug.pluginChan == nil) {
|
||||
log.Info("Action() retrieving the aplug.PluginChannel()", aplug.name)
|
||||
aplug.pluginChan = aplug.PluginChannel()
|
||||
log.Info("Action() retrieved", aplug.pluginChan)
|
||||
}
|
||||
log.Info("Action() SEND to pluginChan", aplug.name, a.ActionType, a.WidgetType, a.WidgetId, a.ProgName)
|
||||
aplug.pluginChan <- *a
|
||||
// added during debugging. might be a good idea in general for a tactile experience
|
||||
log.Sleep(.02) // this delay makes it so SetText() works on initial widget creation
|
||||
}
|
||||
}
|
2
args.go
2
args.go
|
@ -1,8 +1,8 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"go.wit.com/arg"
|
||||
"go.wit.com/log"
|
||||
"go.wit.com/dev/alexflint/arg"
|
||||
)
|
||||
|
||||
var INFO *log.LogFlag
|
||||
|
|
38
box.go
38
box.go
|
@ -4,13 +4,39 @@ import (
|
|||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
func (parent *Node) NewBox(name string, b bool) *Node {
|
||||
newNode := parent.newNode(name, widget.Box)
|
||||
newNode.B = b
|
||||
func (parent *Node) NewBox(progname string, b bool) *Node {
|
||||
newNode := parent.newNode(progname, widget.Box)
|
||||
newNode.progname = progname
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
if b {
|
||||
newNode.direction = widget.Horizontal
|
||||
} else {
|
||||
newNode.direction = widget.Vertical
|
||||
}
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
func (parent *Node) NewHorizontalBox(progname string) *Node {
|
||||
newNode := parent.newNode(progname, widget.Box)
|
||||
newNode.progname = progname
|
||||
|
||||
newNode.direction = widget.Horizontal
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
func (parent *Node) NewVerticalBox(progname string) *Node {
|
||||
newNode := parent.newNode(progname, widget.Box)
|
||||
newNode.progname = progname
|
||||
|
||||
newNode.direction = widget.Vertical
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
27
button.go
27
button.go
|
@ -5,29 +5,10 @@ import "go.wit.com/gui/widget"
|
|||
func (parent *Node) NewButton(name string, custom func()) *Node {
|
||||
newNode := parent.newNode(name, widget.Button)
|
||||
newNode.Custom = custom
|
||||
newNode.value = name
|
||||
newNode.progname = name
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
// find widget by number
|
||||
func (n *Node) FindId(i int) (*Node) {
|
||||
if (n == nil) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if (n.id == i) {
|
||||
return n
|
||||
}
|
||||
|
||||
for _, child := range n.children {
|
||||
newN := child.FindId(i)
|
||||
if (newN != nil) {
|
||||
return newN
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
10
checkbox.go
10
checkbox.go
|
@ -3,15 +3,15 @@ package gui
|
|||
import "go.wit.com/gui/widget"
|
||||
|
||||
func (n *Node) Checked() bool {
|
||||
return n.B
|
||||
return widget.GetBool(n.value)
|
||||
}
|
||||
|
||||
func (n *Node) NewCheckbox(name string) *Node {
|
||||
newNode := n.newNode(name, widget.Checkbox)
|
||||
newNode.value = name
|
||||
newNode.progname = name
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
414
common.go
414
common.go
|
@ -11,104 +11,314 @@ import (
|
|||
// functions for handling text related GUI elements
|
||||
|
||||
func (n *Node) Show() *Node {
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Show)
|
||||
sendAction(a)
|
||||
if ! n.Ready() { return n }
|
||||
if ! n.Hidden() { return n }
|
||||
|
||||
n.hidden = false
|
||||
n.changed = true
|
||||
|
||||
if n.WidgetType == widget.Window {
|
||||
log.Warn("Show on a hidden window", n.progname)
|
||||
log.Warn("this needs to do TestDraw()")
|
||||
n.TestDraw()
|
||||
return n
|
||||
}
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Show)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Hide() *Node {
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Hide)
|
||||
sendAction(a)
|
||||
if ! n.Ready() { return n }
|
||||
if n.Hidden() { return n }
|
||||
|
||||
|
||||
if n.WidgetType == widget.Window {
|
||||
log.Warn("Hide on a window", n.progname)
|
||||
log.Warn("this needs to do TestDestroy() ?")
|
||||
n.Destroy()
|
||||
n.hidden = true
|
||||
n.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
n.hidden = true
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Hide)
|
||||
return n
|
||||
}
|
||||
|
||||
// enables a widget so the user can see it and work/click/etc on it
|
||||
// by default, widgets are enabled when they are created
|
||||
func (n *Node) Enable() *Node {
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Enable)
|
||||
sendAction(a)
|
||||
}
|
||||
if ! n.Ready() { return n }
|
||||
// if n.enabled { return n }
|
||||
|
||||
n.enabled = true
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Enable)
|
||||
return n
|
||||
}
|
||||
|
||||
// disables a widget so the user can see it, but can not
|
||||
// interact or change it.
|
||||
func (n *Node) Disable() *Node {
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Disable)
|
||||
sendAction(a)
|
||||
}
|
||||
if ! n.Ready() { return n }
|
||||
// if ! n.enabled { return n }
|
||||
|
||||
n.enabled = false
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Disable)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Add(str string) {
|
||||
log.Log(GUI, "gui.Add() value =", str)
|
||||
func (n *Node) Destroy() {
|
||||
if ! n.Ready() { return }
|
||||
// if ! n.enabled { return }
|
||||
|
||||
n.S = str
|
||||
n.enabled = false
|
||||
n.changed = true
|
||||
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Delete)
|
||||
return
|
||||
}
|
||||
|
||||
func (n *Node) AddText(str string) {
|
||||
|
||||
// add a new text string to widgets that support
|
||||
// multiple string values
|
||||
// These must be unique. return false if the string already exists
|
||||
func (n *Node) AddText(str string) bool {
|
||||
if ! n.Ready() { return false }
|
||||
log.Log(CHANGE, "AddText() value =", str)
|
||||
|
||||
n.Text = str
|
||||
n.S = str
|
||||
n.value = str
|
||||
// TODO: make sure these are unique
|
||||
n.strings = append(n.strings, str)
|
||||
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.AddText)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.AddText)
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *Node) SetNext(w int, h int) {
|
||||
n.NextW = w
|
||||
n.NextH = h
|
||||
log.Info("SetNext() w,h =", n.NextW, n.NextH)
|
||||
}
|
||||
|
||||
// appends text to the existing text
|
||||
// TODO: this is an experiement
|
||||
func (n *Node) AppendText(str string) {
|
||||
tmp := n.S + str
|
||||
n.Text = tmp
|
||||
n.S = tmp
|
||||
if ! n.Ready() { return }
|
||||
tmp := widget.GetString(n.value) + str
|
||||
n.value = tmp
|
||||
n.changed = true
|
||||
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.SetText)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.SetText)
|
||||
}
|
||||
|
||||
// THESE TWO FUNCTIONS ARE TERRIBLY NAMED AND NEED TO BE FIXED
|
||||
// 5 seconds worth of ideas:
|
||||
// Value() ?
|
||||
// Progname() Reference() ?
|
||||
// 2024/01/13 the names are starting to grow on me and make it clearer to code against
|
||||
|
||||
// should get the value of the node
|
||||
// get a string from the widget
|
||||
func (n *Node) GetText() string {
|
||||
if n.value != nil {
|
||||
return n.value.(string)
|
||||
}
|
||||
if (n.S != n.Text) {
|
||||
log.Warn("GetText() is screwed up. TODO: fix this dumb crap. n.S =", n.S, "and n.Text =", n.Text)
|
||||
}
|
||||
if (n.S != "") {
|
||||
return n.S
|
||||
}
|
||||
return n.Text
|
||||
if ! n.Ready() { return "" }
|
||||
return widget.GetString(n.value)
|
||||
}
|
||||
|
||||
// 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
|
||||
// get a string from the widget
|
||||
func (n *Node) GetInt() int {
|
||||
if ! n.Ready() { return -1 }
|
||||
return widget.GetInt(n.value)
|
||||
}
|
||||
|
||||
// get a string from the widget
|
||||
func (n *Node) GetBool() bool {
|
||||
if ! n.Ready() { return false}
|
||||
return widget.GetBool(n.value)
|
||||
}
|
||||
|
||||
// should get the reference name used for programming and debugging
|
||||
func (n *Node) SetProgName(s string) *Node {
|
||||
if ! n.Ready() { return n }
|
||||
|
||||
if n.progname == s {
|
||||
// don't do anything since nothing changed
|
||||
return n
|
||||
}
|
||||
|
||||
n.changed = true
|
||||
n.progname = s
|
||||
return n
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: ensure these are unique and make a way to look them up
|
||||
myButton = myGroup.NewButton("hit ball", nil).SetName("HIT")
|
||||
myButton.GetName() should return "HIT"
|
||||
n = Find("HIT") should return myButton
|
||||
*/
|
||||
func (n *Node) GetProgName() string {
|
||||
if ! n.Ready() { return "" }
|
||||
return n.progname
|
||||
}
|
||||
|
||||
/*
|
||||
func commonCallback(n *Node) {
|
||||
// TODO: make all of this common code to all the widgets
|
||||
// This might be common everywhere finally (2023/03/01)
|
||||
if (n.Custom == nil) {
|
||||
log.Log(CHANGE, "Not Running n.Custom(n) == nil")
|
||||
} else {
|
||||
log.Log(CHANGE, "Running n.Custom(n)")
|
||||
n.Custom()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func (n *Node) Margin() *Node {
|
||||
if ! n.Ready() { return n }
|
||||
if n.margin { return n }
|
||||
|
||||
n.margin = true
|
||||
n.changed = true
|
||||
|
||||
log.Warn("Margin()", n.WidgetType, n.progname)
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Margin)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Unmargin() *Node {
|
||||
if ! n.Ready() { return n }
|
||||
if ! n.margin { return n }
|
||||
|
||||
n.margin = false
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Unmargin)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Pad() *Node {
|
||||
if ! n.Ready() { return n }
|
||||
if n.pad == true { return n } // nothing changed
|
||||
|
||||
n.pad = true
|
||||
n.changed = true
|
||||
|
||||
log.Warn("Pad()", n.WidgetType, n.progname)
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Pad)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Unpad() *Node {
|
||||
if ! n.Ready() { return n }
|
||||
if n.pad == false { return n } // nothing changed
|
||||
|
||||
n.pad = false
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Unpad)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Expand() *Node {
|
||||
if ! n.Ready() { return n }
|
||||
if n.expand == true { return n } // nothing changed
|
||||
|
||||
n.expand = true
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.SetExpand)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) SetExpand(b bool) *Node {
|
||||
if ! n.Ready() { return n }
|
||||
if n.expand == b { return n } // nothing changed
|
||||
|
||||
n.expand = b
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.SetExpand)
|
||||
return n
|
||||
}
|
||||
|
||||
// is the widget currently viewable?
|
||||
func (n *Node) Hidden() bool {
|
||||
if ! n.Ready() { return false }
|
||||
return n.hidden
|
||||
}
|
||||
|
||||
func (n *Node) Ready() bool {
|
||||
if n == nil {
|
||||
log.Warn("Ready() got node == nil")
|
||||
// TODO: figure out if you can identify the code trace
|
||||
// to help find the root cause
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// DEPRECATE / REDO / SORT OUT THIS STUFF
|
||||
//
|
||||
//
|
||||
|
||||
// This should not really do anything. as per the docs, the "Standard()" way
|
||||
// should be the default way
|
||||
/*
|
||||
func (n *Node) Standard() *Node {
|
||||
log.Warn("Standard() not implemented yet")
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) SetMargin() *Node {
|
||||
log.Warn("DoMargin() not implemented yet")
|
||||
return n
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func (n *Node) Window(title string) *Node {
|
||||
log.Warn("Window()", n)
|
||||
return n.NewWindow(title)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func (n *Node) Add(str string) {
|
||||
log.Log(GUI, "gui.Add() value =", str)
|
||||
|
||||
n.value = str
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Add)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func (n *Node) SetNext(w int, h int) {
|
||||
n.NextW = w
|
||||
n.NextH = h
|
||||
log.Info("SetNext() w,h =", n.NextW, n.NextH)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// string handling examples that might be helpful for normalizeInt()
|
||||
isAlpha := regexp.MustCompile(`^[A-Za-z]+$`).MatchString
|
||||
|
@ -142,93 +352,3 @@ func normalizeInt(s string) string {
|
|||
log.Log(GUI, "normalizeInt() s =", clean)
|
||||
return clean
|
||||
}
|
||||
|
||||
func commonCallback(n *Node) {
|
||||
// TODO: make all of this common code to all the widgets
|
||||
// This might be common everywhere finally (2023/03/01)
|
||||
if (n.Custom == nil) {
|
||||
log.Log(CHANGE, "Not Running n.Custom(n) == nil")
|
||||
} else {
|
||||
log.Log(CHANGE, "Running n.Custom(n)")
|
||||
n.Custom()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) Margin() *Node {
|
||||
n.margin = true
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Margin)
|
||||
sendAction(a)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Unmargin() *Node {
|
||||
n.margin = false
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Unmargin)
|
||||
sendAction(a)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Pad() *Node {
|
||||
n.pad = true
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Pad)
|
||||
sendAction(a)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Unpad() *Node {
|
||||
n.pad = false
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Unpad)
|
||||
sendAction(a)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Expand() *Node {
|
||||
n.expand = true
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Pad)
|
||||
a.Expand = true
|
||||
sendAction(a)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// is this better?
|
||||
// yes, this is better. it allows Internationalization very easily
|
||||
// me.window = myGui.New2().Window("DNS and IPv6 Control Panel").Standard()
|
||||
// myFunnyWindow = myGui.NewWindow("Hello").Standard().SetText("Hola")
|
||||
|
||||
func (n *Node) Window(title string) *Node {
|
||||
log.Warn("Window()", n)
|
||||
return n.NewWindow(title)
|
||||
}
|
||||
|
||||
func (n *Node) Ready() bool {
|
||||
if n == nil {
|
||||
log.Warn("Ready() got node == nil")
|
||||
// TODO: figure out if you can identify the code trace to help find the root cause
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// This should not really do anything. as per the docs, the "Standard()" way
|
||||
// should be the default way
|
||||
/*
|
||||
func (n *Node) Standard() *Node {
|
||||
log.Warn("Standard() not implemented yet")
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) SetMargin() *Node {
|
||||
log.Warn("DoMargin() not implemented yet")
|
||||
return n
|
||||
}
|
||||
*/
|
||||
|
|
14
debug.go
14
debug.go
|
@ -21,7 +21,7 @@ func (n *Node) Dump() {
|
|||
b := true
|
||||
Indent(b, "NODE DUMP START")
|
||||
Indent(b, "id = ", n.id)
|
||||
Indent(b, "Name = ", n.Name)
|
||||
Indent(b, "progname = ", n.progname)
|
||||
Indent(b, "(X,Y) = ", n.X, n.Y)
|
||||
Indent(b, "Next (W,H) = ", n.NextW, n.NextH)
|
||||
|
||||
|
@ -38,10 +38,8 @@ func (n *Node) Dump() {
|
|||
}
|
||||
Indent(b, "NODE DUMP END")
|
||||
|
||||
a := new(widget.Action)
|
||||
a.ActionType = widget.Dump
|
||||
a.WidgetId = n.id
|
||||
sendAction(a)
|
||||
n.changed = true
|
||||
sendAction(n, widget.Dump)
|
||||
}
|
||||
|
||||
func Indent(b bool, a ...interface{}) {
|
||||
|
@ -57,7 +55,7 @@ func (n *Node) dumpWidget(b bool) string {
|
|||
}
|
||||
info = n.WidgetType.String()
|
||||
|
||||
d = strconv.Itoa(n.id) + " " + info + " " + n.Name
|
||||
d = strconv.Itoa(n.id) + " " + info + " " + n.progname
|
||||
|
||||
var tabs string
|
||||
for i := 0; i < listChildrenDepth; i++ {
|
||||
|
@ -86,8 +84,8 @@ func (n *Node) ListChildren(dump bool) {
|
|||
if (listChildrenParent != nil) {
|
||||
log.Log(NODE, "\t\t\tlistChildrenParent =",listChildrenParent.id)
|
||||
if (listChildrenParent.id != n.parent.id) {
|
||||
log.Log(NOW, "parent =",n.parent.id, n.parent.Name)
|
||||
log.Log(NOW, "listChildrenParent =",listChildrenParent.id, listChildrenParent.Name)
|
||||
log.Log(NOW, "parent =",n.parent.id, n.parent.progname)
|
||||
log.Log(NOW, "listChildrenParent =",listChildrenParent.id, listChildrenParent.progname)
|
||||
log.Log(NOW, listChildrenParent.id, "!=", n.parent.id)
|
||||
log.Exit("parent.child does not match child.parent")
|
||||
}
|
||||
|
|
29
dropdown.go
29
dropdown.go
|
@ -6,37 +6,38 @@ package gui
|
|||
// since it is the same. confusing names? maybe...
|
||||
|
||||
import (
|
||||
"go.wit.com/log"
|
||||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
// add a new entry to the dropdown name
|
||||
func (n *Node) AddDropdownName(name string) {
|
||||
if ! n.Ready() { return }
|
||||
log.Warn("AddDropdownName() deprecated")
|
||||
n.AddText(name)
|
||||
}
|
||||
|
||||
// Set the dropdown menu to 'name'
|
||||
func (n *Node) SetDropdownName(name string) {
|
||||
if ! n.Ready() { return }
|
||||
log.Warn("SetDropdownName() deprecated")
|
||||
n.SetText(name)
|
||||
}
|
||||
|
||||
func (n *Node) NewDropdown(name string) *Node {
|
||||
newNode := n.newNode(name, widget.Dropdown)
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
func (n *Node) NewDropdown(progname string) *Node {
|
||||
newNode := n.newNode(progname, widget.Dropdown)
|
||||
newNode.progname = progname
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
func (n *Node) NewCombobox(name string) *Node {
|
||||
newNode := n.newNode(name, widget.Combobox)
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
func (n *Node) NewCombobox(progname string) *Node {
|
||||
newNode := n.newNode(progname, widget.Combobox)
|
||||
newNode.progname = progname
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
10
go.mod
10
go.mod
|
@ -3,12 +3,12 @@ module go.wit.com/gui/gui
|
|||
go 1.21.4
|
||||
|
||||
require (
|
||||
github.com/alexflint/go-arg v1.4.3
|
||||
go.wit.com/gui/widget v0.0.0-20240105185907-84aafa536a93
|
||||
go.wit.com/log v0.3.1
|
||||
go.wit.com/dev/alexflint/arg v1.4.5
|
||||
go.wit.com/gui/widget v1.1.3
|
||||
go.wit.com/log v0.5.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alexflint/go-scalar v1.1.0 // indirect
|
||||
go.wit.com/spew v0.0.0-20240101141411-c7b8e91573c9 // indirect
|
||||
go.wit.com/dev/alexflint/scalar v1.2.1 // indirect
|
||||
go.wit.com/dev/davecgh/spew v1.1.4 // indirect
|
||||
)
|
||||
|
|
32
go.sum
32
go.sum
|
@ -1,22 +1,10 @@
|
|||
github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/uo=
|
||||
github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA=
|
||||
github.com/alexflint/go-scalar v1.1.0 h1:aaAouLLzI9TChcPXotr6gUhq+Scr8rl0P9P4PnltbhM=
|
||||
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
go.wit.com/gui/widget v0.0.0-20240105185907-84aafa536a93 h1:zCzaHvXJJ/rWXmDc/v79VvM6W2lxxzJGfnW2lHCv3Ho=
|
||||
go.wit.com/gui/widget v0.0.0-20240105185907-84aafa536a93/go.mod h1:A6/FaiFQtAHTjgo7c4FrokXe6bXX1Cowo35b2Lgi31E=
|
||||
go.wit.com/log v0.3.1 h1:UXtgJ4dwyWL0Yv4mw6gQnlmrIQU/zz6nClCB7NGKBQs=
|
||||
go.wit.com/log v0.3.1/go.mod h1:GmsggfsKrqdZdAj26fEOlcTz6qEIazbV33uyuuktvB8=
|
||||
go.wit.com/spew v0.0.0-20240101141411-c7b8e91573c9 h1:UEX2EzLQPzLTfy/kUFQD7OXtvKn8wk/+jpDOkbl4ff4=
|
||||
go.wit.com/spew v0.0.0-20240101141411-c7b8e91573c9/go.mod h1:qBpgJXThMMT15vym7/E4Ur9y8oOo2nP7t2RP52QHUNw=
|
||||
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=
|
||||
go.wit.com/dev/alexflint/arg v1.4.5 h1:asDx5f9IlfpknKjPBqqb2qndE91Pbo7ZDkWUgddfMhY=
|
||||
go.wit.com/dev/alexflint/arg v1.4.5/go.mod h1:wnWc+c6z8kSdDKYriMf6RpM+FiXmo5RYp/t4FNi0MU0=
|
||||
go.wit.com/dev/alexflint/scalar v1.2.1 h1:loXOcbVnd+8YeJRLey+XXidecBiedMDO00zQ26TvKNs=
|
||||
go.wit.com/dev/alexflint/scalar v1.2.1/go.mod h1:+rYsfxqdI2cwA8kJ7GCMwWbNJvfvWUurOCXLiwdTtSs=
|
||||
go.wit.com/dev/davecgh/spew v1.1.4 h1:C9hj/rjlUpdK+E6aroyLjCbS5MFcyNUOuP1ICLWdNek=
|
||||
go.wit.com/dev/davecgh/spew v1.1.4/go.mod h1:sihvWmnQ/09FWplnEmozt90CCVqBtGuPXM811tgfhFA=
|
||||
go.wit.com/gui/widget v1.1.3 h1:GvLzGSOF9tfmoh6HNbFdN+NSlBo2qeS/Ba2TnQQ1A1U=
|
||||
go.wit.com/gui/widget v1.1.3/go.mod h1:A6/FaiFQtAHTjgo7c4FrokXe6bXX1Cowo35b2Lgi31E=
|
||||
go.wit.com/log v0.5.4 h1:vijLRPTUgChb8J5tx/7Uma/lGTUxeSXosFbheAmL914=
|
||||
go.wit.com/log v0.5.4/go.mod h1:BaJBfHFqcJSJLXGQ9RHi3XVhPgsStxSMZRlaRxW4kAo=
|
||||
|
|
25
grid.go
25
grid.go
|
@ -23,21 +23,30 @@ import (
|
|||
// -- (1,3) -- -- (3,3) --
|
||||
// -----------------------------
|
||||
|
||||
func (n *Node) NewGrid(name string, w int, h int) *Node {
|
||||
newNode := n.newNode(name, widget.Grid)
|
||||
type Grid struct {
|
||||
Width int
|
||||
Height int
|
||||
}
|
||||
|
||||
type GridOffset struct {
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
|
||||
func (n *Node) NewGrid(progname string, w int, h int) *Node {
|
||||
newNode := n.newNode(progname, widget.Grid)
|
||||
newNode.progname = progname
|
||||
|
||||
newNode.W = w
|
||||
newNode.H = h
|
||||
newNode.NextW = 1
|
||||
newNode.NextH = 1
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
|
||||
// by default, always pad grids
|
||||
newNode.Pad()
|
||||
newNode.pad = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
|
|
13
group.go
13
group.go
|
@ -10,15 +10,10 @@ import (
|
|||
func (parent *Node) NewGroup(name string) *Node {
|
||||
var newNode *Node
|
||||
newNode = parent.newNode(name, widget.Group)
|
||||
newNode.progname = name
|
||||
newNode.value = name
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
|
||||
// by default, always pad groups
|
||||
newNode.Pad()
|
||||
|
||||
// newBox := newNode.NewBox("defaultGroupBox", false)
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
9
image.go
9
image.go
|
@ -1,6 +1,7 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"go.wit.com/log"
|
||||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
|
@ -8,9 +9,9 @@ func (parent *Node) NewImage(name string) *Node {
|
|||
var newNode *Node
|
||||
newNode = parent.newNode(name, widget.Image)
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
log.Warn("NewImage() not implemented. fix this")
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
8
label.go
8
label.go
|
@ -6,10 +6,10 @@ import (
|
|||
|
||||
func (parent *Node) NewLabel(text string) *Node {
|
||||
newNode := parent.newNode(text, widget.Label)
|
||||
newNode.value = text
|
||||
newNode.progname = text
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
75
main.go
75
main.go
|
@ -19,10 +19,11 @@ func init() {
|
|||
log.Log(NOW, "init() has been run")
|
||||
|
||||
me.counter = 0
|
||||
me.prefix = "wit"
|
||||
// me.prefix = "wit"
|
||||
|
||||
// Populates the top of the binary tree
|
||||
me.rootNode = addNode("guiBinaryTree")
|
||||
me.rootNode = addNode()
|
||||
me.rootNode.progname = "guiBinaryTree"
|
||||
me.rootNode.WidgetType = widget.Root
|
||||
me.rootNode.hidden = false // always send the rootNode to the toolkits
|
||||
|
||||
|
@ -37,30 +38,50 @@ func init() {
|
|||
go watchCallback()
|
||||
}
|
||||
|
||||
// lookup the widget by the id sent from the toolkit
|
||||
func (n *Node) findId(i int) (*Node) {
|
||||
if (n == nil) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if (n.id == i) {
|
||||
return n
|
||||
}
|
||||
|
||||
for _, child := range n.children {
|
||||
newN := child.findId(i)
|
||||
if (newN != nil) {
|
||||
return newN
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func watchCallback() {
|
||||
log.Info("watchCallback() START")
|
||||
log.Info("guiChan() START")
|
||||
for {
|
||||
log.Info("watchCallback() restarted select for toolkit user events")
|
||||
log.Info("guiChan() restarted")
|
||||
select {
|
||||
case a := <-me.guiChan:
|
||||
if (a.ActionType == widget.UserQuit) {
|
||||
log.Info("doUserEvent() User sent Quit()")
|
||||
log.Warn("guiChan() User sent Quit()")
|
||||
me.rootNode.doCustom()
|
||||
log.Exit("wit/gui toolkit.UserQuit")
|
||||
break
|
||||
}
|
||||
if (a.ActionType == widget.EnableDebug) {
|
||||
log.Warn("doUserEvent() Enable Debugging Window")
|
||||
log.Warn("doUserEvent() TODO: not implemented")
|
||||
log.Warn("guiChan() Enable Debugging Window")
|
||||
log.Warn("guiChan() TODO: not implemented")
|
||||
// DebugWindow()
|
||||
break
|
||||
}
|
||||
|
||||
n := me.rootNode.FindId(a.WidgetId)
|
||||
n := me.rootNode.findId(a.WidgetId)
|
||||
if (n == nil) {
|
||||
log.Warn("watchCallback() UNKNOWN widget id =", a.WidgetId, a.Name)
|
||||
log.Warn("guiChan() UNKNOWN widget id")
|
||||
log.Warn("id =", a.WidgetId, a.ProgName)
|
||||
} else {
|
||||
log.Info("watchCallback() FOUND widget id =", n.id, n.Name)
|
||||
log.Verbose("guiChan() FOUND widget id =", n.id, n.progname)
|
||||
n.doUserEvent(a)
|
||||
}
|
||||
// this maybe a good idea?
|
||||
|
@ -71,7 +92,7 @@ func watchCallback() {
|
|||
}
|
||||
|
||||
func (n *Node) doCustom() {
|
||||
log.Info("doUserEvent() widget =", n.id, n.Name, n.WidgetType, n.B)
|
||||
log.Info("doUserEvent() widget =", n.id, n.progname, n.WidgetType)
|
||||
if (n.Custom == nil) {
|
||||
log.Warn("Custom() = nil. SKIPPING")
|
||||
return
|
||||
|
@ -80,47 +101,49 @@ func (n *Node) doCustom() {
|
|||
}
|
||||
|
||||
func (n *Node) doUserEvent(a widget.Action) {
|
||||
log.Info("doUserEvent() node =", n.id, n.Name)
|
||||
if a.A != nil {
|
||||
log.Warn("doUserEvent() a.A != nil", n.id, n.Name, "n.value =", a.A)
|
||||
n.value = a.A
|
||||
n.doCustom()
|
||||
log.Info("doUserEvent() node =", n.id, n.progname)
|
||||
if a.Value == nil {
|
||||
log.Warn("doUserEvent() a.A == nil", n.id, n.progname)
|
||||
return
|
||||
}
|
||||
n.value = a.Value
|
||||
n.doCustom()
|
||||
return
|
||||
/*
|
||||
switch n.WidgetType {
|
||||
case widget.Checkbox:
|
||||
n.B = a.B
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.B)
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "set to:", n.value)
|
||||
n.doCustom()
|
||||
case widget.Button:
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "button clicked")
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "button clicked")
|
||||
n.doCustom()
|
||||
case widget.Combobox:
|
||||
n.S = a.S
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.S)
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "set to:", n.S)
|
||||
n.doCustom()
|
||||
case widget.Dropdown:
|
||||
n.S = a.S
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.S)
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "set to:", n.S)
|
||||
n.doCustom()
|
||||
case widget.Textbox:
|
||||
n.S = a.S
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.S)
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "set to:", n.S)
|
||||
n.doCustom()
|
||||
case widget.Spinner:
|
||||
n.I = a.I
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.I)
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "set to:", n.I)
|
||||
n.doCustom()
|
||||
case widget.Slider:
|
||||
n.I = a.I
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "set to:", n.I)
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "set to:", n.I)
|
||||
n.doCustom()
|
||||
case widget.Window:
|
||||
log.Info("doUserEvent() node =", n.id, n.Name, "window closed")
|
||||
log.Info("doUserEvent() node =", n.id, n.progname, "window closed")
|
||||
n.doCustom()
|
||||
default:
|
||||
log.Info("doUserEvent() type =", n.WidgetType)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// There should only be one of these per application
|
||||
|
@ -154,7 +177,7 @@ func (n *Node) Default() *Node {
|
|||
|
||||
// The window is destroyed but the application does not quit
|
||||
func (n *Node) StandardClose() {
|
||||
log.Log(GUI, "wit/gui Standard Window Close. name =", n.Name)
|
||||
log.Log(GUI, "wit/gui Standard Window Close. name =", n.progname)
|
||||
log.Log(GUI, "wit/gui Standard Window Close. n.Custom exit =", n.Custom)
|
||||
}
|
||||
|
||||
|
|
28
node.go
28
node.go
|
@ -7,13 +7,26 @@ import (
|
|||
|
||||
/*
|
||||
generic function to create a new node on the binary tree
|
||||
|
||||
this is called each time you want a new widget
|
||||
and it initializes basic default values
|
||||
|
||||
there isn't much to see here.
|
||||
*/
|
||||
func (n *Node) newNode(title string, t widget.WidgetType) *Node {
|
||||
var newN *Node
|
||||
|
||||
newN = addNode(title)
|
||||
newN = addNode()
|
||||
newN.progname = title
|
||||
newN.value = title
|
||||
newN.WidgetType = t
|
||||
|
||||
// set these defaults
|
||||
newN.expand = true
|
||||
newN.pad = true
|
||||
newN.enabled = true
|
||||
newN.changed = true
|
||||
|
||||
if n.WidgetType == widget.Grid {
|
||||
n.gridIncrement()
|
||||
}
|
||||
|
@ -27,12 +40,10 @@ func (n *Node) newNode(title string, t widget.WidgetType) *Node {
|
|||
}
|
||||
|
||||
/*
|
||||
raw create function for a new node struct
|
||||
raw create function for a new node struct and increments the counter
|
||||
*/
|
||||
func addNode(title string) *Node {
|
||||
func addNode() *Node {
|
||||
n := new(Node)
|
||||
n.Name = title
|
||||
n.Text = title
|
||||
n.id = me.counter
|
||||
log.Log(NODE, "addNode = widget setid =", n.id)
|
||||
|
||||
|
@ -41,17 +52,20 @@ func addNode(title string) *Node {
|
|||
}
|
||||
|
||||
func (n *Node) Parent() *Node {
|
||||
if ! n.Ready() { return n }
|
||||
return n.parent
|
||||
}
|
||||
|
||||
func (n *Node) Delete(d *Node) {
|
||||
if ! n.Ready() { return }
|
||||
|
||||
for i, child := range n.children {
|
||||
log.Log(NODE, "\t", i, child.id, child.Name)
|
||||
log.Log(NODE, "\t", i, child.id, child.progname)
|
||||
if (child.id == d.id) {
|
||||
log.Log(NODE, "\t\t Deleting this")
|
||||
n.children = append(n.children[:i], n.children[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Warn("did not find node to delete", d.id, d.Name)
|
||||
log.Warn("did not find node to delete", d.id, d.progname)
|
||||
}
|
||||
|
|
46
plugin.go
46
plugin.go
|
@ -201,7 +201,6 @@ func initToolkit(name string, filename string) *aplug {
|
|||
// add it to the list of plugins
|
||||
allPlugins = append(allPlugins, newPlug)
|
||||
|
||||
|
||||
// set the communication to the plugins
|
||||
newPlug.pluginChan = newPlug.PluginChannel()
|
||||
if (newPlug.pluginChan == nil) {
|
||||
|
@ -214,51 +213,6 @@ func initToolkit(name string, filename string) *aplug {
|
|||
return newPlug
|
||||
}
|
||||
|
||||
// 2023/05/09 pretty clean
|
||||
// 2023/04/06 Queue() is also being used and channels are being used. memcopy() only
|
||||
func newAction(n *Node, atype widget.ActionType) *widget.Action {
|
||||
var a widget.Action
|
||||
a.ActionType = atype
|
||||
if (n == nil) {
|
||||
return &a
|
||||
}
|
||||
a.Name = n.Name
|
||||
a.Text = n.Text
|
||||
a.WidgetId = n.id
|
||||
|
||||
a.B = n.B
|
||||
a.I = n.I
|
||||
a.S = n.S
|
||||
|
||||
a.X = n.X
|
||||
a.Y = n.Y
|
||||
|
||||
a.AtW = n.AtW
|
||||
a.AtH = n.AtH
|
||||
|
||||
if (n.parent != nil) {
|
||||
a.ParentId = n.parent.id
|
||||
}
|
||||
a.WidgetType = n.WidgetType
|
||||
return &a
|
||||
}
|
||||
|
||||
// sends the action/event to each toolkit via a golang plugin channel
|
||||
func sendAction(a *widget.Action) {
|
||||
for _, aplug := range allPlugins {
|
||||
log.Log(PLUG, "Action() aplug =", aplug.name, "Action type=", a.ActionType)
|
||||
if (aplug.pluginChan == nil) {
|
||||
log.Info("Action() retrieving the aplug.PluginChannel()", aplug.name)
|
||||
aplug.pluginChan = aplug.PluginChannel()
|
||||
log.Info("Action() retrieved", aplug.pluginChan)
|
||||
}
|
||||
log.Info("Action() SEND to pluginChan", aplug.name)
|
||||
aplug.pluginChan <- *a
|
||||
// added during debugging. might be a good idea in general for a tactile experience
|
||||
log.Sleep(.02) // this delay makes it so SetText() works on initial widget creation
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) InitEmbed(resFS embed.FS) *Node {
|
||||
me.resFS = resFS
|
||||
return n
|
||||
|
|
11
redraw.go
11
redraw.go
|
@ -21,12 +21,12 @@ func (n *Node) redraw(p *aplug) {
|
|||
}
|
||||
|
||||
func (n *Node) redo(plug *aplug) {
|
||||
log.Info("redo()", plug.name, n.id, n.WidgetType, n.Name)
|
||||
log.Info("redo()", plug.name, n.id, n.WidgetType, n.progname)
|
||||
|
||||
var a *widget.Action
|
||||
a = new(widget.Action)
|
||||
a.Name = n.Name
|
||||
a.Text = n.Text
|
||||
a.ProgName = n.progname
|
||||
a.Value = n.value
|
||||
|
||||
a.ActionType = widget.Add
|
||||
a.WidgetType = n.WidgetType
|
||||
|
@ -40,11 +40,6 @@ func (n *Node) redo(plug *aplug) {
|
|||
a.AtW = n.AtW
|
||||
a.AtH = n.AtH
|
||||
|
||||
// used for values
|
||||
a.I = n.I
|
||||
a.S = n.S
|
||||
a.B = n.B
|
||||
|
||||
if (n.parent == nil) {
|
||||
a.ParentId = 0
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
func (parent *Node) NewSeparator(progname string) *Node {
|
||||
newNode := parent.newNode(progname, widget.Separator)
|
||||
newNode.progname = progname
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
47
setText.go
47
setText.go
|
@ -11,38 +11,47 @@ import (
|
|||
|
||||
func (n *Node) SetText(text string) *Node {
|
||||
if ! n.Ready() { return n }
|
||||
|
||||
if n.GetText() == text {
|
||||
// nothing changed
|
||||
return n
|
||||
}
|
||||
n.value = text
|
||||
n.changed = true
|
||||
log.Log(CHANGE, "SetText() value =", text)
|
||||
|
||||
n.value = text
|
||||
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.SetText)
|
||||
a.A = n.value
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.SetText)
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Node) Set(val any) {
|
||||
log.Log(CHANGE, "Set() value =", val)
|
||||
|
||||
n.value = val
|
||||
if ! n.Ready() { return }
|
||||
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
n.B = val.(bool)
|
||||
if widget.GetBool(n.value) == val.(bool) {
|
||||
// nothing changed
|
||||
return
|
||||
}
|
||||
case string:
|
||||
n.Text = val.(string)
|
||||
n.S = val.(string)
|
||||
if widget.GetString(n.value) == val.(string) {
|
||||
// nothing changed
|
||||
return
|
||||
}
|
||||
case int:
|
||||
n.I = val.(int)
|
||||
if widget.GetInt(n.value) == val.(int) {
|
||||
// nothing changed
|
||||
return
|
||||
}
|
||||
default:
|
||||
log.Error(errors.New("Set() unknown type"), "v =", v)
|
||||
}
|
||||
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Set)
|
||||
a.A = val
|
||||
sendAction(a)
|
||||
}
|
||||
n.value = val
|
||||
n.changed = true
|
||||
log.Log(CHANGE, "Set() value =", val)
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Set)
|
||||
}
|
||||
|
|
15
slider.go
15
slider.go
|
@ -5,21 +5,18 @@ import (
|
|||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
func (parent *Node) NewSlider(name string, x int, y int) *Node {
|
||||
newNode := parent.newNode(name, widget.Slider)
|
||||
func (parent *Node) NewSlider(progname string, x int, y int) *Node {
|
||||
newNode := parent.newNode(progname, widget.Slider)
|
||||
newNode.progname = progname
|
||||
|
||||
newNode.Custom = func() {
|
||||
log.Log(GUI, "even newer clicker() name in NewSlider name =", name)
|
||||
log.Log(GUI, "even newer clicker() name in NewSlider name =", progname)
|
||||
}
|
||||
|
||||
newNode.X = x
|
||||
newNode.Y = y
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
a.X = x
|
||||
a.Y = y
|
||||
sendAction(a)
|
||||
}
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
13
spinner.go
13
spinner.go
|
@ -5,19 +5,18 @@ import (
|
|||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
func (parent *Node) NewSpinner(name string, x int, y int) *Node {
|
||||
newNode := parent.newNode(name, widget.Spinner)
|
||||
func (parent *Node) NewSpinner(progname string, x int, y int) *Node {
|
||||
newNode := parent.newNode(progname, widget.Spinner)
|
||||
newNode.progname = progname
|
||||
|
||||
newNode.Custom = func() {
|
||||
log.Info("default NewSpinner() change", name)
|
||||
log.Info("default NewSpinner() change", progname)
|
||||
}
|
||||
|
||||
newNode.X = x
|
||||
newNode.Y = y
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
94
structs.go
94
structs.go
|
@ -15,7 +15,7 @@ import (
|
|||
// Native Windows and MacOS toolkits
|
||||
//
|
||||
// If that is the case, this code abstracts the concept of
|
||||
// windows and makes each window a 'tabs' in a single window.
|
||||
// windows and makes each window a 'tab' in a single window.
|
||||
//
|
||||
// Reminder from Goals: This is for simple GUI's.
|
||||
// For example, a "Mouse Control Panel" not the GIMP or blender.
|
||||
|
@ -23,7 +23,19 @@ import (
|
|||
|
||||
var me guiConfig
|
||||
|
||||
// Range(1, 10) includes the values 1 and 10
|
||||
// almost all toolkits use integers so there doesn't
|
||||
// seem to be a good idea to use 'type any' here as it
|
||||
// just makes things more complicated for no good reason
|
||||
type RangeMovedToWidget struct {
|
||||
Low int
|
||||
High int
|
||||
}
|
||||
|
||||
// type List []string
|
||||
|
||||
type guiConfig struct {
|
||||
// a toolkit requirement. never allow more than one per program
|
||||
initOnce sync.Once
|
||||
|
||||
// This is the master node. The Binary Tree starts here
|
||||
|
@ -41,28 +53,68 @@ type guiConfig struct {
|
|||
resFS embed.FS
|
||||
|
||||
// used to beautify logging to Stdout
|
||||
depth int
|
||||
prefix string
|
||||
// depth int
|
||||
// prefix string
|
||||
}
|
||||
|
||||
// The Node is a binary tree. This is how all GUI elements are stored
|
||||
// simply the name and the size of whatever GUI element exists
|
||||
/*
|
||||
The Node is a binary tree. This is how all GUI elements are stored
|
||||
simply the name and the size of whatever GUI element exists
|
||||
|
||||
value : most widgets need 1 value. this is it.
|
||||
For a window -- the title. For a button -- the name
|
||||
|
||||
hidden : this means the widget is not displayed yet. In that
|
||||
case, don't waste time trying to pass information to
|
||||
the toolkits. This makes things efficient and fast if
|
||||
the GUI does not have to display anything
|
||||
|
||||
Custom() : if the user does something like click on a button,
|
||||
this function will be called. (this should probably
|
||||
be renamed Callback()
|
||||
|
||||
progname : a short name to reference the widgets in the debugger
|
||||
n.NewButton("click here to send it").SetProgName("SENT")
|
||||
|
||||
parent, children : the binary tree
|
||||
|
||||
pad, margin, expand : re-think these names and clarify
|
||||
|
||||
*/
|
||||
|
||||
type Node struct {
|
||||
id int // should be unique
|
||||
hidden bool // Sierpinski Carpet mode. It's there, but you can't see it.
|
||||
hidden bool // don't update the toolkits when it's hidden
|
||||
changed bool // do we need to inform the toolkit something changed?
|
||||
enabled bool // if false, then the the user can't click on it
|
||||
|
||||
WidgetType widget.WidgetType
|
||||
|
||||
// most widgets need one value, this is current alue
|
||||
value any
|
||||
|
||||
// this can programatically identify the widget
|
||||
// The name must be unique
|
||||
progname string // a name useful for debugging
|
||||
|
||||
// for widgets that a user select from a list of strings
|
||||
strings []string
|
||||
|
||||
// how to arrange widgets
|
||||
direction widget.Orientation
|
||||
|
||||
// this function is run when there are mouse or keyboard events
|
||||
Custom func()
|
||||
|
||||
parent *Node
|
||||
children []*Node
|
||||
|
||||
|
||||
// RETHINK EVERYTHING BELOW HERE
|
||||
pad bool // the toolkit may use this. it's up to the toolkit
|
||||
margin bool // the toolkit may use this. it's up to the toolkit
|
||||
expand bool // the toolkit may use this. it's up to the toolkit
|
||||
|
||||
WidgetType widget.WidgetType
|
||||
|
||||
// for NewLabel("hello"), Text = 'hello'
|
||||
Text string // what is visable to the user
|
||||
|
||||
// for NewLabel("hello"), if Name = 'HELLO'
|
||||
// this can programatically identify the widget
|
||||
// The name must be unique
|
||||
Name string // a name useful for debugging
|
||||
|
||||
// used for Windows in toolkits measured in pixels
|
||||
width int
|
||||
|
@ -85,16 +137,4 @@ type Node struct {
|
|||
// if this widget is in a grid, this is the position of a widget
|
||||
AtW int
|
||||
AtH int
|
||||
|
||||
// the current widget value.
|
||||
I int
|
||||
S string
|
||||
B bool
|
||||
value any
|
||||
|
||||
// this function is run when there are mouse or keyboard events
|
||||
Custom func()
|
||||
|
||||
parent *Node
|
||||
children []*Node
|
||||
}
|
||||
|
|
16
textbox.go
16
textbox.go
|
@ -8,20 +8,22 @@ import (
|
|||
|
||||
func (parent *Node) NewTextbox(name string) *Node {
|
||||
newNode := parent.newNode(name, widget.Textbox)
|
||||
newNode.value = name
|
||||
newNode.progname = name
|
||||
|
||||
newNode.Custom = func() {
|
||||
log.Log(GUI, "NewTextbox changed =", name)
|
||||
}
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
func (parent *Node) NewEntryLine(name string) *Node {
|
||||
newNode := parent.newNode(name, widget.Textbox)
|
||||
newNode.value = name
|
||||
newNode.progname = name
|
||||
|
||||
newNode.X = 1
|
||||
|
||||
|
@ -29,9 +31,7 @@ func (parent *Node) NewEntryLine(name string) *Node {
|
|||
log.Log(GUI, "NewTextbox changed =", name)
|
||||
}
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
45
window.go
45
window.go
|
@ -15,11 +15,11 @@ func (parent *Node) NewWindow(title string) *Node {
|
|||
newNode.Custom = StandardExit
|
||||
|
||||
log.Info("NewWindow()", title)
|
||||
newNode.progname = title
|
||||
newNode.value = title
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
|
@ -38,26 +38,51 @@ func (parent *Node) RawWindow(title string) *Node {
|
|||
|
||||
// TODO: should do this recursively
|
||||
func (n *Node) UnDraw() *Node {
|
||||
if ! n.hidden {
|
||||
n.Hide()
|
||||
}
|
||||
if ! n.Ready() { return n }
|
||||
|
||||
n.hidden = true
|
||||
n.changed = true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Delete)
|
||||
return n
|
||||
}
|
||||
|
||||
// TODO: should do this recursively
|
||||
func (n *Node) Draw() *Node {
|
||||
n.hidden = false
|
||||
if ! n.Ready() { return n }
|
||||
|
||||
a := newAction(n, widget.Add)
|
||||
sendAction(a)
|
||||
n.hidden = false
|
||||
n.changed= true
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.Add)
|
||||
return n
|
||||
}
|
||||
|
||||
// if the toolkit supports a gui with pixels, it might honor this. no promises
|
||||
// consider this a 'recommendation' or developer 'preference' to the toolkit
|
||||
/*
|
||||
func (n *Node) PixelSize(w, h int) *Node {
|
||||
n.width = w
|
||||
n.height = w
|
||||
return n
|
||||
}
|
||||
*/
|
||||
|
||||
func (n *Node) TestDraw() {
|
||||
if (n == nil) {
|
||||
return
|
||||
}
|
||||
|
||||
// enable and
|
||||
n.hidden = false
|
||||
n.changed = true
|
||||
log.Warn("TestDraw() sending widget.Add", n.id, n.WidgetType, n.progname)
|
||||
sendAction(n, widget.Add)
|
||||
|
||||
for _, child := range n.children {
|
||||
child.TestDraw()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue