summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2024-01-18 00:05:54 -0600
committerJeff Carr <[email protected]>2024-01-18 00:05:54 -0600
commit3ea3dd10db0e728240fc659bdd33c622d33e46b4 (patch)
tree5bf7a6058db46c08e8e074380f05cadf02f9aef5
initial commitv0.0.1
Signed-off-by: Jeff Carr <[email protected]>
-rw-r--r--Makefile4
-rw-r--r--addNode.go47
-rw-r--r--common.go35
-rw-r--r--debug.go44
-rw-r--r--event.go88
-rw-r--r--go.mod10
-rw-r--r--go.sum6
-rw-r--r--init.go58
-rw-r--r--json.go60
-rw-r--r--plugin.go50
-rw-r--r--structs.go51
11 files changed, 453 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..186078d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+redomod:
+ rm -f go.*
+ GO111MODULE= go mod init
+ GO111MODULE= go mod tidy
diff --git a/addNode.go b/addNode.go
new file mode 100644
index 0000000..36c5a06
--- /dev/null
+++ b/addNode.go
@@ -0,0 +1,47 @@
+package tree
+
+import (
+ "errors"
+
+ "go.wit.com/log"
+ "go.wit.com/lib/widget"
+)
+
+// this is in common.go, do not move it
+func (me *TreeInfo) AddNode(a *widget.Action) *Node {
+ n := new(Node)
+ n.WidgetType = a.WidgetType
+ n.WidgetId = a.WidgetId
+ n.ParentId = a.ParentId
+
+ n.State = a.State
+ n.Strings = make(map[string]int)
+
+ if (a.WidgetType == widget.Root) {
+ log.Info("AddNode() Root")
+ n.Parent = n
+ me.treeRoot = n
+ return n
+ }
+
+ if (me.treeRoot.FindWidgetId(a.WidgetId) != nil) {
+ log.Warn("AddNode() WidgetId already exists", a.WidgetId)
+ log.Warn("probably this is a Show() / Hide() issue")
+ log.Warn("TODO: figure out what to do here")
+ return me.treeRoot.FindWidgetId(a.WidgetId)
+ }
+
+ // add this new widget on the binary tree
+ p := me.treeRoot.FindWidgetId(a.ParentId)
+ n.Parent = p
+ if n.Parent == nil {
+ log.Error(errors.New("tree.AddNode() ERROR n.Parent == nil"), a.WidgetId, a.ParentId, a.ActionType)
+ log.Warn("AddNode() ERROR n.Parent == nil", a.WidgetId, a.ParentId, a.ActionType)
+ log.Warn("AddNode() ERROR n.Parent == nil", a.WidgetId, a.ParentId, a.WidgetType)
+ return n
+ }
+ log.Warn("AddNode() Adding to parent =", p.ParentId, p.WidgetType, p.GetProgName())
+ log.Warn("AddNode() Adding child =", n.ParentId, n.WidgetType, n.GetProgName())
+ p.children = append(p.children, n)
+ return n
+}
diff --git a/common.go b/common.go
new file mode 100644
index 0000000..2ae4f9e
--- /dev/null
+++ b/common.go
@@ -0,0 +1,35 @@
+package tree
+
+import (
+ "go.wit.com/lib/widget"
+)
+
+func (n *Node) GetProgName() string {
+ return n.State.ProgName
+}
+
+func (n *Node) GetValue() any {
+ return n.State.Value
+}
+
+func (n *Node) Bool() bool {
+ return widget.GetBool(n.State.Value)
+}
+
+func (n *Node) String() string {
+ return widget.GetString(n.State.Value)
+}
+
+/* avoid this function name as confusing
+func (n *Node) GetText() string {
+ return widget.GetString(n.State.Value)
+}
+*/
+
+func (n *Node) SetValue(a any) {
+ n.State.Value = a
+}
+
+func (n *Node) GetLabel() string {
+ return n.State.Label
+}
diff --git a/debug.go b/debug.go
new file mode 100644
index 0000000..64883ee
--- /dev/null
+++ b/debug.go
@@ -0,0 +1,44 @@
+package tree
+
+import (
+ "go.wit.com/log"
+ "go.wit.com/lib/widget"
+)
+
+func (n *Node) ShowButtons() {
+ if n.WidgetType == widget.Button {
+ n.DumpWidget("Button:")
+ }
+
+ for _, child := range n.children {
+ child.ShowButtons()
+ }
+}
+
+func (n *Node) DumpWidget(pad string) {
+ log.Warn("node:", pad, n.WidgetId, ",", n.WidgetType, ",", n.GetProgName())
+}
+
+var depth int = 0
+
+func (n *Node) ListWidgets() {
+ if (n == nil) {
+ log.Warn("ERRRORRRR: n == nil in ListWidgets()")
+ log.Warn("ERRRORRRR: n == nil in ListWidgets()")
+ log.Warn("ERRRORRRR: n == nil in ListWidgets()")
+ return
+ }
+
+ var pad string
+ for i := 0; i < depth; i++ {
+ pad = pad + " "
+ }
+ n.DumpWidget(pad)
+
+ for _, child := range n.children {
+ depth += 1
+ child.ListWidgets()
+ depth -= 1
+ }
+ return
+}
diff --git a/event.go b/event.go
new file mode 100644
index 0000000..845b47b
--- /dev/null
+++ b/event.go
@@ -0,0 +1,88 @@
+package tree
+
+/*
+ These code should be common to all gui plugins
+
+ There are some helper functions that are probably going to be
+ the same everywhere. Mostly due to handling the binary tree structure
+ and the channel communication
+
+ For now, it's just a symlink to the 'master' version in
+ ./toolkit/nocui/common.go
+*/
+
+import (
+ "go.wit.com/log"
+ "go.wit.com/lib/widget"
+)
+
+func (me *TreeInfo) DoEnableDebugger() {
+ if (me.callback == nil) {
+ log.Warn("DoUserEvent() toolkit panic() callback == nil")
+ return
+ }
+ var a widget.Action
+ a.ActionType = widget.EnableDebug
+ a.ProgName = me.PluginName
+ me.callback <- a
+ return
+}
+
+func (me *TreeInfo) DoToolkitLoad(s string) {
+ if (me.callback == nil) {
+ log.Warn("DoUserEvent() toolkit load callback == nil")
+ return
+ }
+ var a widget.Action
+ a.ActionType = widget.ToolkitLoad
+ a.ProgName = me.PluginName
+ a.Value = s
+ log.Warn("DoUserEvent() START: toolkit load", s)
+ me.callback <- a
+ log.Warn("DoUserEvent() END: toolkit load", s)
+ return
+}
+
+func (me *TreeInfo) DoToolkitPanic() {
+ if (me.callback == nil) {
+ log.Warn("DoUserEvent() toolkit panic() callback == nil")
+ return
+ }
+ var a widget.Action
+ a.ActionType = widget.ToolkitPanic
+ a.ProgName = me.PluginName
+ log.Info("DoUserEvent() START: toolkit panic()")
+ me.callback <- a
+ log.Info("DoUserEvent() END: toolkit panic()")
+ return
+}
+
+func (me *TreeInfo) DoWindowCloseEvent(n *Node) {
+ if (me.callback == nil) {
+ log.Warn("DoUserEvent() callback == nil", n.WidgetId)
+ return
+ }
+ var a widget.Action
+ a.WidgetId = n.WidgetId
+ a.ActionType = widget.CloseWindow
+ log.Info("DoUserEvent() START: user closed the window", n.GetProgName())
+ me.callback <- a
+ log.Info("DoUserEvent() END: user closed the window", n.GetProgName())
+ return
+}
+
+// Other goroutines must use this to access the GUI
+func (me *TreeInfo) DoUserEvent(n *Node) {
+ if (me.callback == nil) {
+ log.Warn("DoUserEvent() callback == nil", n.WidgetId)
+ return
+ }
+ var a widget.Action
+ a.WidgetId = n.WidgetId
+ a.Value = n.State.Value
+ a.ActionType = widget.User
+ log.Info("DoUserEvent() START: send a user event to the callback channel")
+ me.callback <- a
+ log.Info("DoUserEvent() END: sent a user event to the callback channel")
+ return
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..6f2cb79
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,10 @@
+module go.wit.com/toolkits/tree
+
+go 1.21.4
+
+require (
+ go.wit.com/gui/widget v1.1.4
+ go.wit.com/log v0.5.5
+)
+
+require go.wit.com/dev/davecgh/spew v1.1.4 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..4704880
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,6 @@
+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.4 h1:dCztWNSuTSSP+/M8h8F3cT7vWtoKdCL3DUQql0qLKdk=
+go.wit.com/gui/widget v1.1.4/go.mod h1:A6/FaiFQtAHTjgo7c4FrokXe6bXX1Cowo35b2Lgi31E=
+go.wit.com/log v0.5.5 h1:bK3b94uVKgev4jB5wg06FnvCFBEapQICTSH2YW+CWr4=
+go.wit.com/log v0.5.5/go.mod h1:BaJBfHFqcJSJLXGQ9RHi3XVhPgsStxSMZRlaRxW4kAo=
diff --git a/init.go b/init.go
new file mode 100644
index 0000000..55e434d
--- /dev/null
+++ b/init.go
@@ -0,0 +1,58 @@
+package tree
+
+import (
+ "sync"
+ "errors"
+
+ "go.wit.com/log"
+ "go.wit.com/lib/widget"
+)
+
+var muAction sync.Mutex
+
+func (me *TreeInfo) toolkit(a widget.Action) {
+ if me.ActionFromChannel == nil {
+ log.Error(errors.New("toolkit ActionFromChannel == nil"), a.WidgetId, a.ActionType, a.WidgetType)
+ return
+ }
+ me.ActionFromChannel(a)
+}
+
+func (me *TreeInfo) catchActionChannel() {
+ defer func() {
+ if r := recover(); r != nil {
+ log.Warn("nocui YAHOOOO Recovered in simpleStdin()", r)
+ me.DoToolkitPanic()
+ panic(-1)
+ }
+ }()
+ log.Info("catchActionChannel() START")
+ for {
+ log.Info("catchActionChannel() for loop")
+ select {
+ case a := <-me.pluginChan:
+ log.Info("catchActionChannel() SELECT widget id =", a.WidgetId, a.ProgName)
+ log.Warn("catchActionChannel() STUFF", a.WidgetId, a.ActionType, a.WidgetType)
+ if a.WidgetType == widget.Dropdown {
+ log.Warn("Found dropdown", a.WidgetId, a.ActionType, a.WidgetType)
+ for i, s := range a.State.Strings {
+ log.Warn("a.State.Strings =", i, s)
+ }
+ }
+ muAction.Lock()
+ me.toolkit(a)
+ muAction.Unlock()
+ log.Info("catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
+ }
+ }
+}
+
+func New() *TreeInfo {
+ me := new(TreeInfo)
+ me.pluginChan = make(chan widget.Action, 1)
+
+ log.Info("Init() start channel reciever")
+ go me.catchActionChannel()
+ log.Info("Init() END")
+ return me
+}
diff --git a/json.go b/json.go
new file mode 100644
index 0000000..68fe398
--- /dev/null
+++ b/json.go
@@ -0,0 +1,60 @@
+package tree
+
+import (
+ "fmt"
+
+ "go.wit.com/log"
+ "go.wit.com/lib/widget"
+)
+
+// makes a JSON version to pass to the toolkits ?
+// probably this should be in gui/toolkits/tree
+/*
+{"widget": {
+ "debug": "on",
+ "window": {
+ "title": "Sample Konfabulator Widget",
+ "name": "main_window",
+ "width": 500,
+ "height": 500
+ },
+ "image": {
+ "src": "Images/Sun.png",
+ "name": "sun1",
+ "hOffset": 250,
+ "vOffset": 250,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Here",
+ "size": 36,
+ "style": "bold",
+ "name": "text1",
+ "hOffset": 250,
+ "vOffset": 100,
+ "alignment": "center",
+ "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
+ }
+}}
+*/
+
+func (n *Node) Json() []string {
+ var all []string
+ switch n.WidgetType {
+ case widget.Checkbox:
+ case widget.Button:
+ case widget.Combobox:
+ case widget.Dropdown:
+ case widget.Textbox:
+ case widget.Spinner:
+ case widget.Slider:
+ case widget.Window:
+ tmp := fmt.Sprint("{ WidgetType :", n.WidgetType, "}")
+ all = append(all, tmp)
+ log.Warn(tmp)
+ return all
+ default:
+ log.Info("doUserEvent() type =", n.WidgetType)
+ }
+ return all
+}
diff --git a/plugin.go b/plugin.go
new file mode 100644
index 0000000..e8c61da
--- /dev/null
+++ b/plugin.go
@@ -0,0 +1,50 @@
+package tree
+
+/*
+ These code should be common to all gui plugins
+
+ There are some helper functions that are probably going to be
+ the same everywhere. Mostly due to handling the binary tree structure
+ and the channel communication
+
+ For now, it's just a symlink to the 'master' version in
+ ./toolkit/nocui/common.go
+*/
+
+import (
+ "go.wit.com/lib/widget"
+)
+
+// searches the binary tree for a WidgetId
+func (n *Node) FindWidgetId(id int) *Node {
+ if (n == nil) {
+ return nil
+ }
+
+ if n.WidgetId == id {
+ return n
+ }
+
+ for _, child := range n.children {
+ newN := child.FindWidgetId(id)
+ if (newN != nil) {
+ return newN
+ }
+ }
+ return nil
+}
+
+// Other goroutines must use this to access the GUI
+//
+// You can not acess / process the GUI thread directly from
+// other goroutines. This is due to the nature of how
+// Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
+//
+// this sets the channel to send user events back from the plugin
+func (me *TreeInfo) Callback(guiCallback chan widget.Action) {
+ me.callback = guiCallback
+}
+
+func (me *TreeInfo) PluginChannel() chan widget.Action {
+ return me.pluginChan
+}
diff --git a/structs.go b/structs.go
new file mode 100644
index 0000000..e4d7418
--- /dev/null
+++ b/structs.go
@@ -0,0 +1,51 @@
+package tree
+
+/*
+ These code should be common to all gui plugins
+
+ There are some helper functions that are probably going to be
+ the same everywhere. Mostly due to handling the binary tree structure
+ and the channel communication
+
+ For now, it's just a symlink to the 'master' version in
+ ./toolkit/nocui/common.go
+*/
+
+import (
+ // "go.wit.com/log"
+ "go.wit.com/lib/widget"
+)
+
+// var me *TreeInfo
+
+type TreeInfo struct {
+ // this is the channel we send user events like
+ // mouse clicks or keyboard events back to the program
+ callback chan widget.Action
+
+ // this is the channel we get requests to make widgets
+ pluginChan chan widget.Action
+
+ treeRoot *Node
+ NodeI interface {}
+ ActionFromChannel func (widget.Action) ()
+ PluginName string
+}
+
+type Node struct {
+ Parent *Node
+ children []*Node
+
+ WidgetId int // widget ID
+ WidgetType widget.WidgetType
+ ParentId int // parent ID
+
+ State widget.State
+
+ Strings map[string]int
+
+ // the internal plugin toolkit structure
+ // in the gtk plugin, it has gtk things like margin & border settings
+ // in the text console one, it has text console things like colors for menus & buttons
+ TK any
+}