large refactor to use the tree package

Things build and now need to be fixed
    treeRoot has no children
    lists all widgets works
    shows help
    module loads

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2024-01-28 02:20:31 -06:00
parent a9913b70ed
commit 4fbbd2cee1
21 changed files with 624 additions and 693 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.swp

View File

@ -4,9 +4,6 @@ all: plugin
plugin: plugin:
GO111MODULE=off go build -v -buildmode=plugin -o ../gocui.so GO111MODULE=off go build -v -buildmode=plugin -o ../gocui.so
goget:
go get -v -t -u
objdump: objdump:
objdump -t ../gocui.so |less objdump -t ../gocui.so |less
@ -14,11 +11,8 @@ log:
reset reset
tail -f /tmp/witgui.* /tmp/guilogfile tail -f /tmp/witgui.* /tmp/guilogfile
cleanbuild: goimports:
go build -v -x -buildmode=plugin -o ../nocui.so goimports -w *.go
check-git-clean:
@git diff-index --quiet HEAD -- || (echo "Git repository is dirty, please commit your changes first"; exit 1)
redomod: redomod:
rm -f go.* rm -f go.*

30
add.go
View File

@ -2,6 +2,7 @@ package main
import ( import (
log "go.wit.com/log" log "go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/widget" "go.wit.com/widget"
) )
@ -9,11 +10,12 @@ var fakeStartWidth int = me.FakeW
var fakeStartHeight int = me.TabH + me.FramePadH var fakeStartHeight int = me.TabH + me.FramePadH
// setup fake labels for non-visible things off screen // setup fake labels for non-visible things off screen
func (n *node) setFake() { func setFake(n *tree.Node) {
w := n.tk var w *guiWidget
w = n.TK.(*guiWidget)
w.isFake = true w.isFake = true
n.gocuiSetWH(fakeStartWidth, fakeStartHeight) w.gocuiSetWH(fakeStartWidth, fakeStartHeight)
fakeStartHeight += w.gocuiSize.Height() fakeStartHeight += w.gocuiSize.Height()
// TODO: use the actual max hight of the terminal window // TODO: use the actual max hight of the terminal window
@ -22,23 +24,25 @@ func (n *node) setFake() {
fakeStartWidth += me.FakeW fakeStartWidth += me.FakeW
} }
if true { if true {
n.showView() w.showView()
} }
} }
// set the widget start width & height // set the widget start width & height
func (n *node) addWidget() { // func (n *node) addWidget(n *tree.Node) {
nw := n.tk func addWidget(n *tree.Node) {
log.Log(INFO, "setStartWH() w.id =", n.WidgetId, "n.name", n.progname) var nw *guiWidget
nw = n.TK.(*guiWidget)
log.Log(INFO, "setStartWH() w.id =", n.WidgetId, "n.name", n.String())
switch n.WidgetType { switch n.WidgetType {
case widget.Root: case widget.Root:
log.Log(INFO, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.progname) log.Log(INFO, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.String())
nw.color = &colorRoot nw.color = &colorRoot
n.setFake() setFake(n)
return return
case widget.Flag: case widget.Flag:
nw.color = &colorFlag nw.color = &colorFlag
n.setFake() setFake(n)
return return
case widget.Window: case widget.Window:
nw.frame = false nw.frame = false
@ -54,12 +58,12 @@ func (n *node) addWidget() {
case widget.Box: case widget.Box:
nw.color = &colorBox nw.color = &colorBox
nw.isFake = true nw.isFake = true
n.setFake() setFake(n)
return return
case widget.Grid: case widget.Grid:
nw.color = &colorGrid nw.color = &colorGrid
nw.isFake = true nw.isFake = true
n.setFake() setFake(n)
return return
case widget.Group: case widget.Group:
nw.color = &colorGroup nw.color = &colorGroup
@ -76,5 +80,5 @@ func (n *node) addWidget() {
} }
*/ */
} }
n.showWidgetPlacement(true, "addWidget()") showWidgetPlacement(n, true, "addWidget()")
} }

View File

@ -23,10 +23,10 @@ func init() {
short := "gocui" short := "gocui"
NOW = log.NewFlag("NOW", true, full, short, "temp debugging stuff") NOW = log.NewFlag("NOW", true, full, short, "temp debugging stuff")
INFO = log.NewFlag("INFO", false, full, short, "normal debugging stuff") INFO = log.NewFlag("INFO", true, full, short, "normal debugging stuff")
WARN = log.NewFlag("WARN", true, full, short, "bad things") WARN = log.NewFlag("WARN", true, full, short, "bad things")
SPEW = log.NewFlag("SPEW", false, full, short, "spew stuff") SPEW = log.NewFlag("SPEW", false, full, short, "spew stuff")
ERROR = log.NewFlag("ERROR", false, full, short, "toolkit errors") ERROR = log.NewFlag("ERROR", true, full, short, "toolkit errors")
} }

View File

