diff options
Diffstat (limited to 'nocui')
| -rw-r--r-- | nocui/action.go | 159 | ||||
| -rw-r--r-- | nocui/common.go | 218 | ||||
| -rw-r--r-- | nocui/event.go | 19 | ||||
| -rw-r--r-- | nocui/go.mod | 7 | ||||
| -rw-r--r-- | nocui/go.sum | 10 | ||||
| -rw-r--r-- | nocui/main.go | 55 | ||||
| -rw-r--r-- | nocui/stdin.go | 79 | ||||
| -rw-r--r-- | nocui/structs.go | 9 | ||||
| -rw-r--r-- | nocui/tree.go | 24 | ||||
| -rw-r--r-- | nocui/widget.go | 30 |
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 -} |
