common tree package for toolkits

This update provides *lots* of toolkit updates. This will allow
        the next step of debugging the gocui toolkit to make it work
        again. There are new common routines for handling the plugin
        channel communication

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2024-01-17 21:31:49 -06:00
parent ba95c13799
commit 841e6252c9
46 changed files with 1201 additions and 879 deletions

View File

@ -1,47 +1,99 @@
package main package main
import ( import (
"strconv" "errors"
"go.wit.com/dev/andlabs/ui"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
// this will check to make sure that the node
// is valid for making a New TK andlabs widget
// Basically, it makes sure there is a parent ID
// and that there already a widget created
func notNew(n *tree.Node) bool {
if n == nil {
log.Warn("ready() n = nil")
return true
}
if n.TK != nil {
log.Warn("ready() n.TK = nil", n.WidgetId, n.GetProgName())
return true
}
if n.Parent == nil {
log.Warn("ready() n.Parent = nil", n.WidgetId, n.GetProgName())
return true
}
if n.Parent.TK == nil {
log.Warn("ready() n.Parent.TK = nil", n.WidgetId, n.GetProgName())
log.Warn("ready() n.Parent.TK = nil", n.Parent.WidgetId, n.Parent.GetProgName())
return true
}
// this means you can add a new widgets
return false
}
func ready(n *tree.Node) bool {
if n == nil {
log.Warn("ready() n = nil")
return false
}
if n.TK == nil {
log.Warn("ready() n.TK = nil", n.WidgetId, n.GetProgName())
return false
}
if n.Parent == nil {
log.Warn("ready() n.Parent = nil", n.WidgetId, n.GetProgName())
return false
}
if n.Parent.TK == nil {
log.Warn("ready() n.Parent.TK = nil", n.WidgetId, n.GetProgName())
log.Warn("ready() n.Parent.TK = nil", n.Parent.WidgetId, n.Parent.GetProgName())
return false
}
return true
}
func (n *node) ready() bool { func (n *node) ready() bool {
if n == nil { return false } if n == nil { return false }
if n.tk == nil { return false } if n.tk == nil { return false }
return true return true
} }
func (n *node) show(b bool) { func show(n *tree.Node, b bool) {
if n.tk == nil { var tk *guiWidget
tk = n.TK.(*guiWidget)
// tk = getTK(n)
if tk == nil {
return return
} }
if n.tk.uiControl == nil { if tk.uiControl == nil {
return return
} }
if (b) { if (b) {
n.tk.uiControl.Show() tk.uiControl.Show()
} else { } else {
n.tk.uiControl.Hide() tk.uiControl.Hide()
} }
} }
func (n *node) enable(b bool) { func enable(n *tree.Node, b bool) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
if n == nil { if n == nil {
panic("WHAT? enable was passed nil. How does this even happen?") panic("WHAT? enable was passed nil. How does this even happen?")
} }
if n.tk == nil { if tk == nil {
return return
} }
if n.tk.uiControl == nil { if tk.uiControl == nil {
return return
} }
if (b) { if (b) {
n.tk.uiControl.Enable() tk.uiControl.Enable()
} else { } else {
n.tk.uiControl.Disable() tk.uiControl.Disable()
} }
} }
@ -152,73 +204,88 @@ func (n *node) Delete() {
func rawAction(a *widget.Action) { func rawAction(a *widget.Action) {
log.Log(INFO, "rawAction() START a.ActionType =", a.ActionType, "a.Value", a.Value) log.Log(INFO, "rawAction() START a.ActionType =", a.ActionType, "a.Value", a.Value)
if (a.ActionType == widget.InitToolkit) { if (a.ActionType == widget.ToolkitInit) {
// TODO: make sure to only do this once Init()
// go uiMain.Do(func() { return
// ui.Main(demoUI) }
// go catchActionChannel() switch a.WidgetType {
// }) case widget.Root:
// try doing this on toolkit load in init() me.treeRoot = me.myTree.AddNode(a)
log.Log(INFO, "doAction() found treeRoot")
return return
} }
log.Log(INFO, "rawAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId) log.Warn("andlabs rawAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId, a.ActionType)
switch a.WidgetType { switch a.WidgetType {
case widget.Flag: case widget.Flag:
log.Log(ERROR, "rawAction() RE-IMPLEMENT LOG FLAGS") log.Log(ERROR, "rawAction() RE-IMPLEMENT LOG FLAGS")
return return
} }
n := me.rootNode.findWidgetId(a.WidgetId) if me.treeRoot == nil {
panic("me.treeRoot == nil")
}
n := me.treeRoot.FindWidgetId(a.WidgetId)
if (a.ActionType == widget.Add) { if (a.ActionType == widget.Add) {
ui.QueueMain(func() { me.treeRoot.ListWidgets()
// ui.QueueMain(func() {
add(a) add(a)
}) // })
// TODO: remove this artificial delay // TODO: remove this artificial delay
// sleep(.001) // sleep(.001)
return return
} }
if (a.ActionType == widget.Dump) { if (a.ActionType == widget.Dump) {
log.Log(NOW, "rawAction() Dump =", a.ActionType, a.WidgetType, n.progname) log.Log(NOW, "rawAction() Dump =", a.ActionType, a.WidgetType, n.State.ProgName)
me.rootNode.listChildren(true) // me.rootNode.listChildren(true)
return return
} }
if (n == nil) { if (n == nil) {
me.rootNode.listChildren(true) log.Error(errors.New("andlabs rawAction() ERROR findWidgetId found nil"), a.ActionType, a.WidgetType)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil", a.ActionType, a.WidgetType)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId) log.Log(NOW, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil", a.ActionType, a.WidgetType) log.Log(NOW, "rawAction() ERROR findWidgetId found nil", a.ActionType, a.WidgetType)
log.Log(NOW, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId) log.Log(NOW, "rawAction() ERROR findWidgetId found nil for id =", a.WidgetId)
me.treeRoot.ListWidgets()
return return
panic("findWidgetId found nil for id = " + strconv.Itoa(a.WidgetId)) panic("findWidgetId found nil for id = " + string(a.WidgetId))
} }
switch a.ActionType { switch a.ActionType {
case widget.Show: case widget.Show:
n.show(true) show(n, true)
// n.show(true)
case widget.Hide: case widget.Hide:
n.show(false) show(n, false)
//n.show(false)
case widget.Enable: case widget.Enable:
n.enable(true) enable(n, true)
// n.enable(true)
case widget.Disable: case widget.Disable:
log.Warn("andlabs got disable for", n.WidgetId, n.progname) log.Warn("andlabs got disable for", n.WidgetId, n.State.ProgName)
n.enable(false) enable(n, false)
// n.enable(false)
case widget.Get: case widget.Get:
n.setText(a) // n.setText(a)
setText(n, a)
case widget.GetText: case widget.GetText:
switch a.WidgetType { switch a.WidgetType {
case widget.Textbox: case widget.Textbox:
a.Value = n.value a.Value = n.State.Value
} }
case widget.Set: case widget.Set:
n.setText(a) setText(n, a)
// n.setText(a)
case widget.SetText: case widget.SetText:
n.setText(a) setText(n, a)
// n.setText(a)
case widget.AddText: case widget.AddText:
n.addText(a) addText(n, a)
// n.addText(a)
/*
case widget.Margin: case widget.Margin:
n.pad(true) n.pad(true)
case widget.Unmargin: case widget.Unmargin:
@ -231,8 +298,7 @@ func rawAction(a *widget.Action) {
n.Delete() n.Delete()
case widget.Move: case widget.Move:
log.Log(NOW, "rawAction() attempt to move() =", a.ActionType, a.WidgetType) log.Log(NOW, "rawAction() attempt to move() =", a.ActionType, a.WidgetType)
newParent := me.rootNode.findWidgetId(a.ParentId) */
n.move(newParent)
default: default:
log.Log(ERROR, "rawAction() Unknown =", a.ActionType, a.WidgetType) log.Log(ERROR, "rawAction() Unknown =", a.ActionType, a.WidgetType)
} }

View File

@ -6,57 +6,67 @@ import (
) )
func add(a *widget.Action) { func add(a *widget.Action) {
log.Warn("andlabs add()", a.WidgetId, a.State.ProgName)
if (a.WidgetType == widget.Root) { if (a.WidgetType == widget.Root) {
me.rootNode = addNode(a) if me.treeRoot == nil {
me.treeRoot = me.myTree.AddNode(a)
}
return return
} }
n := addNode(a) // n := addNode(a)
n := me.myTree.AddNode(a)
p := n.parent p := n.Parent
switch n.WidgetType { switch n.WidgetType {
case widget.Window: case widget.Window:
newWindow(n) log.Warn("SPEEDY Add window", n.WidgetId, n.GetProgName())
return newWindow(p, n)
case widget.Tab:
p.newTab(n)
return
case widget.Label:
p.newLabel(n)
return
case widget.Button:
p.newButton(n)
return
case widget.Grid:
p.newGrid(n)
return
case widget.Checkbox:
p.newCheckbox(n)
return
case widget.Spinner:
p.newSpinner(n)
return
case widget.Slider:
p.newSlider(n)
return
case widget.Dropdown:
p.newDropdown(n)
return
case widget.Combobox:
p.newCombobox(n)
return
case widget.Textbox:
p.newTextbox(n)
return return
case widget.Group: case widget.Group:
p.newGroup(n) log.Warn("SPEEDY Add Group", n.WidgetId, n.GetProgName())
newGroup(p, n)
return
case widget.Grid:
newGrid(n)
return return
case widget.Box: case widget.Box:
p.newBox(n) newBox(n)
return return
/*
case widget.Tab:
newTab(n)
return
*/
case widget.Label:
newLabel(p, n)
return
case widget.Button:
newButton(p, n)
return
case widget.Checkbox:
newCheckbox(p, n)
return
case widget.Spinner:
newSpinner(p, n)
return
case widget.Slider:
newSlider(p, n)
return
case widget.Dropdown:
newDropdown(p, n)
return
case widget.Combobox:
newCombobox(p, n)
return
case widget.Textbox:
newTextbox(p, n)
return
/*
case widget.Image: case widget.Image:
p.newImage(n) newImage(p, n)
return return
*/
default: default:
log.Log(ERROR, "add() error TODO: ", n.WidgetType, n.progname) log.Log(ERROR, "add() error TODO: ", n.WidgetType, n.State.ProgName)
} }
} }

View File

@ -3,22 +3,40 @@ package main
import ( import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
func (n *node) addText(a *widget.Action) { func compareStrings(n *tree.Node, ss []string) {
log.Log(CHANGE, "addText() START with a.Value =", a.Value) }
t := n.tk
if (t == nil) { // func (n *node) addText(a *widget.Action) {
log.Log(ERROR, "addText error. tk == nil", n.progname, n.WidgetId) func addText(n *tree.Node, a *widget.Action) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Warn("andlabs addText() START with a.Value =", a.Value)
if (tk == nil) {
log.Log(ERROR, "addText error. tk == nil", n.State.ProgName, n.WidgetId)
return return
} }
log.Log(CHANGE, "addText() Attempt on", n.WidgetType, "with", a.Value) log.Warn("andlabs addText() Attempt on", n.WidgetType, "with", a.Value)
switch n.WidgetType { switch n.WidgetType {
case widget.Dropdown: case widget.Dropdown:
n.addDropdownName(widget.GetString(a.Value)) for i, s := range a.State.Strings {
log.Warn("andlabs a.State.Strings =", i, s)
_, ok := n.Strings[s]
// If the key exists
if ok {
log.Warn("andlabs a.State.Strings is here", i, s)
} else {
log.Warn("andlabs is not here", i, s)
addDropdownName(n, s)
// TODO: make numbers
n.Strings[s] = 21
}
}
case widget.Combobox: case widget.Combobox:
n.addComboboxName(widget.GetString(a.Value)) addComboboxName(n, widget.GetString(a.Value))
default: default:
log.Log(ERROR, "plugin Send() Don't know how to addText on", n.WidgetType, "yet", a.ActionType) log.Log(ERROR, "plugin Send() Don't know how to addText on", n.WidgetType, "yet", a.ActionType)
} }

View File

@ -2,17 +2,19 @@ package main
import ( import (
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
// make new Box here // make new Box here
func (p *node) newBox(n *node) { func newBox(n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
var box *ui.Box var box *ui.Box
if n.direction == widget.Horizontal { if n.State.Direction == widget.Horizontal {
box = ui.NewHorizontalBox() box = ui.NewHorizontalBox()
} else { } else {
box = ui.NewVerticalBox() box = ui.NewVerticalBox()
@ -22,8 +24,8 @@ func (p *node) newBox(n *node) {
newt.uiBox = box newt.uiBox = box
newt.uiControl = box newt.uiControl = box
newt.boxC = 0 newt.boxC = 0
n.tk = newt n.TK = newt
p.place(n) place(n.Parent, n)
} }
/* /*
@ -46,10 +48,11 @@ func (p *node) newBox(n *node) {
TODO: handle user killing/closing a window using the OS TODO: handle user killing/closing a window using the OS
*/ */
func (n *node) rawBox() *ui.Box { // func (n *node) rawBox() *ui.Box {
func rawBox(n *tree.Node) *ui.Box {
var box *ui.Box var box *ui.Box
if n.direction == widget.Horizontal { if n.State.Direction == widget.Horizontal {
box = ui.NewHorizontalBox() box = ui.NewHorizontalBox()
} else { } else {
box = ui.NewVerticalBox() box = ui.NewVerticalBox()

View File

@ -1,25 +1,28 @@
package main package main
import ( import (
"go.wit.com/gui/widget" "go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newButton(n *node) { // func (p *node) newButton(n *node) {
t := p.tk func newButton(p *tree.Node, n *tree.Node) {
if notNew(n) { return }
var ptk *guiWidget
ptk = p.TK.(*guiWidget)
newt := new(guiWidget) newt := new(guiWidget)
b := ui.NewButton(widget.GetString(n.value)) b := ui.NewButton(n.GetLabel())
newt.uiButton = b newt.uiButton = b
newt.uiControl = b newt.uiControl = b
newt.parent = t newt.parent = ptk
b.OnClicked(func(*ui.Button) { b.OnClicked(func(*ui.Button) {
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }

View File

@ -1,23 +1,26 @@
package main package main
import ( import (
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newCheckbox(n *node) { func newCheckbox(p *tree.Node, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
newt.uiCheckbox = ui.NewCheckbox(n.label) newt.uiCheckbox = ui.NewCheckbox(n.GetLabel())
newt.uiControl = newt.uiCheckbox newt.uiControl = newt.uiCheckbox
newt.uiCheckbox.OnToggled(func(spin *ui.Checkbox) { newt.uiCheckbox.OnToggled(func(spin *ui.Checkbox) {
n.value = newt.checked() n.SetValue(newt.checked())
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }
func (t *guiWidget) checked() bool { func (t *guiWidget) checked() bool {

View File

@ -5,10 +5,11 @@ import (
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/toolkits/tree"
) )
func (p *node) newCombobox(n *node) { func newCombobox(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
cb := ui.NewEditableCombobox() cb := ui.NewEditableCombobox()
@ -20,46 +21,53 @@ func (p *node) newCombobox(n *node) {
newt.val = make(map[int]string) newt.val = make(map[int]string)
cb.OnChanged(func(spin *ui.EditableCombobox) { cb.OnChanged(func(spin *ui.EditableCombobox) {
n.value = spin.Text() n.SetValue(spin.Text())
log.Warn("combobox changed =" + spin.Text() + ".") log.Warn("combobox changed =" + spin.Text() + ".")
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
n.tk = newt n.TK = newt
p.place(n) place(p, n)
log.Warn("add combobox entries on create:", n.State.Strings)
log.Warn("add combobox entries on create:", n.State.Strings)
log.Warn("add combobox entries on create:", n.State.Strings)
// add the initial combobox entries // add the initial combobox entries
for i, s := range n.strings { for i, s := range n.State.Strings {
log.Warn("add combobox entries on create", n.progname, i, s) log.Warn("add combobox entries on create", n.GetProgName(), i, s)
n.addComboboxName(s) addComboboxName(n, s)
} }
cur := widget.GetString(n.value) cur := n.String()
log.Warn("add combobox: TODO: set default value on create", n.progname, cur) log.Warn("add combobox: TODO: set default value on create", n.GetProgName(), cur)
n.setComboboxName(cur) setComboboxName(n, cur)
} }
func (n *node) addComboboxName(s string) { func addComboboxName(n *tree.Node, s string) {
if ! n.ready() { return } if ! ready(n) { return }
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "addComboboxName()", n.WidgetId, "add:", s) log.Log(INFO, "addComboboxName()", n.WidgetId, "add:", s)
n.tk.uiEditableCombobox.Append(s) tk.uiEditableCombobox.Append(s)
if (n.tk.val == nil) { if (tk.val == nil) {
log.Log(INFO, "make map didn't work") log.Log(INFO, "make map didn't work")
return return
} }
n.tk.val[n.tk.c] = s tk.val[tk.c] = s
// If this is the first menu added, set the dropdown to it // If this is the first menu added, set the dropdown to it
if (n.tk.c == 0) { if (tk.c == 0) {
log.Log(INFO, "THIS IS THE FIRST combobox", s) log.Log(INFO, "THIS IS THE FIRST combobox", s)
n.tk.uiEditableCombobox.SetText(s) tk.uiEditableCombobox.SetText(s)
} }
n.tk.c = n.tk.c + 1 tk.c = tk.c + 1
} }
func (n *node) setComboboxName(s string) bool { func setComboboxName(n *tree.Node, s string) bool {
if ! n.ready() { return false} if ! ready(n) { return false}
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "SetComboboxName()", n.WidgetId, ",", s) log.Log(INFO, "SetComboboxName()", n.WidgetId, ",", s)
n.tk.uiEditableCombobox.SetText(s) tk.uiEditableCombobox.SetText(s)
return false return false
} }

View File

@ -1 +0,0 @@
../nocui/common.go

61
andlabs/common.go Normal file
View File

@ -0,0 +1,61 @@
package main
import (
"go.wit.com/gui/widget"
)
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
}
/*
func (n *node) doUserEvent() {
log.Log(ERROR, "doUserEvent() ERROR")
}
*/

View File

@ -1,8 +1,6 @@
package main package main
import ( import (
"strconv"
"go.wit.com/log" "go.wit.com/log"
// "go.wit.com/gui/widget" // "go.wit.com/gui/widget"
) )
@ -94,7 +92,7 @@ func (n *node) dumpWidget(b bool) {
} }
info = n.WidgetType.String() info = n.WidgetType.String()
d = strconv.Itoa(n.WidgetId) + " " + info + " " + n.progname d = string(n.WidgetId) + " " + info + " " + n.progname
var tabs string var tabs string
for i := 0; i < listChildrenDepth; i++ { for i := 0; i < listChildrenDepth; i++ {

View File

@ -5,12 +5,13 @@ import (
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/toolkits/tree"
) )
func (p *node) newDropdown(n *node) { func newDropdown(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
log.Log(INFO, "gui.Toolbox.newDropdown() START", n.progname) log.Log(INFO, "gui.Toolbox.newDropdown() START", n.GetProgName())
cb := ui.NewCombobox() cb := ui.NewCombobox()
newt.uiCombobox = cb newt.uiCombobox = cb
@ -24,60 +25,69 @@ func (p *node) newDropdown(n *node) {
i := spin.Selected() i := spin.Selected()
if (newt.val == nil) { if (newt.val == nil) {
log.Log(ERROR, "make map didn't work") log.Log(ERROR, "make map didn't work")
n.value = "map did not work. ui.Combobox error" n.SetValue("map did not work. ui.Combobox error")
} else { } else {
n.value = newt.val[i] n.SetValue(newt.val[i])
} }
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
n.tk = newt n.TK = newt
p.place(n) place(p, n)
if n.strings == nil {return} log.Warn("add dropdown entries on create:", n.State.Strings)
log.Warn("add dropdown entries on create:", n.State.Strings)
log.Warn("add dropdown entries on create:", n.State.Strings)
if n.State.Strings == nil {return}
// add the initial dropdown entries // add the initial dropdown entries
for i, s := range n.strings { for i, s := range n.State.Strings {
log.Warn("add dropdown: add entries on create", n.progname, i, s) log.Warn("add dropdown: add entries on create", n.GetProgName(), i, s)
n.addDropdownName(s) addDropdownName(n, s)
} }
cur := widget.GetString(n.value) cur := n.String()
log.Warn("add dropdown: set default value on create", n.progname, cur) log.Warn("add dropdown: set default value on create", n.GetProgName(), cur)
n.setDropdownName(cur) setDropdownName(n, cur)
} }
func (n *node) SetDropdownInt(i int) { func setDropdownInt(n *tree.Node, i int) {
if ! n.ready() { return } if ! ready(n) { return }
n.tk.uiCombobox.SetSelected(i) var tk *guiWidget
tk = n.TK.(*guiWidget)
tk.uiCombobox.SetSelected(i)
} }
func (n *node) addDropdownName(s string) { func addDropdownName(n *tree.Node, s string) {
if ! n.ready() { return } if ! ready(n) { return }
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "addDropdownName()", n.WidgetId, "add:", s) log.Log(INFO, "addDropdownName()", n.WidgetId, "add:", s)
n.tk.uiCombobox.Append(s) tk.uiCombobox.Append(s)
if (n.tk.val == nil) { if (tk.val == nil) {
log.Log(INFO, "make map didn't work") log.Log(INFO, "make map didn't work")
return return
} }
n.tk.val[n.tk.c] = s tk.val[tk.c] = s
// If this is the first menu added, set the dropdown to it // If this is the first menu added, set the dropdown to it
if (n.tk.c == 0) { if (tk.c == 0) {
log.Log(INFO, "THIS IS THE FIRST Dropdown", s) log.Log(INFO, "THIS IS THE FIRST Dropdown", s)
n.tk.uiCombobox.SetSelected(0) tk.uiCombobox.SetSelected(0)
} }
n.tk.c = n.tk.c + 1 tk.c = tk.c + 1
} }
func (n *node) setDropdownName(s string) bool { func setDropdownName(n *tree.Node, s string) bool {
if ! n.ready() { return false} if ! ready(n) { return false}
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(INFO, "SetDropdownName()", n.WidgetId, ",", s) log.Log(INFO, "SetDropdownName()", n.WidgetId, ",", s)
for i, tmp := range n.tk.val { for i, tmp := range tk.val {
if s == tmp { if s == tmp {
n.value = s n.SetValue(s)
n.SetDropdownInt(i) setDropdownInt(n, i)
log.Warn("SetDropdownInt() worked", tmp, i) log.Warn("SetDropdownInt() worked", tmp, i)
return true return true
} }

View File

@ -1,6 +1,8 @@
package main package main
import ( import (
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
@ -10,9 +12,9 @@ import (
// -- (1,1) -- (2,1) -- (3,1) -- // -- (1,1) -- (2,1) -- (3,1) --
// -- (1,2) -- (2,1) -- (3,1) -- // -- (1,2) -- (2,1) -- (3,1) --
// ----------------------------- // -----------------------------
func (p *node) newGrid(n *node) { func newGrid(n *tree.Node) {
if notNew(n) { return }
var newt *guiWidget var newt *guiWidget
newt = new(guiWidget) newt = new(guiWidget)
c := ui.NewGrid() c := ui.NewGrid()
@ -20,6 +22,6 @@ func (p *node) newGrid(n *node) {
newt.uiControl = c newt.uiControl = c
c.SetPadded(true) c.SetPadded(true)
n.tk = newt n.TK = newt
p.place(n) place(n.Parent, n)
} }

View File

@ -1,20 +1,22 @@
package main package main
import ( import (
"go.wit.com/gui/widget" // "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newGroup(n *node) { func newGroup(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
g := ui.NewGroup(widget.GetString(n.value)) g := ui.NewGroup(n.GetLabel())
g.SetMargined(true) g.SetMargined(true)
newt.uiGroup = g newt.uiGroup = g
newt.uiControl = g newt.uiControl = g
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }

View File

@ -16,7 +16,7 @@ func (p *node) newImage(n *node) {
// newt.uiControl = img // newt.uiControl = img
n.tk = newt n.tk = newt
p.place(n) // p.place(n)
} }
/* /*
if (a.Name == "image") { if (a.Name == "image") {

View File

@ -1,18 +1,19 @@
package main package main
import ( import (
"go.wit.com/gui/widget" "go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newLabel(n *node) { func newLabel(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
c := ui.NewLabel(widget.GetString(n.value)) c := ui.NewLabel(n.GetLabel())
newt.uiLabel = c newt.uiLabel = c
newt.uiControl = c newt.uiControl = c
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }

View File

@ -2,8 +2,11 @@ package main
import ( import (
"sync" "sync"
"runtime/debug"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
// the _ means we only need this for the init() // the _ means we only need this for the init()
@ -17,7 +20,11 @@ var muAction sync.Mutex
func queueMain(currentA widget.Action) { func queueMain(currentA widget.Action) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
log.Warn("YAHOOOO Recovered in main application:", r) log.Warn("YAHOOOO Recovered in queueMain() application:", r)
log.Println("Recovered from panic:", r)
log.Println("Stack trace:")
debug.PrintStack()
me.myTree.DoToolkitPanic()
} }
}() }()
ui.QueueMain( func() { ui.QueueMain( func() {
@ -25,29 +32,14 @@ func queueMain(currentA widget.Action) {
}) })
} }
func catchActionChannel() {
log.Log(INFO, "catchActionChannel() START")
for {
log.Log(INFO, "catchActionChannel() for loop")
select {
case a := <-pluginChan:
log.Log(INFO, "catchActionChannel() SELECT widget id =", a.WidgetId, a.ProgName)
log.Log(INFO, "catchActionChannel() STUFF", a.WidgetId, a.ActionType, a.WidgetType)
muAction.Lock()
// TODO ui.QueueMain(f)
// TODO ui.QueueMain( func() {rawAction(a)} )
// rawAction(a)
queueMain(a)
muAction.Unlock()
log.Log(INFO, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
}
}
}
func guiMain() { func guiMain() {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
log.Warn("YAHOOOO Recovered in main application:", r) log.Warn("YAHOOOO Recovered in guiMain application:", r)
log.Println("Recovered from panic:", r)
log.Println("Stack trace:")
debug.PrintStack()
me.myTree.DoToolkitPanic()
} }
}() }()
ui.Main(func() { ui.Main(func() {
@ -55,6 +47,10 @@ func guiMain() {
}) })
} }
func Init() {
log.Warn("Init() TODO: move init() to here")
}
// This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc // This is important. This sets the defaults for the gui. Without this, there isn't correct padding, etc
func init() { func init() {
log.Log(INFO, "Init() START") log.Log(INFO, "Init() START")
@ -63,15 +59,12 @@ func init() {
// log.Log(INFO, "init() Setting defaultBehavior = true") // log.Log(INFO, "init() Setting defaultBehavior = true")
setDefaultBehavior(true) setDefaultBehavior(true)
me.myTree = tree.New()
me.myTree.PluginName = "andlabs"
me.myTree.ActionFromChannel = queueMain
// TODO: this is messed up. run ui.Main() from the first add? Initialize it with an empty thing first? // TODO: this is messed up. run ui.Main() from the first add? Initialize it with an empty thing first?
// fake out the OS toolkit by making a fake window. This is probably needed for macos & windows // fake out the OS toolkit by making a fake window. This is probably needed for macos & windows
// actually, this probably breaks the macos build // actually, this probably breaks the macos build
go guiMain() go guiMain()
// andlabs = make(map[int]*andlabsT)
pluginChan = make(chan widget.Action, 1)
log.Log(INFO, "Init() start channel reciever")
go catchActionChannel()
log.Log(INFO, "Init() END")
} }

View File

@ -1,12 +1,15 @@
package main package main
import ( import (
// "os"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
// This routine is very specific to this toolkit // This routine is very specific to this toolkit
@ -33,62 +36,78 @@ import (
// -- (0,0) -- (1,0) -- (1,0) -- // -- (0,0) -- (1,0) -- (1,0) --
// -- (0,1) -- (1,1) -- (1,1) -- // -- (0,1) -- (1,1) -- (1,1) --
// ----------------------------- // -----------------------------
func (p *node) place(n *node) bool {
log.Log(INFO, "place() START", n.WidgetType, n.progname)
if (p.tk == nil) { func place(p *tree.Node, n *tree.Node) bool {
log.Log(ERROR, "p.tk == nil", p.progname, p.ParentId, p.WidgetType, p.tk) log.Warn("SPEEDY newplace() 1 START", n.WidgetId, n.GetProgName(), n.GetLabel(), n.String())
log.Log(ERROR, "n = ", n.progname, n.ParentId, n.WidgetType, n.tk) log.Warn("SPEEDY newplace() n.State.Strings =", n.State.Strings)
panic("p.tk == nil") log.Log(INFO, "place() 1 START", n.WidgetType, n.GetProgName(), n.GetLabel())
if ! ready(n) {
log.Warn("place() 1 START not ready()")
return false
}
log.Log(INFO, "place() 1 START ready()")
var tk, ptk *guiWidget
tk = n.TK.(*guiWidget)
ptk = p.TK.(*guiWidget)
log.Warn("SPEEDY newplace() 2 START", n.WidgetId, n.GetProgName(), n.GetLabel())
if (ptk == nil) {
log.Log(ERROR, "ptk == nil", p.GetProgName(), p.ParentId, p.WidgetType, ptk)
log.Log(ERROR, "n = ", n.GetProgName(), n.ParentId, n.WidgetType, tk)
log.Warn("SPEEDY ptk == nil", n.WidgetId, n.GetProgName())
log.Sleep(1)
panic("ptk == nil")
} }
log.Log(INFO, "place() switch", p.WidgetType) log.Log(INFO, "place() switch", p.WidgetType)
log.Warn("SPEEDY newplace() before switch", n.WidgetId, n.GetProgName())
switch p.WidgetType { switch p.WidgetType {
case widget.Grid: case widget.Grid:
log.Log(INFO, "place() Grid try at Parent X,Y =", n.X, n.Y) tk.gridX = n.State.GridOffset.X - 1
n.tk.gridX = n.AtW - 1 tk.gridY = n.State.GridOffset.Y - 1
n.tk.gridY = n.AtH - 1 log.Warn("place() on Grid at gridX,gridY", tk.gridX, tk.gridY)
log.Log(INFO, "place() Grid try at gridX,gridY", n.tk.gridX, n.tk.gridY) ptk.uiGrid.Append(tk.uiControl,
// at the very end, subtract 1 from X & Y since andlabs/ui starts counting at zero tk.gridX, tk.gridY, 1, 1,
p.tk.uiGrid.Append(n.tk.uiControl,
n.tk.gridX, n.tk.gridY, 1, 1,
false, ui.AlignFill, false, ui.AlignFill) false, ui.AlignFill, false, ui.AlignFill)
return true return true
case widget.Group: case widget.Group:
if (p.tk.uiBox == nil) { if (ptk.uiBox == nil) {
log.Log(WARN, "place() andlabs hack group to use add a box", n.progname, n.WidgetType) log.Log(WARN, "place() andlabs hack group to use add a box", n.GetProgName(), n.WidgetType)
p.tk.uiBox = n.rawBox() ptk.uiBox = rawBox(n)
p.tk.uiGroup.SetChild(p.tk.uiBox) ptk.uiGroup.SetChild(ptk.uiBox)
} }
p.tk.uiBox.Append(n.tk.uiControl, stretchy) ptk.uiBox.Append(tk.uiControl, stretchy)
return true return true
case widget.Tab: case widget.Tab:
if (p.tk.uiTab == nil) { if (ptk.uiTab == nil) {
log.Log(ERROR, "p.tk.uiTab == nil for n.WidgetId =", n.WidgetId, "p.tk =", p.tk) log.Log(ERROR, "ptk.uiTab == nil for n.WidgetId =", n.WidgetId, "ptk =", ptk)
panic("p.tk.uiTab == nil") panic("ptk.uiTab == nil")
} }
if (n.tk.uiControl == nil) { if (tk.uiControl == nil) {
log.Log(ERROR, "n.tk.uiControl == nil for n.WidgetId =", n.WidgetId, "n.tk =", n.tk) log.Log(ERROR, "tk.uiControl == nil for n.WidgetId =", n.WidgetId, "tk =", tk)
panic("n.tk.uiControl == nil") panic("tk.uiControl == nil")
} }
log.Log(ERROR, "CHECK LOGIC ON THIS. APPENDING directly into a window without a tab") log.Log(ERROR, "CHECK LOGIC ON THIS. APPENDING directly into a window without a tab")
// log.Log(ERROR, "THIS SHOULD NEVER HAPPEN ??????? trying to place() node=", n.WidgetId, n.progname, n.Text, n.WidgetType) // log.Log(ERROR, "THIS SHOULD NEVER HAPPEN ??????? trying to place() node=", n.WidgetId, n.GetProgName(), n.Text, n.WidgetType)
// log.Log(ERROR, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.progname, p.Text, p.WidgetType) // log.Log(ERROR, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.GetProgName(), p.Text, p.WidgetType)
// panic("n.tk.uiControl == nil") // panic("tk.uiControl == nil")
p.tk.uiTab.Append(widget.GetString(n.value), n.tk.uiControl) ptk.uiTab.Append(widget.GetString(n.State.Value), tk.uiControl)
p.tk.boxC += 1 ptk.boxC += 1
return true return true
case widget.Box: case widget.Box:
log.Log(INFO, "place() uiBox =", p.tk.uiBox) log.Warn("SPEEDY Add Something to Box", n.WidgetId, n.GetProgName())
log.Log(INFO, "place() uiControl =", n.tk.uiControl) log.Log(INFO, "place() uiBox =", ptk.uiBox)
p.tk.uiBox.Append(n.tk.uiControl, stretchy) log.Log(INFO, "place() uiControl =", tk.uiControl)
p.tk.boxC += 1 ptk.uiBox.Append(tk.uiControl, stretchy)
ptk.boxC += 1
return true return true
case widget.Window: case widget.Window:
p.tk.uiWindow.SetChild(n.tk.uiControl) log.Warn("SPEEDY Add Something to Window", n.WidgetId, n.GetProgName())
ptk.uiWindow.SetChild(tk.uiControl)
return true return true
default: default:
log.Log(ERROR, "place() how? Parent =", p.WidgetId, p.WidgetType) log.Log(ERROR, "place() how? Parent =", p.WidgetId, p.WidgetType)
} }
log.Warn("SPEEDY newplace() return", n.WidgetId, n.GetProgName())
return false return false
} }

View File

@ -3,15 +3,18 @@ package main
import ( import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
func (n *node) setText(a *widget.Action) { // func (n *node) setText(a *widget.Action) {
func setText(n *tree.Node, a *widget.Action) {
name := widget.GetString(a.Value) name := widget.GetString(a.Value)
var tk *guiWidget
tk = n.TK.(*guiWidget)
log.Log(CHANGE, "setText() START with text =", name) log.Log(CHANGE, "setText() START with text =", name)
t := n.tk if (tk == nil) {
if (t == nil) { log.Log(ERROR, "setText error. tk == nil", n.GetProgName(), n.WidgetId)
log.Log(ERROR, "setText error. tk == nil", n.progname, n.WidgetId)
return return
} }
log.Log(CHANGE, "setText() Attempt on", n.WidgetType, "with", name) log.Log(CHANGE, "setText() Attempt on", n.WidgetType, "with", name)
@ -19,38 +22,38 @@ func (n *node) setText(a *widget.Action) {
switch n.WidgetType { switch n.WidgetType {
case widget.Window: case widget.Window:
log.Warn("setText() Attempt to set the title to", name) log.Warn("setText() Attempt to set the title to", name)
t.uiWindow.SetTitle(name) tk.uiWindow.SetTitle(name)
case widget.Tab: case widget.Tab:
case widget.Group: case widget.Group:
t.uiGroup.SetTitle(name) tk.uiGroup.SetTitle(name)
case widget.Checkbox: case widget.Checkbox:
t.uiCheckbox.SetText(name) tk.uiCheckbox.SetText(name)
case widget.Textbox: case widget.Textbox:
if (t.uiEntry != nil) { if (tk.uiEntry != nil) {
t.uiEntry.SetText(name) tk.uiEntry.SetText(name)
} }
if (t.uiMultilineEntry != nil) { if (tk.uiMultilineEntry != nil) {
t.uiMultilineEntry.SetText(name) tk.uiMultilineEntry.SetText(name)
} }
case widget.Label: case widget.Label:
t.uiLabel.SetText(name) tk.uiLabel.SetText(name)
case widget.Button: case widget.Button:
t.uiButton.SetText(name) tk.uiButton.SetText(name)
case widget.Slider: case widget.Slider:
log.Log(ERROR, "setText() on slider unknown", a.ActionType, "on checkbox", n.progname) log.Log(ERROR, "setText() on slider unknown", a.ActionType, "on checkbox", n.GetProgName())
case widget.Spinner: case widget.Spinner:
log.Log(ERROR, "setText() on spinner unknown", a.ActionType, "on checkbox", n.progname) log.Log(ERROR, "setText() on spinner unknown", a.ActionType, "on checkbox", n.GetProgName())
case widget.Dropdown: case widget.Dropdown:
var orig int var orig int
var i int = -1 var i int = -1
var s string var s string
orig = t.uiCombobox.Selected() orig = tk.uiCombobox.Selected()
log.Log(CHANGE, "try to set the Dropdown to", name, "from", orig) log.Log(CHANGE, "try to set the Dropdown to", name, "from", orig)
// try to find the string // try to find the string
for i, s = range t.val { for i, s = range tk.val {
log.Log(CHANGE, "i, s", i, s) log.Log(CHANGE, "i, s", i, s)
if (name == s) { if (name == s) {
t.uiCombobox.SetSelected(i) tk.uiCombobox.SetSelected(i)
log.Log(CHANGE, "setText() Dropdown worked.", name) log.Log(CHANGE, "setText() Dropdown worked.", name)
return return
} }
@ -62,10 +65,10 @@ func (n *node) setText(a *widget.Action) {
} }
// if the string was never set, then set the dropdown to the last thing added to the menu // if the string was never set, then set the dropdown to the last thing added to the menu
if (orig == -1) { if (orig == -1) {
t.uiCombobox.SetSelected(i) tk.uiCombobox.SetSelected(i)
} }
case widget.Combobox: case widget.Combobox:
t.uiEditableCombobox.SetText(name) tk.uiEditableCombobox.SetText(name)
default: default:
log.Log(ERROR, "plugin Send() Don't know how to setText on", n.WidgetType, "yet", a.ActionType) log.Log(ERROR, "plugin Send() Don't know how to setText on", n.WidgetType, "yet", a.ActionType)
} }

View File

@ -1,22 +1,29 @@
package main package main
import ( import (
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newSlider(n *node) { func newSlider(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
s := ui.NewSlider(n.X, n.Y) var x, y int
x = n.State.Range.Low
y = n.State.Range.High
s := ui.NewSlider(x, y)
newt.uiSlider = s newt.uiSlider = s
newt.uiControl = s newt.uiControl = s
s.OnChanged(func(spin *ui.Slider) { s.OnChanged(func(spin *ui.Slider) {
n.value = newt.uiSlider.Value() n.SetValue(newt.uiSlider.Value())
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }

View File

@ -1,22 +1,25 @@
package main package main
import ( import (
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newSpinner(n *node) { func newSpinner(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
s := ui.NewSpinbox(n.X, n.Y) s := ui.NewSpinbox(n.State.Range.Low,n.State.Range.High)
newt.uiSpinbox = s newt.uiSpinbox = s
newt.uiControl = s newt.uiControl = s
s.OnChanged(func(s *ui.Spinbox) { s.OnChanged(func(s *ui.Spinbox) {
n.value = newt.uiSpinbox.Value() n.SetValue(newt.uiSpinbox.Value())
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }

View File

@ -1,7 +1,11 @@
package main package main
import "go.wit.com/dev/andlabs/ui" import (
import _ "go.wit.com/dev/andlabs/ui/winmanifest" "go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest"
)
// var andlabs map[int]*andlabsT // var andlabs map[int]*andlabsT
// var callback func(int) bool // var callback func(int) bool
@ -11,7 +15,9 @@ import _ "go.wit.com/dev/andlabs/ui/winmanifest"
var me config var me config
type config struct { type config struct {
rootNode *node // the base of the binary tree. it should have id == 0 rootNode *tree.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
} }
// stores the raw toolkit internals // stores the raw toolkit internals

View File

@ -1,21 +1,24 @@
package main package main
import ( import (
"go.wit.com/gui/toolkits/tree"
"go.wit.com/dev/andlabs/ui" "go.wit.com/dev/andlabs/ui"
_ "go.wit.com/dev/andlabs/ui/winmanifest" _ "go.wit.com/dev/andlabs/ui/winmanifest"
) )
func (p *node) newTextbox(n *node) { func newTextbox(p, n *tree.Node) {
if notNew(n) { return }
newt := new(guiWidget) newt := new(guiWidget)
if (n.X == 1) { if (n.State.Range.Low == 1) {
e := ui.NewEntry() e := ui.NewEntry()
newt.uiEntry = e newt.uiEntry = e
newt.uiControl = e newt.uiControl = e
e.OnChanged(func(spin *ui.Entry) { e.OnChanged(func(spin *ui.Entry) {
n.value = spin.Text() n.SetValue(spin.Text())
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
} else { } else {
e := ui.NewNonWrappingMultilineEntry() e := ui.NewNonWrappingMultilineEntry()
@ -23,10 +26,10 @@ func (p *node) newTextbox(n *node) {
newt.uiControl = e newt.uiControl = e
e.OnChanged(func(spin *ui.MultilineEntry) { e.OnChanged(func(spin *ui.MultilineEntry) {
n.value = spin.Text() n.SetValue(spin.Text())
n.doUserEvent() me.myTree.DoUserEvent(n)
}) })
} }
n.tk = newt n.TK = newt
p.place(n) place(p, n)
} }

31
andlabs/tree.go Normal file
View File

@ -0,0 +1,31 @@
package main
/*
This 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/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()
}

View File

@ -2,16 +2,16 @@ package main
import ( import (
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
// this is specific to the nocui toolkit func initWidget(n *tree.Node) *guiWidget {
func initWidget(n *node) *guiWidget {
var w *guiWidget var w *guiWidget
w = new(guiWidget) w = new(guiWidget)
if n.WidgetType == widget.Root { if n.WidgetType == widget.Root {
n.WidgetId = 0 n.WidgetId = 0
me.rootNode = n me.treeRoot = n
return w return w
} }
return w return w

View File

@ -6,6 +6,7 @@ import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
func (t *guiWidget) MessageWindow(msg1 string, msg2 string) { func (t *guiWidget) MessageWindow(msg1 string, msg2 string) {
@ -16,23 +17,24 @@ func (t *guiWidget) ErrorWindow(msg1 string, msg2 string) {
ui.MsgBoxError(t.uiWindow, msg1, msg2) ui.MsgBoxError(t.uiWindow, msg1, msg2)
} }
func newWindow(n *node) { func newWindow(p, n *tree.Node) {
var newt *guiWidget var newt *guiWidget
newt = new(guiWidget) newt = new(guiWidget)
// menubar bool is if the OS defined border on the window should be used // menubar bool is if the OS defined border on the window should be used
win := ui.NewWindow(n.progname, n.X, n.Y, menubar) win := ui.NewWindow(n.GetProgName(), 640, 480, menubar)
win.SetBorderless(canvas) win.SetBorderless(canvas)
win.SetMargined(margin) win.SetMargined(margin)
win.OnClosing(func(*ui.Window) bool { win.OnClosing(func(*ui.Window) bool {
n.show(false) // show(n, false)
n.doUserEvent() me.myTree.DoWindowCloseEvent(n)
return false return false
}) })
newt.uiWindow = win newt.uiWindow = win
newt.uiControl = win newt.uiControl = win
n.tk = newt n.TK = newt
place(p, n)
win.Show() win.Show()
return return
} }

View File

@ -1,68 +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 (
"reflect"
"strconv"
"go.wit.com/log"
"go.wit.com/gui/widget"
)
// 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
}

View File

@ -1 +0,0 @@
../nocui/common.go

218
gocui/common.go Normal file
View File

@ -0,0 +1,218 @@
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 string(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
}

View File

@ -50,7 +50,7 @@ func action(a *widget.Action) {
n.AddText(widget.GetString(a.Value)) n.AddText(widget.GetString(a.Value))
case widget.Move: case widget.Move:
log.Log(NOW, "attempt to move() =", a.ActionType, a.WidgetType, a.ProgName) log.Log(NOW, "attempt to move() =", a.ActionType, a.WidgetType, a.ProgName)
case widget.CloseToolkit: case widget.ToolkitClose:
log.Log(NOW, "attempting to close the plugin and release stdout and stderr") log.Log(NOW, "attempting to close the plugin and release stdout and stderr")
standardExit() standardExit()
case widget.Enable: case widget.Enable:

View File

@ -3,7 +3,6 @@ package main
import ( import (
"fmt" "fmt"
"errors" "errors"
"strconv"
"bufio" "bufio"
"strings" "strings"
@ -60,7 +59,7 @@ func (n *node) showView() {
if (w.cuiName == "") { if (w.cuiName == "") {
log.Log(ERROR, "showView() w.cuiName was not set for widget", w) log.Log(ERROR, "showView() w.cuiName was not set for widget", w)
w.cuiName = strconv.Itoa(n.WidgetId) w.cuiName = string(n.WidgetId)
} }
// if the gocui element doesn't exist, create it // if the gocui element doesn't exist, create it

View File

@ -1,8 +1,6 @@
package main package main
import ( import (
"strconv"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
) )
@ -15,7 +13,7 @@ func initWidget(n *node) *guiWidget {
w.frame = true w.frame = true
// set the name used by gocui to the id // set the name used by gocui to the id
w.cuiName = strconv.Itoa(n.WidgetId) w.cuiName = string(n.WidgetId)
if n.WidgetType == widget.Root { if n.WidgetType == widget.Root {
log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId) log.Log(INFO, "setupWidget() FOUND ROOT w.id =", n.WidgetId)

View File

@ -1,152 +1,87 @@
package main package main
/*
a simple function to handle widget actions
You can tie this into your toolkit here.
*/
import ( import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
// "go.wit.com/gui/toolkits/tree"
) )
func (n *node) show(b bool) { func doAction(a widget.Action) {
}
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) {
log.Log(INFO, "doAction() START a.ActionType =", a.ActionType) log.Log(INFO, "doAction() START a.ActionType =", a.ActionType)
log.Log(INFO, "doAction() START a.ProgName =", a.ProgName) log.Log(INFO, "doAction() START a.ProgName =", a.ProgName)
if (a.ActionType == widget.InitToolkit) { if (a.ActionType == widget.ToolkitInit) {
// 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()
return return
} }
log.Log(INFO, "doAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId) log.Log(INFO, "doAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId)
switch a.WidgetType { switch a.WidgetType {
case widget.Root: case widget.Root:
me.rootNode = addNode(a) me.treeRoot = me.myTree.AddNode(&a)
log.Log(INFO, "doAction() found rootNode") log.Log(INFO, "doAction() found treeRoot")
return
case widget.Flag:
// flag(&a)
return return
} }
n := me.rootNode.findWidgetId(a.WidgetId)
switch a.ActionType { switch a.ActionType {
case widget.Add: case widget.Add:
addNode(a) me.myTree.AddNode(&a)
return
}
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.Show: case widget.Show:
n.show(true) n.State.Visable = true
case widget.Hide: case widget.Hide:
n.show(false) n.State.Visable = false
case widget.Enable: case widget.Enable:
n.enable(true) n.State.Visable = true
case widget.Disable: case widget.Disable:
n.enable(false) n.State.Visable = false
case widget.Get: case widget.Get:
// n.setText(a.S) log.Warn("value =", n.State.Value)
case widget.GetText: case widget.GetText:
switch a.WidgetType { log.Warn("value =", n.String())
case widget.Textbox:
a.Value = n.value
}
case widget.Set: case widget.Set:
// n.setText(a.S) n.State.Value = a.State.Value
case widget.SetText: 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: case widget.AddText:
// n.setText(a.S) n.State.Strings = append(a.State.Strings, widget.GetString(a.State.Value))
case widget.Margin: case widget.Margin:
n.pad(widget.Unmargin) n.State.Pad = true
case widget.Unmargin: case widget.Unmargin:
n.pad(widget.Margin) n.State.Pad = false
case widget.Pad: case widget.Pad:
n.pad(widget.Pad) n.State.Pad = true
case widget.Unpad: case widget.Unpad:
n.pad(widget.Unpad) n.State.Pad = false
case widget.Delete: case widget.Delete:
n.Delete() log.Warn("doAction() TODO: Delete()")
// n.Delete()
case widget.Move: case widget.Move:
log.Log(INFO, "doAction() attempt to move() =", a.ActionType, a.WidgetType) log.Warn("doAction() TODO: Move()")
newParent := me.rootNode.findWidgetId(a.ParentId)
n.move(newParent)
default: default:
log.Log(ERROR, "doAction() Unknown =", a.ActionType, a.WidgetType) log.Log(ERROR, "doAction() Unknown =", a.ActionType, a.WidgetType)
} }

View File

@ -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
}

View File

@ -1,11 +1,13 @@
package main package main
/*
import ( import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
"go.wit.com/gui/toolkits/tree"
) )
func (n *node) doWidgetClick() { func doWidgetClick(n *tree.Node) {
switch n.WidgetType { switch n.WidgetType {
case widget.Root: case widget.Root:
// THIS IS THE BEGINING OF THE LAYOUT // THIS IS THE BEGINING OF THE LAYOUT
@ -17,32 +19,33 @@ func (n *node) doWidgetClick() {
// rootNode.dumpTree(true) // rootNode.dumpTree(true)
case widget.Window: case widget.Window:
// setCurrentWindow(w) // setCurrentWindow(w)
n.doUserEvent() // n.doUserEvent()
case widget.Tab: case widget.Tab:
// setCurrentTab(w) // setCurrentTab(w)
case widget.Group: case widget.Group:
// n.placeWidgets() // n.placeWidgets()
// n.toggleTree() // n.toggleTree()
case widget.Checkbox: case widget.Checkbox:
if widget.GetBool(n.value) { if n.Bool() {
// n.setCheckbox(false) // n.setCheckbox(false)
} else { } else {
// n.setCheckbox(true) // n.setCheckbox(true)
} }
n.doUserEvent() // n.doUserEvent()
case widget.Grid: case widget.Grid:
// rootNode.hideWidgets() // rootNode.hideWidgets()
// n.placeGrid() // n.placeGrid()
// n.showWidgets() // n.showWidgets()
case widget.Box: case widget.Box:
// n.showWidgetPlacement(logNow, "drawTree()") // n.showWidgetPlacement(logNow, "drawTree()")
if widget.GetBool(n.value) { if n.Bool() {
log.Log(NOW, "BOX IS HORIZONTAL", n.progname) log.Log(NOW, "BOX IS HORIZONTAL", n.GetProgName())
} else { } else {
log.Log(NOW, "BOX IS VERTICAL", n.progname) log.Log(NOW, "BOX IS VERTICAL", n.GetProgName())
} }
case widget.Button: case widget.Button:
n.doUserEvent() // n.doUserEvent()
default: default:
} }
} }
*/

View File

@ -1,10 +1,3 @@
module go.wit.com/gui/toolkits/nocui module go.wit.com/gui/toolkits/nocui
go 1.21.4 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

View File

@ -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=

View File

@ -1,55 +1,24 @@
package main 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 This is reference code for toolkit developers
//
// 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 { The 'nocui' is a bare minimum toolkit. It's all you need
return pluginChan 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() { func init() {
log.Log(INFO, "Init()") log.Log(INFO, "Init()")
// andlabs = make(map[int]*andlabsT) me.myTree = tree.New()
pluginChan = make(chan widget.Action, 1) me.myTree.PluginName = "nocui"
me.myTree.ActionFromChannel = doAction
log.Log(NOW, "Init() start channel reciever")
go catchActionChannel()
go simpleStdin() go simpleStdin()
log.Log(NOW, "Init() END") log.Log(INFO, "Init() END")
} }

View File

@ -4,6 +4,7 @@ import (
"os" "os"
"fmt" "fmt"
"bufio" "bufio"
"runtime/debug"
"strings" "strings"
"strconv" "strconv"
@ -12,6 +13,15 @@ import (
) )
func simpleStdin() { 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) scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() { for scanner.Scan() {
s := scanner.Text() s := scanner.Text()
@ -19,63 +29,46 @@ func simpleStdin() {
switch s { switch s {
case "l": case "l":
log.Log(NOW, "list widgets") log.Log(NOW, "list widgets")
me.rootNode.listWidgets() me.treeRoot.ListWidgets()
case "b": case "b":
log.Log(NOW, "show buttons") 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": case "d":
var a widget.Action me.myTree.DoEnableDebugger()
a.ActionType = widget.EnableDebug
callback <- a
case "": case "":
fmt.Println("") fmt.Println("")
fmt.Println("Enter:") fmt.Println("Enter:")
fmt.Println("'l': list all widgets") fmt.Println("'l': list all widgets")
fmt.Println("'b': for buttons") fmt.Println("'b': for buttons")
fmt.Println("'g': load gocui plugin")
fmt.Println("'a': load andlabs plugin")
fmt.Println("'d': enable debugging") fmt.Println("'d': enable debugging")
default: default:
i, _ := strconv.Atoi(s) i, _ := strconv.Atoi(s)
log.Log(NOW, "got input:", i) log.Log(NOW, "got input:", i)
n := me.rootNode.findWidgetId(i) n := me.treeRoot.FindWidgetId(i)
if (n != nil) { if (n != nil) {
n.dumpWidget("found node") n.DumpWidget("found node")
n.doUserEvent() 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
}

View File

@ -1,17 +1,22 @@
package main package main
import (
"go.wit.com/gui/toolkits/tree"
)
// stores the raw toolkit internals // stores the raw toolkit internals
type guiWidget struct { type guiWidget struct {
Width int Width int
Height int Height int
c int c int
val map[int]string val map[string]int
} }
// It's probably a terrible idea to call this 'me' // It's probably a terrible idea to call this 'me'
var me config var me config
type config struct { 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
} }

24
nocui/tree.go Normal file
View File

@ -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()
}

View File

@ -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
}

47
tree/addNode.go Normal file
View File

@ -0,0 +1,47 @@
package tree
import (
"errors"
"go.wit.com/log"
"go.wit.com/gui/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
}

35
tree/common.go Normal file
View File

@ -0,0 +1,35 @@
package tree
import (
"go.wit.com/gui/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
}

44
tree/debug.go Normal file
View File

@ -0,0 +1,44 @@
package tree
import (
"go.wit.com/log"
"go.wit.com/gui/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
}

88
tree/event.go Normal file
View File

@ -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/gui/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
}

58
tree/init.go Normal file
View File

@ -0,0 +1,58 @@
package tree
import (
"sync"
"errors"
"go.wit.com/log"
"go.wit.com/gui/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
}

View File

@ -1,4 +1,4 @@
package main package tree
/* /*
These code should be common to all gui plugins These code should be common to all gui plugins
@ -12,15 +12,11 @@ package main
*/ */
import ( import (
"reflect"
"strconv"
"go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
) )
// searches the binary tree for a WidgetId // searches the binary tree for a WidgetId
func (n *node) findWidgetId(id int) *node { func (n *Node) FindWidgetId(id int) *Node {
if (n == nil) { if (n == nil) {
return nil return nil
} }
@ -30,7 +26,7 @@ func (n *node) findWidgetId(id int) *node {
} }
for _, child := range n.children { for _, child := range n.children {
newN := child.findWidgetId(id) newN := child.FindWidgetId(id)
if (newN != nil) { if (newN != nil) {
return newN return newN
} }
@ -38,21 +34,6 @@ func (n *node) findWidgetId(id int) *node {
return nil 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 // Other goroutines must use this to access the GUI
// //
// You can not acess / process the GUI thread directly from // You can not acess / process the GUI thread directly from
@ -60,10 +41,10 @@ func (n *node) doUserEvent() {
// Linux, MacOS and Windows work (they all work differently. suprise. surprise.) // Linux, MacOS and Windows work (they all work differently. suprise. surprise.)
// //
// this sets the channel to send user events back from the plugin // this sets the channel to send user events back from the plugin
func Callback(guiCallback chan widget.Action) { func (me *TreeInfo) Callback(guiCallback chan widget.Action) {
callback = guiCallback me.callback = guiCallback
} }
func PluginChannel() chan widget.Action { func (me *TreeInfo) PluginChannel() chan widget.Action {
return pluginChan return me.pluginChan
} }

View File

@ -1,4 +1,4 @@
package main package tree
/* /*
These code should be common to all gui plugins These code should be common to all gui plugins
@ -12,23 +12,29 @@ package main
*/ */
import ( import (
"reflect" // "go.wit.com/log"
"strconv"
"go.wit.com/log"
"go.wit.com/gui/widget" "go.wit.com/gui/widget"
) )
// this is the channel we send user events like // var me *TreeInfo
// mouse clicks or keyboard events back to the program
var callback chan widget.Action
// this is the channel we get requests to make widgets type TreeInfo struct {
var pluginChan chan widget.Action // 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 { type Node struct {
parent *node Parent *Node
children []*node children []*Node
WidgetId int // widget ID WidgetId int // widget ID
WidgetType widget.WidgetType WidgetType widget.WidgetType
@ -36,6 +42,8 @@ type Node struct {
State widget.State State widget.State
Strings map[string]int
// the internal plugin toolkit structure // the internal plugin toolkit structure
// in the gtk plugin, it has gtk things like margin & border settings // 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 // in the text console one, it has text console things like colors for menus & buttons