@ -1,23 +1,21 @@
package main package main
import ( import (
// "github.com/awesome-gocui/gocui"
"go.wit.com/widget" "go.wit.com/widget"
) )
func (n *node) setCheckbox(b any) { func (w *guiWidget) setCheckbox(b any) {
w := n.tk if w.node.WidgetType != widget.Checkbox {
if n.WidgetType != widget.Checkbox {
return return
} }
if widget.GetBool(b) { if widget.GetBool(b) {
n.value = b w.checked = widget.GetBool(b)
n.tk.label = "X " + n.label w.label = "X " + w.label
} else { } else {
n.value = b w.checked = widget.GetBool(b)
n.tk.label = " " + n.label w.label = " " + w.label
} }
t := len(n.tk.label) + 1 t := len(w.label) + 1
w.gocuiSize.w1 = w.gocuiSize.w0 + t w.gocuiSize.w1 = w.gocuiSize.w0 + t
// w.realWidth = w.gocuiSize.Width() + me.PadW // w.realWidth = w.gocuiSize.Width() + me.PadW
@ -28,6 +26,6 @@ func (n *node) setCheckbox(b any) {
// w.realHeight += me.FramePadH // w.realHeight += me.FramePadH
// } // }
n.deleteView() w.deleteView()
n.showView() w.showView()
} }

274
click.go
View File

@ -2,22 +2,23 @@ package main
import ( import (
"fmt" "fmt"
"github.com/awesome-gocui/gocui" "github.com/awesome-gocui/gocui"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/widget" "go.wit.com/widget"
) )
// set isCurrent = false everywhere // set isCurrent = false everywhere
func unsetCurrent(n *node) { func unsetCurrent(w *guiWidget) {
w := n.tk
w.isCurrent = false w.isCurrent = false
if n.WidgetType == widget.Tab { if w.node.WidgetType == widget.Tab {
// n.tk.color = &colorTab // n.tk.color = &colorTab
// n.setColor() // n.setColor()
} }
for _, child := range n.children { for _, child := range w.children {
unsetCurrent(child) unsetCurrent(child)
} }
} }
@ -25,14 +26,17 @@ func unsetCurrent(n *node) {
// when adding a new widget, this will update the display // when adding a new widget, this will update the display
// of the current widgets if that widget is supposed // of the current widgets if that widget is supposed
// to be in current display // to be in current display
func (n *node) updateCurrent() { func updateCurrent(n *tree.Node) {
log.Log(NOW, "updateCurrent()", n.progname) var w *guiWidget
w = n.TK.(*guiWidget)
log.Log(NOW, "updateCurrent()", w.String())
if n.WidgetType == widget.Tab { if n.WidgetType == widget.Tab {
if n.IsCurrent() { if w.IsCurrent() {
// n.tk.color = &colorActiveT // n.tk.color = &colorActiveT
n.setColor(&colorActiveT) setColor(n, &colorActiveT)
n.hideView() w.hideView()
n.showView() w.showView()
setCurrentTab(n) setCurrentTab(n)
} else { } else {
// n.tk.color = &colorTab // n.tk.color = &colorTab
@ -41,7 +45,7 @@ func (n *node) updateCurrent() {
return return
} }
if n.WidgetType == widget.Window { if n.WidgetType == widget.Window {
if n.IsCurrent() { if w.IsCurrent() {
// setCurrentWindow(n) // setCurrentWindow(n)
} }
return return
@ -49,24 +53,27 @@ func (n *node) updateCurrent() {
if n.WidgetType == widget.Root { if n.WidgetType == widget.Root {
return return
} }
n.parent.updateCurrent() updateCurrent(n.Parent)
} }
// shows the widgets in a window // shows the widgets in a window
func setCurrentWindow(n *node) { func setCurrentWindow(n *tree.Node) {
if n.IsCurrent() { var w *guiWidget
w = n.TK.(*guiWidget)
if w.IsCurrent() {
return return
} }
w := n.tk
if n.WidgetType != widget.Window { if n.WidgetType != widget.Window {
return return
} }
unsetCurrent(me.rootNode) var rootTK *guiWidget
rootTK = me.treeRoot.TK.(*guiWidget)
unsetCurrent(rootTK)
if n.hasTabs { if w.hasTabs {
// set isCurrent = true on the first tab // set isCurrent = true on the first tab
for _, child := range n.children { for _, child := range w.children {
child.tk.isCurrent = true child.isCurrent = true
break break
} }
} else { } else {
@ -75,46 +82,53 @@ func setCurrentWindow(n *node) {
} }
// shows the widgets in a tab // shows the widgets in a tab
func setCurrentTab(n *node) { func setCurrentTab(n *tree.Node) {
w := n.tk var w, p, rootTK *guiWidget
w = n.TK.(*guiWidget)
if n.WidgetType != widget.Tab { if n.WidgetType != widget.Tab {
return return
} }
unsetCurrent(me.rootNode) rootTK = me.treeRoot.TK.(*guiWidget)
unsetCurrent(rootTK)
w.isCurrent = true w.isCurrent = true
p := n.parent.tk p = n.Parent.TK.(*guiWidget)
p.isCurrent = true p.isCurrent = true
log.Log(NOW, "setCurrent()", n.progname) log.Log(NOW, "setCurrent()", n.String())
} }
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
log.Log(NOW, "doWidgetClick()", n.progname) log.Log(NOW, "doWidgetClick()", n.String())
redoWindows(0, 0) redoWindows(0, 0)
case widget.Flag: case widget.Flag:
log.Log(NOW, "doWidgetClick() FLAG widget name =", n.progname) log.Log(NOW, "doWidgetClick() FLAG widget name =", n.String())
log.Log(NOW, "doWidgetClick() if this is the dropdown menu, handle it here?") log.Log(NOW, "doWidgetClick() if this is the dropdown menu, handle it here?")
case widget.Window: case widget.Window:
if me.currentWindow == n { if me.currentWindow == n {
return return
} }
if me.currentWindow != nil { if me.currentWindow != nil {
unsetCurrent(me.currentWindow) var w *guiWidget
me.currentWindow.setColor(&colorWindow) w = me.currentWindow.TK.(*guiWidget)
me.currentWindow.hideWidgets() unsetCurrent(w)
setColor(me.currentWindow, &colorWindow)
w.hideWidgets()
} }
n.hideWidgets()
me.currentWindow = n me.currentWindow = n
// setCurrentWindow(n) // probably delete this // setCurrentWindow(n) // probably delete this
n.setColor(&colorActiveW) setColor(n, &colorActiveW)
n.redoTabs(me.TabW, me.TabH)
for _, child := range n.children { var w *guiWidget
w = n.TK.(*guiWidget)
w.hideWidgets()
w.redoTabs(me.TabW, me.TabH)
for _, child := range w.children {
if child.currentTab == true { if child.currentTab == true {
log.Log(NOW, "FOUND CURRENT TAB", child.progname) log.Log(NOW, "FOUND CURRENT TAB", child.String())
setCurrentTab(child) setCurrentTab(child.node)
child.placeWidgets(me.RawW, me.RawH) placeWidgets(child.node, me.RawW, me.RawH)
child.showWidgets() child.showWidgets()
return return
} }
@ -124,62 +138,76 @@ func (n *node) doWidgetClick() {
} }
*/ */
case widget.Tab: case widget.Tab:
if n.IsCurrent() { var w *guiWidget
w = n.TK.(*guiWidget)
if w.IsCurrent() {
return // do nothing if you reclick on the already selected tab return // do nothing if you reclick on the already selected tab
} }
// find the window and disable the active tab // find the window and disable the active tab
p := n.parent p := n.Parent
if p != nil { if p != nil {
p.hideWidgets() var w *guiWidget
p.redoTabs(me.TabW, me.TabH) w = p.TK.(*guiWidget)
unsetCurrent(p) w.hideWidgets()
for _, child := range p.children { w.redoTabs(me.TabW, me.TabH)
if child.WidgetType == widget.Tab { unsetCurrent(w)
child.setColor(&colorTab) for _, child := range w.children {
n.currentTab = false if child.node.WidgetType == widget.Tab {
setColor(child.node, &colorTab)
child.currentTab = false
} }
} }
} }
n.currentTab = true w.currentTab = true
n.setColor(&colorActiveT) setColor(n, &colorActiveT)
setCurrentTab(n) setCurrentTab(n)
n.placeWidgets(me.RawW, me.RawH) placeWidgets(n, me.RawW, me.RawH)
n.showWidgets() w.showWidgets()
case widget.Group: case widget.Group:
// n.placeWidgets(p.tk.startH, newH) // n.placeWidgets(p.tk.startH, newH)
n.toggleTree() toggleTree(n)
case widget.Checkbox: case widget.Checkbox:
if widget.GetBool(n.value) { var w *guiWidget
n.setCheckbox(false) w = n.TK.(*guiWidget)
if widget.GetBool(w.value) {
w.setCheckbox(false)
} else { } else {
n.setCheckbox(true) w.setCheckbox(true)
} }
n.doUserEvent() // n.doUserEvent()
me.myTree.SendUserEvent(me.treeRoot)
case widget.Grid: case widget.Grid:
newR := n.realGocuiSize() newR := realGocuiSize(n)
// w,h := n.logicalSize() // w,h := n.logicalSize()
// w := newR.w1 - newR.w0 // w := newR.w1 - newR.w0
// h := newR.h1 - newR.h0 // h := newR.h1 - newR.h0
n.placeGrid(newR.w0, newR.h0) placeGrid(n, newR.w0, newR.h0)
n.showWidgets() var w *guiWidget
w = n.TK.(*guiWidget)
w.showWidgets()
case widget.Box: case widget.Box:
var w *guiWidget
w = n.TK.(*guiWidget)
// w.showWidgetPlacement(logNow, "drawTree()") // w.showWidgetPlacement(logNow, "drawTree()")
if n.direction == widget.Horizontal { if w.direction == widget.Horizontal {
log.Log(NOW, "BOX IS HORIZONTAL", n.progname) log.Log(NOW, "BOX IS HORIZONTAL", n.String())
} else { } else {
log.Log(NOW, "BOX IS VERTICAL", n.progname) log.Log(NOW, "BOX IS VERTICAL", n.String())
} }
// n.placeWidgets() placeWidgets(n, me.RawW, me.RawH)
n.toggleTree() toggleTree(n)
case widget.Button: case widget.Button:
n.doUserEvent() // doUserEvent(n)
me.myTree.SendUserEvent(n)
case widget.Dropdown: case widget.Dropdown:
log.Log(NOW, "do the dropdown here") log.Log(NOW, "do the dropdown here")
if me.ddview == nil { if me.ddview == nil {
me.ddview = addDropdown() me.ddview = addDropdown()
tk := me.ddview.tk // n.TK = initWidget(n)
var tk *guiWidget
tk = me.ddview.TK.(*guiWidget)
tk.gocuiSize.w0 = 20 tk.gocuiSize.w0 = 20
tk.gocuiSize.w1 = 40 tk.gocuiSize.w1 = 40
tk.gocuiSize.h0 = 10 tk.gocuiSize.h0 = 10
@ -196,28 +224,30 @@ func (n *node) doWidgetClick() {
tk.v.Frame = true tk.v.Frame = true
tk.v.Clear() tk.v.Clear()
fmt.Fprint(tk.v, "example.com\nwit.com") fmt.Fprint(tk.v, "example.com\nwit.com")
me.ddview.SetVisible(true) SetVisible(me.ddview, true)
return return
} }
log.Log(NOW, "doWidgetClick() visible =", me.ddview.Visible()) log.Log(NOW, "doWidgetClick() visible =", Visible(me.ddview))
if me.ddview.Visible() { var tk *guiWidget
me.ddview.SetVisible(false) tk = me.ddview.TK.(*guiWidget)
if Visible(me.ddview) {
SetVisible(me.ddview, false)
me.baseGui.DeleteView("ddview") me.baseGui.DeleteView("ddview")
me.ddview.tk.v = nil tk.v = nil
} else { } else {
var dnsList string var dnsList string
for i, s := range n.vals { for i, s := range tk.vals {
log.Log(NOW, "AddText()", n.progname, i, s) log.Log(NOW, "AddText()", n.String(), i, s)
dnsList += s + "\n" dnsList += s + "\n"
} }
me.ddNode = n me.ddNode = n
log.Log(NOW, "new dns list should be set to:", dnsList) log.Log(NOW, "new dns list should be set to:", dnsList)
me.ddview.label = dnsList tk.label = dnsList
me.ddview.SetText(dnsList) tk.SetText(dnsList)
me.ddview.SetVisible(true) SetVisible(me.ddview, true)
} }
for i, s := range n.vals { for i, s := range tk.vals {
log.Log(NOW, "AddText()", n.progname, i, s) log.Log(NOW, "AddText()", tk.String(), i, s)
} }
default: default:
} }
@ -225,32 +255,35 @@ func (n *node) doWidgetClick() {
var toggle bool = true var toggle bool = true
func (n *node) toggleTree() { func toggleTree(n *tree.Node) {
var w *guiWidget
w = n.TK.(*guiWidget)
if toggle { if toggle {
n.drawTree(toggle) drawTree(n, toggle)
toggle = false toggle = false
} else { } else {
n.hideWidgets() w.hideWidgets()
toggle = true toggle = true
} }
} }
// display the widgets in the binary tree // display the widgets in the binary tree
func (n *node) drawTree(draw bool) { func drawTree(n *tree.Node, draw bool) {
w := n.tk var w *guiWidget
w = n.TK.(*guiWidget)
if w == nil { if w == nil {
return return
} }
n.showWidgetPlacement(true, "drawTree()") showWidgetPlacement(n, true, "drawTree()")
if draw { if draw {
// w.textResize() // w.textResize()
n.showView() w.showView()
} else { } else {
n.deleteView() w.deleteView()
} }
for _, child := range n.children { for _, child := range w.children {
child.drawTree(draw) drawTree(child.node, draw)
} }
} }
@ -261,14 +294,16 @@ func click(g *gocui.Gui, v *gocui.View) error {
log.Log(INFO, "click() START", v.Name()) log.Log(INFO, "click() START", v.Name())
// n := me.rootNode.findWidgetName(v.Name()) // n := me.rootNode.findWidgetName(v.Name())
n := findUnderMouse() n := findUnderMouse()
var w *guiWidget
w = n.TK.(*guiWidget)
if n != nil { if n != nil {
log.Log(NOW, "click() Found widget =", n.WidgetId, n.progname, ",", n.label) log.Log(NOW, "click() Found widget =", n.WidgetId, n.String(), ",", w.label)
if n.progname == "DropBox" { if n.String() == "DropBox" {
log.Log(NOW, "click() this is the dropdown menu. set a flag here what did I click? where is the mouse?") log.Log(NOW, "click() this is the dropdown menu. set a flag here what did I click? where is the mouse?")
log.Log(NOW, "click() set a global dropdown clicked flag=true here") log.Log(NOW, "click() set a global dropdown clicked flag=true here")
me.ddClicked = true me.ddClicked = true
} }
n.doWidgetClick() doWidgetClick(n)
} else { } else {
log.Log(NOW, "click() could not find node name =", v.Name()) log.Log(NOW, "click() could not find node name =", v.Name())
} }
@ -282,17 +317,18 @@ func click(g *gocui.Gui, v *gocui.View) error {
return nil return nil
} }
func findUnderMouse() *node { func findUnderMouse() *tree.Node {
var found *node var found *tree.Node
var widgets []*node var widgets []*tree.Node
var f func(n *node) var f func(n *tree.Node)
w, h := me.baseGui.MousePosition() w, h := me.baseGui.MousePosition()
// find buttons that are below where the mouse button click // find buttons that are below where the mouse button click
f = func(n *node) { f = func(n *tree.Node) {
widget := n.tk var widget *guiWidget
widget = n.TK.(*guiWidget)
// ignore widgets that are not visible // ignore widgets that are not visible
if n.Visible() { if Visible(n) {
if (widget.gocuiSize.w0 <= w) && (w <= widget.gocuiSize.w1) && if (widget.gocuiSize.w0 <= w) && (w <= widget.gocuiSize.w1) &&
(widget.gocuiSize.h0 <= h) && (h <= widget.gocuiSize.h1) { (widget.gocuiSize.h0 <= h) && (h <= widget.gocuiSize.h1) {
widgets = append(widgets, n) widgets = append(widgets, n)
@ -301,7 +337,7 @@ func findUnderMouse() *node {
} }
if n == me.ddview { if n == me.ddview {
log.Log(NOW, "findUnderMouse() found ddview") log.Log(NOW, "findUnderMouse() found ddview")
if n.Visible() { if Visible(n) {
log.Log(NOW, "findUnderMouse() and ddview is visable. hide it here. TODO: find highlighted row") log.Log(NOW, "findUnderMouse() and ddview is visable. hide it here. TODO: find highlighted row")
found = n found = n
// find the actual value here and set the dropdown widget // find the actual value here and set the dropdown widget
@ -311,47 +347,51 @@ func findUnderMouse() *node {
} }
} }
for _, child := range n.children { for _, child := range widget.children {
f(child) f(child.node)
} }
} }
f(me.rootNode) f(me.treeRoot)
// widgets has everything that matches // widgets has everything that matches
// TODO: pop up menu with a list of them // TODO: pop up menu with a list of them
for _, n := range widgets { for _, n := range widgets {
//log(logNow, "ctrlDown() FOUND widget", widget.id, widget.name) //log(logNow, "ctrlDown() FOUND widget", widget.id, widget.name)
n.showWidgetPlacement(true, "findUnderMouse() FOUND") showWidgetPlacement(n, true, "findUnderMouse() FOUND")
} }
return found return found
} }
// find the widget under the mouse click // find the widget under the mouse click
func ctrlDown(g *gocui.Gui, v *gocui.View) error { func ctrlDown(g *gocui.Gui, v *gocui.View) error {
var found *node var found *tree.Node
// var widgets []*node // var widgets []*node
// var f func (n *node) // var f func (n *node)
found = findUnderMouse() found = findUnderMouse()
if me.ctrlDown == nil { if me.ctrlDown == nil {
setupCtrlDownWidget() setupCtrlDownWidget()
me.ctrlDown.label = found.progname
me.ctrlDown.tk.cuiName = "ctrlDown" var tk *guiWidget
tk = me.ctrlDown.TK.(*guiWidget)
tk.label = found.String()
tk.cuiName = "ctrlDown"
// me.ctrlDown.parent = me.rootNode // me.ctrlDown.parent = me.rootNode
} }
cd := me.ctrlDown.tk var tk *guiWidget
tk = me.ctrlDown.TK.(*guiWidget)
if found == nil { if found == nil {
found = me.rootNode found = me.treeRoot
} }
me.ctrlDown.label = found.progname tk.label = found.String()
newR := found.realGocuiSize() newR := realGocuiSize(found)
cd.gocuiSize.w0 = newR.w0 tk.gocuiSize.w0 = newR.w0
cd.gocuiSize.h0 = newR.h0 tk.gocuiSize.h0 = newR.h0
cd.gocuiSize.w1 = newR.w1 tk.gocuiSize.w1 = newR.w1
cd.gocuiSize.h1 = newR.h1 tk.gocuiSize.h1 = newR.h1
if me.ctrlDown.Visible() { if tk.Visible() {
me.ctrlDown.hideView() // me.ctrlDown.hideView()
} else { } else {
me.ctrlDown.showView() // me.ctrlDown.showView()
} }
me.ctrlDown.showWidgetPlacement(true, "ctrlDown:") // me.ctrlDown.showWidgetPlacement(true, "ctrlDown:")
return nil return nil
} }

View File

@ -1,10 +1,12 @@
package main package main
import ( import (
"github.com/awesome-gocui/gocui"
"math/rand" "math/rand"
"github.com/awesome-gocui/gocui"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/toolkits/tree"
) )
//w.v.SelBgColor = gocui.ColorCyan //w.v.SelBgColor = gocui.ColorCyan
@ -65,8 +67,10 @@ var colorNone colorT = colorT{none, none, none, none, none, "debug none"}
// TODO: maybe enough of us could actually do that if we made it a goal. // TODO: maybe enough of us could actually do that if we made it a goal.
// TODO: start with riscv boards and fix it universally there // TODO: start with riscv boards and fix it universally there
// TODO: so just a small little 'todo' item here // TODO: so just a small little 'todo' item here
func (n *node) setColor(newColor *colorT) { func setColor(n *tree.Node, newColor *colorT) {
tk := n.tk var tk *guiWidget
tk = n.TK.(*guiWidget)
if tk.color == newColor { if tk.color == newColor {
// nothing to do since the colors have nto changed // nothing to do since the colors have nto changed
return return
@ -80,15 +84,18 @@ func (n *node) setColor(newColor *colorT) {
tk.color = &colorNone tk.color = &colorNone
} }
log.Log(NOW, "Set the node to color =", tk.color.name) log.Log(NOW, "Set the node to color =", tk.color.name)
n.recreateView() tk.recreateView()
} }
func (n *node) setDefaultWidgetColor() { func setDefaultWidgetColor(n *tree.Node) {
n.showView() var w *guiWidget
w = n.TK.(*guiWidget)
w.showView()
} }
func (n *node) setDefaultHighlight() { func setDefaultHighlight(n *tree.Node) {
w := n.tk var w *guiWidget
w = n.TK.(*guiWidget)
if w.v == nil { if w.v == nil {
log.Log(ERROR, "SetColor() failed on view == nil") log.Log(ERROR, "SetColor() failed on view == nil")
return return
@ -104,17 +111,16 @@ func randColor() gocui.Attribute {
return gocui.GetColor(colors[i]) return gocui.GetColor(colors[i])
} }
func (n *node) redoColor(draw bool) { func (w *guiWidget) redoColor(draw bool) {
w := n.tk
if w == nil { if w == nil {
return return
} }
log.Sleep(.05) log.Sleep(.05)
n.setDefaultHighlight() setDefaultHighlight(w.node)
n.setDefaultWidgetColor() setDefaultWidgetColor(w.node)
for _, child := range n.children { for _, child := range w.children {
child.redoColor(draw) child.redoColor(draw)
} }
} }

218
common.go
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/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

@ -2,59 +2,68 @@ package main
import ( import (
"fmt" "fmt"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/widget" "go.wit.com/widget"
) )
func (n *node) dumpTree(draw bool) { func dumpTree(n *tree.Node, draw bool) {
w := n.tk w := n.TK.(*guiWidget)
log.Log(ERROR, "dumpTree n", n.WidgetId, n.WidgetType, n.String())
if w == nil { if w == nil {
log.Log(ERROR, "dumpTree n.TK == nil", n.WidgetId, n.WidgetType, n.String())
return return
} }
n.showWidgetPlacement(true, "dumpTree()") showWidgetPlacement(n, true, "dumpTree()")
for _, child := range n.children { for _, child := range w.children {
child.dumpTree(draw) dumpTree(child.node, draw)
} }
} }
func (n *node) showWidgetPlacement(b bool, s string) { func showWidgetPlacement(n *tree.Node, b bool, s string) {
if n == nil { if n == nil {
log.Log(ERROR, "WTF w == nil") log.Log(ERROR, "WTF w == nil")
return return
} }
w := n.tk w := n.TK.(*guiWidget)
w.showWidgetPlacement(b, s)
}
func (w *guiWidget) showWidgetPlacement(b bool, s string) {
var s1 string var s1 string
var pId int var pId int
if n.parent == nil { if w.node.Parent == nil {
log.Log(INFO, "showWidgetPlacement() parent == nil", n.WidgetId, w.cuiName) log.Log(INFO, "showWidgetPlacement() parent == nil", w.node.WidgetId, w.cuiName)
pId = 0 pId = 0
} else { } else {
pId = n.parent.WidgetId pId = w.node.Parent.WidgetId
} }
s1 = fmt.Sprintf("(wId,pId)=(%2d,%2d) ", n.WidgetId, pId) s1 = fmt.Sprintf("(wId,pId)=(%2d,%2d) ", w.node.WidgetId, pId)
if n.Visible() { if w.Visible() {
s1 += fmt.Sprintf("gocui=(%2d,%2d)(%2d,%2d,%2d,%2d)", s1 += fmt.Sprintf("gocui=(%2d,%2d)(%2d,%2d,%2d,%2d)",
w.gocuiSize.Width(), w.gocuiSize.Height(), w.gocuiSize.Width(), w.gocuiSize.Height(),
w.gocuiSize.w0, w.gocuiSize.h0, w.gocuiSize.w1, w.gocuiSize.h1) w.gocuiSize.w0, w.gocuiSize.h0, w.gocuiSize.w1, w.gocuiSize.h1)
} else { } else {
s1 += fmt.Sprintf(" ") s1 += fmt.Sprintf(" ")
} }
if n.parent != nil { if w.node.Parent != nil {
if n.parent.WidgetType == widget.Grid { if w.node.Parent.WidgetType == widget.Grid {
s1 += fmt.Sprintf("At(%2d,%2d) ", n.AtW, n.AtH) s1 += fmt.Sprintf("At(%2d,%2d) ", w.AtW, w.AtH)
} }
} }
tmp := "." + n.progname + "." tmp := "." + w.String() + "."
log.Log(INFO, s1, s, n.WidgetType, ",", tmp) // , "text=", w.text) log.Log(INFO, s1, s, w.node.WidgetType, ",", tmp) // , "text=", w.text)
} }
func (n *node) dumpWidget(pad string) { /*
func dumpWidget(n *tree.Node, pad string) {
log.Log(NOW, "node:", pad, n.WidgetId, "At(", n.AtW, n.AtH, ") ,", n.WidgetType, ", n.progname =", n.progname, ", n.label =", n.label) log.Log(NOW, "node:", pad, n.WidgetId, "At(", n.AtW, n.AtH, ") ,", n.WidgetType, ", n.progname =", n.progname, ", n.label =", n.label)
} }
*/
func (n *node) listWidgets() { /*
func listWidgets(n *tree.Node) {
if n == nil { if n == nil {
return return
} }
@ -72,3 +81,4 @@ func (n *node) listWidgets() {
} }
return return
} }
*/

View File

@ -6,6 +6,7 @@ package main
import ( import (
"errors" "errors"
"github.com/awesome-gocui/gocui" "github.com/awesome-gocui/gocui"
"go.wit.com/log" "go.wit.com/log"

View File

@ -8,7 +8,6 @@ import (
"github.com/awesome-gocui/gocui" "github.com/awesome-gocui/gocui"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/widget"
) )
func defaultKeybindings(g *gocui.Gui) error { func defaultKeybindings(g *gocui.Gui) error {
@ -51,11 +50,13 @@ func addDebugKeys(g *gocui.Gui) {
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
fakeStartWidth = me.FakeW fakeStartWidth = me.FakeW
fakeStartHeight = me.TabH + me.FramePadH fakeStartHeight = me.TabH + me.FramePadH
var w *guiWidget
w = me.treeRoot.TK.(*guiWidget)
if showDebug { if showDebug {
me.rootNode.showFake() w.showFake()
showDebug = false showDebug = false
} else { } else {
me.rootNode.hideFake() w.hideFake()
showDebug = true showDebug = true
} }
return nil return nil
@ -77,11 +78,13 @@ func addDebugKeys(g *gocui.Gui) {
// redraw all the widgets // redraw all the widgets
g.SetKeybinding("", 'r', gocui.ModNone, g.SetKeybinding("", 'r', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
var w *guiWidget
w = me.treeRoot.TK.(*guiWidget)
if redoWidgets { if redoWidgets {
redoWindows(0, 0) redoWindows(0, 0)
redoWidgets = false redoWidgets = false
} else { } else {
me.rootNode.hideWidgets() w.hideWidgets()
redoWidgets = true redoWidgets = true
} }
return nil return nil
@ -90,28 +93,32 @@ func addDebugKeys(g *gocui.Gui) {
// hide all widgets // hide all widgets
g.SetKeybinding("", 'h', gocui.ModNone, g.SetKeybinding("", 'h', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
me.rootNode.hideWidgets() var w *guiWidget
w = me.treeRoot.TK.(*guiWidget)
w.hideWidgets()
return nil return nil
}) })
// show all widgets // show all widgets
g.SetKeybinding("", 's', gocui.ModNone, g.SetKeybinding("", 's', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
me.rootNode.showWidgets() var w *guiWidget
w = me.treeRoot.TK.(*guiWidget)
w.showWidgets()
return nil return nil
}) })
// list all widgets // list all widgets
g.SetKeybinding("", 'L', gocui.ModNone, g.SetKeybinding("", 'L', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
me.rootNode.listWidgets() me.treeRoot.ListWidgets()
return nil return nil
}) })
// list all widgets with positions // list all widgets with positions
g.SetKeybinding("", 'M', gocui.ModNone, g.SetKeybinding("", 'M', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
me.rootNode.dumpTree(true) dumpTree(me.treeRoot, true)
return nil return nil
}) })
@ -119,6 +126,7 @@ func addDebugKeys(g *gocui.Gui) {
g.SetKeybinding("", 'o', gocui.ModNone, g.SetKeybinding("", 'o', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
log.Log(ERROR, "TODO: re-implement this") log.Log(ERROR, "TODO: re-implement this")
/*
if me.logStdout.Visible() { if me.logStdout.Visible() {
me.logStdout.SetVisible(false) me.logStdout.SetVisible(false)
// setOutput(os.Stdout) // setOutput(os.Stdout)
@ -126,6 +134,7 @@ func addDebugKeys(g *gocui.Gui) {
me.logStdout.SetVisible(true) me.logStdout.SetVisible(true)
// setOutput(me.logStdout.tk) // setOutput(me.logStdout.tk)
} }
*/
return nil return nil
}) })
@ -143,10 +152,7 @@ func addDebugKeys(g *gocui.Gui) {
g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone, g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
if showDebug { if showDebug {
var a widget.Action me.myTree.SendEnableDebugger()
a.Value = true
a.ActionType = widget.EnableDebug
callback <- a
} }
return nil return nil
}) })

41
main.go
View File

@ -8,7 +8,7 @@ import (
"os" "os"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/widget" "go.wit.com/toolkits/tree"
) )
// sets defaults and establishes communication // sets defaults and establishes communication
@ -19,38 +19,19 @@ func init() {
// init the config struct default values // init the config struct default values
Set(&me, "default") Set(&me, "default")
pluginChan = make(chan widget.Action) me.myTree = tree.New()
me.myTree.PluginName = "gocui"
me.myTree.ActionFromChannel = action
// pluginChan = make(chan widget.Action)
log.Log(NOW, "Init() start pluginChan") log.Log(NOW, "Init() start pluginChan")
go catchActionChannel() // go catchActionChannel()
log.Sleep(.1) // probably not needed, but in here for now under development log.Sleep(.1) // probably not needed, but in here for now under development
go main() go main()
log.Sleep(.1) // probably not needed, but in here for now under development log.Sleep(.1) // probably not needed, but in here for now under development
} }
/*
recieves requests from the program to do things like:
* add new widgets
* change the text of a label
* etc..
*/
func catchActionChannel() {
log.Log(INFO, "catchActionChannel() START")
for {
log.Log(INFO, "catchActionChannel() infinite for() loop restarted select on channel")
select {
case a := <-pluginChan:
if me.baseGui == nil {
// something went wrong initializing the gocui
log.Log(ERROR, "ERROR: console did not initialize")
continue
}
log.Log(INFO, "catchActionChannel()", a.WidgetId, a.ActionType, a.WidgetType, a.ProgName)
action(&a)
}
}
}
func Exit() { func Exit() {
// TODO: what should actually happen here? // TODO: what should actually happen here?
log.Log(NOW, "Exit() here. doing standardExit()") log.Log(NOW, "Exit() here. doing standardExit()")
@ -65,18 +46,12 @@ func standardExit() {
// log(true, "standardExit() setOutput(os.Stdout)") // log(true, "standardExit() setOutput(os.Stdout)")
// setOutput(os.Stdout) // setOutput(os.Stdout)
log.Log(NOW, "standardExit() send back Quit()") log.Log(NOW, "standardExit() send back Quit()")
go sendBackQuit() // don't stall here in case the // go sendBackQuit() // don't stall here in case the
// induces a delay in case the callback channel is broken // induces a delay in case the callback channel is broken
log.Sleep(1) log.Sleep(1)
log.Log(NOW, "standardExit() exit()") log.Log(NOW, "standardExit() exit()")
os.Exit(0) os.Exit(0)
} }
func sendBackQuit() {
// send 'Quit' back to the program (?)
var a widget.Action
a.ActionType = widget.UserQuit
callback <- a
}
var outf *os.File var outf *os.File

View File

@ -7,6 +7,7 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/awesome-gocui/gocui" "github.com/awesome-gocui/gocui"
"go.wit.com/log" "go.wit.com/log"
@ -36,15 +37,17 @@ func msgDown(g *gocui.Gui, v *gocui.View) error {
} }
func hideDDview() error { func hideDDview() error {
var tk *guiWidget
tk = me.ddview.TK.(*guiWidget)
w, h := me.baseGui.MousePosition() w, h := me.baseGui.MousePosition()
log.Log(NOW, "hide dropdown menu() view msgMouseDown (w,h) =", w, h) log.Log(NOW, "hide dropdown menu() view msgMouseDown (w,h) =", w, h)
if me.ddview == nil { if me.ddview == nil {
return gocui.ErrUnknownView return gocui.ErrUnknownView
} }
if me.ddview.tk.v == nil { if tk.v == nil {
return gocui.ErrUnknownView return gocui.ErrUnknownView
} }
me.ddview.SetVisible(false) SetVisible(me.ddview, false)
return nil return nil
} }
@ -54,40 +57,50 @@ func showDDview() error {
if me.ddview == nil { if me.ddview == nil {
return gocui.ErrUnknownView return gocui.ErrUnknownView
} }
if me.ddview.tk.v == nil { var tk *guiWidget
tk = me.ddview.TK.(*guiWidget)
if tk.v == nil {
return gocui.ErrUnknownView return gocui.ErrUnknownView
} }
me.ddview.SetVisible(true) SetVisible(me.ddview, true)
return nil return nil
} }
func mouseUp(g *gocui.Gui, v *gocui.View) error { func mouseUp(g *gocui.Gui, v *gocui.View) error {
var tk *guiWidget
tk = me.ddview.TK.(*guiWidget)
w, h := g.MousePosition() w, h := g.MousePosition()
log.Log(NOW, "mouseUp() view msgMouseDown (check here for dropdown menu click) (w,h) =", w, h) log.Log(NOW, "mouseUp() view msgMouseDown (check here for dropdown menu click) (w,h) =", w, h)
if me.ddClicked { if me.ddClicked {
me.ddClicked = false me.ddClicked = false
log.Log(NOW, "mouseUp() ddview is the thing that was clicked", w, h) log.Log(NOW, "mouseUp() ddview is the thing that was clicked", w, h)
log.Log(NOW, "mouseUp() find out what the string is here", w, h, me.ddview.tk.gocuiSize.h1) log.Log(NOW, "mouseUp() find out what the string is here", w, h, tk.gocuiSize.h1)
var newZone string = "" var newZone string = ""
if me.ddNode != nil { if me.ddNode != nil {
value := h - me.ddview.tk.gocuiSize.h0 - 1 var ddtk *guiWidget
log.Log(NOW, "mouseUp() me.ddview.tk.gocuiSize.h1 =", me.ddview.tk.gocuiSize.h1) ddtk = me.ddview.TK.(*guiWidget)
log.Log(NOW, "mouseUp() me.ddNode.vals =", me.ddNode.vals) value := h - tk.gocuiSize.h0 - 1
valsLen := len(me.ddNode.vals) log.Log(NOW, "mouseUp() me.ddview.tk.gocuiSize.h1 =", tk.gocuiSize.h1)
log.Log(NOW, "mouseUp() me.ddNode.vals =", ddtk.vals)
valsLen := len(ddtk.vals)
log.Log(NOW, "mouseUp() value =", value, "valsLen =", valsLen) log.Log(NOW, "mouseUp() value =", value, "valsLen =", valsLen)
log.Log(NOW, "mouseUp() me.ddNode.vals =", me.ddNode.vals) log.Log(NOW, "mouseUp() me.ddNode.vals =", ddtk.vals)
if (value >= 0) && (value < valsLen) { if (value >= 0) && (value < valsLen) {
newZone = me.ddNode.vals[value] newZone = ddtk.vals[value]
log.Log(NOW, "mouseUp() value =", value, "newZone =", newZone) log.Log(NOW, "mouseUp() value =", value, "newZone =", newZone)
} }
} }
hideDDview() hideDDview()
if newZone != "" { if newZone != "" {
if me.ddNode != nil { if me.ddNode != nil {
me.ddNode.SetText(newZone) var ddtk *guiWidget
me.ddNode.value = newZone ddtk = me.ddview.TK.(*guiWidget)
me.ddNode.doUserEvent() ddtk.SetText(newZone)
ddtk.value = newZone
// me.ddNode.doUserEvent()
me.myTree.SendUserEvent(me.ddNode)
} }
} }
return nil return nil
@ -125,7 +138,7 @@ func mouseDown(g *gocui.Gui, v *gocui.View) error {
test := findUnderMouse() test := findUnderMouse()
msg := fmt.Sprintf("Mouse really down at: %d,%d", mx, my) + "foobar" msg := fmt.Sprintf("Mouse really down at: %d,%d", mx, my) + "foobar"
if test == me.ddview { if test == me.ddview {
if me.ddview.Visible() { if Visible(me.ddview) {
log.Log(NOW, "hide DDview() Mouse really down at:", mx, my) log.Log(NOW, "hide DDview() Mouse really down at:", mx, my)
hideDDview() hideDDview()
} else { } else {

100
place.go
View File

@ -4,29 +4,33 @@ import (
"strings" "strings"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/widget" "go.wit.com/widget"
) )
func (n *node) placeBox(startW int, startH int) { func placeBox(n *tree.Node, startW int, startH int) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
if n.WidgetType != widget.Box { if n.WidgetType != widget.Box {
return return
} }
n.showWidgetPlacement(true, "boxS()") showWidgetPlacement(n, true, "boxS()")
newW := startW newW := startW
newH := startH newH := startH
for _, child := range n.children { for _, child := range tk.children {
child.placeWidgets(newW, newH) placeWidgets(child.node, newW, newH)
// n.showWidgetPlacement(logNow, "boxS()") // n.showWidgetPlacement(logNow, "boxS()")
newR := child.realGocuiSize() newR := realGocuiSize(child.node)
w := newR.w1 - newR.w0 w := newR.w1 - newR.w0
h := newR.h1 - newR.h0 h := newR.h1 - newR.h0
if n.direction == widget.Horizontal { if child.direction == widget.Horizontal {
log.Log(NOW, "BOX IS HORIZONTAL", n.progname, "newWH()", newW, newH, "child()", w, h, child.progname) log.Log(NOW, "BOX IS HORIZONTAL", n.String(), "newWH()", newW, newH, "child()", w, h, child.String())
// expand based on the child width // expand based on the child width
newW += w newW += w
} else { } else {
log.Log(NOW, "BOX IS VERTICAL ", n.progname, "newWH()", newW, newH, "child()", w, h, child.progname) log.Log(NOW, "BOX IS VERTICAL ", n.String(), "newWH()", newW, newH, "child()", w, h, child.String())
// expand based on the child height // expand based on the child height
newH += h newH += h
} }
@ -35,43 +39,46 @@ func (n *node) placeBox(startW int, startH int) {
// just compute this every time? // just compute this every time?
// newR := n.realGocuiSize() // newR := n.realGocuiSize()
n.showWidgetPlacement(true, "boxE()") showWidgetPlacement(n, true, "boxE()")
} }
func (n *node) placeWidgets(startW int, startH int) { func placeWidgets(n *tree.Node, startW int, startH int) {
if n == nil { if n == nil {
return return
} }
if me.rootNode == nil { if me.treeRoot == nil {
return return
} }
var tk *guiWidget
tk = n.TK.(*guiWidget)
switch n.WidgetType { switch n.WidgetType {
case widget.Window: case widget.Window:
for _, child := range n.children { for _, child := range tk.children {
child.placeWidgets(me.RawW, me.RawH) placeWidgets(child.node, me.RawW, me.RawH)
return return
} }
case widget.Tab: case widget.Tab:
for _, child := range n.children { for _, child := range tk.children {
child.placeWidgets(me.RawW, me.RawH) placeWidgets(child.node, me.RawW, me.RawH)
return return
} }
case widget.Grid: case widget.Grid:
n.placeGrid(startW, startH) placeGrid(n, startW, startH)
case widget.Box: case widget.Box:
n.placeBox(startW, startH) placeBox(n, startW, startH)
case widget.Group: case widget.Group:
// move the group to the parent's next location // move the group to the parent's next location
n.gocuiSetWH(startW, startH) tk.gocuiSetWH(startW, startH)
n.showWidgetPlacement(true, "group()") showWidgetPlacement(n, true, "group()")
newW := startW + me.GroupPadW newW := startW + me.GroupPadW
newH := startH + 3 // normal hight of the group label newH := startH + 3 // normal hight of the group label
// now move all the children aka: run place() on them // now move all the children aka: run place() on them
for _, child := range n.children { for _, child := range tk.children {
child.placeWidgets(newW, newH) placeWidgets(child.node, newW, newH)
newR := child.realGocuiSize() newR := realGocuiSize(child.node)
// w := newR.w1 - newR.w0 // w := newR.w1 - newR.w0
h := newR.h1 - newR.h0 h := newR.h1 - newR.h0
@ -79,21 +86,22 @@ func (n *node) placeWidgets(startW int, startH int) {
newH += h newH += h
} }
default: default:
n.gocuiSetWH(startW, startH) tk.gocuiSetWH(startW, startH)
// n.moveTo(startW, startH) // n.moveTo(startW, startH)
} }
} }
func (n *node) placeGrid(startW int, startH int) { func placeGrid(n *tree.Node, startW int, startH int) {
w := n.tk var w *guiWidget
n.showWidgetPlacement(true, "grid0:") w = n.TK.(*guiWidget)
showWidgetPlacement(n, true, "grid0:")
if n.WidgetType != widget.Grid { if n.WidgetType != widget.Grid {
return return
} }
// first compute the max sizes of the rows and columns // first compute the max sizes of the rows and columns
for _, child := range n.children { for _, child := range w.children {
newR := child.realGocuiSize() newR := realGocuiSize(child.node)
childW := newR.w1 - newR.w0 childW := newR.w1 - newR.w0
childH := newR.h1 - newR.h0 childH := newR.h1 - newR.h0
@ -105,12 +113,12 @@ func (n *node) placeGrid(startW int, startH int) {
w.heights[child.AtH] = childH w.heights[child.AtH] = childH
} }
// child.showWidgetPlacement(logInfo, "grid: ") // child.showWidgetPlacement(logInfo, "grid: ")
log.Log(INFO, "placeGrid:", child.progname, "child()", childW, childH, "At()", child.AtW, child.AtH) log.Log(INFO, "placeGrid:", child.String(), "child()", childW, childH, "At()", child.AtW, child.AtH)
} }
// find the width and height offset of the grid for AtW,AtH // find the width and height offset of the grid for AtW,AtH
for _, child := range n.children { for _, child := range w.children {
child.showWidgetPlacement(true, "grid1:") showWidgetPlacement(w.node, true, "grid1:")
var totalW, totalH int var totalW, totalH int
for i, w := range w.widths { for i, w := range w.widths {
@ -128,16 +136,16 @@ func (n *node) placeGrid(startW int, startH int) {
newW := startW + totalW newW := startW + totalW
newH := startH + totalH newH := startH + totalH
log.Log(INFO, "placeGrid:", child.progname, "new()", newW, newH, "At()", child.AtW, child.AtH) log.Log(INFO, "placeGrid:", child.String(), "new()", newW, newH, "At()", child.AtW, child.AtH)
child.placeWidgets(newW, newH) placeWidgets(child.node, newW, newH)
child.showWidgetPlacement(true, "grid2:") showWidgetPlacement(child.node, true, "grid2:")
} }
n.showWidgetPlacement(true, "grid3:") showWidgetPlacement(n, true, "grid3:")
} }
// computes the real, actual size of all the gocli objects in a widget // computes the real, actual size of all the gocli objects in a widget
func (n *node) realGocuiSize() *rectType { func realGocuiSize(n *tree.Node) *rectType {
var f func(n *node, r *rectType) var f func(n *tree.Node, r *rectType)
newR := new(rectType) newR := new(rectType)
// initialize the values to opposite // initialize the values to opposite
newR.w0 = 80 newR.w0 = 80
@ -151,9 +159,11 @@ func (n *node) realGocuiSize() *rectType {
newR.h1 = 0 newR.h1 = 0
// expand the rectangle to the biggest thing displayed // expand the rectangle to the biggest thing displayed
f = func(n *node, r *rectType) { f = func(n *tree.Node, r *rectType) {
newR := n.tk.gocuiSize var tk *guiWidget
if !n.tk.isFake { tk = n.TK.(*guiWidget)
newR := tk.gocuiSize
if !tk.isFake {
if r.w0 > newR.w0 { if r.w0 > newR.w0 {
r.w0 = newR.w0 r.w0 = newR.w0
} }
@ -167,18 +177,20 @@ func (n *node) realGocuiSize() *rectType {
r.h1 = newR.h1 r.h1 = newR.h1
} }
} }
for _, child := range n.children { for _, child := range tk.children {
f(child, r) f(child.node, r)
} }
} }
f(n, newR) f(n, newR)
return newR return newR
} }
func (n *node) textSize() (int, int) { func textSize(n *tree.Node) (int, int) {
var tk *guiWidget
tk = n.TK.(*guiWidget)
var width, height int var width, height int
for _, s := range strings.Split(widget.GetString(n.value), "\n") { for _, s := range strings.Split(widget.GetString(tk.value), "\n") {
if width < len(s) { if width < len(s) {
width = len(s) width = len(s)
} }

View File

@ -7,19 +7,27 @@ import (
"go.wit.com/widget" "go.wit.com/widget"
) )
func action(a *widget.Action) { func action(a widget.Action) {
log.Log(INFO, "action() START", a.WidgetId, a.ActionType, a.WidgetType, a.ProgName) log.Log(INFO, "action() START", a.WidgetId, a.ActionType, a.WidgetType, a.ProgName)
n := me.rootNode.findWidgetId(a.WidgetId) // n := me.rootNode.findWidgetId(a.WidgetId)
n := me.treeRoot.FindWidgetId(a.WidgetId)
var w *guiWidget var w *guiWidget
if n != nil { if n != nil {
w = n.tk w = n.TK.(*guiWidget)
} }
switch a.ActionType { switch a.ActionType {
case widget.Add: case widget.Add:
if w == nil { if w == nil {
n := addNode(a) n := me.myTree.AddNode(&a)
// w = n.tk if n == nil {
n.addWidget() log.Warn("WTF")
panic("WTF")
}
n.TK = initWidget(n)
if n.WidgetType == widget.Root {
me.treeRoot = n
}
addWidget(n)
} else { } else {
// this is done to protect the plugin being 'refreshed' with the // this is done to protect the plugin being 'refreshed' with the
// widget binary tree. TODO: find a way to keep them in sync // widget binary tree. TODO: find a way to keep them in sync
@ -28,42 +36,42 @@ func action(a *widget.Action) {
} }
case widget.Show: case widget.Show:
if widget.GetBool(a.Value) { if widget.GetBool(a.Value) {
n.showView() w.showView()
} else { } else {
n.hideWidgets() w.hideWidgets()
} }
case widget.Set: case widget.Set:
if a.WidgetType == widget.Flag { if a.WidgetType == widget.Flag {
log.Log(NOW, "TODO: set flag here", a.ActionType, a.WidgetType, a.ProgName) log.Log(NOW, "TODO: set flag here", a.ActionType, a.WidgetType, a.ProgName)
log.Log(NOW, "TODO: n.WidgetType =", n.WidgetType, "n.progname =", a.ProgName) log.Log(NOW, "TODO: n.WidgetType =", n.WidgetType, "n.String() =", a.ProgName)
} else { } else {
if a.Value == nil { if a.Value == nil {
log.Log(ERROR, "TODO: Set here. a == nil id =", a.WidgetId, "type =", a.WidgetType, "Name =", a.ProgName) log.Log(ERROR, "TODO: Set here. a == nil id =", a.WidgetId, "type =", a.WidgetType, "Name =", a.ProgName)
log.Log(ERROR, "TODO: Set here. id =", a.WidgetId, "n.progname =", n.progname) log.Log(ERROR, "TODO: Set here. id =", a.WidgetId, "n.String() =", n.String())
} else { } else {
n.Set(a.Value) w.Set(a.Value)
} }
} }
case widget.SetText: case widget.SetText:
n.SetText(widget.GetString(a.Value)) w.SetText(widget.GetString(a.Value))
case widget.AddText: case widget.AddText:
n.AddText(widget.GetString(a.Value)) w.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.ToolkitClose: 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:
if n.Visible() { if w.Visible() {
// widget was already shown // widget was already shown
} else { } else {
log.Log(INFO, "Setting Visable to true", a.ProgName) log.Log(INFO, "Setting Visible to true", a.ProgName)
n.SetVisible(true) SetVisible(n, true)
} }
case widget.Disable: case widget.Disable:
if n.Visible() { if w.Visible() {
log.Log(INFO, "Setting Visable to false", a.ProgName) log.Log(INFO, "Setting Visible to false", a.ProgName)
n.SetVisible(false) SetVisible(n, false)
} else { } else {
// widget was already hidden // widget was already hidden
} }
@ -73,45 +81,44 @@ func action(a *widget.Action) {
log.Log(INFO, "action() END") log.Log(INFO, "action() END")
} }
func (n *node) AddText(text string) { func (w *guiWidget) AddText(text string) {
if n == nil { if w == nil {
log.Log(NOW, "widget is nil") log.Log(NOW, "widget is nil")
return return
} }
n.vals = append(n.vals, text) w.vals = append(w.vals, text)
for i, s := range n.vals { for i, s := range w.vals {
log.Log(NOW, "AddText()", n.progname, i, s) log.Log(NOW, "AddText()", w.String(), i, s)
} }
n.SetText(text) w.SetText(text)
} }
func (n *node) SetText(text string) { func (w *guiWidget) SetText(text string) {
var changed bool = false var changed bool = false
if n == nil { if w == nil {
log.Log(NOW, "widget is nil") log.Log(NOW, "widget is nil")
return return
} }
if widget.GetString(n.value) != text { if widget.GetString(w.value) != text {
n.value = text w.value = text
changed = true changed = true
} }
if !changed { if !changed {
return return
} }
if n.Visible() { if w.Visible() {
n.textResize() w.textResize()
n.deleteView() w.deleteView()
n.showView() w.showView()
} }
} }
func (n *node) Set(val any) { func (w *guiWidget) Set(val any) {
// w := n.tk
log.Log(INFO, "Set() value =", val) log.Log(INFO, "Set() value =", val)
n.value = val w.value = val.(string)
if n.WidgetType != widget.Checkbox { if w.node.WidgetType != widget.Checkbox {
n.setCheckbox(val) w.setCheckbox(val)
} }
} }

View File

@ -43,7 +43,7 @@ func showMsg(g *gocui.Gui, v *gocui.View) error {
func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View { func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
maxX, maxY := g.Size() maxX, maxY := g.Size()
if me.rootNode == nil { if me.treeRoot == nil {
// keep skipping this until the binary tree is initialized // keep skipping this until the binary tree is initialized
return nil return nil
} }
@ -54,12 +54,17 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
a.WidgetType = widget.Stdout a.WidgetType = widget.Stdout
a.WidgetId = -3 a.WidgetId = -3
a.ParentId = 0 a.ParentId = 0
n := addNode(a) // n := addNode(a)
n := me.myTree.AddNode(a)
n.TK = initWidget(n)
me.logStdout = n me.logStdout = n
me.logStdout.tk.gocuiSize.w0 = maxX - 32
me.logStdout.tk.gocuiSize.h0 = maxY / 2 var tk *guiWidget
me.logStdout.tk.gocuiSize.w1 = me.logStdout.tk.gocuiSize.w0 + outputW tk = me.logStdout.TK.(*guiWidget)
me.logStdout.tk.gocuiSize.h1 = me.logStdout.tk.gocuiSize.h0 + outputH tk.gocuiSize.w0 = maxX - 32
tk.gocuiSize.h0 = maxY / 2
tk.gocuiSize.w1 = tk.gocuiSize.w0 + outputW
tk.gocuiSize.h1 = tk.gocuiSize.h0 + outputH
} }
v, err := g.View("msg") v, err := g.View("msg")
if v == nil { if v == nil {
@ -85,7 +90,9 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
log.Log(NOW, "makeoutputwindow() msg == nil. WTF now? err =", err) log.Log(NOW, "makeoutputwindow() msg == nil. WTF now? err =", err)
return nil return nil
} else { } else {
me.logStdout.tk.v = v var tk *guiWidget
tk = me.logStdout.TK.(*guiWidget)
tk.v = v
} }
v.Clear() v.Clear()

View File

@ -10,13 +10,16 @@ package main
import ( import (
"fmt" "fmt"
"github.com/awesome-gocui/gocui"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"github.com/awesome-gocui/gocui"
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/widget"
) )
// It's probably a terrible idea to call this 'me' // It's probably a terrible idea to call this 'me'
@ -27,19 +30,22 @@ var showHelp bool = true
var redoWidgets bool = true var redoWidgets bool = true
// This is the window that is currently active // This is the window that is currently active
var currentWindow *node var currentWindow *tree.Node
type config struct { type config struct {
baseGui *gocui.Gui // the main gocui handle baseGui *gocui.Gui // the main gocui handle
rootNode *node // the base of the binary tree. it should have id == 0 // rootNode *node // the base of the binary tree. it should have id == 0
ctrlDown *node // shown if you click the mouse when the ctrl key is pressed treeRoot *tree.Node // the base of the binary tree. it should have id == 0
currentWindow *node // this is the current tab or window to show myTree *tree.TreeInfo
logStdout *node // where to show STDOUT
ctrlDown *tree.Node // shown if you click the mouse when the ctrl key is pressed
currentWindow *tree.Node // this is the current tab or window to show
logStdout *tree.Node // where to show STDOUT
helpLabel *gocui.View helpLabel *gocui.View
ddview *node // the gocui view to select dropdrown lists ddview *tree.Node // the gocui view to select dropdrown lists
ddClicked bool // the dropdown menu view was clicked ddClicked bool // the dropdown menu view was clicked
ddNode *node // the dropdown menu is for this widget ddNode *tree.Node // the dropdown menu is for this widget
/* /*
// this is the channel we send user events like // this is the channel we send user events like
@ -118,9 +124,32 @@ type guiWidget struct {
v *gocui.View // this is nil if the widget is not displayed v *gocui.View // this is nil if the widget is not displayed
cuiName string // what gocui uses to reference the widget cuiName string // what gocui uses to reference the widget
WidgetType widget.WidgetType
// tw *toolkit.Widget
parent *guiWidget
children []*guiWidget
node *tree.Node
hasTabs bool // does the window have tabs?
currentTab bool // the visible tab
value string
checked bool
// the actual text to display in the console // the actual text to display in the console
label string label string
vals []string // dropdown menu items
AtW int
AtH int
direction widget.Orientation
progname string
// the logical size of the widget // the logical size of the widget
// For example, 40x12 would be the center of a normal terminal // For example, 40x12 would be the center of a normal terminal
// size rectType // size rectType
@ -140,7 +169,7 @@ type guiWidget struct {
frame bool frame bool
// for a window, this is currently selected tab // for a window, this is currently selected tab
selectedTab *node selectedTab *tree.Node
// what color to use // what color to use
color *colorT color *colorT
@ -156,7 +185,9 @@ func (w *guiWidget) Write(p []byte) (n int, err error) {
w.tainted = true w.tainted = true
me.writeMutex.Lock() me.writeMutex.Lock()
defer me.writeMutex.Unlock() defer me.writeMutex.Unlock()
if me.logStdout.tk.v == nil { var tk *guiWidget
tk = me.logStdout.TK.(*guiWidget)
if tk.v == nil {
// optionally write the output to /tmp // optionally write the output to /tmp
s := fmt.Sprint(string(p)) s := fmt.Sprint(string(p))
s = strings.TrimSuffix(s, "\n") s = strings.TrimSuffix(s, "\n")
@ -164,11 +195,11 @@ func (w *guiWidget) Write(p []byte) (n int, err error) {
v, _ := me.baseGui.View("msg") v, _ := me.baseGui.View("msg")
if v != nil { if v != nil {
// fmt.Fprintln(outf, "found msg") // fmt.Fprintln(outf, "found msg")
me.logStdout.tk.v = v tk.v = v
} }
} else { } else {
// display the output in the gocui window // display the output in the gocui window
me.logStdout.tk.v.Clear() tk.v.Clear()
s := fmt.Sprint(string(p)) s := fmt.Sprint(string(p))
s = strings.TrimSuffix(s, "\n") s = strings.TrimSuffix(s, "\n")
@ -178,7 +209,7 @@ func (w *guiWidget) Write(p []byte) (n int, err error) {
l := len(outputS) - outputH l := len(outputS) - outputH
outputS = outputS[l:] outputS = outputS[l:]
} }
fmt.Fprintln(me.logStdout.tk.v, strings.Join(outputS, "\n")) fmt.Fprintln(tk.v, strings.Join(outputS, "\n"))
} }
return len(p), nil return len(p), nil

57
tab.go
View File

@ -23,12 +23,12 @@ func (w *guiWidget) Height() int {
return w.gocuiSize.h1 - w.gocuiSize.h0 - 1 return w.gocuiSize.h1 - w.gocuiSize.h0 - 1
} }
func (n *node) gocuiSetWH(sizeW, sizeH int) { func (tk *guiWidget) gocuiSetWH(sizeW, sizeH int) {
w := len(widget.GetString(n.value)) w := len(widget.GetString(tk.value))
lines := strings.Split(widget.GetString(n.value), "\n") lines := strings.Split(widget.GetString(tk.value), "\n")
h := len(lines) h := len(lines)
tk := n.tk // tk := n.tk
if tk.isFake { if tk.isFake {
tk.gocuiSize.w0 = sizeW tk.gocuiSize.w0 = sizeW
tk.gocuiSize.h0 = sizeH tk.gocuiSize.h0 = sizeH
@ -51,61 +51,60 @@ func (n *node) gocuiSetWH(sizeW, sizeH int) {
} }
func redoWindows(nextW int, nextH int) { func redoWindows(nextW int, nextH int) {
for _, n := range me.rootNode.children { wRoot := me.treeRoot.TK.(*guiWidget)
if n.WidgetType != widget.Window { for _, win := range wRoot.children {
if win.node.WidgetType != widget.Window {
continue continue
} }
w := n.tk
var tabs bool var tabs bool
for _, child := range n.children { for _, child := range win.children {
if child.WidgetType == widget.Tab { if child.node.WidgetType == widget.Tab {
tabs = true tabs = true
} }
} }
if tabs { if tabs {
// window is tabs. Don't show it as a standard button // window is tabs. Don't show it as a standard button
w.frame = false win.frame = false
n.hasTabs = true win.hasTabs = true
} else { } else {
w.frame = false win.frame = false
n.hasTabs = false win.hasTabs = false
} }
n.gocuiSetWH(nextW, nextH) win.gocuiSetWH(nextW, nextH)
n.deleteView() win.deleteView()
n.showView() win.showView()
sizeW := w.Width() + me.WindowPadW sizeW := win.Width() + me.WindowPadW
sizeH := w.Height() sizeH := win.Height()
nextW += sizeW nextW += sizeW
log.Log(NOW, "redoWindows() start nextW,H =", nextW, nextH, "gocuiSize.W,H =", sizeW, sizeH, n.progname) log.Log(NOW, "redoWindows() start nextW,H =", nextW, nextH, "gocuiSize.W,H =", sizeW, sizeH, win.String())
if n.hasTabs { if win.hasTabs {
n.redoTabs(me.TabW, me.TabH) win.redoTabs(me.TabW, me.TabH)
} }
} }
} }
func (p *node) redoTabs(nextW int, nextH int) { func (p *guiWidget) redoTabs(nextW int, nextH int) {
for _, n := range p.children { for _, w := range p.children {
if n.WidgetType != widget.Tab { if w.node.WidgetType != widget.Tab {
continue continue
} }
w := n.tk
w.frame = true w.frame = true
n.gocuiSetWH(nextW, nextH) w.gocuiSetWH(nextW, nextH)
n.deleteView() w.deleteView()
// setCurrentTab(n) // setCurrentTab(n)
// if (len(w.cuiName) < 4) { // if (len(w.cuiName) < 4) {
// w.cuiName = "abcd" // w.cuiName = "abcd"
// } // }
n.showView() w.showView()
sizeW := w.Width() + me.TabPadW sizeW := w.Width() + me.TabPadW
sizeH := w.Height() sizeH := w.Height()
log.Log(NOW, "redoTabs() start nextW,H =", nextW, nextH, "gocuiSize.W,H =", sizeW, sizeH, n.progname) log.Log(NOW, "redoTabs() start nextW,H =", nextW, nextH, "gocuiSize.W,H =", sizeW, sizeH, w.String())
nextW += sizeW nextW += sizeW
} }
} }

24
tree.go Normal file
View File

@ -0,0 +1,24 @@
package main
/*
This is reference code for toolkit developers
*/
import (
"go.wit.com/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()
}

104
view.go
View File

@ -21,12 +21,12 @@ func splitLines(s string) []string {
return lines return lines
} }
func (n *node) textResize() bool { func (w *guiWidget) textResize() bool {
w := n.tk // w := n.tk
var width, height int = 0, 0 var width, height int = 0, 0
var changed bool = false var changed bool = false
for i, s := range splitLines(n.tk.label) { for i, s := range splitLines(w.label) {
log.Log(INFO, "textResize() len =", len(s), i, s) log.Log(INFO, "textResize() len =", len(s), i, s)
if width < len(s) { if width < len(s) {
width = len(s) width = len(s)
@ -42,78 +42,76 @@ func (n *node) textResize() bool {
changed = true changed = true
} }
if changed { if changed {
n.showWidgetPlacement(true, "textResize() changed") showWidgetPlacement(w.node, true, "textResize() changed")
} }
return changed return changed
} }
func (n *node) hideView() { func (w *guiWidget) hideView() {
n.SetVisible(false) SetVisible(w.node, false)
} }
// display's the text of the widget in gocui // display's the text of the widget in gocui
// will create a new gocui view if there isn't one or if it has been moved // will create a new gocui view if there isn't one or if it has been moved
func (n *node) showView() { func (w *guiWidget) showView() {
var err error var err error
w := n.tk
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 = string(n.WidgetId) w.cuiName = string(w.node.WidgetId)
} }
// if the gocui element doesn't exist, create it // if the gocui element doesn't exist, create it
if w.v == nil { if w.v == nil {
n.recreateView() w.recreateView()
} }
x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName) x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName)
log.Log(INFO, "showView() w.v already defined for widget", n.progname, err) log.Log(INFO, "showView() w.v already defined for widget", w.String(), err)
// n.smartGocuiSize() // n.smartGocuiSize()
changed := n.textResize() changed := w.textResize()
if changed { if changed {
log.Log(NOW, "showView() textResize() changed. Should recreateView here wId =", w.cuiName) log.Log(NOW, "showView() textResize() changed. Should recreateView here wId =", w.cuiName)
} else { } else {
log.Log(NOW, "showView() Clear() and Fprint() here wId =", w.cuiName) log.Log(NOW, "showView() Clear() and Fprint() here wId =", w.cuiName)
w.v.Clear() w.v.Clear()
fmt.Fprint(w.v, n.tk.label) fmt.Fprint(w.v, w.label)
n.SetVisible(false) w.SetVisible(false)
n.SetVisible(true) w.SetVisible(true)
return return
} }
// if the gocui element has changed where it is supposed to be on the screen // if the gocui element has changed where it is supposed to be on the screen
// recreate it // recreate it
if x0 != w.gocuiSize.w0 { if x0 != w.gocuiSize.w0 {
n.recreateView() w.recreateView()
return return
} }
if y0 != w.gocuiSize.h0 { if y0 != w.gocuiSize.h0 {
log.Log(ERROR, "showView() start hight mismatch id=", w.cuiName, "gocui h vs computed h =", w.gocuiSize.h0, y0) log.Log(ERROR, "showView() start hight mismatch id=", w.cuiName, "gocui h vs computed h =", w.gocuiSize.h0, y0)
n.recreateView() w.recreateView()
return return
} }
if x1 != w.gocuiSize.w1 { if x1 != w.gocuiSize.w1 {
log.Log(ERROR, "showView() too wide", w.cuiName, "w,w", w.gocuiSize.w1, x1) log.Log(ERROR, "showView() too wide", w.cuiName, "w,w", w.gocuiSize.w1, x1)
n.recreateView() w.recreateView()
return return
} }
if y1 != w.gocuiSize.h1 { if y1 != w.gocuiSize.h1 {
log.Log(ERROR, "showView() too high", w.cuiName, "h,h", w.gocuiSize.h1, y1) log.Log(ERROR, "showView() too high", w.cuiName, "h,h", w.gocuiSize.h1, y1)
n.recreateView() w.recreateView()
return return
} }
n.SetVisible(true) w.SetVisible(true)
} }
// create or recreate the gocui widget visible // create or recreate the gocui widget visible
// deletes the old view if it exists and recreates it // deletes the old view if it exists and recreates it
func (n *node) recreateView() { func (w *guiWidget) recreateView() {
var err error var err error
w := n.tk log.Log(ERROR, "recreateView() START", w.WidgetType, w.String())
log.Log(ERROR, "recreateView() START", n.WidgetType, n.progname)
if me.baseGui == nil { if me.baseGui == nil {
log.Log(ERROR, "recreateView() ERROR: me.baseGui == nil", w) log.Log(ERROR, "recreateView() ERROR: me.baseGui == nil", w)
return return
@ -123,11 +121,11 @@ func (n *node) recreateView() {
me.baseGui.DeleteView(w.cuiName) me.baseGui.DeleteView(w.cuiName)
w.v = nil w.v = nil
if n.progname == "CLOUDFLARE_EMAIL" { if w.String() == "CLOUDFLARE_EMAIL" {
n.showWidgetPlacement(true, "n.progname="+n.progname+" n.tk.label="+n.tk.label+" "+w.cuiName) w.showWidgetPlacement(true, "n.String()="+w.String()+" n.tk.label="+w.label+" "+w.cuiName)
n.dumpWidget("jwc") // w.dumpWidget("jwc")
n.textResize() w.textResize()
n.showWidgetPlacement(true, "n.progname="+n.progname+" n.tk.label="+n.tk.label+" "+w.cuiName) w.showWidgetPlacement(true, "n.String()="+w.String()+" n.tk.label="+w.label+" "+w.cuiName)
} }
a := w.gocuiSize.w0 a := w.gocuiSize.w0
@ -137,12 +135,12 @@ func (n *node) recreateView() {
w.v, err = me.baseGui.SetView(w.cuiName, a, b, c, d, 0) w.v, err = me.baseGui.SetView(w.cuiName, a, b, c, d, 0)
if err == nil { if err == nil {
n.showWidgetPlacement(true, "recreateView()") showWidgetPlacement(w.node, true, "recreateView()")
log.Log(ERROR, "recreateView() internal plugin error err = nil") log.Log(ERROR, "recreateView() internal plugin error err = nil")
return return
} }
if !errors.Is(err, gocui.ErrUnknownView) { if !errors.Is(err, gocui.ErrUnknownView) {
n.showWidgetPlacement(true, "recreateView()") showWidgetPlacement(w.node, true, "recreateView()")
log.Log(ERROR, "recreateView() internal plugin error error.IS()", err) log.Log(ERROR, "recreateView() internal plugin error error.IS()", err)
return return
} }
@ -161,8 +159,8 @@ func (n *node) recreateView() {
w.v.Wrap = true w.v.Wrap = true
w.v.Frame = w.frame w.v.Frame = w.frame
w.v.Clear() w.v.Clear()
fmt.Fprint(w.v, n.tk.label) fmt.Fprint(w.v, w.label)
// n.showWidgetPlacement(true, "n.progname=" + n.progname + " n.tk.label=" + n.tk.label + " " + w.cuiName) // n.showWidgetPlacement(true, "n.String()=" + n.String() + " n.tk.label=" + n.tk.label + " " + w.cuiName)
// n.dumpWidget("jwc 2") // n.dumpWidget("jwc 2")
// if you don't do this here, it will be black & white only // if you don't do this here, it will be black & white only
@ -173,61 +171,57 @@ func (n *node) recreateView() {
w.v.SelFgColor = w.color.selFg w.v.SelFgColor = w.color.selFg
w.v.SelBgColor = w.color.selBg w.v.SelBgColor = w.color.selBg
} }
if n.progname == "CLOUDFLARE_EMAIL" { if w.String() == "CLOUDFLARE_EMAIL" {
n.showWidgetPlacement(true, "n.progname="+n.progname+" n.tk.label="+n.tk.label+" "+w.cuiName) w.showWidgetPlacement(true, "w.String()="+w.String()+" w.label="+w.label+" "+w.cuiName)
n.dumpTree(true) dumpTree(w.node, true)
} }
log.Log(ERROR, "recreateView() END") log.Log(ERROR, "recreateView() END")
} }
func (n *node) hideWidgets() { func (w *guiWidget) hideWidgets() {
w := n.tk
w.isCurrent = false w.isCurrent = false
switch n.WidgetType { switch w.node.WidgetType {
case widget.Root: case widget.Root:
case widget.Flag: case widget.Flag:
case widget.Window: case widget.Window:
case widget.Box: case widget.Box:
case widget.Grid: case widget.Grid:
default: default:
n.hideView() w.hideView()
} }
for _, child := range n.children { for _, child := range w.children {
child.hideWidgets() child.hideWidgets()
} }
} }
func (n *node) hideFake() { func (w *guiWidget) hideFake() {
w := n.tk
if w.isFake { if w.isFake {
n.hideView() w.hideView()
} }
for _, child := range n.children { for _, child := range w.children {
child.hideFake() child.hideFake()
} }
} }
func (n *node) showFake() { func (w *guiWidget) showFake() {
w := n.tk
if w.isFake { if w.isFake {
n.setFake() // w.setFake()
n.showWidgetPlacement(true, "showFake:") w.showWidgetPlacement(true, "showFake:")
n.showView() w.showView()
} }
for _, child := range n.children { for _, child := range w.children {
child.showFake() child.showFake()
} }
} }
func (n *node) showWidgets() { func (w *guiWidget) showWidgets() {
w := n.tk
if w.isFake { if w.isFake {
// don't display by default // don't display by default
} else { } else {
n.showWidgetPlacement(true, "current:") w.showWidgetPlacement(true, "current:")
n.showView() w.showView()
} }
for _, child := range n.children { for _, child := range w.children {
child.showWidgets() child.showWidgets()
} }
} }

101
widget.go
View File

@ -2,10 +2,11 @@ package main
import ( import (
"go.wit.com/log" "go.wit.com/log"
"go.wit.com/toolkits/tree"
"go.wit.com/widget" "go.wit.com/widget"
) )
func initWidget(n *node) *guiWidget { func initWidget(n *tree.Node) *guiWidget {
var w *guiWidget var w *guiWidget
w = new(guiWidget) w = new(guiWidget)
// Set(w, "default") // Set(w, "default")
@ -15,11 +16,12 @@ func initWidget(n *node) *guiWidget {
// set the name used by gocui to the id // set the name used by gocui to the id
w.cuiName = string(n.WidgetId) w.cuiName = string(n.WidgetId)
w.node = n
w.WidgetType = n.WidgetType
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)
n.WidgetId = 0 // me.treeRoot = n
me.rootNode = n
return w
} }
if n.WidgetType == widget.Grid { if n.WidgetType == widget.Grid {
@ -36,13 +38,13 @@ func setupCtrlDownWidget() {
a.WidgetType = widget.Dialog a.WidgetType = widget.Dialog
a.WidgetId = -1 a.WidgetId = -1
a.ParentId = 0 a.ParentId = 0
n := addNode(a) // n := addNode(a)
n := me.myTree.AddNode(a)
me.ctrlDown = n me.ctrlDown = n
} }
func (n *node) deleteView() { func (w *guiWidget) deleteView() {
w := n.tk
if w.v != nil { if w.v != nil {
w.v.Visible = false w.v.Visible = false
return return
@ -52,8 +54,9 @@ func (n *node) deleteView() {
w.v = nil w.v = nil
} }
/*
// searches the binary tree for a WidgetId // searches the binary tree for a WidgetId
func (n *node) findWidgetName(name string) *node { func findWidgetName(n *tree.Node, name string) *node {
if n == nil { if n == nil {
return nil return nil
} }
@ -70,70 +73,94 @@ func (n *node) findWidgetName(name string) *node {
} }
return nil return nil
} }
*/
func (n *node) IsCurrent() bool { func (w *guiWidget) IsCurrent() bool {
w := n.tk if w.node.WidgetType == widget.Tab {
if n.WidgetType == widget.Tab {
return w.isCurrent return w.isCurrent
} }
if n.WidgetType == widget.Window { if w.node.WidgetType == widget.Window {
return w.isCurrent return w.isCurrent
} }
if n.WidgetType == widget.Root { if w.node.WidgetType == widget.Root {
return false return false
} }
return n.parent.IsCurrent() return w.parent.IsCurrent()
} }
func (n *node) Visible() bool { func (tk *guiWidget) String() string {
return tk.progname
}
func (tk *guiWidget) Visible() bool {
if tk == nil {
return false
}
if tk.v == nil {
return false
}
return tk.v.Visible
}
func Visible(n *tree.Node) bool {
if n == nil { if n == nil {
return false return false
} }
if n.tk == nil { if n.TK == nil {
return false return false
} }
if n.tk.v == nil { var w *guiWidget
return false w = n.TK.(*guiWidget)
} return w.Visible()
return n.tk.v.Visible
} }
func (n *node) SetVisible(b bool) { func (w *guiWidget) SetVisible(b bool) {
if w.v == nil {
return
}
w.v.Visible = b
}
func SetVisible(n *tree.Node, b bool) {
if n == nil { if n == nil {
return return
} }
if n.tk == nil { if n.TK == nil {
return return
} }
if n.tk.v == nil { var w *guiWidget
w = n.TK.(*guiWidget)
if w.v == nil {
return return
} }
n.tk.v.Visible = b w.v.Visible = b
} }
func addDropdown() *node { func addDropdown() *tree.Node {
n := new(node) n := new(tree.Node)
n.WidgetType = widget.Flag n.WidgetType = widget.Flag
n.WidgetId = -2 n.WidgetId = -2
n.ParentId = 0 n.ParentId = 0
// copy the data from the action message
n.progname = "DropBox"
n.tk.label = "DropBox text"
// store the internal toolkit information // store the internal toolkit information
n.tk = new(guiWidget) tk := new(guiWidget)
n.tk.frame = true tk.frame = true
tk.label = "DropBox text"
// copy the data from the action message
tk.progname = "DropBox"
// set the name used by gocui to the id // set the name used by gocui to the id
n.tk.cuiName = "-1 dropbox" tk.cuiName = "-1 dropbox"
n.tk.color = &colorFlag tk.color = &colorFlag
// add this new widget on the binary tree // add this new widget on the binary tree
n.parent = me.rootNode tk.parent = me.treeRoot.TK.(*guiWidget)
if n.parent != nil { if tk.parent != nil {
n.parent.children = append(n.parent.children, n) tk.parent.children = append(tk.parent.children, tk)
} }
n.TK = tk
return n return n
} }