summaryrefslogtreecommitdiff
path: root/nocui
diff options
context:
space:
mode:
Diffstat (limited to 'nocui')
-rw-r--r--nocui/action.go159
-rw-r--r--nocui/common.go218
-rw-r--r--nocui/event.go19
-rw-r--r--nocui/go.mod7
-rw-r--r--nocui/go.sum10
-rw-r--r--nocui/main.go55
-rw-r--r--nocui/stdin.go79
-rw-r--r--nocui/structs.go9
-rw-r--r--nocui/tree.go24
-rw-r--r--nocui/widget.go30
10 files changed, 137 insertions, 473 deletions
diff --git a/nocui/action.go b/nocui/action.go
index 892bd54..cf258c1 100644
--- a/nocui/action.go
+++ b/nocui/action.go
@@ -1,152 +1,87 @@
package main
+/*
+ a simple function to handle widget actions
+
+ You can tie this into your toolkit here.
+*/
+
import (
"go.wit.com/log"
"go.wit.com/gui/widget"
+ // "go.wit.com/gui/toolkits/tree"
)
-func (n *node) show(b bool) {
-}
-
-func (n *node) enable(b bool) {
-}
-
-func (n *node) pad(at widget.ActionType) {
- switch n.WidgetType {
- case widget.Group:
- switch at {
- case widget.Margin:
- // SetMargined(true)
- case widget.Unmargin:
- // SetMargined(false)
- case widget.Pad:
- // SetMargined(true)
- case widget.Unpad:
- // SetMargined(false)
- }
- case widget.Tab:
- case widget.Window:
- case widget.Grid:
- case widget.Box:
- case widget.Textbox:
- log.Log(ERROR, "TODO: implement ActionType =", at)
- default:
- log.Log(ERROR, "TODO: implement pad() for", at)
- }
-}
-
-func (n *node) move(newParent *node) {
- p := n.parent
-
- switch p.WidgetType {
- case widget.Group:
- case widget.Tab:
- // tabSetMargined(tParent.uiTab, true)
- case widget.Window:
- // t.uiWindow.SetBorderless(false)
- case widget.Grid:
- // t.uiGrid.SetPadded(true)
- case widget.Box:
- log.Log(INFO, "TODO: move() where =", p.ParentId)
- log.Log(INFO, "TODO: move() for widget =", n.WidgetId)
- default:
- log.Log(ERROR, "TODO: need to implement move() for type =", n.WidgetType)
- log.Log(ERROR, "TODO: need to implement move() for where =", p.ParentId)
- log.Log(ERROR, "TODO: need to implement move() for widget =", n.WidgetId)
- }
-}
-
-func (n *node) Delete() {
- p := n.parent
- log.Log(NOW, "uiDelete()", n.WidgetId, "to", p.WidgetId)
-
- switch p.WidgetType {
- case widget.Group:
- // tParent.uiGroup.SetMargined(true)
- case widget.Tab:
- // tabSetMargined(tParent.uiTab, true)
- case widget.Window:
- // t.uiWindow.SetBorderless(false)
- case widget.Grid:
- // t.uiGrid.SetPadded(true)
- case widget.Box:
- log.Log(NOW, "tWidget.boxC =", p.progname)
- log.Log(NOW, "is there a tParent parent? =", p.parent)
- // this didn't work:
- // tWidget.uiControl.Disable()
- // sleep(.8)
- // tParent.uiBox.Append(tWidget.uiControl, stretchy)
- default:
- log.Log(ERROR, "TODO: need to implement uiDelete() for widget =", n.WidgetId, n.WidgetType)
- log.Log(ERROR, "TODO: need to implement uiDelete() for parent =", p.WidgetId, p.WidgetType)
- }
-}
-
-func doAction(a *widget.Action) {
+func doAction(a widget.Action) {
log.Log(INFO, "doAction() START a.ActionType =", a.ActionType)
log.Log(INFO, "doAction() START a.ProgName =", a.ProgName)
- if (a.ActionType == widget.InitToolkit) {
- // TODO: make sure to only do this once
- // go uiMain.Do(func() {
- // ui.Main(demoUI)
- // go catchActionChannel()
- // })
- // try doing this on toolkit load in init()
+ if (a.ActionType == widget.ToolkitInit) {
return
}
log.Log(INFO, "doAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId)
switch a.WidgetType {
case widget.Root:
- me.rootNode = addNode(a)
- log.Log(INFO, "doAction() found rootNode")
+ me.treeRoot = me.myTree.AddNode(&a)
+ log.Log(INFO, "doAction() found treeRoot")
return
- case widget.Flag:
- // flag(&a)
+ }
+
+ switch a.ActionType {
+ case widget.Add:
+ me.myTree.AddNode(&a)
return
}
- n := me.rootNode.findWidgetId(a.WidgetId)
+ n := me.treeRoot.FindWidgetId(a.WidgetId)
+ if n == nil {
+ log.Warn("FindId() n == nil", a.WidgetId, a.ActionType)
+ log.Warn("FindId() n == nil", a.WidgetId, a.ActionType)
+ log.Warn("FindId() n == nil", a.WidgetId, a.ActionType)
+ log.Warn("Aaaaa!, return")
+ return
+ }
switch a.ActionType {
- case widget.Add:
- addNode(a)
case widget.Show:
- n.show(true)
+ n.State.Visable = true
case widget.Hide:
- n.show(false)
+ n.State.Visable = false
case widget.Enable:
- n.enable(true)
+ n.State.Visable = true
case widget.Disable:
- n.enable(false)
+ n.State.Visable = false
case widget.Get:
- // n.setText(a.S)
+ log.Warn("value =", n.State.Value)
case widget.GetText:
- switch a.WidgetType {
- case widget.Textbox:
- a.Value = n.value
- }
+ log.Warn("value =", n.String())
case widget.Set:
- // n.setText(a.S)
+ n.State.Value = a.State.Value
case widget.SetText:
- // n.setText(a.S)
+ log.Warn("GOT TO SetText()", a.WidgetId)
+ log.Warn("GOT TO SetText()", a.WidgetId)
+ log.Warn("GOT TO SetText()", a.WidgetId)
+ log.Warn("GOT TO SetText()", a.WidgetId)
+ if n == nil {
+ log.Warn("HOT DIGGITY. n == nil")
+ }
+ n.State.Value = a.State.Value
case widget.AddText:
- // n.setText(a.S)
+ n.State.Strings = append(a.State.Strings, widget.GetString(a.State.Value))
case widget.Margin:
- n.pad(widget.Unmargin)
+ n.State.Pad = true
case widget.Unmargin:
- n.pad(widget.Margin)
+ n.State.Pad = false
case widget.Pad:
- n.pad(widget.Pad)
+ n.State.Pad = true
case widget.Unpad:
- n.pad(widget.Unpad)
+ n.State.Pad = false
case widget.Delete:
- n.Delete()
+ log.Warn("doAction() TODO: Delete()")
+ // n.Delete()
case widget.Move:
- log.Log(INFO, "doAction() attempt to move() =", a.ActionType, a.WidgetType)
- newParent := me.rootNode.findWidgetId(a.ParentId)
- n.move(newParent)
+ log.Warn("doAction() TODO: Move()")
default:
log.Log(ERROR, "doAction() Unknown =", a.ActionType, a.WidgetType)
}
diff --git a/nocui/common.go b/nocui/common.go
deleted file mode 100644
index 7b79ca0..0000000
--- a/nocui/common.go
+++ /dev/null
@@ -1,218 +0,0 @@
-package main
-
-/*
- 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/gui/widget"
-)
-
-// this is the channel we send user events like
-// mouse clicks or keyboard events back to the program
-var callback chan widget.Action
-
-// this is the channel we get requests to make widgets
-var pluginChan chan widget.Action
-
-type node struct {
- parent *node
- children []*node
-
- WidgetId int // widget ID
- WidgetType widget.WidgetType
- ParentId int // parent ID
-
- state widget.State
-
- // a reference name for programming and debuggign. Must be unique
- progname string
-
- // the text used for button labesl, window titles, checkbox names, etc
- label string
-
- // horizontal means layout widgets like books on a bookshelf
- // vertical means layout widgets like books in a stack
- // direction widget.Orientation
- direction widget.Orientation
-
- // This is how the values are passed back and forth
- // values from things like checkboxes & dropdown's
- value any
-
- strings []string
-
- // This is used for things like a slider(0,100)
- X int
- Y int
-
- // This is for the grid size & widget position
- W int
- H int
- AtW int
- AtH int
-
- vals []string // dropdown menu items
-
- // horizontal bool `default:false`
-
- hasTabs bool // does the window have tabs?
- currentTab bool // the visible tab
-
- // 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 *guiWidget
-}
-
-// 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
-}
-
-func (n *node) doUserEvent() {
- if (callback == nil) {
- log.Log(ERROR, "doUserEvent() callback == nil", n.WidgetId)
- return
- }
- var a widget.Action
- a.WidgetId = n.WidgetId
- a.Value = n.value
- a.ActionType = widget.User
- log.Log(INFO, "doUserEvent() START: send a user event to the callback channel")
- callback <- a
- log.Log(INFO, "doUserEvent() END: sent a user event to the callback channel")
- return
-}
-
-// 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 Callback(guiCallback chan widget.Action) {
- callback = guiCallback
-}
-
-func PluginChannel() chan widget.Action {
- return pluginChan
-}
-
-/*
-func convertString(val any) string {
- 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)
- }
-}
-*/
-
-/*
-// this is in common.go, do not move it
-func getString(A any) string {
- if A == nil {
- log.Warn("getString() got nil")
- return ""
- }
- var k reflect.Kind
- k = reflect.TypeOf(A).Kind()
-
- switch k {
- case reflect.Int:
- var i int
- i = A.(int)
- return strconv.Itoa(i)
- case reflect.String:
- return A.(string)
- case reflect.Bool:
- if A.(bool) == true {
- return "true"
- } else {
- return "false"
- }
- default:
- log.Warn("getString uknown kind", k, "value =", A)
- return ""
- }
- return ""
-}
-*/
-
-// this is in common.go, do not move it
-func addNode(a *widget.Action) *node {
- n := new(node)
- n.WidgetType = a.WidgetType
- n.WidgetId = a.WidgetId
- n.ParentId = a.ParentId
-
- n.state = a.State
-
- // copy the data from the action message
- n.progname = a.ProgName
- n.value = a.Value
- n.direction = a.Direction
- n.strings = a.Strings
-
- // TODO: these need to be rethought
- n.X = a.X
- n.Y = a.Y
- n.W = a.W
- n.H = a.H
- n.AtW = a.AtW
- n.AtH = a.AtH
-
- // store the internal toolkit information
- n.tk = initWidget(n)
- // n.tk = new(guiWidget)
-
- if (a.WidgetType == widget.Root) {
- log.Log(INFO, "addNode() Root")
- return n
- }
-
- if (me.rootNode.findWidgetId(a.WidgetId) != nil) {
- log.Log(ERROR, "addNode() WidgetId already exists", a.WidgetId)
- return me.rootNode.findWidgetId(a.WidgetId)
- }
-
- // add this new widget on the binary tree
- n.parent = me.rootNode.findWidgetId(a.ParentId)
- if n.parent != nil {
- n.parent.children = append(n.parent.children, n)
- //w := n.tk
- //w.parent = n.parent.tk
- //w.parent.children = append(w.parent.children, w)
- }
- return n
-}
diff --git a/nocui/event.go b/nocui/event.go
index 97f2aed..9bbafdb 100644
--- a/nocui/event.go
+++ b/nocui/event.go
@@ -1,11 +1,13 @@
package main
+/*
import (
"go.wit.com/log"
"go.wit.com/gui/widget"
+ "go.wit.com/gui/toolkits/tree"
)
-func (n *node) doWidgetClick() {
+func doWidgetClick(n *tree.Node) {
switch n.WidgetType {
case widget.Root:
// THIS IS THE BEGINING OF THE LAYOUT
@@ -17,32 +19,33 @@ func (n *node) doWidgetClick() {
// rootNode.dumpTree(true)
case widget.Window:
// setCurrentWindow(w)
- n.doUserEvent()
+ // n.doUserEvent()
case widget.Tab:
// setCurrentTab(w)
case widget.Group:
// n.placeWidgets()
// n.toggleTree()
case widget.Checkbox:
- if widget.GetBool(n.value) {
+ if n.Bool() {
// n.setCheckbox(false)
} else {
// n.setCheckbox(true)
}
- n.doUserEvent()
+ // n.doUserEvent()
case widget.Grid:
// rootNode.hideWidgets()
// n.placeGrid()
// n.showWidgets()
case widget.Box:
// n.showWidgetPlacement(logNow, "drawTree()")
- if widget.GetBool(n.value) {
- log.Log(NOW, "BOX IS HORIZONTAL", n.progname)
+ if n.Bool() {
+ log.Log(NOW, "BOX IS HORIZONTAL", n.GetProgName())
} else {
- log.Log(NOW, "BOX IS VERTICAL", n.progname)
+ log.Log(NOW, "BOX IS VERTICAL", n.GetProgName())
}
case widget.Button:
- n.doUserEvent()
+ // n.doUserEvent()
default:
}
}
+*/
diff --git a/nocui/go.mod b/nocui/go.mod
index ec42260..e802e10 100644
--- a/nocui/go.mod
+++ b/nocui/go.mod
@@ -1,10 +1,3 @@
module go.wit.com/gui/toolkits/nocui
go 1.21.4
-
-require (
- go.wit.com/gui/widget v1.1.3
- go.wit.com/log v0.5.4
-)
-
-require go.wit.com/dev/davecgh/spew v1.1.4 // indirect
diff --git a/nocui/go.sum b/nocui/go.sum
deleted file mode 100644
index 3af9a6c..0000000
--- a/nocui/go.sum
+++ /dev/null
@@ -1,10 +0,0 @@
-go.wit.com/dev/davecgh/spew v1.1.3 h1:hqnB5qsPgC2cLZaJXqQJspQ5n/Ugry9kyL3tLk0hVzQ=
-go.wit.com/dev/davecgh/spew v1.1.3/go.mod h1:sihvWmnQ/09FWplnEmozt90CCVqBtGuPXM811tgfhFA=
-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.3 h1:/zHkniOPusPEuX1R401rMny9uwSO/nSU/QOMx6qoEnE=
-go.wit.com/log v0.5.3/go.mod h1:LzIzVxc2xJQxWQBtV9VbV605P4TOxmYDCl+BZF38yGE=
-go.wit.com/log v0.5.4 h1:vijLRPTUgChb8J5tx/7Uma/lGTUxeSXosFbheAmL914=
-go.wit.com/log v0.5.4/go.mod h1:BaJBfHFqcJSJLXGQ9RHi3XVhPgsStxSMZRlaRxW4kAo=
diff --git a/nocui/main.go b/nocui/main.go
index f6cfb3b..ebf3fae 100644
--- a/nocui/main.go
+++ b/nocui/main.go
@@ -1,55 +1,24 @@
package main
-import (
- "sync"
- "go.wit.com/log"
- "go.wit.com/gui/widget"
-)
-
-var muAction sync.Mutex
-
-func catchActionChannel() {
- log.Log(NOW, "catchActionChannel() START")
- for {
- log.Log(NOW, "catchActionChannel() for loop")
- select {
- case a := <-pluginChan:
- log.Log(NOW, "catchActionChannel() SELECT widget id =", a.WidgetId, a.ProgName)
- log.Log(NOW, "catchActionChannel() STUFF", a.WidgetId, a.ActionType, a.WidgetType)
- muAction.Lock()
- doAction(&a)
- muAction.Unlock()
- log.Log(NOW, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
- }
- }
-}
-
/*
-// 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 Callback(guiCallback chan widget.Action) {
- callback = guiCallback
-}
+ This is reference code for toolkit developers
-func PluginChannel() chan widget.Action {
- return pluginChan
-}
+ The 'nocui' is a bare minimum toolkit. It's all you need
+ to interact with the GUI
*/
-// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
+import (
+ "go.wit.com/log"
+ "go.wit.com/gui/toolkits/tree"
+)
+
func init() {
log.Log(INFO, "Init()")
- // andlabs = make(map[int]*andlabsT)
- pluginChan = make(chan widget.Action, 1)
+ me.myTree = tree.New()
+ me.myTree.PluginName = "nocui"
+ me.myTree.ActionFromChannel = doAction
- log.Log(NOW, "Init() start channel reciever")
- go catchActionChannel()
go simpleStdin()
- log.Log(NOW, "Init() END")
+ log.Log(INFO, "Init() END")
}
diff --git a/nocui/stdin.go b/nocui/stdin.go
index f7469c6..f003ee4 100644
--- a/nocui/stdin.go
+++ b/nocui/stdin.go
@@ -4,6 +4,7 @@ import (
"os"
"fmt"
"bufio"
+ "runtime/debug"
"strings"
"strconv"
@@ -12,6 +13,15 @@ import (
)
func simpleStdin() {
+ defer func() {
+ if r := recover(); r != nil {
+ log.Warn("nocui YAHOOOO Recovered in simpleStdin()", r)
+ log.Println("Recovered from panic:", r)
+ log.Println("Stack trace:")
+ debug.PrintStack()
+ me.myTree.DoToolkitPanic()
+ }
+ }()
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
s := scanner.Text()
@@ -19,63 +29,46 @@ func simpleStdin() {
switch s {
case "l":
log.Log(NOW, "list widgets")
- me.rootNode.listWidgets()
+ me.treeRoot.ListWidgets()
case "b":
log.Log(NOW, "show buttons")
- me.rootNode.showButtons()
+ me.treeRoot.ShowButtons()
+ case "g":
+ me.myTree.DoToolkitLoad("gocui")
+ case "a":
+ me.myTree.DoToolkitLoad("andlabs")
case "d":
- var a widget.Action
- a.ActionType = widget.EnableDebug
- callback <- a
+ me.myTree.DoEnableDebugger()
case "":
fmt.Println("")
fmt.Println("Enter:")
fmt.Println("'l': list all widgets")
fmt.Println("'b': for buttons")
+ fmt.Println("'g': load gocui plugin")
+ fmt.Println("'a': load andlabs plugin")
fmt.Println("'d': enable debugging")
default:
i, _ := strconv.Atoi(s)
log.Log(NOW, "got input:", i)
- n := me.rootNode.findWidgetId(i)
+ n := me.treeRoot.FindWidgetId(i)
if (n != nil) {
- n.dumpWidget("found node")
- n.doUserEvent()
+ n.DumpWidget("found node")
+ for i, s := range n.State.Strings {
+ log.Warn("n.State.Strings =", i, s)
+ }
+ switch n.WidgetType {
+ case widget.Root:
+ log.Warn("this is the root widget")
+ case widget.Dropdown:
+ log.Warn("print out dropdown values here")
+ case widget.Button:
+ me.myTree.DoUserEvent(n)
+ case widget.Checkbox:
+ me.myTree.DoUserEvent(n)
+ default:
+ log.Warn("you haven't defined an event for", n.WidgetType)
+ }
}
}
}
}
-
-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.Log(NOW, "node:", pad, n.WidgetId, ",", n.WidgetType, ",", n.progname)
-}
-
-var depth int = 0
-
-func (n *node) listWidgets() {
- if (n == nil) {
- 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/nocui/structs.go b/nocui/structs.go
index 888bcb5..c8a7cb4 100644
--- a/nocui/structs.go
+++ b/nocui/structs.go
@@ -1,17 +1,22 @@
package main
+import (
+ "go.wit.com/gui/toolkits/tree"
+)
+
// stores the raw toolkit internals
type guiWidget struct {
Width int
Height int
c int
- val map[int]string
+ val map[string]int
}
// It's probably a terrible idea to call this 'me'
var me config
type config struct {
- rootNode *node // the base of the binary tree. it should have id == 0
+ treeRoot *tree.Node // the base of the binary tree. it should have id == 0
+ myTree *tree.TreeInfo
}
diff --git a/nocui/tree.go b/nocui/tree.go
new file mode 100644
index 0000000..784e923
--- /dev/null
+++ b/nocui/tree.go
@@ -0,0 +1,24 @@
+package main
+
+/*
+ This is reference code for toolkit developers
+*/
+
+import (
+ "go.wit.com/gui/widget"
+)
+
+// 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 Callback(guiCallback chan widget.Action) {
+ me.myTree.Callback(guiCallback)
+}
+
+func PluginChannel() chan widget.Action {
+ return me.myTree.PluginChannel()
+}
diff --git a/nocui/widget.go b/nocui/widget.go
deleted file mode 100644
index 6e50705..0000000
--- a/nocui/widget.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- "go.wit.com/log"
- "go.wit.com/gui/widget"
-)
-
-// this is specific to the nocui toolkit
-func initWidget(n *node) *guiWidget {
- var w *guiWidget
- w = new(guiWidget)
- // Set(w, "default")
-
- if n.WidgetType == widget.Root {
- log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId)
- n.WidgetId = 0
- me.rootNode = n
- return w
- }
-
- if (n.WidgetType == widget.Box) {
- if (n.direction == widget.Horizontal) {
- // n.horizontal = true
- } else {
- // n.horizontal = false
- }
- }
-
- return w
-}