commit
3ea3dd10db
|
@ -0,0 +1,4 @@
|
||||||
|
redomod:
|
||||||
|
rm -f go.*
|
||||||
|
GO111MODULE= go mod init
|
||||||
|
GO111MODULE= go mod tidy
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
@ -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=
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue