Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
|
391ed60415 | |
|
7af0ecf8f1 | |
|
844668dabd | |
|
ebeeed84b4 | |
|
732edc3faf | |
|
1e2fa2dce9 | |
|
25ed10c0ec |
14
Makefile
14
Makefile
|
@ -28,20 +28,6 @@ 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
|
||||
|
|
48
box.go
48
box.go
|
@ -4,39 +4,39 @@ import (
|
|||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
func (parent *Node) NewBox(name string, b bool) *Node {
|
||||
newNode := parent.newNode(name, widget.Box)
|
||||
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)
|
||||
if b {
|
||||
a.Direction = widget.Horizontal
|
||||
} else {
|
||||
a.Direction = widget.Vertical
|
||||
}
|
||||
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(name string) *Node {
|
||||
newNode := parent.newNode(name, widget.Box)
|
||||
func (parent *Node) NewHorizontalBox(progname string) *Node {
|
||||
newNode := parent.newNode(progname, widget.Box)
|
||||
newNode.progname = progname
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
a.Direction = widget.Horizontal
|
||||
sendAction(a)
|
||||
}
|
||||
newNode.direction = widget.Horizontal
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
||||
func (parent *Node) NewVerticalBox(name string) *Node {
|
||||
newNode := parent.newNode(name, widget.Box)
|
||||
func (parent *Node) NewVerticalBox(progname string) *Node {
|
||||
newNode := parent.newNode(progname, widget.Box)
|
||||
newNode.progname = progname
|
||||
|
||||
if ! newNode.hidden {
|
||||
a := newAction(newNode, widget.Add)
|
||||
a.Direction = widget.Vertical
|
||||
sendAction(a)
|
||||
}
|
||||
newNode.direction = widget.Vertical
|
||||
|
||||
// inform the toolkits
|
||||
sendAction(newNode, widget.Add)
|
||||
return newNode
|
||||
}
|
||||
|
|
25
button.go
25
button.go
|
@ -8,28 +8,7 @@ func (parent *Node) NewButton(name string, custom func()) *Node {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -11,9 +11,7 @@ func (n *Node) NewCheckbox(name string) *Node {
|
|||
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
|
||||
}
|
||||
|
|
382
common.go
382
common.go
|
@ -11,79 +11,121 @@ 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.value = 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.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) {
|
||||
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
|
||||
|
||||
// get a string from the widget
|
||||
func (n *Node) GetText() string {
|
||||
|
@ -104,14 +146,179 @@ func (n *Node) GetBool() bool {
|
|||
}
|
||||
|
||||
// should get the reference name used for programming and debugging
|
||||
// myButton = myGroup.NewButton("hit ball", nil).SetName("HIT")
|
||||
// myButton.GetName() should return "HIT"
|
||||
// n = Find("HIT") should return myButton
|
||||
func (n *Node) GetName() string {
|
||||
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
|
||||
|
@ -145,100 +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) ProgName() string {
|
||||
if ! n.Ready() { return "" }
|
||||
return n.progname
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
*/
|
||||
|
|
6
debug.go
6
debug.go
|
@ -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{}) {
|
||||
|
|
33
dropdown.go
33
dropdown.go
|
@ -6,41 +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)
|
||||
newNode.progname = name
|
||||
newNode.value = name
|
||||
|
||||
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)
|
||||
newNode.progname = name
|
||||
newNode.value = name
|
||||
|
||||
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=
|
||||
|
|
15
grid.go
15
grid.go
|
@ -33,21 +33,20 @@ type GridOffset struct {
|
|||
Y int
|
||||
}
|
||||
|
||||
func (n *Node) NewGrid(name string, w int, h int) *Node {
|
||||
newNode := n.newNode(name, widget.Grid)
|
||||
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
|
||||
}
|
||||
|
||||
|
|
11
group.go
11
group.go
|
@ -13,14 +13,7 @@ func (parent *Node) NewGroup(name string) *Node {
|
|||
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
|
||||
}
|
||||
|
|
6
label.go
6
label.go
|
@ -9,9 +9,7 @@ func (parent *Node) NewLabel(text string) *Node {
|
|||
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
|
||||
}
|
||||
|
|
41
main.go
41
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.ProgName)
|
||||
log.Warn("guiChan() UNKNOWN widget id")
|
||||
log.Warn("id =", a.WidgetId, a.ProgName)
|
||||
} else {
|
||||
log.Info("watchCallback() FOUND widget id =", n.id, n.progname)
|
||||
log.Verbose("guiChan() FOUND widget id =", n.id, n.progname)
|
||||
n.doUserEvent(a)
|
||||
}
|
||||
// this maybe a good idea?
|
||||
|
|
23
node.go
23
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,11 +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.label = title
|
||||
n.id = me.counter
|
||||
log.Log(NODE, "addNode = widget setid =", n.id)
|
||||
|
||||
|
@ -40,10 +52,13 @@ 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.progname)
|
||||
if (child.id == d.id) {
|
||||
|
|
43
plugin.go
43
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,48 +213,6 @@ func initToolkit(name string, filename string) *aplug {
|
|||
return newPlug
|
||||
}
|
||||
|
||||
// 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 newAction(n *Node, atype widget.ActionType) *widget.Action {
|
||||
var a widget.Action
|
||||
a.ActionType = atype
|
||||
if (n == nil) {
|
||||
return &a
|
||||
}
|
||||
a.WidgetId = n.id
|
||||
a.ProgName = n.progname
|
||||
a.Value = n.value
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
}
|
69
setText.go
69
setText.go
|
@ -3,64 +3,55 @@ package gui
|
|||
// Common actions for widgets like 'Enable' or 'Hide'
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"go.wit.com/log"
|
||||
"go.wit.com/gui/widget"
|
||||
)
|
||||
|
||||
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.Value = n.value
|
||||
sendAction(a)
|
||||
}
|
||||
// inform the toolkits
|
||||
sendAction(n, widget.SetText)
|
||||
return n
|
||||
}
|
||||
|
||||
/*
|
||||
func convertString(val any) string {
|
||||
func (n *Node) Set(val any) {
|
||||
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.label = 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)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
func (n *Node) Set(val any) {
|
||||
n.value = val
|
||||
n.changed = true
|
||||
log.Log(CHANGE, "Set() value =", val)
|
||||
|
||||
n.value = val
|
||||
/*
|
||||
n.value = val
|
||||
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
n.B = val.(bool)
|
||||
case string:
|
||||
n.label = val.(string)
|
||||
n.S = val.(string)
|
||||
case int:
|
||||
n.I = val.(int)
|
||||
default:
|
||||
log.Error(errors.New("Set() unknown type"), "v =", v)
|
||||
}
|
||||
*/
|
||||
|
||||
if ! n.hidden {
|
||||
a := newAction(n, widget.Set)
|
||||
a.Value = n.value
|
||||
sendAction(a)
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
|
71
structs.go
71
structs.go
|
@ -27,14 +27,15 @@ var me guiConfig
|
|||
// 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 Range struct {
|
||||
type RangeMovedToWidget struct {
|
||||
Low int
|
||||
High int
|
||||
}
|
||||
|
||||
type List []string
|
||||
// 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
|
||||
|
@ -52,28 +53,69 @@ 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.
|
||||
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
|
||||
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
|
||||
|
||||
// the current widget value.
|
||||
// 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
|
||||
|
||||
|
||||
// used for Windows in toolkits measured in pixels
|
||||
width int
|
||||
height int
|
||||
|
@ -95,11 +137,4 @@ type Node struct {
|
|||
// if this widget is in a grid, this is the position of a widget
|
||||
AtW int
|
||||
AtH int
|
||||
|
||||
|
||||
// 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
|
||||
}
|
||||
|
|
43
window.go
43
window.go
|
@ -18,10 +18,8 @@ func (parent *Node) NewWindow(title string) *Node {
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -40,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