gocui: fixes to labels + line entries

correct line hight
    dump non-working size rectangle code
    somehow works better
    better dropdown menu debugging
    minor fixes to common.go
    more common code

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2023-12-16 06:57:39 -06:00
parent 90c020369a
commit f67e03db16
19 changed files with 136 additions and 202 deletions

View File

@ -88,11 +88,11 @@ func makeConfigTab(window *gui.Node) {
grid := g1.NewGrid("credsGrid", 2, 4) // width = 2 grid := g1.NewGrid("credsGrid", 2, 4) // width = 2
grid.NewLabel("Auth Key") grid.NewLabel("Auth Key")
aw := grid.NewEntryLine(os.Getenv("CLOUDFLARE_AUTHKEY")) aw := grid.NewEntryLine("CLOUDFLARE_AUTHKEY")
aw.SetText(os.Getenv("CLOUDFLARE_AUTHKEY")) aw.SetText(os.Getenv("CLOUDFLARE_AUTHKEY"))
grid.NewLabel("Email") grid.NewLabel("Email")
ew := grid.NewEntryLine(os.Getenv("CLOUDFLARE_EMAIL")) ew := grid.NewEntryLine("CLOUDFLARE_EMAIL")
ew.SetText(os.Getenv("CLOUDFLARE_EMAIL")) ew.SetText(os.Getenv("CLOUDFLARE_EMAIL"))
var url string = "https://api.cloudflare.com/client/v4/zones/" var url string = "https://api.cloudflare.com/client/v4/zones/"
@ -144,16 +144,16 @@ func showCloudflareCredentials(box *gui.Node) {
grid := box.NewGrid("credsGrid", 2, 4) // width = 2 grid := box.NewGrid("credsGrid", 2, 4) // width = 2
grid.NewLabel("Domain") grid.NewLabel("Domain")
domainWidget = grid.NewEntryLine(os.Getenv("CLOUDFLARE_DOMAIN")) domainWidget = grid.NewEntryLine("CLOUDFLARE_DOMAIN")
grid.NewLabel("Zone ID") grid.NewLabel("Zone ID")
zoneWidget = grid.NewEntryLine(os.Getenv("CLOUDFLARE_ZONEID")) zoneWidget = grid.NewEntryLine("CLOUDFLARE_ZONEID")
grid.NewLabel("Auth Key") grid.NewLabel("Auth Key")
authWidget = grid.NewEntryLine(os.Getenv("CLOUDFLARE_AUTHKEY")) authWidget = grid.NewEntryLine("CLOUDFLARE_AUTHKEY")
grid.NewLabel("Email") grid.NewLabel("Email")
emailWidget = grid.NewEntryLine(os.Getenv("CLOUDFLARE_EMAIL")) emailWidget = grid.NewEntryLine("CLOUDFLARE_EMAIL")
var url string = "https://api.cloudflare.com/client/v4/zones/" var url string = "https://api.cloudflare.com/client/v4/zones/"
grid.NewLabel("Cloudflare API") grid.NewLabel("Cloudflare API")

View File

@ -174,7 +174,7 @@ func (n *node) Delete() {
} }
} }
func rawAction(a toolkit.Action) { func rawAction(a *toolkit.Action) {
log(logInfo, "rawAction() START a.ActionType =", a.ActionType) log(logInfo, "rawAction() START a.ActionType =", a.ActionType)
log(logInfo, "rawAction() START a.S =", a.S) log(logInfo, "rawAction() START a.S =", a.S)
@ -191,7 +191,7 @@ func rawAction(a toolkit.Action) {
log(logInfo, "rawAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId) log(logInfo, "rawAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId)
switch a.WidgetType { switch a.WidgetType {
case toolkit.Flag: case toolkit.Flag:
flag(&a) flag(a)
return return
} }
@ -232,18 +232,18 @@ func rawAction(a toolkit.Action) {
case toolkit.Disable: case toolkit.Disable:
n.enable(false) n.enable(false)
case toolkit.Get: case toolkit.Get:
n.setText(&a) n.setText(a)
case toolkit.GetText: case toolkit.GetText:
switch a.WidgetType { switch a.WidgetType {
case toolkit.Textbox: case toolkit.Textbox:
a.S = n.S a.S = n.S
} }
case toolkit.Set: case toolkit.Set:
n.setText(&a) n.setText(a)
case toolkit.SetText: case toolkit.SetText:
n.setText(&a) n.setText(a)
case toolkit.AddText: case toolkit.AddText:
n.setText(&a) n.setText(a)
case toolkit.Margin: case toolkit.Margin:
n.pad(toolkit.Unmargin) n.pad(toolkit.Unmargin)
case toolkit.Unmargin: case toolkit.Unmargin:

View File

@ -15,12 +15,12 @@ func actionDump(b bool, a *toolkit.Action) {
log(b, "actionDump() ParentId =", a.ParentId) log(b, "actionDump() ParentId =", a.ParentId)
} }
func add(a toolkit.Action) { func add(a *toolkit.Action) {
if (a.WidgetType == toolkit.Root) { if (a.WidgetType == toolkit.Root) {
me.rootNode = addWidget(&a) me.rootNode = addNode(a)
return return
} }
n := addWidget(&a) n := addNode(a)
p := n.parent p := n.parent
switch n.WidgetType { switch n.WidgetType {

View File

@ -9,12 +9,6 @@ import (
_ "github.com/andlabs/ui/winmanifest" _ "github.com/andlabs/ui/winmanifest"
) )
// this is the channel we get requests to make widgets
var pluginChan chan toolkit.Action
// the starting point of the binary tree
// var rootNode *node
var uiMainUndef bool = true var uiMainUndef bool = true
var uiMain sync.Once var uiMain sync.Once
var muAction sync.Mutex var muAction sync.Mutex
@ -30,7 +24,7 @@ func catchActionChannel() {
muAction.Lock() muAction.Lock()
// TODO ui.QueueMain(f) // TODO ui.QueueMain(f)
// TODO ui.QueueMain( func() {rawAction(a)} ) // TODO ui.QueueMain( func() {rawAction(a)} )
ui.QueueMain( func() {rawAction(a)} ) ui.QueueMain( func() {rawAction(&a)} )
// rawAction(a) // rawAction(a)
muAction.Unlock() muAction.Unlock()
log(logInfo, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType) log(logInfo, "catchActionChannel() STUFF END", a.WidgetId, a.ActionType, a.WidgetType)
@ -38,21 +32,6 @@ func catchActionChannel() {
} }
} }
// 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 toolkit.Action) {
callback = guiCallback
}
func PluginChannel() chan toolkit.Action {
return pluginChan
}
// 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(logNow, "Init() START") log(logNow, "Init() START")

View File

@ -16,41 +16,6 @@ type config struct {
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
} }
/*
type node struct {
parent *node
children []*node
WidgetId int // widget ID
WidgetType toolkit.WidgetType
ParentId int // parent ID
Name string
Text string
// This is how the values are passed back and forth
// values from things like checkboxes & dropdown's
B bool
I int
S string
A any // switch to this or deprecate this? pros/cons?
// 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
// the internal plugin toolkit structure
tk *andlabsT
}
*/
// stores the raw toolkit internals // stores the raw toolkit internals
type guiWidget struct { type guiWidget struct {
Width int Width int

View File

@ -93,8 +93,8 @@ func (n *node) doWidgetClick() {
log("doWidgetClick()", n.Name) log("doWidgetClick()", n.Name)
redoWindows(0,0) redoWindows(0,0)
case toolkit.Flag: case toolkit.Flag:
// me.rootNode.redoColor(true) log("doWidgetClick() FLAG widget name =", n.Name)
me.rootNode.dumpTree(true) log("doWidgetClick() if this is the dropdown menu, handle it here?")
case toolkit.Window: case toolkit.Window:
if (me.currentWindow == n) { if (me.currentWindow == n) {
return return
@ -155,7 +155,13 @@ func (n *node) doWidgetClick() {
} }
n.doUserEvent() n.doUserEvent()
case toolkit.Grid: case toolkit.Grid:
n.placeGrid(n.tk.size.w0, n.tk.size.h0) newR := n.realGocuiSize()
// w,h := n.logicalSize()
// w := newR.w1 - newR.w0
// h := newR.h1 - newR.h0
n.placeGrid(newR.w0, newR.h0)
n.showWidgets() n.showWidgets()
case toolkit.Box: case toolkit.Box:
// w.showWidgetPlacement(logNow, "drawTree()") // w.showWidgetPlacement(logNow, "drawTree()")
@ -267,12 +273,14 @@ func click(g *gocui.Gui, v *gocui.View) error {
} }
if _, err := g.SetCurrentView(v.Name()); err != nil { if _, err := g.SetCurrentView(v.Name()); err != nil {
log(logNow, "click() END err =", err)
return err return err
} }
log(logVerbose, "click() END") log(logVerbose, "click() END")
return nil return nil
} }
func findUnderMouse() *node { func findUnderMouse() *node {
var found *node var found *node
var widgets []*node var widgets []*node

View File

@ -10,7 +10,7 @@ func (n *node) dumpTree(draw bool) {
if (w == nil) { if (w == nil) {
return return
} }
n.showWidgetPlacement(logNow, "Tree:") n.showWidgetPlacement(logNow, "dumpTree()")
for _, child := range n.children { for _, child := range n.children {
child.dumpTree(draw) child.dumpTree(draw)
@ -33,13 +33,12 @@ func (n *node) showWidgetPlacement(b bool, s string) {
pId = n.parent.WidgetId pId = n.parent.WidgetId
} }
s1 = fmt.Sprintf("(wId,pId)=(%2d,%2d) ", n.WidgetId, pId) s1 = fmt.Sprintf("(wId,pId)=(%2d,%2d) ", n.WidgetId, pId)
s1 += fmt.Sprintf("size=(%2d,%2d)(%2d,%2d,%2d,%2d)",
w.size.Width(), w.size.Height(),
w.size.w0, w.size.h0, w.size.w1, w.size.h1)
if n.Visible() { if n.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 {
s1 += fmt.Sprintf(" ")
} }
if (n.parent != nil) { if (n.parent != nil) {
if (n.parent.WidgetType == toolkit.Grid) { if (n.parent.WidgetType == toolkit.Grid) {
@ -50,7 +49,7 @@ func (n *node) showWidgetPlacement(b bool, s string) {
} }
func (n *node) dumpWidget(pad string) { func (n *node) dumpWidget(pad string) {
log(true, "node:", pad, n.WidgetId, "At(", n.AtW, n.AtH, ") ,", n.WidgetType, ",", n.Name) log(true, "node:", pad, n.WidgetId, "At(", n.AtW, n.AtH, ") ,", n.WidgetType, ", n.Name =", n.Name, ", n.Text =", n.Text)
} }
func (n *node) listWidgets() { func (n *node) listWidgets() {

View File

@ -19,6 +19,7 @@ var helpText []string = []string{"KEYBINDINGS",
"r: redraw widgets", "r: redraw widgets",
"s/h: show/hide all widgets", "s/h: show/hide all widgets",
"L: list all widgets", "L: list all widgets",
"M: list all widgets positions",
"q: quit()", "q: quit()",
"p: panic()", "p: panic()",
"o: show Stdout", "o: show Stdout",

View File

@ -29,6 +29,9 @@ func defaultKeybindings(g *gocui.Gui) error {
if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown); err != nil { if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown); err != nil {
return err return err
} }
// if err := g.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click); err != nil {
// return err
// }
/* /*
if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil { if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil {
return err return err
@ -45,8 +48,6 @@ func addDebugKeys(g *gocui.Gui) {
// show debugging buttons // show debugging buttons
g.SetKeybinding("", 'd', gocui.ModNone, g.SetKeybinding("", 'd', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error { func(g *gocui.Gui, v *gocui.View) error {
log(logNow, "gocui.SetKeyBinding() dumpTree() START")
// me.rootNode.dumpTree(true)
fakeStartWidth = me.FakeW fakeStartWidth = me.FakeW
fakeStartHeight = me.TabH + me.FramePadH fakeStartHeight = me.TabH + me.FramePadH
if (showDebug) { if (showDebug) {
@ -106,6 +107,13 @@ func addDebugKeys(g *gocui.Gui) {
return nil return nil
}) })
// list all widgets with positions
g.SetKeybinding("", 'M', gocui.ModNone,
func(g *gocui.Gui, v *gocui.View) error {
me.rootNode.dumpTree(true)
return nil
})
// log to output window // log to output window
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 {
@ -136,7 +144,7 @@ func addDebugKeys(g *gocui.Gui) {
var a toolkit.Action var a toolkit.Action
a.B = true a.B = true
a.ActionType = toolkit.EnableDebug a.ActionType = toolkit.EnableDebug
me.callback <- a callback <- a
logInfo = true logInfo = true
logVerbose = true logVerbose = true
} else { } else {

View File

@ -17,7 +17,7 @@ func init() {
// init the config struct default values // init the config struct default values
Set(&me, "default") Set(&me, "default")
me.pluginChan = make(chan toolkit.Action) pluginChan = make(chan toolkit.Action)
log(logNow, "Init() start pluginChan") log(logNow, "Init() start pluginChan")
go catchActionChannel() go catchActionChannel()
@ -26,15 +26,6 @@ func init() {
sleep(.1) // probably not needed, but in here for now under development sleep(.1) // probably not needed, but in here for now under development
} }
// this sets the channel to send user events back from the plugin
func Callback(guiCallback chan toolkit.Action) {
me.callback = guiCallback
}
func PluginChannel() chan toolkit.Action {
return me.pluginChan
}
/* /*
recieves requests from the program to do things like: recieves requests from the program to do things like:
* add new widgets * add new widgets
@ -46,7 +37,7 @@ func catchActionChannel() {
for { for {
log(logInfo, "catchActionChannel() infinite for() loop restarted select on channel") log(logInfo, "catchActionChannel() infinite for() loop restarted select on channel")
select { select {
case a := <-me.pluginChan: case a := <-pluginChan:
if (me.baseGui == nil) { if (me.baseGui == nil) {
// something went wrong initializing the gocui // something went wrong initializing the gocui
log(logError,"ERROR: console did not initialize") log(logError,"ERROR: console did not initialize")
@ -60,22 +51,29 @@ func catchActionChannel() {
func Exit() { func Exit() {
// TODO: what should actually happen here? // TODO: what should actually happen here?
log(true, "Exit() here. doing standardExit()")
standardExit() standardExit()
} }
func standardExit() { func standardExit() {
log(true, "standardExit() doing baseGui.Close()")
me.baseGui.Close() me.baseGui.Close()
log(true, "standardExit() doing outf.Close()")
outf.Close() outf.Close()
setOutput(os.Stdout) // log(true, "standardExit() setOutput(os.Stdout)")
sendBackQuit() // setOutput(os.Stdout)
sleep(.5) log(true, "standardExit() send back Quit()")
go sendBackQuit() // don't stall here in case the
// induces a delay in case the callback channel is broken
sleep(1)
log(true, "standardExit() exit()")
exit() exit()
} }
func sendBackQuit() { func sendBackQuit() {
// send 'Quit' back to the program (?) // send 'Quit' back to the program (?)
var a toolkit.Action var a toolkit.Action
a.ActionType = toolkit.UserQuit a.ActionType = toolkit.UserQuit
me.callback <- a callback <- a
} }
var outf *os.File var outf *os.File

View File

@ -9,8 +9,6 @@ func (n *node) placeBox(startW int, startH int) {
if (n.WidgetType != toolkit.Box) { if (n.WidgetType != toolkit.Box) {
return return
} }
n.tk.size.w0 = startW
n.tk.size.h0 = startH
n.showWidgetPlacement(logNow, "boxS()") n.showWidgetPlacement(logNow, "boxS()")
newW := startW newW := startW
@ -18,7 +16,6 @@ func (n *node) placeBox(startW int, startH int) {
for _, child := range n.children { for _, child := range n.children {
child.placeWidgets(newW, newH) child.placeWidgets(newW, newH)
// n.showWidgetPlacement(logNow, "boxS()") // n.showWidgetPlacement(logNow, "boxS()")
// w,h := child.logicalSize()
newR := child.realGocuiSize() newR := child.realGocuiSize()
w := newR.w1 - newR.w0 w := newR.w1 - newR.w0
h := newR.h1 - newR.h0 h := newR.h1 - newR.h0
@ -32,13 +29,10 @@ func (n *node) placeBox(startW int, startH int) {
newH += h newH += h
} }
} }
// w,h := n.logicalSize()
newR := n.realGocuiSize()
w := newR.w1 - newR.w0
h := newR.h1 - newR.h0
n.tk.size.w1 = n.tk.size.w0 + w // just compute this every time?
n.tk.size.h1 = n.tk.size.h0 + h // newR := n.realGocuiSize()
n.showWidgetPlacement(logNow, "boxE()") n.showWidgetPlacement(logNow, "boxE()")
} }
@ -75,7 +69,6 @@ func (n *node) placeWidgets(startW int, startH int) {
// 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 n.children {
child.placeWidgets(newW, newH) child.placeWidgets(newW, newH)
// _,h := child.logicalSize()
newR := child.realGocuiSize() newR := child.realGocuiSize()
// w := newR.w1 - newR.w0 // w := newR.w1 - newR.w0
h := newR.h1 - newR.h0 h := newR.h1 - newR.h0
@ -91,8 +84,6 @@ func (n *node) placeWidgets(startW int, startH int) {
func (n *node) placeGrid(startW int, startH int) { func (n *node) placeGrid(startW int, startH int) {
w := n.tk w := n.tk
w.size.w0 = startW
w.size.h0 = startH
n.showWidgetPlacement(logInfo, "grid0:") n.showWidgetPlacement(logInfo, "grid0:")
if (n.WidgetType != toolkit.Grid) { if (n.WidgetType != toolkit.Grid) {
return return
@ -100,7 +91,6 @@ func (n *node) placeGrid(startW int, startH int) {
// 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 n.children {
// childW, childH := child.logicalSize()
newR := child.realGocuiSize() newR := child.realGocuiSize()
childW := newR.w1 - newR.w0 childW := newR.w1 - newR.w0
childH := newR.h1 - newR.h0 childH := newR.h1 - newR.h0

View File

@ -62,9 +62,9 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
} }
v, err := g.View("msg") v, err := g.View("msg")
if (v == nil) { if (v == nil) {
log("this is supposed to happen. v == nil", err) log("makeoutputwindow() this is supposed to happen. v == nil", err)
} else { } else {
log("msg != nil. WTF now? err =", err) log("makeoutputwindow() msg != nil. WTF now? err =", err)
} }
// help, err := g.SetView("help", maxX-32, 0, maxX-1, 13, 0) // help, err := g.SetView("help", maxX-32, 0, maxX-1, 13, 0)
@ -72,16 +72,16 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
v, err = g.SetView("msg", maxX-32, maxY/2, maxX/2+outputW, maxY/2+outputH, 0) v, err = g.SetView("msg", maxX-32, maxY/2, maxX/2+outputW, maxY/2+outputH, 0)
if errors.Is(err, gocui.ErrUnknownView) { if errors.Is(err, gocui.ErrUnknownView) {
log("this is supposed to happen?", err) log("makeoutputwindow() this is supposed to happen?", err)
} }
if (err != nil) { if (err != nil) {
log("create output window failed", err) log("makeoutputwindow() create output window failed", err)
return nil return nil
} }
if (v == nil) { if (v == nil) {
log("msg == nil. WTF now? err =", err) log("makeoutputwindow() msg == nil. WTF now? err =", err)
return nil return nil
} else { } else {
me.logStdout.tk.v = v me.logStdout.tk.v = v

View File

@ -15,7 +15,7 @@ import (
"sync" "sync"
"strings" "strings"
"github.com/awesome-gocui/gocui" "github.com/awesome-gocui/gocui"
"git.wit.org/wit/gui/toolkit" // "git.wit.org/wit/gui/toolkit"
) )
// It's probably a terrible idea to call this 'me' // It's probably a terrible idea to call this 'me'
@ -40,12 +40,14 @@ type config struct {
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 *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
// mouse clicks or keyboard events back to the program // mouse clicks or keyboard events back to the program
callback chan toolkit.Action callback chan toolkit.Action
// this is the channel we get requests to make widgets // this is the channel we get requests to make widgets
pluginChan chan toolkit.Action pluginChan chan toolkit.Action
*/
// When the widget has a frame, like a button, it adds 2 lines runes on each side // When the widget has a frame, like a button, it adds 2 lines runes on each side
// so you need 3 char spacing in each direction to not have them overlap // so you need 3 char spacing in each direction to not have them overlap
@ -117,7 +119,7 @@ type guiWidget struct {
// 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
// the actual gocui display view of this widget // the actual gocui display view of this widget
// sometimes this isn't visible like with a Box or Grid // sometimes this isn't visible like with a Box or Grid

View File

@ -36,17 +36,13 @@ func (n *node) gocuiSetWH(sizeW, sizeH int) {
} }
if tk.frame { if tk.frame {
tk.size.w0 = sizeW tk.gocuiSize.w0 = sizeW
tk.size.h0 = sizeH tk.gocuiSize.h0 = sizeH
tk.gocuiSize.w0 = tk.size.w0
tk.gocuiSize.h0 = tk.size.h0
tk.gocuiSize.w1 = tk.gocuiSize.w0 + w + me.FramePadW tk.gocuiSize.w1 = tk.gocuiSize.w0 + w + me.FramePadW
tk.gocuiSize.h1 = tk.gocuiSize.h0 + h + me.FramePadH tk.gocuiSize.h1 = tk.gocuiSize.h0 + h + me.FramePadH
} else { } else {
tk.size.w0 = sizeW - 1 tk.gocuiSize.w0 = sizeW - 1
tk.size.h0 = sizeH - 1 tk.gocuiSize.h0 = sizeH - 1
tk.gocuiSize.w0 = tk.size.w0
tk.gocuiSize.h0 = tk.size.h0
tk.gocuiSize.w1 = tk.gocuiSize.w0 + w + 1 tk.gocuiSize.w1 = tk.gocuiSize.w0 + w + 1
tk.gocuiSize.h1 = tk.gocuiSize.h0 + h + 1 tk.gocuiSize.h1 = tk.gocuiSize.h0 + h + 1
} }
@ -73,8 +69,6 @@ func redoWindows(nextW int, nextH int) {
n.hasTabs = false n.hasTabs = false
} }
w.size.w0 = nextW
w.size.h0 = nextH
n.gocuiSetWH(nextW, nextH) n.gocuiSetWH(nextW, nextH)
n.deleteView() n.deleteView()
n.showView() n.showView()
@ -98,8 +92,6 @@ func (p *node) redoTabs(nextW int, nextH int) {
w := n.tk w := n.tk
w.frame = true w.frame = true
w.size.w0 = nextW
w.size.h0 = nextH
n.gocuiSetWH(nextW, nextH) n.gocuiSetWH(nextW, nextH)
n.deleteView() n.deleteView()
// setCurrentTab(n) // setCurrentTab(n)

View File

@ -22,14 +22,14 @@ func splitLines(s string) []string {
func (n *node) textResize() { func (n *node) textResize() {
w := n.tk w := n.tk
var width, height int var width, height int = 0, 0
for i, s := range splitLines(n.Text) { for i, s := range splitLines(n.Text) {
log(logNow, "textResize() len =", len(s), i, s) log(logNow, "textResize() len =", len(s), i, s)
if (width < len(s)) { if (width < len(s)) {
width = len(s) width = len(s)
} }
height = i height += 1
} }
w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW
w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH
@ -81,13 +81,23 @@ func (n *node) showView() {
func (n *node) recreateView() { func (n *node) recreateView() {
var err error var err error
w := n.tk w := n.tk
log(logError, "recreateView() START", n.WidgetType, n.Name)
if (me.baseGui == nil) { if (me.baseGui == nil) {
log(logError, "showView() ERROR: me.baseGui == nil", w) log(logError, "recreateView() ERROR: me.baseGui == nil", w)
return return
} }
// this deletes the button from gocui
me.baseGui.DeleteView(w.cuiName) me.baseGui.DeleteView(w.cuiName)
w.v = nil w.v = nil
if (n.Name == "CLOUDFLARE_EMAIL") {
n.showWidgetPlacement(logNow, "n.Name=" + n.Name + " n.Text=" + n.Text + " " + w.cuiName)
n.dumpWidget("jwc")
n.textResize()
n.showWidgetPlacement(logNow, "n.Name=" + n.Name + " n.Text=" + n.Text + " " + w.cuiName)
}
a := w.gocuiSize.w0 a := w.gocuiSize.w0
b := w.gocuiSize.h0 b := w.gocuiSize.h0
c := w.gocuiSize.w1 c := w.gocuiSize.w1
@ -95,23 +105,33 @@ 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(logError, "drawView()") n.showWidgetPlacement(logError, "recreateView()")
log(logError, "drawView() internal plugin error err = nil") log(logError, "recreateView() internal plugin error err = nil")
return return
} }
if !errors.Is(err, gocui.ErrUnknownView) { if !errors.Is(err, gocui.ErrUnknownView) {
n.showWidgetPlacement(logError, "drawView()") n.showWidgetPlacement(logError, "recreateView()")
log(logError, "drawView() internal plugin error error.IS()", err) log(logError, "recreateView() internal plugin error error.IS()", err)
return return
} }
// this sets up the keybinding for the name of the window
// does this really need to be done? I think we probably already
// know everything about where all the widgets are so we could bypass
// the gocui package and just handle all the mouse events internally here (?)
// for now, the w.v.Name is a string "1", "2", "3", etc from the widgetId
// set the binding for this gocui view now that it has been created
// gocui handles overlaps of views so it will run on the view that is clicked on
me.baseGui.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click) me.baseGui.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click)
// this actually sends the text to display to gocui
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.Text) fmt.Fprint(w.v, n.Text)
n.showWidgetPlacement(logNow, "Window: " + n.Text) // n.showWidgetPlacement(logNow, "n.Name=" + n.Name + " n.Text=" + n.Text + " " + w.cuiName)
// 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
if (w.color != nil) { if (w.color != nil) {
@ -121,6 +141,11 @@ 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.Name == "CLOUDFLARE_EMAIL") {
n.showWidgetPlacement(logNow, "n.Name=" + n.Name + " n.Text=" + n.Text + " " + w.cuiName)
n.dumpTree(true)
}
log(logError, "recreateView() END")
} }
func (n *node) hideWidgets() { func (n *node) hideWidgets() {
@ -167,13 +192,8 @@ func (n *node) showWidgets() {
if (w.isFake) { if (w.isFake) {
// don't display by default // don't display by default
} else { } else {
// if n.IsCurrent() { n.showWidgetPlacement(logInfo, "current:")
n.showWidgetPlacement(logInfo, "current:") n.showView()
n.showView()
// } else {
// n.showWidgetPlacement(logInfo, "not:")
// w.drawView()
// }
} }
for _, child := range n.children { for _, child := range n.children {
child.showWidgets() child.showWidgets()

View File

@ -98,7 +98,7 @@ func doAction(a *toolkit.Action) {
log(logNow, "doAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId) log(logNow, "doAction() START a.WidgetId =", a.WidgetId, "a.ParentId =", a.ParentId)
switch a.WidgetType { switch a.WidgetType {
case toolkit.Root: case toolkit.Root:
rootNode = addWidget(a) me.rootNode = addNode(a)
log(logNow, "doAction() found rootNode") log(logNow, "doAction() found rootNode")
return return
case toolkit.Flag: case toolkit.Flag:
@ -106,11 +106,11 @@ func doAction(a *toolkit.Action) {
return return
} }
n := rootNode.findWidgetId(a.WidgetId) n := me.rootNode.findWidgetId(a.WidgetId)
switch a.ActionType { switch a.ActionType {
case toolkit.Add: case toolkit.Add:
addWidget(a) addNode(a)
case toolkit.Show: case toolkit.Show:
n.show(true) n.show(true)
case toolkit.Hide: case toolkit.Hide:
@ -144,7 +144,7 @@ func doAction(a *toolkit.Action) {
n.Delete() n.Delete()
case toolkit.Move: case toolkit.Move:
log(logNow, "doAction() attempt to move() =", a.ActionType, a.WidgetType) log(logNow, "doAction() attempt to move() =", a.ActionType, a.WidgetType)
newParent := rootNode.findWidgetId(a.ParentId) newParent := me.rootNode.findWidgetId(a.ParentId)
n.move(newParent) n.move(newParent)
default: default:
log(logError, "doAction() Unknown =", a.ActionType, a.WidgetType) log(logError, "doAction() Unknown =", a.ActionType, a.WidgetType)

View File

@ -15,10 +15,13 @@ import (
"git.wit.org/wit/gui/toolkit" "git.wit.org/wit/gui/toolkit"
) )
// this is the channel that sends the events from the user clicking or typing // this is the channel we send user events like
// back to the program using this golang package // mouse clicks or keyboard events back to the program
var callback chan toolkit.Action var callback chan toolkit.Action
// this is the channel we get requests to make widgets
var pluginChan chan toolkit.Action
type node struct { type node struct {
parent *node parent *node
children []*node children []*node
@ -82,48 +85,6 @@ func (n *node) findWidgetId(id int) *node {
return nil return nil
} }
func addWidget(a *toolkit.Action) *node {
n := new(node)
n.WidgetType = a.WidgetType
n.WidgetId = a.WidgetId
n.ParentId = a.ParentId
// copy the data from the action message
n.Name = a.Name
n.Text = a.Text
n.I = a.I
n.S = a.S
n.B = a.B
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 = new(guiWidget)
if (a.WidgetType == toolkit.Root) {
log(logInfo, "addWidget() Root")
return n
}
if (me.rootNode.findWidgetId(a.WidgetId) != nil) {
log(logError, "addWidget() 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)
}
return n
}
func (n *node) doUserEvent() { func (n *node) doUserEvent() {
if (callback == nil) { if (callback == nil) {
log(logError, "doUserEvent() callback == nil", n.WidgetId) log(logError, "doUserEvent() callback == nil", n.WidgetId)
@ -188,3 +149,18 @@ func addNode(a *toolkit.Action) *node {
} }
return n return n
} }
// 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 toolkit.Action) {
callback = guiCallback
}
func PluginChannel() chan toolkit.Action {
return pluginChan
}

View File

@ -5,12 +5,6 @@ import (
"git.wit.org/wit/gui/toolkit" "git.wit.org/wit/gui/toolkit"
) )
// this is the channel we get requests to make widgets
var pluginChan chan toolkit.Action
// the starting point of the binary tree
var rootNode *node
var muAction sync.Mutex var muAction sync.Mutex
func catchActionChannel() { func catchActionChannel() {
@ -29,6 +23,7 @@ func catchActionChannel() {
} }
} }
/*
// 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
@ -43,6 +38,7 @@ func Callback(guiCallback chan toolkit.Action) {
func PluginChannel() chan toolkit.Action { func PluginChannel() chan toolkit.Action {
return pluginChan return pluginChan
} }
*/
// 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() {

View File

@ -18,10 +18,10 @@ func simpleStdin() {
switch s { switch s {
case "l": case "l":
log(true, "list widgets") log(true, "list widgets")
rootNode.listWidgets() me.rootNode.listWidgets()
case "b": case "b":
log(true, "show buttons") log(true, "show buttons")
rootNode.showButtons() me.rootNode.showButtons()
case "d": case "d":
var a toolkit.Action var a toolkit.Action
a.ActionType = toolkit.EnableDebug a.ActionType = toolkit.EnableDebug
@ -35,7 +35,7 @@ func simpleStdin() {
default: default:
i, _ := strconv.Atoi(s) i, _ := strconv.Atoi(s)
log(true, "got input:", i) log(true, "got input:", i)
n := rootNode.findWidgetId(i) n := me.rootNode.findWidgetId(i)
if (n != nil) { if (n != nil) {
n.dumpWidget("found node") n.dumpWidget("found node")
n.doUserEvent() n.doUserEvent()