gocui plugin refactor to a *node binary tree
rename arg '--gui <toolkit>' add a cloudflare example fixes since go v1.21 didn't compile anymore due to argv order more place() changes recursive size computation gocui: Major refactor to use the *node binary tree gocui: refactor place() and size() gocui: better place() and spacing (tab, buttons, etc) gocui: better mouse click handling gocui: switch to using tk.gocuiSize & tk.size gocui: event handling cleanups gocui: add window labels work gocui: struct cleanups gocui: duplicate binary tree structs removed gocui: deprecate old children Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
603d5ba7de
commit
fe6a8dd969
|
@ -8,6 +8,7 @@ cmds/console-ui-helloworld/console-ui-helloworld
|
|||
cmds/debug/debug
|
||||
cmds/helloworld/helloworld
|
||||
cmds/textbox/textbox
|
||||
cmds/cloudflare/cloudflare
|
||||
cmds/*/helloconsole
|
||||
|
||||
# temporary files when building debian packages
|
||||
|
|
7
Makefile
7
Makefile
|
@ -8,6 +8,7 @@ all: README.md
|
|||
@echo
|
||||
make clean
|
||||
make plugins
|
||||
make cmds-buttonplugin
|
||||
|
||||
build-dep:
|
||||
apt install -f libgtk-3-dev
|
||||
|
@ -82,11 +83,11 @@ clean:
|
|||
plugins: plugins-gocui plugins-andlabs
|
||||
|
||||
plugins-gocui:
|
||||
GO111MODULE="off" go build -v -x -C toolkit/gocui -buildmode=plugin -o ../gocui.so
|
||||
GO111MODULE="off" go build -v -x -C toolkit/nocui -buildmode=plugin -o ../nocui.so
|
||||
GO111MODULE="off" go build -C toolkit/gocui -v -buildmode=plugin -o ../gocui.so
|
||||
GO111MODULE="off" go build -C toolkit/nocui -v -buildmode=plugin -o ../nocui.so
|
||||
|
||||
plugins-andlabs:
|
||||
GO111MODULE="off" go build -v -x -C toolkit/andlabs -buildmode=plugin -o ../andlabs.so
|
||||
GO111MODULE="off" go build -C toolkit/andlabs -v -buildmode=plugin -o ../andlabs.so
|
||||
|
||||
objdump:
|
||||
objdump -t toolkit/andlabs.so |less
|
||||
|
|
|
@ -139,7 +139,7 @@ Creates a window helpful for debugging this package
|
|||
|
||||
`func ShowDebugValues()`
|
||||
|
||||
### func [StandardExit](/main.go#L149)
|
||||
### func [StandardExit](/main.go#L153)
|
||||
|
||||
`func StandardExit()`
|
||||
|
||||
|
@ -158,13 +158,19 @@ This goroutine can be used like a watchdog timer
|
|||
|
||||
## Types
|
||||
|
||||
### type [GuiArgs](/structs.go#L27)
|
||||
### type [GuiArgs](/structs.go#L29)
|
||||
|
||||
`type GuiArgs struct { ... }`
|
||||
|
||||
This struct can be used with the go-arg package
|
||||
|
||||
### type [Node](/structs.go#L57)
|
||||
#### Variables
|
||||
|
||||
```golang
|
||||
var GuiArg GuiArgs
|
||||
```
|
||||
|
||||
### type [Node](/structs.go#L59)
|
||||
|
||||
`type Node struct { ... }`
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
|
||||
run: build
|
||||
./buttonplugin --gui-toolkit gocui >/tmp/witgui.log.stderr 2>&1
|
||||
./buttonplugin --gui gocui >/tmp/witgui.log.stderr 2>&1
|
||||
|
||||
build-release:
|
||||
go get -v -u -x .
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
arg "github.com/alexflint/go-arg"
|
||||
"git.wit.org/wit/gui"
|
||||
log "git.wit.org/wit/gui/log"
|
||||
)
|
||||
|
||||
|
||||
|
@ -14,6 +15,7 @@ var args struct {
|
|||
User string `arg:"env:USER"`
|
||||
Demo bool `help:"run a demo"`
|
||||
gui.GuiArgs
|
||||
log.LogArgs
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -26,6 +28,11 @@ func init() {
|
|||
arg.MustParse(&args)
|
||||
fmt.Println(args.Foo, args.Bar, args.User)
|
||||
|
||||
if (args.Gui != "") {
|
||||
gui.GuiArg.Gui = args.Gui
|
||||
}
|
||||
log.Log(true, "INIT() args.GuiArg.Gui =", gui.GuiArg.Gui)
|
||||
|
||||
/*
|
||||
log.Println()
|
||||
log.Println("STDOUT is now at /tmp/guilogfile")
|
||||
|
|
|
@ -20,14 +20,7 @@ func main() {
|
|||
// This will turn on all debugging
|
||||
// gui.SetDebug(true)
|
||||
|
||||
// myGui = gui.New().LoadToolkit("gocui")
|
||||
// myGui = gui.New().LoadToolkit("andlabs")
|
||||
// myGui = gui.New().Default()
|
||||
if (args.GuiToolkit == nil) {
|
||||
myGui = gui.New().Default()
|
||||
} else {
|
||||
myGui = gui.New().LoadToolkit(args.GuiToolkit[0])
|
||||
}
|
||||
buttonWindow()
|
||||
|
||||
// This is just a optional goroutine to watch that things are alive
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
run: build
|
||||
./cloudflare
|
||||
|
||||
build-release:
|
||||
go get -v -u -x .
|
||||
go build
|
||||
./cloudflare
|
||||
|
||||
build:
|
||||
GO111MODULE="off" go get -v -x .
|
||||
GO111MODULE="off" go build
|
||||
|
||||
update:
|
||||
GO111MODULE="off" go get -v -u -x .
|
||||
|
||||
log:
|
||||
reset
|
||||
tail -f /tmp/witgui.* /tmp/guilogfile
|
|
@ -0,0 +1,30 @@
|
|||
// This creates a simple hello world window
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
arg "github.com/alexflint/go-arg"
|
||||
"git.wit.org/wit/gui"
|
||||
log "git.wit.org/wit/gui/log"
|
||||
)
|
||||
|
||||
|
||||
var args struct {
|
||||
Foo string
|
||||
Bar bool
|
||||
User string `arg:"env:USER"`
|
||||
Demo bool `help:"run a demo"`
|
||||
gui.GuiArgs
|
||||
log.LogArgs
|
||||
}
|
||||
|
||||
func init() {
|
||||
arg.MustParse(&args)
|
||||
fmt.Println(args.Foo, args.Bar, args.User)
|
||||
|
||||
if (args.Gui != "") {
|
||||
gui.GuiArg.Gui = args.Gui
|
||||
}
|
||||
log.Log(true, "INIT() args.GuiArg.Gui =", gui.GuiArg.Gui)
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
// This is a simple example
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"log"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Define a struct to match the JSON structure of the response.
|
||||
// This structure should be adjusted based on the actual format of the response.
|
||||
type DNSRecords struct {
|
||||
Result []struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Proxied bool `json:"proxied"`
|
||||
Proxiable bool `json:"proxiable"`
|
||||
TTL int `json:"ttl"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// var domain string = "wit.org"
|
||||
// var os.Getenv("CLOUDFLARE_DOMAIN")
|
||||
|
||||
func loadDNS(hostname string) {
|
||||
log.Println("adding DNS record")
|
||||
|
||||
// more2.NewButton(name, func () {
|
||||
// log.Println(name, "ip =", ip)
|
||||
// })
|
||||
|
||||
newt := mainWindow.NewTab(hostname)
|
||||
newg := newt.NewGroup("more")
|
||||
more2 := newg.NewGrid("gridnuts", 5, gridH)
|
||||
|
||||
records := getRecords()
|
||||
for _, record := range records.Result {
|
||||
more2.NewLabel(record.Type)
|
||||
more2.NewLabel(record.Name)
|
||||
if (record.Proxied) {
|
||||
more2.NewLabel("Proxied")
|
||||
} else {
|
||||
more2.NewLabel("DNS")
|
||||
}
|
||||
var ttl, short string
|
||||
if (record.TTL == 1) {
|
||||
ttl = "Auto"
|
||||
} else {
|
||||
ttl = strconv.Itoa(record.TTL)
|
||||
}
|
||||
more2.NewLabel(ttl)
|
||||
// short = fmt.Sprintf("%80s", record.Content)
|
||||
short = record.Content
|
||||
if len(short) > 40 {
|
||||
short = short[:40] // Slice the first 20 characters
|
||||
}
|
||||
more2.NewLabel(short)
|
||||
|
||||
fmt.Printf("ID: %s, Type: %s, Name: %s, short Content: %s\n", record.ID, record.Type, record.Name, short)
|
||||
fmt.Printf("\tproxied: %b, %b, string TTL: %i\n", record.Proxied, record.Proxiable, ttl)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func getRecords() *DNSRecords {
|
||||
var url string = os.Getenv("CLOUDFLARE_URL")
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var authKey string = os.Getenv("CLOUDFLARE_AUTHKEY")
|
||||
var email string = os.Getenv("CLOUDFLARE_EMAIL")
|
||||
|
||||
// Set headers
|
||||
req.Header.Set("X-Auth-Key", authKey)
|
||||
req.Header.Set("X-Auth-Email", email)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var records DNSRecords
|
||||
if err := json.Unmarshal(body, &records); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Process the records as needed
|
||||
/*
|
||||
for _, record := range records.Result {
|
||||
fmt.Printf("ID: %s, Type: %s, Name: %s, Content: %s\n", record.ID, record.Type, record.Name, record.Content)
|
||||
fmt.Printf("\tproxied: %b, %b, TTL: %i\n", record.Proxied, record.Proxiable, record.TTL)
|
||||
}
|
||||
*/
|
||||
|
||||
return &records
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
// This is a simple example
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"git.wit.org/wit/gui"
|
||||
)
|
||||
|
||||
var title string = "Cloudflare DNS Control Panel"
|
||||
var outfile string = "/tmp/guilogfile"
|
||||
var myGui *gui.Node
|
||||
|
||||
var buttonCounter int = 5
|
||||
var gridW int = 5
|
||||
var gridH int = 3
|
||||
|
||||
var mainWindow, more, more2 *gui.Node
|
||||
|
||||
func main() {
|
||||
myGui = gui.New().Default()
|
||||
buttonWindow()
|
||||
|
||||
// This is just a optional goroutine to watch that things are alive
|
||||
gui.Watchdog()
|
||||
gui.StandardExit()
|
||||
}
|
||||
|
||||
// This creates a window
|
||||
func buttonWindow() {
|
||||
var t, g *gui.Node
|
||||
|
||||
log.Println("buttonWindow() START")
|
||||
|
||||
mainWindow = myGui.NewWindow(title).SetText(title)
|
||||
t = mainWindow.NewTab("Cloudflare")
|
||||
g = t.NewGroup("buttons")
|
||||
g1 := t.NewGroup("buttonGroup 2")
|
||||
|
||||
more = g1.NewGroup("more")
|
||||
showCloudflareCredentials(more)
|
||||
|
||||
g1.NewButton("hello", func () {
|
||||
log.Println("world")
|
||||
})
|
||||
more2 = g1.NewGrid("gridnuts", gridW, gridH)
|
||||
|
||||
var domain string = os.Getenv("CLOUDFLARE_DOMAIN")
|
||||
if (domain == "") {
|
||||
domain = "example.org"
|
||||
}
|
||||
|
||||
g.NewButton("Load " + domain + " DNS", func () {
|
||||
loadDNS(domain)
|
||||
})
|
||||
|
||||
g.NewButton("Load 'gocui'", func () {
|
||||
// this set the xterm and mate-terminal window title. maybe works generally?
|
||||
fmt.Println("\033]0;" + title + "blah \007")
|
||||
myGui.LoadToolkit("gocui")
|
||||
})
|
||||
|
||||
g.NewButton("Load 'andlabs'", func () {
|
||||
myGui.LoadToolkit("andlabs")
|
||||
})
|
||||
|
||||
g.NewButton("NewButton(more)", func () {
|
||||
name := "foobar " + strconv.Itoa(buttonCounter)
|
||||
log.Println("NewButton(more) Adding button", name)
|
||||
buttonCounter += 1
|
||||
more.NewButton(name, func () {
|
||||
log.Println("Got all the way to main() name =", name)
|
||||
})
|
||||
})
|
||||
|
||||
g.NewButton("NewButton(more2)", func () {
|
||||
name := "foobar " + strconv.Itoa(buttonCounter)
|
||||
log.Println("NewButton(more2) Adding button", name)
|
||||
buttonCounter += 1
|
||||
more2.NewButton(name, func () {
|
||||
log.Println("Got all the way to main() name =", name)
|
||||
})
|
||||
})
|
||||
|
||||
g.NewButton("NewButton(more2 d)", func () {
|
||||
name := "d" + strconv.Itoa(buttonCounter)
|
||||
log.Println("NewButton(more2 d) Adding button", name)
|
||||
buttonCounter += 1
|
||||
more2.NewButton(name, func () {
|
||||
log.Println("Got all the way to main() name =", name)
|
||||
})
|
||||
})
|
||||
|
||||
g.NewButton("NewGroup()", func () {
|
||||
name := "neat " + strconv.Itoa(buttonCounter)
|
||||
log.Println("NewGroup() Adding button", name)
|
||||
buttonCounter += 1
|
||||
more.NewGroup(name)
|
||||
})
|
||||
|
||||
g.NewButton("gui.DebugWindow()", func () {
|
||||
gui.DebugWindow()
|
||||
})
|
||||
}
|
||||
|
||||
func showCloudflareCredentials(box *gui.Node) {
|
||||
grid := box.NewGrid("credsGrid", 2, 4) // width = 2
|
||||
|
||||
grid.NewLabel("Domain")
|
||||
grid.NewLabel(os.Getenv("CLOUDFLARE_DOMAIN"))
|
||||
|
||||
grid.NewLabel("Auth Key")
|
||||
grid.NewLabel(os.Getenv("CLOUDFLARE_AUTHKEY"))
|
||||
|
||||
grid.NewLabel("Email")
|
||||
grid.NewLabel(os.Getenv("CLOUDFLARE_EMAIL"))
|
||||
|
||||
grid.NewLabel("URL")
|
||||
grid.NewLabel(os.Getenv("CLOUDFLARE_URL"))
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package witlog
|
||||
|
||||
import (
|
||||
)
|
||||
|
||||
//
|
||||
// Attempt to switch logging to syslog on linux
|
||||
//
|
||||
|
||||
// This struct can be used with the go-arg package
|
||||
type LogArgs struct {
|
||||
Log []string `arg:"--log" help:"Where to log [syslog,stdout]"`
|
||||
}
|
4
main.go
4
main.go
|
@ -123,6 +123,10 @@ func New() *Node {
|
|||
|
||||
// try to load andlabs, if that doesn't work, fall back to the console
|
||||
func (n *Node) Default() *Node {
|
||||
if (GuiArg.Gui != "") {
|
||||
log(logError, "New.Default() try toolkit =", GuiArg.Gui)
|
||||
return n.LoadToolkit(GuiArg.Gui)
|
||||
}
|
||||
// if DISPLAY isn't set, return since gtk can't load
|
||||
// TODO: figure out how to check what to do in macos and mswindows
|
||||
if (os.Getenv("DISPLAY") == "") {
|
||||
|
|
|
@ -119,8 +119,15 @@ func searchPaths(name string) *aplug {
|
|||
filename = "plugins/" + name + ".so"
|
||||
pfile, err = me.resFS.ReadFile(filename)
|
||||
if (err == nil) {
|
||||
filename = "/tmp/" + name + ".so"
|
||||
log(logError, "write out file here", name, filename, len(pfile))
|
||||
exit()
|
||||
f, _ := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600)
|
||||
f.Write(pfile)
|
||||
f.Close()
|
||||
p := initToolkit(name, filename)
|
||||
if (p != nil) {
|
||||
return p
|
||||
}
|
||||
} else {
|
||||
log(logError, filename, "was not embedded. Error:", err)
|
||||
}
|
||||
|
|
|
@ -23,9 +23,11 @@ import (
|
|||
|
||||
var me guiConfig
|
||||
|
||||
var GuiArg GuiArgs
|
||||
|
||||
// This struct can be used with the go-arg package
|
||||
type GuiArgs struct {
|
||||
GuiToolkit []string `arg:"--gui-toolkit" help:"The order to attempt loading plugins [gocui,andlabs,gtk,qt]"`
|
||||
Gui string `arg:"--gui" help:"Use this gui toolkit [andlabs,gocui,nocui]"`
|
||||
GuiDebug bool `arg:"--gui-debug" help:"open the GUI debugger"`
|
||||
GuiVerbose bool `arg:"--gui-verbose" help:"enable all logging"`
|
||||
}
|
||||
|
|
|
@ -1,88 +1,67 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// "github.com/awesome-gocui/gocui"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
||||
// TODO: make these defaults in config struct definition
|
||||
var fakeStartWidth int = me.DevelOffsetW
|
||||
var fakeStartWidth int = me.FakeW
|
||||
var fakeStartHeight int = me.TabH + me.FramePadH
|
||||
func (w *cuiWidget) setFake() {
|
||||
// setup fake labels for non-visible things off screen
|
||||
func (n *node) setFake() {
|
||||
w := n.tk
|
||||
w.isFake = true
|
||||
t := len(w.name)
|
||||
// setup fake labels for non-visable things off screen
|
||||
|
||||
w.gocuiSize.w0 = fakeStartWidth
|
||||
w.gocuiSize.h0 = fakeStartHeight
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + t + me.PadW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + me.DefaultHeight + me.PadH
|
||||
n.gocuiSetWH(fakeStartWidth, fakeStartHeight)
|
||||
|
||||
w.realWidth = w.gocuiSize.Width() + me.FramePadW
|
||||
w.realHeight = w.gocuiSize.Height() + me.FramePadH
|
||||
|
||||
fakeStartHeight += w.realHeight
|
||||
fakeStartHeight += w.gocuiSize.Height()
|
||||
// TODO: use the actual max hight of the terminal window
|
||||
if (fakeStartHeight > 24) {
|
||||
fakeStartHeight = me.TabH + me.FramePadH
|
||||
fakeStartWidth += me.DevelOffsetW
|
||||
fakeStartHeight = me.TabH
|
||||
fakeStartWidth += me.FakeW
|
||||
}
|
||||
if (logInfo) {
|
||||
w.showView()
|
||||
n.showView()
|
||||
}
|
||||
}
|
||||
|
||||
// set the widget start width & height
|
||||
func (w *cuiWidget) addWidget() {
|
||||
log(logInfo, "setStartWH() w.id =", w.id, "w.name", w.name)
|
||||
switch w.widgetType {
|
||||
func (n *node) addWidget() {
|
||||
nw := n.tk
|
||||
log(logInfo, "setStartWH() w.id =", n.WidgetId, "n.name", n.Name)
|
||||
switch n.WidgetType {
|
||||
case toolkit.Root:
|
||||
log(logInfo, "setStartWH() rootNode w.id =", w.id, "w.name", w.name)
|
||||
w.setFake()
|
||||
log(logInfo, "setStartWH() rootNode w.id =", n.WidgetId, "w.name", n.Name)
|
||||
n.setFake()
|
||||
return
|
||||
case toolkit.Flag:
|
||||
w.setFake()
|
||||
n.setFake()
|
||||
return
|
||||
case toolkit.Window:
|
||||
me.current = w
|
||||
updateCurrentTabs()
|
||||
setCurrentWindow(w)
|
||||
nw.frame = false
|
||||
redoWindows(0,0)
|
||||
return
|
||||
case toolkit.Tab:
|
||||
// if this is the first tab, set it to the current one and stay here
|
||||
if (me.current != nil) {
|
||||
// there is already a current tab. just redraw the tabs
|
||||
updateCurrentTabs()
|
||||
return
|
||||
}
|
||||
setCurrentTab(w)
|
||||
return
|
||||
case toolkit.Box:
|
||||
w.isFake = true
|
||||
w.setFake()
|
||||
w.startW = w.parent.startW
|
||||
w.startH = w.parent.startH
|
||||
nw.isFake = true
|
||||
n.setFake()
|
||||
return
|
||||
case toolkit.Grid:
|
||||
w.isFake = true
|
||||
w.setFake()
|
||||
w.startW = w.parent.startW
|
||||
w.startH = w.parent.startH
|
||||
nw.isFake = true
|
||||
n.setFake()
|
||||
return
|
||||
case toolkit.Group:
|
||||
w.startW = w.parent.startW + 4
|
||||
w.startH = w.parent.startH + me.DefaultHeight + me.FramePadH
|
||||
|
||||
t := len(w.text)
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + t + me.FramePadW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + me.DefaultHeight + me.FramePadH
|
||||
nw.frame = false
|
||||
return
|
||||
case toolkit.Label:
|
||||
nw.frame = false
|
||||
return
|
||||
default:
|
||||
w.startW = w.parent.startW
|
||||
w.startH = w.parent.startH
|
||||
if w.IsCurrent() {
|
||||
w.updateCurrent()
|
||||
/*
|
||||
if n.IsCurrent() {
|
||||
n.updateCurrent()
|
||||
}
|
||||
*/
|
||||
}
|
||||
w.showWidgetPlacement(logInfo, "addWidget()")
|
||||
n.showWidgetPlacement(logInfo, "addWidget()")
|
||||
}
|
||||
|
|
|
@ -5,28 +5,29 @@ import (
|
|||
"git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
||||
func (w *cuiWidget) setCheckbox(b bool) {
|
||||
if (w.widgetType != toolkit.Checkbox) {
|
||||
func (n *node) setCheckbox(b bool) {
|
||||
w := n.tk
|
||||
if (n.WidgetType != toolkit.Checkbox) {
|
||||
return
|
||||
}
|
||||
if (b) {
|
||||
w.b = b
|
||||
w.text = "X " + w.name
|
||||
n.B = b
|
||||
n.Text = "X " + n.Name
|
||||
} else {
|
||||
w.b = b
|
||||
w.text = " " + w.name
|
||||
n.B = b
|
||||
n.Text = " " + n.Name
|
||||
}
|
||||
t := len(w.text) + 1
|
||||
t := len(n.Text) + 1
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + t
|
||||
|
||||
w.realWidth = w.gocuiSize.Width() + me.PadW
|
||||
w.realHeight = w.gocuiSize.Height() + me.PadH
|
||||
// w.realWidth = w.gocuiSize.Width() + me.PadW
|
||||
// w.realHeight = w.gocuiSize.Height() + me.PadH
|
||||
|
||||
if w.frame {
|
||||
w.realWidth += me.FramePadW
|
||||
w.realHeight += me.FramePadH
|
||||
}
|
||||
// if w.frame {
|
||||
// w.realWidth += me.FramePadW
|
||||
// w.realHeight += me.FramePadH
|
||||
// }
|
||||
|
||||
w.deleteView()
|
||||
w.showView()
|
||||
n.deleteView()
|
||||
n.showView()
|
||||
}
|
||||
|
|
|
@ -1,278 +1,275 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
// "errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/awesome-gocui/gocui"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
||||
// set isCurrent = false everywhere
|
||||
func UnsetCurrent(w *cuiWidget) {
|
||||
func UnsetCurrent(n *node) {
|
||||
w := n.tk
|
||||
w.isCurrent = false
|
||||
|
||||
for _, child := range w.children {
|
||||
for _, child := range n.children {
|
||||
UnsetCurrent(child)
|
||||
}
|
||||
}
|
||||
|
||||
func updateCurrentTabs() {
|
||||
me.rootNode.nextW = 0
|
||||
me.rootNode.nextH = 0
|
||||
me.rootNode.redoTabs(true)
|
||||
}
|
||||
|
||||
// when adding a new widget, this will update the display
|
||||
// of the current widgets if that widget is supposed
|
||||
// to be in current display
|
||||
func (w *cuiWidget) updateCurrent() {
|
||||
if w.widgetType == toolkit.Tab {
|
||||
if w.IsCurrent() {
|
||||
setCurrentTab(w)
|
||||
func (n *node) updateCurrent() {
|
||||
log("updateCurrent()", n.Name)
|
||||
if n.WidgetType == toolkit.Tab {
|
||||
if n.IsCurrent() {
|
||||
setCurrentTab(n)
|
||||
}
|
||||
return
|
||||
}
|
||||
if w.widgetType == toolkit.Window {
|
||||
if w.IsCurrent() {
|
||||
setCurrentWindow(w)
|
||||
if n.WidgetType == toolkit.Window {
|
||||
if n.IsCurrent() {
|
||||
// setCurrentWindow(n)
|
||||
}
|
||||
return
|
||||
}
|
||||
if w.widgetType == toolkit.Root {
|
||||
if n.WidgetType == toolkit.Root {
|
||||
return
|
||||
}
|
||||
w.parent.updateCurrent()
|
||||
n.parent.updateCurrent()
|
||||
}
|
||||
|
||||
// shows the widgets in a window
|
||||
func setCurrentWindow(w *cuiWidget) {
|
||||
if w.widgetType != toolkit.Window {
|
||||
func setCurrentWindow(n *node) {
|
||||
if n.IsCurrent() {
|
||||
return
|
||||
}
|
||||
w := n.tk
|
||||
if n.WidgetType != toolkit.Window {
|
||||
return
|
||||
}
|
||||
UnsetCurrent(me.rootNode)
|
||||
me.rootNode.hideWidgets()
|
||||
|
||||
// THIS IS THE BEGINING OF THE LAYOUT
|
||||
me.rootNode.nextW = 0
|
||||
me.rootNode.nextH = 0
|
||||
|
||||
w.isCurrent = true
|
||||
if w.hasTabs {
|
||||
if n.hasTabs {
|
||||
// set isCurrent = true on the first tab
|
||||
for _, child := range w.children {
|
||||
child.isCurrent = true
|
||||
for _, child := range n.children {
|
||||
child.tk.isCurrent = true
|
||||
break
|
||||
}
|
||||
} else {
|
||||
w.isCurrent = true
|
||||
}
|
||||
me.rootNode.redoTabs(true)
|
||||
|
||||
w.placeWidgets()
|
||||
w.showWidgets()
|
||||
}
|
||||
|
||||
// shows the widgets in a tab
|
||||
func setCurrentTab(w *cuiWidget) {
|
||||
if w.widgetType != toolkit.Tab {
|
||||
func setCurrentTab(n *node) {
|
||||
w := n.tk
|
||||
if n.WidgetType != toolkit.Tab {
|
||||
return
|
||||
}
|
||||
me.current = w
|
||||
UnsetCurrent(me.rootNode)
|
||||
me.rootNode.hideWidgets()
|
||||
w.isCurrent = true
|
||||
w.parent.isCurrent = true
|
||||
updateCurrentTabs()
|
||||
w.placeWidgets()
|
||||
w.showWidgets()
|
||||
p := n.parent.tk
|
||||
p.isCurrent = true
|
||||
log("setCurrent()", n.Name)
|
||||
}
|
||||
|
||||
func (w *cuiWidget) doWidgetClick() {
|
||||
switch w.widgetType {
|
||||
func (n *node) doWidgetClick() {
|
||||
switch n.WidgetType {
|
||||
case toolkit.Root:
|
||||
// THIS IS THE BEGINING OF THE LAYOUT
|
||||
me.rootNode.nextW = 0
|
||||
me.rootNode.nextH = 0
|
||||
me.rootNode.redoTabs(true)
|
||||
log("doWidgetClick()", n.Name)
|
||||
redoWindows(0,0)
|
||||
case toolkit.Flag:
|
||||
// me.rootNode.redoColor(true)
|
||||
me.rootNode.dumpTree(true)
|
||||
case toolkit.Window:
|
||||
setCurrentWindow(w)
|
||||
case toolkit.Tab:
|
||||
setCurrentTab(w)
|
||||
case toolkit.Group:
|
||||
w.placeWidgets()
|
||||
w.toggleTree()
|
||||
case toolkit.Checkbox:
|
||||
if (w.b) {
|
||||
w.setCheckbox(false)
|
||||
} else {
|
||||
w.setCheckbox(true)
|
||||
}
|
||||
w.doUserEvent()
|
||||
case toolkit.Grid:
|
||||
me.rootNode.hideWidgets()
|
||||
w.placeGrid()
|
||||
w.showWidgets()
|
||||
n.redoTabs(me.TabW, me.TabH)
|
||||
if ! n.hasTabs {
|
||||
setCurrentWindow(n)
|
||||
n.placeWidgets(me.RawW, me.RawH)
|
||||
n.showWidgets()
|
||||
}
|
||||
case toolkit.Tab:
|
||||
setCurrentTab(n)
|
||||
n.placeWidgets(me.RawW, me.RawH)
|
||||
n.showWidgets()
|
||||
case toolkit.Group:
|
||||
// n.placeWidgets(p.tk.startH, newH)
|
||||
n.toggleTree()
|
||||
case toolkit.Checkbox:
|
||||
if (n.B) {
|
||||
n.setCheckbox(false)
|
||||
} else {
|
||||
n.setCheckbox(true)
|
||||
}
|
||||
n.doUserEvent()
|
||||
case toolkit.Grid:
|
||||
n.placeGrid(n.tk.size.w0, n.tk.size.h0)
|
||||
n.showWidgets()
|
||||
case toolkit.Box:
|
||||
// w.showWidgetPlacement(logNow, "drawTree()")
|
||||
if (w.horizontal) {
|
||||
log("BOX IS HORIZONTAL", w.name)
|
||||
if (n.horizontal) {
|
||||
log("BOX IS HORIZONTAL", n.Name)
|
||||
} else {
|
||||
log("BOX IS VERTICAL", w.name)
|
||||
log("BOX IS VERTICAL", n.Name)
|
||||
}
|
||||
w.placeWidgets()
|
||||
w.toggleTree()
|
||||
// n.placeWidgets()
|
||||
n.toggleTree()
|
||||
case toolkit.Button:
|
||||
w.doUserEvent()
|
||||
n.doUserEvent()
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// this passes the user event back from the plugin
|
||||
func (w *cuiWidget) doUserEvent() {
|
||||
if (me.callback == nil) {
|
||||
log(logError, "doUserEvent() no callback channel was configured")
|
||||
return
|
||||
}
|
||||
var a toolkit.Action
|
||||
a.WidgetId = w.id
|
||||
a.Name = w.name
|
||||
a.Text = w.text
|
||||
a.B = w.b
|
||||
a.ActionType = toolkit.User
|
||||
me.callback <- a
|
||||
log(logNow, "END: sent a button click callback()")
|
||||
}
|
||||
|
||||
var toggle bool = true
|
||||
func (w *cuiWidget) toggleTree() {
|
||||
func (n *node) toggleTree() {
|
||||
if (toggle) {
|
||||
w.drawTree(toggle)
|
||||
n.drawTree(toggle)
|
||||
toggle = false
|
||||
} else {
|
||||
w.hideWidgets()
|
||||
n.hideWidgets()
|
||||
toggle = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// display the widgets in the binary tree
|
||||
func (w *cuiWidget) drawTree(draw bool) {
|
||||
func (n *node) drawTree(draw bool) {
|
||||
w := n.tk
|
||||
if (w == nil) {
|
||||
return
|
||||
}
|
||||
w.showWidgetPlacement(logNow, "drawTree()")
|
||||
n.showWidgetPlacement(logNow, "drawTree()")
|
||||
if (draw) {
|
||||
// w.textResize()
|
||||
w.showView()
|
||||
n.showView()
|
||||
} else {
|
||||
w.deleteView()
|
||||
n.deleteView()
|
||||
}
|
||||
|
||||
for _, child := range w.children {
|
||||
for _, child := range n.children {
|
||||
child.drawTree(draw)
|
||||
}
|
||||
}
|
||||
|
||||
func click(g *gocui.Gui, v *gocui.View) error {
|
||||
// var l string
|
||||
var err error
|
||||
// var err error
|
||||
|
||||
log(logNow, "click() START", v.Name())
|
||||
log(logVerbose, "click() START", v.Name())
|
||||
// n := me.rootNode.findWidgetName(v.Name())
|
||||
n := findUnderMouse()
|
||||
if (n != nil) {
|
||||
log(logNow, "click() Found widget =", n.WidgetId, n.Name, ",", n.Text)
|
||||
n.doWidgetClick()
|
||||
} else {
|
||||
log(logNow, "click() could not find node name =", v.Name())
|
||||
}
|
||||
/*
|
||||
i, err := strconv.Atoi(v.Name())
|
||||
if (err != nil) {
|
||||
log(logNow, "click() Can't find widget. error =", err)
|
||||
log(logError, "click() Can't find widget. error =", err)
|
||||
} else {
|
||||
log(logNow, "click() ok v.Name() =", v.Name())
|
||||
w := findWidget(i, me.rootNode)
|
||||
if (w == nil) {
|
||||
log(logVerbose, "click() ok v.Name() =", v.Name())
|
||||
n := me.rootNode.findWidgetId(i)
|
||||
if (n == nil) {
|
||||
log(logError, "click() CANT FIND VIEW in binary tree. v.Name =", v.Name())
|
||||
return nil
|
||||
}
|
||||
log(logNow, "click() Found widget =", w.id, w.name, ",", w.text)
|
||||
w.doWidgetClick()
|
||||
log(logNow, "click() Found widget =", n.WidgetId, n.Name, ",", n.Text)
|
||||
n.doWidgetClick()
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
|
||||
if _, err := g.SetCurrentView(v.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
_, cy := v.Cursor()
|
||||
if l, err = v.Line(cy); err != nil {
|
||||
l = ""
|
||||
}
|
||||
|
||||
maxX, maxY := g.Size()
|
||||
if v, err := g.SetView("msg", maxX/2-10, maxY/2, maxX/2+10, maxY/2+2, 0); err == nil || errors.Is(err, gocui.ErrUnknownView) {
|
||||
v.Clear()
|
||||
v.SelBgColor = gocui.ColorCyan
|
||||
v.SelFgColor = gocui.ColorBlack
|
||||
fmt.Fprintln(v, l)
|
||||
}
|
||||
*/
|
||||
|
||||
// this seems to delete the button(?)
|
||||
// g.SetViewOnBottom(v.Name())
|
||||
log(logNow, "click() END")
|
||||
log(logVerbose, "click() END")
|
||||
return nil
|
||||
}
|
||||
|
||||
// display the widgets in the binary tree
|
||||
|
||||
func ctrlDown(g *gocui.Gui, v *gocui.View) error {
|
||||
var found *cuiWidget
|
||||
var widgets []*cuiWidget
|
||||
var f func (widget *cuiWidget)
|
||||
w, h := g.MousePosition()
|
||||
func findUnderMouse() *node {
|
||||
var found *node
|
||||
var widgets []*node
|
||||
var f func (n *node)
|
||||
w, h := me.baseGui.MousePosition()
|
||||
|
||||
// find buttons that are below where the mouse button click
|
||||
f = func(widget *cuiWidget) {
|
||||
// if ((widget.logicalSize.w0 < w) && (w < widget.logicalSize.w1)) {
|
||||
f = func(n *node) {
|
||||
widget := n.tk
|
||||
// ignore widgets that are not visible
|
||||
if n.Visible() {
|
||||
if ((widget.gocuiSize.w0 <= w) && (w <= widget.gocuiSize.w1) &&
|
||||
(widget.gocuiSize.h0 <= h) && (h <= widget.gocuiSize.h1)) {
|
||||
widgets = append(widgets, widget)
|
||||
found = widget
|
||||
widgets = append(widgets, n)
|
||||
found = n
|
||||
}
|
||||
}
|
||||
|
||||
for _, child := range widget.children {
|
||||
for _, child := range n.children {
|
||||
f(child)
|
||||
}
|
||||
}
|
||||
f(me.rootNode)
|
||||
var t string
|
||||
for _, widget := range widgets {
|
||||
// log(logNow, "ctrlDown() FOUND widget", widget.id, widget.name)
|
||||
t += widget.cuiName + " " + widget.name + "\n"
|
||||
widget.showWidgetPlacement(logNow, "ctrlDown() FOUND")
|
||||
// widgets has everything that matches
|
||||
// TODO: pop up menu with a list of them
|
||||
for _, n := range widgets {
|
||||
//log(logNow, "ctrlDown() FOUND widget", widget.id, widget.name)
|
||||
n.showWidgetPlacement(logNow, "ctrlDown() FOUND")
|
||||
}
|
||||
t = strings.TrimSpace(t)
|
||||
return found
|
||||
}
|
||||
|
||||
// find the widget under the mouse click
|
||||
func ctrlDown(g *gocui.Gui, v *gocui.View) error {
|
||||
var found *node
|
||||
// var widgets []*node
|
||||
// var f func (n *node)
|
||||
found = findUnderMouse()
|
||||
/*
|
||||
w, h := g.MousePosition()
|
||||
|
||||
// find buttons that are below where the mouse button click
|
||||
f = func(n *node) {
|
||||
widget := n.tk
|
||||
// ignore widgets that are not visible
|
||||
if n.Visible() {
|
||||
if ((widget.gocuiSize.w0 <= w) && (w <= widget.gocuiSize.w1) &&
|
||||
(widget.gocuiSize.h0 <= h) && (h <= widget.gocuiSize.h1)) {
|
||||
widgets = append(widgets, n)
|
||||
found = n
|
||||
}
|
||||
}
|
||||
|
||||
for _, child := range n.children {
|
||||
f(child)
|
||||
}
|
||||
}
|
||||
f(me.rootNode)
|
||||
*/
|
||||
if (me.ctrlDown == nil) {
|
||||
setupCtrlDownWidget()
|
||||
me.ctrlDown.text = "ctrlDown" // t
|
||||
me.ctrlDown.cuiName = "ctrlDown"
|
||||
me.ctrlDown.parent = me.rootNode
|
||||
me.ctrlDown.Text = found.Name
|
||||
me.ctrlDown.tk.cuiName = "ctrlDown"
|
||||
// me.ctrlDown.parent = me.rootNode
|
||||
}
|
||||
cd := me.ctrlDown.tk
|
||||
if (found == nil) {
|
||||
found = me.rootNode
|
||||
}
|
||||
// ? TODO: found.setRealSize()
|
||||
me.ctrlDown.gocuiSize.w0 = found.startW
|
||||
me.ctrlDown.gocuiSize.h0 = found.startH
|
||||
me.ctrlDown.gocuiSize.w1 = me.ctrlDown.gocuiSize.w0 + found.realWidth
|
||||
me.ctrlDown.gocuiSize.h1 = me.ctrlDown.gocuiSize.h0 + found.realHeight
|
||||
if (me.ctrlDown.v == nil) {
|
||||
me.ctrlDown.text = found.text
|
||||
me.ctrlDown.showWidgetPlacement(logNow, "ctrlDown:")
|
||||
me.ctrlDown.showView()
|
||||
} else {
|
||||
me.ctrlDown.Text = found.Name
|
||||
newR := found.realGocuiSize()
|
||||
cd.gocuiSize.w0 = newR.w0
|
||||
cd.gocuiSize.h0 = newR.h0
|
||||
cd.gocuiSize.w1 = newR.w1
|
||||
cd.gocuiSize.h1 = newR.h1
|
||||
if me.ctrlDown.Visible() {
|
||||
me.ctrlDown.deleteView()
|
||||
} else {
|
||||
me.ctrlDown.updateView()
|
||||
}
|
||||
|
||||
log(logNow, "ctrlDown()", w, h)
|
||||
me.ctrlDown.showWidgetPlacement(logNow, "ctrlDown:")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -8,8 +8,9 @@ import (
|
|||
|
||||
// ColorBlack ColorRed ColorGreen ColorYellow ColorBlue ColorMagenta ColorCyan ColorWhite
|
||||
// gocui.GetColor("#FFAA55") // Dark Purple
|
||||
func (w *cuiWidget) setDefaultWidgetColor() {
|
||||
log(logInfo, "setDefaultWidgetColor() on", w.widgetType, w.name)
|
||||
func (n *node) setDefaultWidgetColor() {
|
||||
w := n.tk
|
||||
log(logInfo, "setDefaultWidgetColor() on", n.WidgetType, n.Name)
|
||||
v, _ := me.baseGui.View(w.cuiName)
|
||||
if (v == nil) {
|
||||
log(logError, "setDefaultWidgetColor() failed on view == nil")
|
||||
|
@ -24,7 +25,7 @@ func (w *cuiWidget) setDefaultWidgetColor() {
|
|||
|
||||
// v.BgColor = gocui.GetColor("#55AAFF") // super light grey
|
||||
// v.BgColor = gocui.GetColor("#FFC0CB") // 'w3c pink' yellow
|
||||
switch w.widgetType {
|
||||
switch n.WidgetType {
|
||||
case toolkit.Root:
|
||||
v.FrameColor = gocui.ColorRed
|
||||
v.BgColor = gocui.GetColor("#B0E0E6") // w3c 'powerder blue'
|
||||
|
@ -84,7 +85,8 @@ func (w *cuiWidget) SetColor(c string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (w *cuiWidget) setDefaultHighlight() {
|
||||
func (n *node) setDefaultHighlight() {
|
||||
w := n.tk
|
||||
if (w.v == nil) {
|
||||
log(logError, "SetColor() failed on view == nil")
|
||||
return
|
||||
|
@ -100,16 +102,17 @@ func randColor() gocui.Attribute {
|
|||
return gocui.GetColor(colors[i])
|
||||
}
|
||||
|
||||
func (w *cuiWidget) redoColor(draw bool) {
|
||||
func (n *node) redoColor(draw bool) {
|
||||
w := n.tk
|
||||
if (w == nil) {
|
||||
return
|
||||
}
|
||||
|
||||
sleep(.05)
|
||||
w.setDefaultHighlight()
|
||||
// w.setDefaultWidgetColor()
|
||||
n.setDefaultHighlight()
|
||||
n.setDefaultWidgetColor()
|
||||
|
||||
for _, child := range w.children {
|
||||
for _, child := range n.children {
|
||||
child.redoColor(draw)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,118 +3,182 @@ package main
|
|||
import (
|
||||
"strconv"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
// "github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
func makeWidget(a *toolkit.Action) *cuiWidget {
|
||||
func makeWidget(n *node) *cuiWidget {
|
||||
var w *cuiWidget
|
||||
w = new(cuiWidget)
|
||||
// Set(w, "default")
|
||||
|
||||
w.name = a.Name
|
||||
w.text = a.Text
|
||||
w.b = a.B
|
||||
w.i = a.I
|
||||
w.s = a.S
|
||||
|
||||
w.X = a.X
|
||||
w.Y = a.Y
|
||||
|
||||
t := len(w.text)
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + t + me.PadW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + me.DefaultHeight + me.PadH
|
||||
|
||||
w.realWidth = w.gocuiSize.Width()
|
||||
w.realHeight = w.gocuiSize.Height()
|
||||
|
||||
// set the gocui view.Frame = true by default
|
||||
w.frame = true
|
||||
if (w.frame) {
|
||||
w.realHeight += me.FramePadH
|
||||
w.gocuiSize.height += me.FramePadH
|
||||
}
|
||||
|
||||
w.widgetType = a.WidgetType
|
||||
w.id = a.WidgetId
|
||||
// set the name used by gocui to the id
|
||||
w.cuiName = strconv.Itoa(w.id)
|
||||
w.cuiName = strconv.Itoa(n.WidgetId)
|
||||
|
||||
if w.widgetType == toolkit.Root {
|
||||
log(logInfo, "setupWidget() FOUND ROOT w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
|
||||
w.id = 0
|
||||
me.rootNode = w
|
||||
if n.WidgetType == toolkit.Root {
|
||||
log(logInfo, "setupWidget() FOUND ROOT w.id =", n.WidgetId)
|
||||
n.WidgetId = 0
|
||||
me.rootNode = n
|
||||
return w
|
||||
}
|
||||
|
||||
w.parent = findWidget(a.ParentId, me.rootNode)
|
||||
log(logInfo, "setupWidget() w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
|
||||
if (w.parent == nil) {
|
||||
log(logError, "setupWidget() ERROR: PARENT = NIL w.id =", w.id, "w.parent", w.parent, "ParentId =", a.ParentId)
|
||||
// just use the rootNode (hopefully it's not nil)
|
||||
w.parent = me.rootNode
|
||||
// return w
|
||||
}
|
||||
|
||||
// add this widget as a child for the parent
|
||||
w.parent.Append(w)
|
||||
|
||||
if (a.WidgetType == toolkit.Box) {
|
||||
if (a.B) {
|
||||
w.horizontal = true
|
||||
if (n.WidgetType == toolkit.Box) {
|
||||
if (n.B) {
|
||||
n.horizontal = true
|
||||
} else {
|
||||
w.horizontal = false
|
||||
n.horizontal = false
|
||||
}
|
||||
}
|
||||
if (a.WidgetType == toolkit.Grid) {
|
||||
|
||||
if (n.WidgetType == toolkit.Grid) {
|
||||
w.widths = make(map[int]int) // how tall each row in the grid is
|
||||
w.heights = make(map[int]int) // how wide each column in the grid is
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
func setupCtrlDownWidget() {
|
||||
var w *cuiWidget
|
||||
w = new(cuiWidget)
|
||||
a := new(toolkit.Action)
|
||||
a.Name = "ctrlDown"
|
||||
a.WidgetType = toolkit.Dialog
|
||||
a.WidgetId = -1
|
||||
a.ParentId = 0
|
||||
n := addNode(a)
|
||||
|
||||
w.name = "ctrlDown"
|
||||
|
||||
w.widgetType = toolkit.Flag
|
||||
w.id = -1
|
||||
me.ctrlDown = w
|
||||
// me.rootNode.Append(w)
|
||||
me.ctrlDown = n
|
||||
}
|
||||
|
||||
func (w *cuiWidget) deleteView() {
|
||||
func (n *node) deleteView() {
|
||||
w := n.tk
|
||||
if (w.v != nil) {
|
||||
me.baseGui.DeleteView(w.cuiName)
|
||||
w.v.Visible = false
|
||||
return
|
||||
}
|
||||
// make sure the view isn't really there
|
||||
me.baseGui.DeleteView(w.cuiName)
|
||||
w.v = nil
|
||||
}
|
||||
|
||||
func (n *cuiWidget) Append(child *cuiWidget) {
|
||||
n.children = append(n.children, child)
|
||||
// child.parent = n
|
||||
}
|
||||
|
||||
// find widget by number
|
||||
func findWidget(i int, w *cuiWidget) (*cuiWidget) {
|
||||
if (w == nil) {
|
||||
log(logVerbose, "findWidget() Trying to find i =", i, "currently checking against w.id = nil")
|
||||
// searches the binary tree for a WidgetId
|
||||
func (n *node) findWidgetId(id int) *node {
|
||||
if (n == nil) {
|
||||
return nil
|
||||
}
|
||||
log(logVerbose, "findWidget() Trying to find i =", i, "currently checking against w.id =", w.id)
|
||||
|
||||
if (w.id == i) {
|
||||
log(logInfo, "findWidget() FOUND w.id ==", i, w.widgetType, w.name)
|
||||
return w
|
||||
if n.WidgetId == id {
|
||||
return n
|
||||
}
|
||||
|
||||
for _, child := range w.children {
|
||||
newW := findWidget(i, child)
|
||||
log(logVerbose, "findWidget() Trying to find i =", i, "currently checking against child.id =", child.id)
|
||||
if (newW != nil) {
|
||||
return newW
|
||||
for _, child := range n.children {
|
||||
newN := child.findWidgetId(id)
|
||||
if (newN != nil) {
|
||||
return newN
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// searches the binary tree for a WidgetId
|
||||
func (n *node) findWidgetName(name string) *node {
|
||||
if (n == nil) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if n.tk.cuiName == name {
|
||||
return n
|
||||
}
|
||||
|
||||
for _, child := range n.children {
|
||||
newN := child.findWidgetName(name)
|
||||
if (newN != nil) {
|
||||
return newN
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addNode(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 = makeWidget(n)
|
||||
|
||||
if (a.WidgetType == toolkit.Root) {
|
||||
log(logInfo, "addNode() Root")
|
||||
return n
|
||||
}
|
||||
|
||||
if (me.rootNode.findWidgetId(a.WidgetId) != nil) {
|
||||
log(logError, "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
|
||||
}
|
||||
|
||||
func (n *node) IsCurrent() bool {
|
||||
w := n.tk
|
||||
if (n.WidgetType == toolkit.Tab) {
|
||||
return w.isCurrent
|
||||
}
|
||||
if (n.WidgetType == toolkit.Window) {
|
||||
return w.isCurrent
|
||||
}
|
||||
if (n.WidgetType == toolkit.Root) {
|
||||
return false
|
||||
}
|
||||
return n.parent.IsCurrent()
|
||||
}
|
||||
|
||||
func (n *node) Visible() bool {
|
||||
if (n == nil) {
|
||||
return false
|
||||
}
|
||||
if (n.tk == nil) {
|
||||
return false
|
||||
}
|
||||
if (n.tk.v == nil) {
|
||||
return false
|
||||
}
|
||||
return n.tk.v.Visible
|
||||
}
|
||||
|
||||
func (n *node) SetVisible(b bool) {
|
||||
if (n == nil) {
|
||||
return
|
||||
}
|
||||
if (n.tk == nil) {
|
||||
return
|
||||
}
|
||||
if (n.tk.v == nil) {
|
||||
return
|
||||
}
|
||||
n.tk.v.Visible = b
|
||||
}
|
||||
|
|
|
@ -2,37 +2,72 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
||||
func (w *cuiWidget) dumpTree(draw bool) {
|
||||
func (n *node) dumpTree(draw bool) {
|
||||
w := n.tk
|
||||
if (w == nil) {
|
||||
return
|
||||
}
|
||||
w.showWidgetPlacement(logNow, "Tree:")
|
||||
n.showWidgetPlacement(logNow, "Tree:")
|
||||
|
||||
for _, child := range w.children {
|
||||
for _, child := range n.children {
|
||||
child.dumpTree(draw)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *cuiWidget) showWidgetPlacement(b bool, s string) {
|
||||
var s1 string
|
||||
var pId int
|
||||
if (w == nil) {
|
||||
func (n *node) showWidgetPlacement(b bool, s string) {
|
||||
if (n == nil) {
|
||||
log(logError, "WTF w == nil")
|
||||
return
|
||||
}
|
||||
if (w.parent == nil) {
|
||||
log(logVerbose, "showWidgetPlacement() parent == nil", w.id, w.cuiName)
|
||||
w := n.tk
|
||||
|
||||
var s1 string
|
||||
var pId int
|
||||
if (n.parent == nil) {
|
||||
log(logVerbose, "showWidgetPlacement() parent == nil", n.WidgetId, w.cuiName)
|
||||
pId = 0
|
||||
} else {
|
||||
pId = w.parent.id
|
||||
pId = n.parent.WidgetId
|
||||
}
|
||||
s1 = fmt.Sprintf("(wId,pId)=(%2d,%2d) ", w.id, pId)
|
||||
s1 += fmt.Sprintf("s/n (%2d,%2d) (%2d,%2d) ", w.startW, w.startH, w.nextW, w.nextH)
|
||||
s1 += fmt.Sprintf("size (%2d,%2d) ", w.realWidth, w.realHeight)
|
||||
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() {
|
||||
s1 += fmt.Sprintf("gocui=(%2d,%2d)(%2d,%2d,%2d,%2d)",
|
||||
w.gocuiSize.Width(), w.gocuiSize.Height(),
|
||||
w.gocuiSize.w0, w.gocuiSize.h0, w.gocuiSize.w1, w.gocuiSize.h1)
|
||||
log(b, s1, s, w.widgetType, ",", w.name) // , "text=", w.text)
|
||||
}
|
||||
if (n.parent != nil) {
|
||||
if (n.parent.WidgetType == toolkit.Grid) {
|
||||
s1 += fmt.Sprintf("At(%2d,%2d) ", n.AtW, n.AtH)
|
||||
}
|
||||
}
|
||||
log(b, s1, s, n.WidgetType, ",", n.Name) // , "text=", w.text)
|
||||
}
|
||||
|
||||
func (n *node) dumpWidget(pad string) {
|
||||
log(true, "node:", pad, n.WidgetId, "At(", n.AtW, n.AtH, ") ,", n.WidgetType, ",", n.Name)
|
||||
}
|
||||
|
||||
func (n *node) listWidgets() {
|
||||
if (n == nil) {
|
||||
return
|
||||
}
|
||||
|
||||
var pad string
|
||||
for i := 0; i < me.depth; i++ {
|
||||
pad = pad + " "
|
||||
}
|
||||
n.dumpWidget(pad)
|
||||
|
||||
for _, child := range n.children {
|
||||
me.depth += 1
|
||||
child.listWidgets()
|
||||
me.depth -= 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2014 The gocui Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
func globalDown(g *gocui.Gui, v *gocui.View) error {
|
||||
mx, my := g.MousePosition()
|
||||
if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil {
|
||||
if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 {
|
||||
return msgDown(g, v)
|
||||
}
|
||||
}
|
||||
globalMouseDown = true
|
||||
maxX, _ := g.Size()
|
||||
msg := fmt.Sprintf("Mouse really down at: %d,%d", mx, my) + "foo\n" + "bar\n"
|
||||
x := mx - len(msg)/2
|
||||
if x < 0 {
|
||||
x = 0
|
||||
} else if x+len(msg)+1 > maxX-1 {
|
||||
x = maxX - 1 - len(msg) - 1
|
||||
}
|
||||
if v, err := g.SetView("globalDown", x, my-1, x+len(msg)+1, my+1, 0); err != nil {
|
||||
if !errors.Is(err, gocui.ErrUnknownView) {
|
||||
return err
|
||||
}
|
||||
v.WriteString(msg)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright 2014 The gocui Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
// This initializes the gocui package
|
||||
// it runs SetManagerFunc which passes every input
|
||||
// event (keyboard, mouse, etc) to the function "gocuiEvent()"
|
||||
func gocuiMain() {
|
||||
g, err := gocui.NewGui(gocui.OutputNormal, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer g.Close()
|
||||
|
||||
me.baseGui = g
|
||||
|
||||
g.Cursor = true
|
||||
g.Mouse = true
|
||||
|
||||
// this sets the function that is run on every event. For example:
|
||||
// When you click the mouse, move the mouse, or press a key on the keyboard
|
||||
// This is equivalent to xev or similar to cat /dev/input on linux
|
||||
g.SetManagerFunc(gocuiEvent)
|
||||
|
||||
if err := defaultKeybindings(g); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Thanks to the gocui developers -- your package kicks ass
|
||||
// This function is called on every event. It is a callback function from the gocui package
|
||||
// which has an excellent implementation. While gocui handles things like text highlighting
|
||||
// and the layout of the text areas -- also things like handling SIGWINCH and lots of really
|
||||
// complicated console handling, it sends events here in a clean way.
|
||||
// This is equivalent to the linux command xev (apt install x11-utils)
|
||||
func gocuiEvent(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
mx, my := g.MousePosition()
|
||||
log(logVerbose, "handleEvent() START", maxX, maxY, mx, my, msgMouseDown)
|
||||
if _, err := g.View("msg"); msgMouseDown && err == nil {
|
||||
moveMsg(g)
|
||||
}
|
||||
if widgetView, _ := g.View("msg"); widgetView == nil {
|
||||
log(logNow, "handleEvent() create output widget now", maxX, maxY, mx, my)
|
||||
makeOutputWidget(g, "this is a create before a mouse click")
|
||||
if (me.logStdout != nil) {
|
||||
// setOutput(me.logStdout)
|
||||
}
|
||||
} else {
|
||||
log(logInfo, "output widget already exists", maxX, maxY, mx, my)
|
||||
}
|
||||
mouseMove(g)
|
||||
log(logVerbose, "handleEvent() END ", maxX, maxY, mx, my, msgMouseDown)
|
||||
return nil
|
||||
}
|
||||
|
||||
func dragOutputWindow() {
|
||||
}
|
||||
|
||||
// turns off the frame on the global window
|
||||
func setFrame(b bool) {
|
||||
// TODO: figure out what this might be useful for
|
||||
// what is this do? I made it just 2 lines for now. Is this useful for something?
|
||||
v := SetView("global", 15, 5, 80, 8, 10)
|
||||
if (v == nil) {
|
||||
log(logError, "setFrame() global failed")
|
||||
}
|
||||
v.Frame = b
|
||||
}
|
||||
|
||||
func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
return gocui.ErrQuit
|
||||
}
|
||||
|
||||
func SetView(name string, x0, y0, x1, y1 int, overlaps byte) *gocui.View {
|
||||
if (me.baseGui == nil) {
|
||||
log(logError, "SetView() ERROR: me.baseGui == nil")
|
||||
return nil
|
||||
}
|
||||
|
||||
v, err := me.baseGui.SetView(name, x0, y0, x1, y1, overlaps)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gocui.ErrUnknownView) {
|
||||
log(logError, "SetView() global failed on name =", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
|
@ -12,25 +12,23 @@ import (
|
|||
"github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
func addHelp() {
|
||||
me.baseGui.SetManagerFunc(helplayout)
|
||||
}
|
||||
|
||||
var helpText []string = []string{"KEYBINDINGS",
|
||||
"",
|
||||
"d: show/hide debugging",
|
||||
"h: hide widgets",
|
||||
"s: show all widgets",
|
||||
"s/h: show/hide all widgets",
|
||||
"L: list all widgets",
|
||||
"q: quit()",
|
||||
"p: panic()",
|
||||
"o: show Stdout",
|
||||
"l: log to /tmp/witgui.log",
|
||||
"Ctrl-D: Enable Debugging",
|
||||
"Ctrl-D: Toggle Debugging",
|
||||
"Ctrl-V: Toggle Verbose Debugging",
|
||||
"Ctrl-C: Exit",
|
||||
"",
|
||||
}
|
||||
|
||||
func helplayout(g *gocui.Gui) error {
|
||||
func helplayout() error {
|
||||
g := me.baseGui
|
||||
var err error
|
||||
maxX, _ := g.Size()
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"github.com/awesome-gocui/gocui"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
@ -21,7 +22,7 @@ func defaultKeybindings(g *gocui.Gui) error {
|
|||
if err := g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, globalDown); err != nil {
|
||||
if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, mouseDown); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown); err != nil {
|
||||
|
@ -47,7 +48,7 @@ func addDebugKeys(g *gocui.Gui) {
|
|||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
log(logNow, "gocui.SetKeyBinding() dumpTree() START")
|
||||
// me.rootNode.dumpTree(true)
|
||||
fakeStartWidth = me.DevelOffsetW
|
||||
fakeStartWidth = me.FakeW
|
||||
fakeStartHeight = me.TabH + me.FramePadH
|
||||
if (showDebug) {
|
||||
me.rootNode.showFake()
|
||||
|
@ -59,6 +60,12 @@ func addDebugKeys(g *gocui.Gui) {
|
|||
return nil
|
||||
})
|
||||
|
||||
// display the help menu
|
||||
g.SetKeybinding("", '?', gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
helplayout()
|
||||
return nil
|
||||
})
|
||||
// hide all widgets
|
||||
g.SetKeybinding("", 'h', gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
|
@ -73,6 +80,26 @@ func addDebugKeys(g *gocui.Gui) {
|
|||
return nil
|
||||
})
|
||||
|
||||
// list all widgets
|
||||
g.SetKeybinding("", 'L', gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
me.rootNode.listWidgets()
|
||||
return nil
|
||||
})
|
||||
|
||||
// log to output window
|
||||
g.SetKeybinding("", 'o', gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
if me.logStdout.Visible() {
|
||||
me.logStdout.SetVisible(false)
|
||||
setOutput(os.Stdout)
|
||||
} else {
|
||||
me.logStdout.SetVisible(true)
|
||||
setOutput(me.logStdout.tk)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// exit
|
||||
g.SetKeybinding("", 'q', gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
|
@ -86,9 +113,28 @@ func addDebugKeys(g *gocui.Gui) {
|
|||
})
|
||||
g.SetKeybinding("", gocui.KeyCtrlD, gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
if (showDebug) {
|
||||
var a toolkit.Action
|
||||
a.B = true
|
||||
a.ActionType = toolkit.EnableDebug
|
||||
me.callback <- a
|
||||
logInfo = true
|
||||
logVerbose = true
|
||||
} else {
|
||||
logInfo = false
|
||||
logVerbose = false
|
||||
}
|
||||
return nil
|
||||
})
|
||||
g.SetKeybinding("", gocui.KeyCtrlV, gocui.ModNone,
|
||||
func(g *gocui.Gui, v *gocui.View) error {
|
||||
if (logVerbose) {
|
||||
logInfo = false
|
||||
logVerbose = false
|
||||
} else {
|
||||
logInfo = true
|
||||
logVerbose = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ func main() {
|
|||
|
||||
ferr, _ := os.OpenFile("/tmp/witgui.err", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
||||
os.Stderr = ferr
|
||||
MouseMain()
|
||||
gocuiMain()
|
||||
|
||||
log(true, "MouseMain() closed")
|
||||
standardExit()
|
||||
|
|
|
@ -6,68 +6,13 @@ package main
|
|||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"fmt"
|
||||
"github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
func MouseMain() {
|
||||
g, err := gocui.NewGui(gocui.OutputNormal, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer g.Close()
|
||||
|
||||
me.baseGui = g
|
||||
|
||||
g.Cursor = true
|
||||
g.Mouse = true
|
||||
|
||||
g.SetManagerFunc(layout)
|
||||
|
||||
if err := defaultKeybindings(g); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func layout(g *gocui.Gui) error {
|
||||
maxX, maxY := g.Size()
|
||||
mx, my := g.MousePosition()
|
||||
if _, err := g.View("msg"); msgMouseDown && err == nil {
|
||||
moveMsg(g)
|
||||
}
|
||||
// TODO: figure out what this might be useful for
|
||||
// what is this do? I made it just 2 lines for now. Is this useful for something?
|
||||
if v, err := g.SetView("global", 15, 5, maxX, 8, 10); err != nil {
|
||||
if !errors.Is(err, gocui.ErrUnknownView) {
|
||||
log("global failed", maxX, maxY)
|
||||
return err
|
||||
}
|
||||
v.Frame = false
|
||||
}
|
||||
helplayout(g)
|
||||
if widgetView, _ := g.View("msg"); widgetView == nil {
|
||||
log(logInfo, "create output widget now", maxX, maxY, mx, my)
|
||||
makeOutputWidget(g, "this is a create before a mouse click")
|
||||
if (me.logStdout != nil) {
|
||||
setOutput(me.logStdout)
|
||||
}
|
||||
} else {
|
||||
log(logInfo, "output widget already exists", maxX, maxY, mx, my)
|
||||
}
|
||||
updateHighlightedView(g)
|
||||
log(logInfo, "layout() END", maxX, maxY, mx, my)
|
||||
return nil
|
||||
}
|
||||
|
||||
func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
return gocui.ErrQuit
|
||||
}
|
||||
|
||||
func updateHighlightedView(g *gocui.Gui) {
|
||||
// this function uses the mouse position to highlight & unhighlight things
|
||||
// this is run every time the user moves the mouse over the terminal window
|
||||
func mouseMove(g *gocui.Gui) {
|
||||
mx, my := g.MousePosition()
|
||||
for _, view := range g.Views() {
|
||||
view.Highlight = false
|
||||
|
@ -102,3 +47,28 @@ func mouseUp(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func mouseDown(g *gocui.Gui, v *gocui.View) error {
|
||||
mx, my := g.MousePosition()
|
||||
if vx0, vy0, vx1, vy1, err := g.ViewPosition("msg"); err == nil {
|
||||
if mx >= vx0 && mx <= vx1 && my >= vy0 && my <= vy1 {
|
||||
return msgDown(g, v)
|
||||
}
|
||||
}
|
||||
globalMouseDown = true
|
||||
maxX, _ := g.Size()
|
||||
msg := fmt.Sprintf("Mouse really down at: %d,%d", mx, my) + "foo\n" + "bar\n"
|
||||
x := mx - len(msg)/2
|
||||
if x < 0 {
|
||||
x = 0
|
||||
} else if x+len(msg)+1 > maxX-1 {
|
||||
x = maxX - 1 - len(msg) - 1
|
||||
}
|
||||
if v, err := g.SetView("globalDown", x, my-1, x+len(msg)+1, my+1, 0); err != nil {
|
||||
if !errors.Is(err, gocui.ErrUnknownView) {
|
||||
return err
|
||||
}
|
||||
v.WriteString(msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,263 +1,196 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
// "github.com/awesome-gocui/gocui"
|
||||
"strings"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
)
|
||||
|
||||
func (w *cuiWidget) placeBox() {
|
||||
if (w.widgetType != toolkit.Box) {
|
||||
func (n *node) placeBox(startW int, startH int) {
|
||||
if (n.WidgetType != toolkit.Box) {
|
||||
return
|
||||
}
|
||||
w.startW = w.parent.nextW
|
||||
w.startH = w.parent.nextH
|
||||
w.nextW = w.parent.nextW
|
||||
w.nextH = w.parent.nextH
|
||||
w.realWidth = 0
|
||||
w.realHeight = 0
|
||||
n.tk.size.w0 = startW
|
||||
n.tk.size.h0 = startH
|
||||
n.showWidgetPlacement(logNow, "boxS()")
|
||||
|
||||
var maxW int
|
||||
var maxH int
|
||||
for _, child := range w.children {
|
||||
w.showWidgetPlacement(logNow, "boxS()")
|
||||
child.placeWidgets()
|
||||
if (w.horizontal) {
|
||||
log(logVerbose, "BOX IS HORIZONTAL")
|
||||
newW := startW
|
||||
newH := startH
|
||||
for _, child := range n.children {
|
||||
child.placeWidgets(newW, newH)
|
||||
// n.showWidgetPlacement(logNow, "boxS()")
|
||||
// w,h := child.logicalSize()
|
||||
newR := child.realGocuiSize()
|
||||
w := newR.w1 - newR.w0
|
||||
h := newR.h1 - newR.h0
|
||||
if (n.horizontal) {
|
||||
log(logNow, "BOX IS HORIZONTAL", n.Name, "newWH()", newW, newH, "child()", w, h, child.Name)
|
||||
// expand based on the child width
|
||||
w.nextW += child.realWidth
|
||||
w.realWidth += child.realWidth
|
||||
newW += w
|
||||
} else {
|
||||
log(logVerbose, "BOX IS VERTICAL")
|
||||
log(logNow, "BOX IS VERTICAL ", n.Name, "newWH()", newW, newH, "child()", w, h, child.Name)
|
||||
// expand based on the child height
|
||||
w.nextH += child.realHeight
|
||||
w.realHeight += child.realHeight
|
||||
}
|
||||
if (maxW < child.realWidth) {
|
||||
maxW = child.realWidth
|
||||
}
|
||||
if (maxH < child.realHeight) {
|
||||
maxH = child.realHeight
|
||||
newH += h
|
||||
}
|
||||
}
|
||||
if (w.horizontal) {
|
||||
w.realHeight = maxH
|
||||
} else {
|
||||
w.realWidth = maxW
|
||||
}
|
||||
w.showWidgetPlacement(logNow, "boxE()")
|
||||
// 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
|
||||
n.tk.size.h1 = n.tk.size.h0 + h
|
||||
n.showWidgetPlacement(logNow, "boxE()")
|
||||
}
|
||||
|
||||
func (w *cuiWidget) placeWidgets() {
|
||||
if (w == nil) {
|
||||
func (n *node) placeWidgets(startW int, startH int) {
|
||||
if (n == nil) {
|
||||
return
|
||||
}
|
||||
if (me.rootNode == nil) {
|
||||
return
|
||||
}
|
||||
p := w.parent
|
||||
if (p == nil) {
|
||||
log(logInfo, "place()", w.id, "parent == nil")
|
||||
return
|
||||
}
|
||||
|
||||
switch w.widgetType {
|
||||
switch n.WidgetType {
|
||||
case toolkit.Window:
|
||||
for _, child := range w.children {
|
||||
w.startW = me.RawW
|
||||
w.startH = me.RawH
|
||||
w.nextW = me.RawW
|
||||
w.nextH = me.RawH
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
child.placeWidgets()
|
||||
if (w.realWidth < child.realWidth) {
|
||||
w.realWidth = child.realWidth
|
||||
}
|
||||
if (w.realHeight < child.realHeight) {
|
||||
w.realHeight = child.realHeight
|
||||
}
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
for _, child := range n.children {
|
||||
child.placeWidgets(me.RawW, me.RawH)
|
||||
return
|
||||
}
|
||||
case toolkit.Tab:
|
||||
for _, child := range w.children {
|
||||
w.startW = me.RawW
|
||||
w.startH = me.RawH
|
||||
w.nextW = me.RawW
|
||||
w.nextH = me.RawH
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
child.placeWidgets()
|
||||
if (w.realWidth < child.realWidth) {
|
||||
w.realWidth = child.realWidth
|
||||
}
|
||||
if (w.realHeight < child.realHeight) {
|
||||
w.realHeight = child.realHeight
|
||||
}
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
for _, child := range n.children {
|
||||
child.placeWidgets(me.RawW, me.RawH)
|
||||
return
|
||||
}
|
||||
case toolkit.Grid:
|
||||
w.showWidgetPlacement(logNow, "placeGrid() START")
|
||||
w.placeGrid()
|
||||
w.showWidgetPlacement(logNow, "placeGrid() END")
|
||||
n.placeGrid(startW, startH)
|
||||
case toolkit.Box:
|
||||
w.showWidgetPlacement(logNow, "placeBox() START")
|
||||
w.placeBox()
|
||||
w.showWidgetPlacement(logNow, "placeBox() END")
|
||||
n.placeBox(startW, startH)
|
||||
case toolkit.Group:
|
||||
// move the group to the parent's next location
|
||||
w.startW = p.nextW
|
||||
w.startH = p.nextH
|
||||
w.nextW = p.nextW
|
||||
w.nextH = p.nextH
|
||||
w.moveTo(p.nextW, p.nextH)
|
||||
n.gocuiSetWH(startW, startH)
|
||||
n.showWidgetPlacement(logNow, "group()")
|
||||
|
||||
// initialize the real width to just the group gocui view
|
||||
w.realWidth = w.gocuiSize.Width() + me.FramePadW
|
||||
w.realHeight = w.gocuiSize.Height() + me.FramePadH
|
||||
|
||||
// indent the widgets for a group
|
||||
w.nextW = p.nextW + me.GroupPadW
|
||||
w.nextH = p.nextH + w.realHeight
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
|
||||
// mow move all the children aka: run place() on them
|
||||
var maxW int
|
||||
for _, child := range w.children {
|
||||
child.showWidgetPlacement(logNow, "place()")
|
||||
child.placeWidgets()
|
||||
child.showWidgetPlacement(logNow, "place()")
|
||||
newW := startW + me.GroupPadW
|
||||
newH := startH + 3 // normal hight of the group label
|
||||
// now move all the children aka: run place() on them
|
||||
for _, child := range n.children {
|
||||
child.placeWidgets(newW, newH)
|
||||
// _,h := child.logicalSize()
|
||||
newR := child.realGocuiSize()
|
||||
// w := newR.w1 - newR.w0
|
||||
h := newR.h1 - newR.h0
|
||||
|
||||
// increment straight down
|
||||
w.nextH += child.realHeight
|
||||
w.realHeight += child.realHeight
|
||||
|
||||
// track largest width
|
||||
if (maxW < child.realWidth) {
|
||||
maxW = child.realWidth
|
||||
newH += h
|
||||
}
|
||||
|
||||
}
|
||||
// add real width of largest child
|
||||
w.realWidth += maxW
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
default:
|
||||
w.startW = p.nextW
|
||||
w.startH = p.nextH
|
||||
w.nextW = p.nextW
|
||||
w.nextH = p.nextH
|
||||
newW := w.gocuiSize.Width()
|
||||
newH := w.gocuiSize.Height()
|
||||
w.gocuiSize.w0 = w.startW
|
||||
w.gocuiSize.h0 = w.startH
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + newW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + newH
|
||||
|
||||
// the realSize should not be smaller than the gocui view (?)
|
||||
// this might not be a needed check? Maybe there are legit exceptions?
|
||||
if (w.realWidth < newW) {
|
||||
w.realWidth = newW
|
||||
}
|
||||
if (w.realHeight < newH) {
|
||||
w.realHeight = newH
|
||||
}
|
||||
w.showWidgetPlacement(logNow, "place()")
|
||||
n.gocuiSetWH(startW, startH)
|
||||
// n.moveTo(startW, startH)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func (w *cuiWidget) setWH() {
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + w.gocuiSize.width
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + w.gocuiSize.height
|
||||
}
|
||||
*/
|
||||
|
||||
func (w *cuiWidget) moveTo(leftW int, topH int) {
|
||||
if (w.isFake) {
|
||||
func (n *node) placeGrid(startW int, startH int) {
|
||||
w := n.tk
|
||||
w.size.w0 = startW
|
||||
w.size.h0 = startH
|
||||
n.showWidgetPlacement(logInfo, "grid0:")
|
||||
if (n.WidgetType != toolkit.Grid) {
|
||||
return
|
||||
}
|
||||
newW := w.gocuiSize.Width()
|
||||
newH := w.gocuiSize.Height()
|
||||
w.gocuiSize.w0 = leftW
|
||||
w.gocuiSize.h0 = topH
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + newW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + newH
|
||||
w.showWidgetPlacement(logInfo, "moveTo()")
|
||||
}
|
||||
|
||||
func (w *cuiWidget) placeGrid() {
|
||||
w.showWidgetPlacement(logNow, "grid0:")
|
||||
if (w.widgetType != toolkit.Grid) {
|
||||
return
|
||||
}
|
||||
w.startW = w.parent.nextW
|
||||
w.startH = w.parent.nextH
|
||||
w.nextW = w.parent.nextW
|
||||
w.nextH = w.parent.nextH
|
||||
|
||||
var wCount int = 0
|
||||
var hCount int = 0
|
||||
for _, child := range w.children {
|
||||
// increment for the next child
|
||||
w.nextW = w.startW + wCount * 20
|
||||
w.nextH = w.startH + hCount * 2
|
||||
// first compute the max sizes of the rows and columns
|
||||
for _, child := range n.children {
|
||||
// childW, childH := child.logicalSize()
|
||||
newR := child.realGocuiSize()
|
||||
childW := newR.w1 - newR.w0
|
||||
childH := newR.h1 - newR.h0
|
||||
|
||||
// set the child's realWidth, and grid offset
|
||||
child.parentH = hCount
|
||||
child.parentW = wCount
|
||||
if (w.widths[wCount] < child.realWidth) {
|
||||
w.widths[wCount] = child.realWidth
|
||||
if (w.widths[child.AtW] < childW) {
|
||||
w.widths[child.AtW] = childW
|
||||
}
|
||||
if (w.heights[hCount] < child.realHeight) {
|
||||
w.heights[hCount] = child.realHeight
|
||||
}
|
||||
log(logVerbose, "grid1: (w,h count)", wCount, hCount, "(X,Y)", w.X, w.Y, w.name)
|
||||
child.showWidgetPlacement(logNow, "grid1: " + fmt.Sprintf("next()=(%2d,%2d)", w.nextW, w.nextH))
|
||||
|
||||
if ((wCount + 1) < w.X) {
|
||||
wCount += 1
|
||||
} else {
|
||||
wCount = 0
|
||||
hCount += 1
|
||||
if (w.heights[child.AtH] < childH) {
|
||||
w.heights[child.AtH] = childH
|
||||
}
|
||||
// child.showWidgetPlacement(logInfo, "grid: ")
|
||||
log(logVerbose, "placeGrid:", child.Name, "child()", childW, childH, "At()", child.AtW, child.AtH)
|
||||
}
|
||||
|
||||
// reset the size of the whole grid
|
||||
w.realWidth = 0
|
||||
w.realHeight = 0
|
||||
for _, val := range w.widths {
|
||||
w.realWidth += val
|
||||
}
|
||||
for _, val := range w.heights {
|
||||
w.realHeight += val
|
||||
}
|
||||
// find the width and height offset of the grid for AtW,AtH
|
||||
for _, child := range n.children {
|
||||
child.showWidgetPlacement(logInfo, "grid1:")
|
||||
|
||||
for _, child := range w.children {
|
||||
child.showWidgetPlacement(logVerbose, "grid2:")
|
||||
var totalW, totalH int
|
||||
for i, val := range w.widths {
|
||||
if (i < child.parentW) {
|
||||
log(logVerbose, "grid2: (w, widths[])", i, val)
|
||||
totalW += w.widths[i]
|
||||
for i, w := range w.widths {
|
||||
if (i < child.AtW) {
|
||||
totalW += w
|
||||
}
|
||||
}
|
||||
for i, h := range w.heights {
|
||||
if (i < child.parentH) {
|
||||
if (i < child.AtH) {
|
||||
totalH += h
|
||||
}
|
||||
}
|
||||
|
||||
// the new corner to move the child to
|
||||
w.nextW = w.startW + totalW
|
||||
w.nextH = w.startH + totalH
|
||||
newW := startW + totalW
|
||||
newH := startH + totalH
|
||||
|
||||
child.placeWidgets()
|
||||
log(logVerbose, "placeGrid:", child.Name, "new()", newW, newH, "At()", child.AtW, child.AtH)
|
||||
child.placeWidgets(newW, newH)
|
||||
child.showWidgetPlacement(logInfo, "grid2:")
|
||||
log(logInfo)
|
||||
}
|
||||
// w.updateLogicalSizes()
|
||||
w.showWidgetPlacement(logNow, "grid3:")
|
||||
n.showWidgetPlacement(logInfo, "grid3:")
|
||||
}
|
||||
|
||||
/*
|
||||
func (w *cuiWidget) setRealSize() {
|
||||
// computes the real, actual size of all the gocli objects in a widget
|
||||
func (n *node) realGocuiSize() *rectType {
|
||||
var f func (n *node, r *rectType)
|
||||
newR := new(rectType)
|
||||
// initialize the values to opposite
|
||||
newR.w0 = 80
|
||||
newR.h0 = 24
|
||||
if me.baseGui != nil {
|
||||
maxW, maxH := me.baseGui.Size()
|
||||
newR.w0 = maxW
|
||||
newR.h0 = maxH
|
||||
}
|
||||
newR.w1 = 0
|
||||
newR.h1 = 0
|
||||
|
||||
// expand the rectangle to the biggest thing displayed
|
||||
f = func(n *node, r *rectType) {
|
||||
newR := n.tk.gocuiSize
|
||||
if ! n.tk.isFake {
|
||||
if r.w0 > newR.w0 {
|
||||
r.w0 = newR.w0
|
||||
}
|
||||
if r.h0 > newR.h0 {
|
||||
r.h0 = newR.h0
|
||||
}
|
||||
if r.w1 < newR.w1 {
|
||||
r.w1 = newR.w1
|
||||
}
|
||||
if r.h1 < newR.h1 {
|
||||
r.h1 = newR.h1
|
||||
}
|
||||
}
|
||||
for _, child := range n.children {
|
||||
f(child, r)
|
||||
}
|
||||
}
|
||||
f(n, newR)
|
||||
return newR
|
||||
}
|
||||
|
||||
func (n *node) textSize() (int, int) {
|
||||
var width, height int
|
||||
|
||||
for _, s := range strings.Split(n.Text, "\n") {
|
||||
if (width < len(s)) {
|
||||
width = len(s)
|
||||
}
|
||||
height += 1
|
||||
}
|
||||
return width, height
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -8,12 +8,17 @@ import (
|
|||
|
||||
func action(a *toolkit.Action) {
|
||||
log(logInfo, "action() START", a.WidgetId, a.ActionType, a.WidgetType, a.Name)
|
||||
w := findWidget(a.WidgetId, me.rootNode)
|
||||
n := me.rootNode.findWidgetId(a.WidgetId)
|
||||
var w *cuiWidget
|
||||
if (n != nil) {
|
||||
w = n.tk
|
||||
}
|
||||
switch a.ActionType {
|
||||
case toolkit.Add:
|
||||
if (w == nil) {
|
||||
w = makeWidget(a)
|
||||
w.addWidget()
|
||||
n := addNode(a)
|
||||
// w = n.tk
|
||||
n.addWidget()
|
||||
} else {
|
||||
// this is done to protect the plugin being 'refreshed' with the
|
||||
// widget binary tree. TODO: find a way to keep them in sync
|
||||
|
@ -22,16 +27,25 @@ func action(a *toolkit.Action) {
|
|||
}
|
||||
case toolkit.Show:
|
||||
if (a.B) {
|
||||
w.showView()
|
||||
n.showView()
|
||||
} else {
|
||||
w.hideWidgets()
|
||||
n.hideWidgets()
|
||||
}
|
||||
case toolkit.Set:
|
||||
w.Set(a.A)
|
||||
if a.WidgetType == toolkit.Flag {
|
||||
log(logNow, "TODO: set flag here", a.ActionType, a.WidgetType, a.Name)
|
||||
log(logNow, "TODO: n.WidgetType =", n.WidgetType, "n.Name =", a.Name)
|
||||
} else {
|
||||
if (a.A == nil) {
|
||||
log(logError, "TODO: Set here. a == nil", a.ActionType, "WidgetType =", a.WidgetType, "Name =", a.Name)
|
||||
} else {
|
||||
n.Set(a.A)
|
||||
}
|
||||
}
|
||||
case toolkit.SetText:
|
||||
w.SetText(a.S)
|
||||
n.SetText(a.S)
|
||||
case toolkit.AddText:
|
||||
w.AddText(a.S)
|
||||
n.AddText(a.S)
|
||||
case toolkit.Move:
|
||||
log(logNow, "attempt to move() =", a.ActionType, a.WidgetType, a.Name)
|
||||
case toolkit.CloseToolkit:
|
||||
|
@ -43,42 +57,61 @@ func action(a *toolkit.Action) {
|
|||
log(logInfo, "action() END")
|
||||
}
|
||||
|
||||
func (w *cuiWidget) AddText(text string) {
|
||||
if (w == nil) {
|
||||
func (n *node) AddText(text string) {
|
||||
if (n == nil) {
|
||||
log(logNow, "widget is nil")
|
||||
return
|
||||
}
|
||||
w.vals = append(w.vals, text)
|
||||
for i, s := range w.vals {
|
||||
log(logNow, "AddText()", w.name, i, s)
|
||||
n.vals = append(n.vals, text)
|
||||
for i, s := range n.vals {
|
||||
log(logNow, "AddText()", n.Name, i, s)
|
||||
}
|
||||
w.SetText(text)
|
||||
n.SetText(text)
|
||||
}
|
||||
|
||||
func (w *cuiWidget) SetText(text string) {
|
||||
if (w == nil) {
|
||||
func (n *node) SetText(text string) {
|
||||
if (n == nil) {
|
||||
log(logNow, "widget is nil")
|
||||
return
|
||||
}
|
||||
w.text = text
|
||||
w.s = text
|
||||
w.textResize()
|
||||
w.deleteView()
|
||||
w.showView()
|
||||
n.S = text
|
||||
n.Text = text
|
||||
|
||||
n.textResize()
|
||||
n.deleteView()
|
||||
n.showView()
|
||||
}
|
||||
|
||||
func (w *cuiWidget) Set(val any) {
|
||||
func (n *node) Set(val any) {
|
||||
// w := n.tk
|
||||
log(logInfo, "Set() value =", val)
|
||||
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
w.b = val.(bool)
|
||||
w.setCheckbox(val.(bool))
|
||||
n.B = val.(bool)
|
||||
n.setCheckbox(val.(bool))
|
||||
case string:
|
||||
w.SetText(val.(string))
|
||||
n.SetText(val.(string))
|
||||
case int:
|
||||
w.i = val.(int)
|
||||
n.I = val.(int)
|
||||
default:
|
||||
log(logError, "Set() unknown type =", val, v)
|
||||
}
|
||||
}
|
||||
|
||||
// this passes the user event back from the plugin
|
||||
func (n *node) doUserEvent() {
|
||||
if (me.callback == nil) {
|
||||
log(logError, "doUserEvent() no callback channel was configured")
|
||||
return
|
||||
}
|
||||
var a toolkit.Action
|
||||
a.WidgetId = n.WidgetId
|
||||
a.Name = n.Name
|
||||
a.Text = n.Text
|
||||
a.B = n.B
|
||||
a.ActionType = toolkit.User
|
||||
log(logInfo, "doUserEvent() START: send a button click callback()", a.WidgetId, a.Name)
|
||||
me.callback <- a
|
||||
log(logInfo, "doUserEvent() END: sent a button click callback()", a.WidgetId, a.Name)
|
||||
}
|
||||
|
|
|
@ -52,14 +52,12 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
|
|||
a.WidgetType = toolkit.Stdout
|
||||
a.WidgetId = -3
|
||||
a.ParentId = 0
|
||||
me.logStdout = makeWidget(a)
|
||||
me.logStdout.gocuiSize.w0 = maxX - 32
|
||||
me.logStdout.gocuiSize.h0 = maxY/2
|
||||
me.logStdout.gocuiSize.w1 = me.logStdout.gocuiSize.w0 + outputW
|
||||
me.logStdout.gocuiSize.h1 = me.logStdout.gocuiSize.h0 + outputH
|
||||
|
||||
me.logStdout.realWidth = me.logStdout.gocuiSize.Width()
|
||||
me.logStdout.realHeight = me.logStdout.gocuiSize.Height()
|
||||
n := addNode(a)
|
||||
me.logStdout = n
|
||||
me.logStdout.tk.gocuiSize.w0 = maxX - 32
|
||||
me.logStdout.tk.gocuiSize.h0 = maxY/2
|
||||
me.logStdout.tk.gocuiSize.w1 = me.logStdout.tk.gocuiSize.w0 + outputW
|
||||
me.logStdout.tk.gocuiSize.h1 = me.logStdout.tk.gocuiSize.h0 + outputH
|
||||
}
|
||||
v, err := g.View("msg")
|
||||
if (v == nil) {
|
||||
|
@ -78,19 +76,19 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
|
|||
|
||||
if (err != nil) {
|
||||
log("create output window failed", err)
|
||||
// return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if (v == nil) {
|
||||
log("msg == nil. WTF now? err =", err)
|
||||
return nil
|
||||
} else {
|
||||
me.logStdout.v = v
|
||||
me.logStdout.tk.v = v
|
||||
}
|
||||
|
||||
me.logStdout.v.Clear()
|
||||
me.logStdout.v.SelBgColor = gocui.ColorCyan
|
||||
me.logStdout.v.SelFgColor = gocui.ColorBlack
|
||||
v.Clear()
|
||||
v.SelBgColor = gocui.ColorCyan
|
||||
v.SelFgColor = gocui.ColorBlack
|
||||
fmt.Fprintln(v, "figure out how to capture STDOUT to here\n" + stringFromMouseClick)
|
||||
g.SetViewOnBottom("msg")
|
||||
// g.SetViewOnBottom(v.Name())
|
||||
|
|
|
@ -23,11 +23,12 @@ var me config
|
|||
|
||||
type config struct {
|
||||
baseGui *gocui.Gui // the main gocui handle
|
||||
rootNode *cuiWidget // the base of the binary tree. it should have id == 0
|
||||
ctrlDown *cuiWidget // shown if you click the mouse when the ctrl key is pressed
|
||||
current *cuiWidget // this is the current tab or window to show
|
||||
logStdout *cuiWidget // where to show STDOUT
|
||||
logStdoutV *gocui.View // where to show STDOUT
|
||||
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
|
||||
// current *cuiWidget // this is the current tab or window to show
|
||||
logStdout *node // where to show STDOUT
|
||||
helpLabel *gocui.View
|
||||
|
||||
// this is the channel we send user events like
|
||||
// mouse clicks or keyboard events back to the program
|
||||
|
@ -36,53 +37,47 @@ type config struct {
|
|||
// this is the channel we get requests to make widgets
|
||||
pluginChan chan toolkit.Action
|
||||
|
||||
helpLabel *gocui.View
|
||||
|
||||
DefaultBehavior bool `default:"true"`
|
||||
|
||||
// Buttons, Group, Tabs, Windows, etc are by default assumed to be a single line
|
||||
// as a default, we make buttons 8 chars wide
|
||||
DefaultWidth int `default:"8"`
|
||||
DefaultHeight int `default:"1"`
|
||||
|
||||
// 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
|
||||
// the amount of padding when there is a frame
|
||||
FramePadW int `default:"4" dense:"0"`
|
||||
FramePadW int `default:"1" dense:"0"`
|
||||
FramePadH int `default:"1" dense:"0"`
|
||||
|
||||
PadW int `default:"1" dense:"0"`
|
||||
PadH int `default:"1" dense:"0"`
|
||||
|
||||
// additional amount of space to put between window & tab widgets
|
||||
WindowPadW int `default:"8" dense:"0"`
|
||||
TabPadW int `default:"4" dense:"0"`
|
||||
|
||||
// how far down to start Window or Tab headings
|
||||
WindowW int `default:"8" dense:"0"`
|
||||
WindowH int `default:"-1"`
|
||||
TabW int `default:"2" dense:"0"`
|
||||
TabW int `default:"5" dense:"0"`
|
||||
TabH int `default:"1" dense:"0"`
|
||||
|
||||
// additional amount of space to put between window & tab widgets
|
||||
WindowPadW int `default:"8" dense:"0"`
|
||||
TabPadW int `default:"4" dense:"0"`
|
||||
|
||||
// additional amount of space to indent on a group
|
||||
GroupPadW int `default:"6" dense:"2"`
|
||||
|
||||
// the raw beginning of each window (or tab)
|
||||
RawW int `default:"7"`
|
||||
RawH int `default:"3"`
|
||||
RawW int `default:"1"`
|
||||
RawH int `default:"5"`
|
||||
|
||||
// offset for the hidden widgets
|
||||
DevelOffsetW int `default:"20"`
|
||||
FakeW int `default:"20"`
|
||||
|
||||
padded bool // add space between things like buttons
|
||||
bookshelf bool // do you want things arranged in the box like a bookshelf or a stack?
|
||||
canvas bool // if set to true, the windows are a raw canvas
|
||||
menubar bool // for windows
|
||||
stretchy bool // expand things like buttons to the maximum size
|
||||
padded bool // add space between things like buttons
|
||||
margin bool // add space around the frames of windows
|
||||
|
||||
// writeMutex protects locks the write process
|
||||
writeMutex sync.Mutex
|
||||
|
||||
// used for listWidgets() debugging
|
||||
depth int
|
||||
}
|
||||
|
||||
// deprecate these
|
||||
|
@ -121,23 +116,21 @@ type node struct {
|
|||
AtW int
|
||||
AtH int
|
||||
|
||||
vals []string // dropdown menu items
|
||||
|
||||
// horizontal=true means layout widgets like books on a bookshelf
|
||||
// horizontal=false means layout widgets like books in a stack
|
||||
horizontal bool `default:false`
|
||||
|
||||
hasTabs bool // does the window have tabs?
|
||||
|
||||
// the internal plugin toolkit structure
|
||||
tk *cuiWidget
|
||||
}
|
||||
|
||||
// the gocui way
|
||||
// the logical size of the widget
|
||||
// this is the gocui way
|
||||
// corner starts at in the upper left corner
|
||||
type rectType struct {
|
||||
// where the widget should calculate it's existance from
|
||||
// startW int
|
||||
// startH int
|
||||
|
||||
// the is a shortcut to access
|
||||
// width int // this is always w1 - w0
|
||||
height int // this is always h1 - h0
|
||||
|
||||
// this is the gocui way
|
||||
w0, h0, w1, h1 int // left top right bottom
|
||||
}
|
||||
|
||||
|
@ -150,82 +143,27 @@ func (r *rectType) Height() int {
|
|||
}
|
||||
|
||||
type cuiWidget struct {
|
||||
id int // widget ID
|
||||
// parentId int
|
||||
widgetType toolkit.WidgetType
|
||||
|
||||
name string // a descriptive name of the widget
|
||||
text string // the current text being displayed
|
||||
// the gocui package variables
|
||||
v *gocui.View // this is nil if the widget is not displayed
|
||||
cuiName string // what gocui uses to reference the widget
|
||||
|
||||
vals []string // dropdown menu options
|
||||
// the logical size of the widget
|
||||
// For example, 40x12 would be the center of a normal terminal
|
||||
size rectType
|
||||
|
||||
// the actual gocui display view of this widget
|
||||
// sometimes this isn't visable like with a Box or Grid
|
||||
gocuiSize rectType
|
||||
|
||||
isCurrent bool // is this the currently displayed Window or Tab?
|
||||
hasTabs bool // does the window have tabs?
|
||||
isFake bool // widget types like 'box' are 'false'
|
||||
|
||||
// where the widget's real corner is
|
||||
// should we always compute this?
|
||||
startW int
|
||||
startH int
|
||||
|
||||
// where the next child should be placed
|
||||
nextW int
|
||||
nextH int
|
||||
|
||||
// the widget size to reserve or things will overlap
|
||||
realWidth int
|
||||
realHeight int
|
||||
|
||||
gocuiSize rectType // the display size of this widget
|
||||
// logicalSize rectType // the logical size. Includes all the child widgets
|
||||
|
||||
// used to track the size of grids
|
||||
widths map[int]int // how tall each row in the grid is
|
||||
heights map[int]int // how wide each column in the grid is
|
||||
|
||||
// deprecate // where in the parent grid this widget should go
|
||||
parentW int
|
||||
parentH int
|
||||
|
||||
// things from toolkit/action
|
||||
b bool
|
||||
i int
|
||||
s string
|
||||
X int
|
||||
Y int
|
||||
width int
|
||||
height int
|
||||
|
||||
// horizontal=true means layout widgets like books on a bookshelf
|
||||
// horizontal=false means layout widgets like books in a stack
|
||||
horizontal bool `default:false`
|
||||
|
||||
tainted bool
|
||||
v *gocui.View
|
||||
frame bool
|
||||
|
||||
parent *cuiWidget
|
||||
children []*cuiWidget
|
||||
}
|
||||
|
||||
func (w *cuiWidget) IsCurrent() bool {
|
||||
if (w.widgetType == toolkit.Tab) {
|
||||
return w.isCurrent
|
||||
}
|
||||
if (w.widgetType == toolkit.Window) {
|
||||
return w.isCurrent
|
||||
}
|
||||
if (w.widgetType == toolkit.Root) {
|
||||
return false
|
||||
}
|
||||
return w.parent.IsCurrent()
|
||||
}
|
||||
|
||||
func (w *cuiWidget) StartW() {
|
||||
}
|
||||
|
||||
func (w *cuiWidget) StartH() {
|
||||
}
|
||||
|
||||
// from the gocui devs:
|
||||
|
@ -238,7 +176,7 @@ func (w *cuiWidget) Write(p []byte) (n int, err error) {
|
|||
w.tainted = true
|
||||
me.writeMutex.Lock()
|
||||
defer me.writeMutex.Unlock()
|
||||
if (me.logStdout.v == nil) {
|
||||
if (me.logStdout.tk.v == nil) {
|
||||
// optionally write the output to /tmp
|
||||
s := fmt.Sprint(string(p))
|
||||
s = strings.TrimSuffix(s, "\n")
|
||||
|
@ -246,11 +184,11 @@ func (w *cuiWidget) Write(p []byte) (n int, err error) {
|
|||
v, _ := me.baseGui.View("msg")
|
||||
if (v != nil) {
|
||||
// fmt.Fprintln(outf, "found msg")
|
||||
me.logStdout.v = v
|
||||
me.logStdout.tk.v = v
|
||||
}
|
||||
} else {
|
||||
// display the output in the gocui window
|
||||
me.logStdout.v.Clear()
|
||||
me.logStdout.tk.v.Clear()
|
||||
|
||||
s := fmt.Sprint(string(p))
|
||||
s = strings.TrimSuffix(s, "\n")
|
||||
|
@ -260,7 +198,7 @@ func (w *cuiWidget) Write(p []byte) (n int, err error) {
|
|||
l := len(outputS) - outputH
|
||||
outputS = outputS[l:]
|
||||
}
|
||||
fmt.Fprintln(me.logStdout.v, strings.Join(outputS, "\n"))
|
||||
fmt.Fprintln(me.logStdout.tk.v, strings.Join(outputS, "\n"))
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
|
|
|
@ -3,136 +3,111 @@ package main
|
|||
// implements widgets 'Window' and 'Tab'
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"git.wit.org/wit/gui/toolkit"
|
||||
// "github.com/awesome-gocui/gocui"
|
||||
)
|
||||
|
||||
func (w *cuiWidget) hideWidgets() {
|
||||
w.isCurrent = false
|
||||
switch w.widgetType {
|
||||
case toolkit.Root:
|
||||
case toolkit.Flag:
|
||||
case toolkit.Window:
|
||||
// case toolkit.Tab:
|
||||
case toolkit.Box:
|
||||
case toolkit.Grid:
|
||||
default:
|
||||
w.deleteView()
|
||||
}
|
||||
for _, child := range w.children {
|
||||
child.hideWidgets()
|
||||
func (w *cuiWidget) Width() int {
|
||||
if w.frame {
|
||||
return w.gocuiSize.w1 - w.gocuiSize.w0
|
||||
}
|
||||
return w.gocuiSize.w1 - w.gocuiSize.w0 - 1
|
||||
}
|
||||
|
||||
func (w *cuiWidget) hideFake() {
|
||||
if (w.isFake) {
|
||||
w.deleteView()
|
||||
}
|
||||
for _, child := range w.children {
|
||||
child.hideFake()
|
||||
func (w *cuiWidget) Height() int {
|
||||
if w.frame {
|
||||
return w.gocuiSize.h1 - w.gocuiSize.h0
|
||||
}
|
||||
return w.gocuiSize.h1 - w.gocuiSize.h0 - 1
|
||||
}
|
||||
|
||||
func (w *cuiWidget) showFake() {
|
||||
if (w.isFake) {
|
||||
w.setFake()
|
||||
w.showWidgetPlacement(logNow, "showFake:")
|
||||
w.showView()
|
||||
}
|
||||
for _, child := range w.children {
|
||||
child.showFake()
|
||||
}
|
||||
}
|
||||
func (n *node) gocuiSetWH(sizeW, sizeH int) {
|
||||
w := len(n.Text)
|
||||
lines := strings.Split(n.Text, "\n")
|
||||
h := len(lines)
|
||||
|
||||
func (w *cuiWidget) showWidgets() {
|
||||
if (w.isFake) {
|
||||
// don't display by default
|
||||
tk := n.tk
|
||||
if tk.isFake {
|
||||
tk.gocuiSize.w0 = sizeW
|
||||
tk.gocuiSize.h0 = sizeH
|
||||
tk.gocuiSize.w1 = tk.gocuiSize.w0 + w + me.FramePadW
|
||||
tk.gocuiSize.h1 = tk.gocuiSize.h0 + h + me.FramePadH
|
||||
return
|
||||
}
|
||||
|
||||
if tk.frame {
|
||||
tk.size.w0 = sizeW
|
||||
tk.size.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.h1 = tk.gocuiSize.h0 + h + me.FramePadH
|
||||
} else {
|
||||
if w.IsCurrent() {
|
||||
w.showWidgetPlacement(logInfo, "current:")
|
||||
w.showView()
|
||||
} else {
|
||||
w.showWidgetPlacement(logInfo, "not:")
|
||||
// w.drawView()
|
||||
}
|
||||
}
|
||||
for _, child := range w.children {
|
||||
child.showWidgets()
|
||||
tk.size.w0 = sizeW - 1
|
||||
tk.size.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.h1 = tk.gocuiSize.h0 + h + 1
|
||||
}
|
||||
}
|
||||
|
||||
func (w *cuiWidget) setWindowWH() {
|
||||
w.gocuiSize.w0 = me.rootNode.nextW
|
||||
w.gocuiSize.h0 = me.WindowH
|
||||
|
||||
t := len(w.text)
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + t + me.PadW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + me.DefaultHeight + me.PadH
|
||||
|
||||
w.realWidth = w.gocuiSize.Width()
|
||||
w.realHeight = w.gocuiSize.Height()
|
||||
|
||||
// move the rootNode width over for the next window
|
||||
me.rootNode.nextW += w.realWidth + me.WindowPadW
|
||||
|
||||
w.nextW = 4
|
||||
w.nextH = 2
|
||||
|
||||
w.showWidgetPlacement(logNow, "setWindowWH:")
|
||||
}
|
||||
|
||||
func (w *cuiWidget) setTabWH() {
|
||||
// set the start and size of the tab gocui button
|
||||
|
||||
w.gocuiSize.w0 = w.parent.nextW
|
||||
w.gocuiSize.h0 = me.TabH
|
||||
|
||||
t := len(w.text)
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + t + me.PadW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + me.DefaultHeight + me.PadH
|
||||
|
||||
w.realWidth = w.gocuiSize.Width()
|
||||
w.realHeight = w.gocuiSize.Height()
|
||||
|
||||
w.realWidth += me.FramePadW
|
||||
w.realHeight += me.FramePadH
|
||||
|
||||
w.parent.nextW += w.realWidth + me.TabPadW
|
||||
|
||||
w.showWidgetPlacement(logNow, "setTabWH:")
|
||||
}
|
||||
|
||||
func (w *cuiWidget) redoTabs(draw bool) {
|
||||
if (w.widgetType == toolkit.Window) {
|
||||
var tabs bool = false
|
||||
// figure out if the window is just a bunch of tabs
|
||||
for _, child := range w.children {
|
||||
if (child.widgetType == toolkit.Tab) {
|
||||
func redoWindows(nextW int, nextH int) {
|
||||
for _, n := range me.rootNode.children {
|
||||
if n.WidgetType != toolkit.Window {
|
||||
continue
|
||||
}
|
||||
w := n.tk
|
||||
var tabs bool
|
||||
for _, child := range n.children {
|
||||
if (child.WidgetType == toolkit.Tab) {
|
||||
tabs = true
|
||||
}
|
||||
}
|
||||
if (tabs) {
|
||||
// window is tabs. Don't show it as a standard button
|
||||
w.frame = false
|
||||
w.hasTabs = true
|
||||
n.hasTabs = true
|
||||
} else {
|
||||
w.frame = true
|
||||
w.hasTabs = false
|
||||
}
|
||||
w.setWindowWH()
|
||||
w.deleteView()
|
||||
w.showView()
|
||||
}
|
||||
if (w.widgetType == toolkit.Tab) {
|
||||
w.setTabWH()
|
||||
w.deleteView()
|
||||
// show all the tabs for the current window
|
||||
if w.parent.isCurrent {
|
||||
w.showView()
|
||||
}
|
||||
w.frame = false
|
||||
n.hasTabs = false
|
||||
}
|
||||
|
||||
for _, child := range w.children {
|
||||
child.redoTabs(draw)
|
||||
w.size.w0 = nextW
|
||||
w.size.h0 = nextH
|
||||
n.gocuiSetWH(nextW, nextH)
|
||||
n.deleteView()
|
||||
n.showView()
|
||||
|
||||
sizeW := w.Width() + me.WindowPadW
|
||||
sizeH := w.Height()
|
||||
nextW += sizeW
|
||||
log(logNow, "redoWindows() start nextW,H =", nextW, nextH, "gocuiSize.W,H =", sizeW, sizeH, n.Name)
|
||||
|
||||
if n.hasTabs {
|
||||
n.redoTabs(me.TabW, me.TabH)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *node) redoTabs(nextW int, nextH int) {
|
||||
for _, n := range p.children {
|
||||
if n.WidgetType != toolkit.Tab {
|
||||
continue
|
||||
}
|
||||
w := n.tk
|
||||
w.frame = true
|
||||
|
||||
w.size.w0 = nextW
|
||||
w.size.h0 = nextH
|
||||
n.gocuiSetWH(nextW, nextH)
|
||||
n.deleteView()
|
||||
// setCurrentTab(n)
|
||||
n.showView()
|
||||
|
||||
sizeW := w.Width() + me.TabPadW
|
||||
sizeH := w.Height()
|
||||
log(logNow, "redoTabs() start nextW,H =", nextW, nextH, "gocuiSize.W,H =", sizeW, sizeH, n.Name)
|
||||
nextW += sizeW
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,11 @@ func splitLines(s string) []string {
|
|||
return lines
|
||||
}
|
||||
|
||||
func (w *cuiWidget) textResize() {
|
||||
func (n *node) textResize() {
|
||||
w := n.tk
|
||||
var width, height int
|
||||
|
||||
for i, s := range splitLines(w.text) {
|
||||
for i, s := range splitLines(n.Text) {
|
||||
log(logNow, "textResize() len =", len(s), i, s)
|
||||
if (width < len(s)) {
|
||||
width = len(s)
|
||||
|
@ -32,38 +33,52 @@ func (w *cuiWidget) textResize() {
|
|||
}
|
||||
w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW
|
||||
w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH
|
||||
w.showWidgetPlacement(logNow, "textResize()")
|
||||
n.showWidgetPlacement(logNow, "textResize()")
|
||||
}
|
||||
|
||||
// display's the text of the widget in gocui
|
||||
func (w *cuiWidget) showView() {
|
||||
func (n *node) showView() {
|
||||
var err error
|
||||
w := n.tk
|
||||
|
||||
if (w.cuiName == "") {
|
||||
log(logError, "drawView() w.cuiName was not set for widget", w)
|
||||
w.cuiName = strconv.Itoa(w.id)
|
||||
log(logError, "showView() w.cuiName was not set for widget", w)
|
||||
w.cuiName = strconv.Itoa(n.WidgetId)
|
||||
}
|
||||
|
||||
if (w.v != nil) {
|
||||
log(logInfo, "drawView() w.v already defined for widget", w)
|
||||
v, _ := me.baseGui.View(w.cuiName)
|
||||
if (v == nil) {
|
||||
log(logError, "drawView() ERROR view does not really exist", w)
|
||||
w.v = nil
|
||||
} else {
|
||||
if (w.v == nil) {
|
||||
n.updateView()
|
||||
}
|
||||
x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName)
|
||||
log(logInfo, "showView() w.v already defined for widget", n.Name, err)
|
||||
if (x0 != w.gocuiSize.w0) || (y0 != w.gocuiSize.h0) {
|
||||
log(logError, "showView() w.v.w0 != x0", n.Name, w.gocuiSize.w0, x0)
|
||||
log(logError, "showView() w.v.h0 != y0", n.Name, w.gocuiSize.h0, y0)
|
||||
n.updateView()
|
||||
return
|
||||
}
|
||||
if (x1 != w.gocuiSize.w1) || (y1 != w.gocuiSize.h1) {
|
||||
log(logError, "showView() w.v.w1 != x1", n.Name, w.gocuiSize.w1, x1)
|
||||
log(logError, "showView() w.v.h1 != y1", n.Name, w.gocuiSize.h1, y1)
|
||||
n.updateView()
|
||||
return
|
||||
}
|
||||
|
||||
if (w.v.Visible == false) {
|
||||
log(logInfo, "showView() w.v.Visible set to true ", n.Name)
|
||||
w.v.Visible = true
|
||||
}
|
||||
}
|
||||
|
||||
func (n *node) updateView() {
|
||||
var err error
|
||||
w := n.tk
|
||||
if (me.baseGui == nil) {
|
||||
log(logError, "drawView() ERROR: me.baseGui == nil", w)
|
||||
return
|
||||
}
|
||||
v, _ := me.baseGui.View(w.cuiName)
|
||||
if (v != nil) {
|
||||
log(logError, "drawView() already defined for name", w.cuiName)
|
||||
w.v = v
|
||||
log(logError, "showView() ERROR: me.baseGui == nil", w)
|
||||
return
|
||||
}
|
||||
me.baseGui.DeleteView(w.cuiName)
|
||||
w.v = nil
|
||||
|
||||
a := w.gocuiSize.w0
|
||||
b := w.gocuiSize.h0
|
||||
|
@ -72,12 +87,12 @@ func (w *cuiWidget) showView() {
|
|||
|
||||
w.v, err = me.baseGui.SetView(w.cuiName, a, b, c, d, 0)
|
||||
if err == nil {
|
||||
w.showWidgetPlacement(logError, "drawView()")
|
||||
n.showWidgetPlacement(logError, "drawView()")
|
||||
log(logError, "drawView() internal plugin error err = nil")
|
||||
return
|
||||
}
|
||||
if !errors.Is(err, gocui.ErrUnknownView) {
|
||||
w.showWidgetPlacement(logError, "drawView()")
|
||||
n.showWidgetPlacement(logError, "drawView()")
|
||||
log(logError, "drawView() internal plugin error error.IS()", err)
|
||||
return
|
||||
}
|
||||
|
@ -85,13 +100,68 @@ func (w *cuiWidget) showView() {
|
|||
me.baseGui.SetKeybinding(w.v.Name(), gocui.MouseLeft, gocui.ModNone, click)
|
||||
|
||||
w.v.Wrap = true
|
||||
if (w.widgetType == toolkit.Window) {
|
||||
w.v.Frame = w.frame
|
||||
w.v.Clear()
|
||||
fmt.Fprint(w.v, w.text)
|
||||
} else {
|
||||
fmt.Fprintln(w.v, w.text)
|
||||
}
|
||||
fmt.Fprint(w.v, n.Text)
|
||||
n.showWidgetPlacement(logNow, "Window: " + n.Text)
|
||||
|
||||
w.setDefaultWidgetColor()
|
||||
n.setDefaultHighlight()
|
||||
n.setDefaultWidgetColor()
|
||||
}
|
||||
|
||||
func (n *node) hideWidgets() {
|
||||
w := n.tk
|
||||
w.isCurrent = false
|
||||
switch n.WidgetType {
|
||||
case toolkit.Root:
|
||||
case toolkit.Flag:
|
||||
case toolkit.Window:
|
||||
case toolkit.Box:
|
||||
case toolkit.Grid:
|
||||
default:
|
||||
n.deleteView()
|
||||
}
|
||||
for _, child := range n.children {
|
||||
child.hideWidgets()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *node) hideFake() {
|
||||
w := n.tk
|
||||
if (w.isFake) {
|
||||
n.deleteView()
|
||||
}
|
||||
for _, child := range n.children {
|
||||
child.hideFake()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *node) showFake() {
|
||||
w := n.tk
|
||||
if (w.isFake) {
|
||||
n.setFake()
|
||||
n.showWidgetPlacement(logNow, "showFake:")
|
||||
n.showView()
|
||||
}
|
||||
for _, child := range n.children {
|
||||
child.showFake()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *node) showWidgets() {
|
||||
w := n.tk
|
||||
if (w.isFake) {
|
||||
// don't display by default
|
||||
} else {
|
||||
if n.IsCurrent() {
|
||||
n.showWidgetPlacement(logInfo, "current:")
|
||||
n.showView()
|
||||
} else {
|
||||
n.showWidgetPlacement(logInfo, "not:")
|
||||
// w.drawView()
|
||||
}
|
||||
}
|
||||
for _, child := range n.children {
|
||||
child.showWidgets()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue