summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--common.go11
-rw-r--r--examples/cloudflare/api.go62
-rwxr-xr-x[-rw-r--r--]examples/cloudflare/curl.sh31
-rw-r--r--examples/cloudflare/gui.go91
-rw-r--r--examples/cloudflare/main.go32
-rw-r--r--examples/cloudflare/structs.go17
-rw-r--r--main.go30
-rw-r--r--protobuf/Makefile34
-rw-r--r--protobuf/widget.proto117
-rw-r--r--toolkit/andlabs/action.go4
-rw-r--r--toolkit/andlabs/add.go9
-rw-r--r--toolkit/andlabs/debug.go12
-rw-r--r--toolkit/andlabs/main.go11
-rw-r--r--toolkit/andlabs/updateui.go3
-rw-r--r--toolkit/gocui/debug.go3
-rw-r--r--toolkit/gocui/main.go2
-rw-r--r--toolkit/gocui/plugin.go38
-rw-r--r--toolkit/gocui/view.go53
19 files changed, 407 insertions, 156 deletions
diff --git a/.gitignore b/.gitignore
index 6dafe23..239f615 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,9 @@ examples/textbox/textbox
examples/cloudflare/cloudflare
examples/*/helloconsole
+# protobuf compiled files
+protobuf/*.pb.go
+
# temporary files when building debian packages
/*.deb
/files
diff --git a/common.go b/common.go
index 6f42ce4..462f37d 100644
--- a/common.go
+++ b/common.go
@@ -170,6 +170,13 @@ func (n *Node) Unpad() *Node {
return n
}
+func (n *Node) Expand() *Node {
+ a := newAction(n, toolkit.Pad)
+ a.Expand = true
+ sendAction(a)
+ return n
+}
+
// is this better?
// yes, this is better. it allows Internationalization very easily
// me.window = myGui.New2().Window("DNS and IPv6 Control Panel").Standard()
@@ -182,8 +189,9 @@ func (n *Node) Window(title string) *Node {
// This should not really do anything. as per the docs, the "Standard()" way
// should be the default way
+/*
func (n *Node) Standard() *Node {
- log(debugError, "Standard() not implemented yet")
+ log(debugInfo, "Standard() not implemented yet")
return n
}
@@ -191,3 +199,4 @@ func (n *Node) SetMargin() *Node {
log(debugError, "DoMargin() not implemented yet")
return n
}
+*/
diff --git a/examples/cloudflare/api.go b/examples/cloudflare/api.go
index 8cf550e..9522b07 100644
--- a/examples/cloudflare/api.go
+++ b/examples/cloudflare/api.go
@@ -4,10 +4,11 @@ package main
import (
"os"
"log"
+ "fmt"
"encoding/json"
"io/ioutil"
"net/http"
- "strconv"
+// "strconv"
"bytes"
"github.com/davecgh/go-spew/spew"
@@ -19,7 +20,17 @@ func doChange(dnsRow *RRT) {
log.Println("Content", dnsRow.Content, "vs", dnsRow.valueNode.S)
if (dnsRow.Content != dnsRow.valueNode.S) {
log.Println("UPDATE VALUE", dnsRow.nameNode.Name, dnsRow.typeNode.Name, "to", dnsRow.valueNode.S)
- httpPut(dnsRow)
+ stuff, result := httpPut(dnsRow)
+ if (dnsRow.curlNode != nil) {
+ pretty, _ := formatJSON(stuff)
+ log.Println("http PUT curl =", pretty)
+ dnsRow.curlNode.SetText(pretty)
+ }
+ if (dnsRow.resultNode != nil) {
+ pretty, _ := formatJSON(result)
+ log.Println("http PUT result =", pretty)
+ dnsRow.resultNode.SetText(pretty)
+ }
}
dnsRow.saveNode.Disable()
}
@@ -73,24 +84,26 @@ func getZonefile(c *configT) *DNSRecords {
go.wit.com. 3600 IN A 1.1.1.9
test.wit.com. 3600 IN NS ns1.wit.com.
*/
-func httpPut(dnsRow *RRT) {
- var url string = cloudflareURL + os.Getenv("CLOUDFLARE_ZONEID") + "/dns_records/" + dnsRow.ID
- var authKey string = os.Getenv("CLOUDFLARE_AUTHKEY")
- var email string = os.Getenv("CLOUDFLARE_EMAIL")
+func httpPut(dnsRow *RRT) (string, string) {
+ var url string = cloudflareURL + os.Getenv("CF_API_ZONEID") + "/dns_records/" + dnsRow.ID
+ var authKey string = os.Getenv("CF_API_KEY")
+ var email string = os.Getenv("CF_API_EMAIL")
- // make a json record to send on port 90 to cloudflare
+ // make a json record to send on port 80 to cloudflare
var tmp string
tmp = `{"content": "` + dnsRow.valueNode.S + `", `
tmp += `"name": "` + dnsRow.Name + `", `
tmp += `"type": "` + dnsRow.Type + `", `
- tmp+= `"ttl": "` + strconv.Itoa(dnsRow.TTL) + `", `
+ tmp+= `"ttl": "` + "1" + `", `
tmp += `"comment": "WIT DNS Control Panel"`
tmp += `}`
data := []byte(tmp)
log.Println("http PUT url =", url)
- log.Println("http PUT data =", data)
- spew.Dump(data)
+ // log.Println("http PUT data =", data)
+ // spew.Dump(data)
+ pretty, _ := formatJSON(string(data))
+ log.Println("http PUT data =", pretty)
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(data))
@@ -103,19 +116,19 @@ func httpPut(dnsRow *RRT) {
resp, err := client.Do(req)
if err != nil {
log.Println(err)
- return
+ return tmp, fmt.Sprintf("blah err =", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
- return
+ return tmp, fmt.Sprintf("blah err =", err)
}
- log.Println("http PUT body =", body)
- spew.Dump(body)
+ // log.Println("http PUT body =", body)
+ // spew.Dump(body)
- return
+ return tmp, string(body)
}
// https://api.cloudflare.com/client/v4/zones
@@ -185,3 +198,22 @@ func getZones(auth, email string) *DNSRecords {
return &records
}
+
+// formatJSON takes an unformatted JSON string and returns a formatted version.
+func formatJSON(unformattedJSON string) (string, error) {
+ var jsonData interface{}
+
+ // Decode the JSON string into an interface
+ err := json.Unmarshal([]byte(unformattedJSON), &jsonData)
+ if err != nil {
+ return "", err
+ }
+
+ // Re-encode the JSON with indentation for formatting
+ formattedJSON, err := json.MarshalIndent(jsonData, "", " ")
+ if err != nil {
+ return "", err
+ }
+
+ return string(formattedJSON), nil
+}
diff --git a/examples/cloudflare/curl.sh b/examples/cloudflare/curl.sh
index ec8c014..1edd53e 100644..100755
--- a/examples/cloudflare/curl.sh
+++ b/examples/cloudflare/curl.sh
@@ -1,3 +1,28 @@
-curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
- -H "Authorization: Bearer AAAPutYourTokenInHereSoYouCanTestItL5Cl3" \
- -H "Content-Type:application/json"
+#curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
+# -H "Authorization: Bearer AAAPutYourTokenInHereSoYouCanTestItL5Cl3" \
+# -H "Content-Type:application/json"
+
+# https://api.cloudflare.com/client/v4/zones/27b900d9e05cfb9f3a64fecff2497f90/dns_records
+#
+# {
+# "comment": "WIT DNS Control Panel",
+# "content": "2001:4860:4860::8888",
+# "name": "www",
+# "proxied": false,
+# "ttl": 3600,
+# "type": "AAAA"
+#}
+
+curl --request POST \
+ --url https://api.cloudflare.com/client/v4/zones/27b900d9e05cfb9f3a64fecff2497f90/dns_records \
+ --header 'Content-Type: application/json' \
+ --header 'X-Auth-Key: e08806ad85ef97aebaacd2d7fa462a7d417a7x' \
+ --header 'X-Auth-Email: [email protected]' \
+ --data '{
+ "comment": "WIT DNS Control Panel",
+ "content": "2001:4860:4860::5555",
+ "name": "www5",
+ "proxied": false,
+ "ttl": 3600,
+ "type": "AAAA"
+}'
diff --git a/examples/cloudflare/gui.go b/examples/cloudflare/gui.go
index 60fd5fe..ed08482 100644
--- a/examples/cloudflare/gui.go
+++ b/examples/cloudflare/gui.go
@@ -4,6 +4,8 @@ package main
import (
"log"
"strconv"
+
+ "git.wit.org/jcarr/control-panel-dns/cloudflare"
)
func loadDNS(c *configT) {
@@ -11,7 +13,8 @@ func loadDNS(c *configT) {
log.Println("adding DNS record", hostname)
newt := mainWindow.NewTab(hostname)
- newg := newt.NewGroup("more")
+ vb := newt.NewBox("vBox", false)
+ newg := vb.NewGroup("more zoneID = " + c.zoneID)
// make a grid 6 things wide
grid := newg.NewGrid("gridnuts", 6, gridH)
@@ -19,41 +22,22 @@ func loadDNS(c *configT) {
// grid.NewButton("Type", func () {
// log.Println("sort by Type")
// })
- typedrop := grid.NewDropdown("type")
- typedrop.AddText("A")
- typedrop.AddText("AAAA")
- typedrop.AddText("CNAME")
- typedrop.Custom = func () {
- log.Println("custom dropdown() a =", typedrop.Name, typedrop.S)
- }
- nb := grid.NewButton("Name", func () {
- log.Println("sort by Name")
- })
- nb.Disable()
+ grid.NewLabel("RR type")
+ grid.NewLabel("hostname")
- grid.NewButton("Protection", func () {
- log.Println("sort proxied")
- })
- grid.NewButton("TTL", func () {
- log.Println("sort by TTL")
- })
- nb = grid.NewButton("Value", func () {
- log.Println("sort by Value")
- })
- nb.Disable()
- nb = grid.NewButton("Save", func () {
- log.Println("click below to save")
- })
- nb.Disable()
+ grid.NewLabel("Proxy")
+ grid.NewLabel("TTL")
+ grid.NewLabel("Value")
+ grid.NewLabel("Save")
- masterSave = newt.NewButton("Master Save", func () {
+ masterSave = vb.NewButton("Master Save", func () {
log.Println("save stuff to cloudflare")
})
masterSave.Disable()
records := getZonefile(c)
for _, record := range records.Result {
- var rr RRT // dns zonefile resource record
+ var rr cloudflare.RRT // dns zonefile resource record
// copy all the JSON values into the row record.
rr.ID = record.ID
@@ -62,59 +46,34 @@ func loadDNS(c *configT) {
rr.Content = record.Content
rr.Proxied = record.Proxied
rr.Proxiable = record.Proxiable
- rr.TTL = record.TTL
+ // rr.Ttl = record.TTL
- rr.typeNode = grid.NewLabel(record.Type)
- rr.nameNode = grid.NewEntryLine(record.Name)
- rr.nameNode.SetText(record.Name)
- rr.nameNode.Disable()
+ grid.NewLabel(record.Type)
+ grid.NewLabel(record.Name)
- // set proxy or unproxied
- rr.proxyNode = grid.NewDropdown("proxy")
+ proxy := grid.NewLabel("proxy")
if (record.Proxied) {
- rr.proxyNode.AddText("Proxied")
- rr.proxyNode.AddText("DNS")
+ proxy.SetText("On")
} else {
- rr.proxyNode.AddText("DNS")
- rr.proxyNode.AddText("Proxied")
- }
- rr.proxyNode.Custom = func () {
- log.Println("proxy dropdown() a =", rr.proxyNode.Name, rr.proxyNode.S, rr.ID)
- rr.saveNode.Enable()
- masterSave.Enable()
+ proxy.SetText("Off")
}
- var ttl, short string
+ var ttl string
if (record.TTL == 1) {
ttl = "Auto"
} else {
ttl = strconv.Itoa(record.TTL)
}
- rr.ttlNode = grid.NewLabel(ttl)
- // short = fmt.Sprintf("%80s", record.Content)
- short = record.Content
- if len(short) > 40 {
- short = short[:40] // Slice the first 20 characters
- }
-
- rr.valueNode = grid.NewEntryLine(short)
- rr.valueNode.SetText(record.Content)
-
- rr.valueNode.Custom = func () {
- log.Println("value changed =", rr.valueNode.Name, rr.proxyNode.S, rr.ID)
- rr.saveNode.Enable()
- masterSave.Enable()
- }
+ grid.NewLabel(ttl)
- // 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)
+ val := grid.NewLabel("Value")
+ val.SetText(record.Content)
- rr.saveNode = grid.NewButton("Save", nil)
- rr.saveNode.Disable()
- rr.saveNode.Custom = func () {
+ load := grid.NewButton("Load", nil)
+ load.Custom = func () {
name := "save stuff to cloudflare for " + rr.ID
log.Println(name)
- doChange(&rr)
+ // doChange(&rr)
}
}
diff --git a/examples/cloudflare/main.go b/examples/cloudflare/main.go
index 4e72668..aeb8570 100644
--- a/examples/cloudflare/main.go
+++ b/examples/cloudflare/main.go
@@ -7,7 +7,9 @@ import (
"log"
"bufio"
"strings"
+
"git.wit.org/wit/gui"
+ "git.wit.org/jcarr/control-panel-dns/cloudflare"
)
var title string = "Cloudflare DNS Control Panel"
@@ -44,7 +46,8 @@ func makeCloudflareWindow() {
makeConfigTab(mainWindow)
t = mainWindow.NewTab("Zones")
- g1 := t.NewGroup("zones")
+ vb := t.NewBox("vBox", false)
+ g1 := vb.NewGroup("zones")
// make dropdown list of zones
zonedrop = g1.NewDropdown("zone")
@@ -52,6 +55,7 @@ func makeCloudflareWindow() {
for d, _ := range config {
zonedrop.AddText(d)
}
+ zonedrop.AddText("stablesid.org")
zonedrop.Custom = func () {
domain := zonedrop.S
@@ -82,18 +86,18 @@ func makeConfigTab(window *gui.Node) {
vb := t.NewBox("vBox", false)
g1 := vb.NewGroup("Cloudflare API Config")
- g1.NewLabel("If you have an API key with access to list all of /n your zone files, enter it here. \n \n Alternatively, you can set the enviroment variables: \n env $CLOUDFLARE_AUTHKEY \n env $CLOUDFLARE_EMAIL \n env $CLOUDFLARE_URL \n")
+ g1.NewLabel("If you have an API key with access to list all of /n your zone files, enter it here. \n \n Alternatively, you can set the enviroment variables: \n env $CF_API_KEY \n env $CF_API_EMAIL\n")
// make grid to display credentials
grid := g1.NewGrid("credsGrid", 2, 4) // width = 2
grid.NewLabel("Auth Key")
- aw := grid.NewEntryLine("CLOUDFLARE_AUTHKEY")
- aw.SetText(os.Getenv("CLOUDFLARE_AUTHKEY"))
+ aw := grid.NewEntryLine("CF_API_KEY")
+ aw.SetText(os.Getenv("CF_API_KEY"))
grid.NewLabel("Email")
- ew := grid.NewEntryLine("CLOUDFLARE_EMAIL")
- ew.SetText(os.Getenv("CLOUDFLARE_EMAIL"))
+ ew := grid.NewEntryLine("CF_API_EMAIL")
+ ew.SetText(os.Getenv("CF_API_EMAIL"))
var url string = "https://api.cloudflare.com/client/v4/zones/"
grid.NewLabel("Cloudflare API")
@@ -106,6 +110,10 @@ func makeConfigTab(window *gui.Node) {
getZones(aw.S, ew.S)
})
+ vb.NewButton("cloudflare wit.com", func () {
+ cloudflare.CreateRR(myGui, "wit.com", "3777302ac4a78cd7fa4f6d3f72086d06")
+ })
+
t.Pad()
t.Margin()
vb.Pad()
@@ -144,16 +152,16 @@ func showCloudflareCredentials(box *gui.Node) {
grid := box.NewGrid("credsGrid", 2, 4) // width = 2
grid.NewLabel("Domain")
- domainWidget = grid.NewEntryLine("CLOUDFLARE_DOMAIN")
+ domainWidget = grid.NewEntryLine("CF_API_DOMAIN")
grid.NewLabel("Zone ID")
- zoneWidget = grid.NewEntryLine("CLOUDFLARE_ZONEID")
+ zoneWidget = grid.NewEntryLine("CF_API_ZONEID")
grid.NewLabel("Auth Key")
- authWidget = grid.NewEntryLine("CLOUDFLARE_AUTHKEY")
+ authWidget = grid.NewEntryLine("CF_API_KEY")
grid.NewLabel("Email")
- emailWidget = grid.NewEntryLine("CLOUDFLARE_EMAIL")
+ emailWidget = grid.NewEntryLine("CF_API_EMAIL")
var url string = "https://api.cloudflare.com/client/v4/zones/"
grid.NewLabel("Cloudflare API")
@@ -161,10 +169,6 @@ func showCloudflareCredentials(box *gui.Node) {
grid.Pad()
- saveButton = box.NewButton("Save to config", func () {
- })
- saveButton.Disable()
-
loadButton = box.NewButton("Load Cloudflare DNS zonefile", func () {
var domain configT
domain.domain = domainWidget.S
diff --git a/examples/cloudflare/structs.go b/examples/cloudflare/structs.go
index af4d7f3..50647d7 100644
--- a/examples/cloudflare/structs.go
+++ b/examples/cloudflare/structs.go
@@ -34,20 +34,23 @@ var zonedrop *gui.Node
// Resource Record (used in a DNS zonefile)
type RRT struct {
- typeNode *gui.Node
- nameNode *gui.Node
- proxyNode *gui.Node
- ttlNode *gui.Node
- valueNode *gui.Node
- saveNode *gui.Node
+ typeNode *gui.Node // CNAME, A, AAAA, ...
+ nameNode *gui.Node // www, mail, ...
+ proxyNode *gui.Node // If cloudflare is a port 80 & 443 proxy
+ ttlNode *gui.Node // just set to 1 which means automatic to cloudflare
+ valueNode *gui.Node // 4.2.2.2, "dkim stuff", etc
+ curlNode *gui.Node // shows you what you could run via curl
+ resultNode *gui.Node // what the cloudflare API returned
+ saveNode *gui.Node // button to send it to cloudflare
ID string
Type string
Name string
Content string
+ ProxyS string
Proxied bool
Proxiable bool
- TTL int
+ Ttl string
}
/*
diff --git a/main.go b/main.go
index 03479bba..f529539 100644
--- a/main.go
+++ b/main.go
@@ -37,17 +37,17 @@ func init() {
func watchCallback() {
log(logInfo, "watchCallback() START")
for {
- log(logNow, "watchCallback() restarted select for toolkit user events")
+ log(logInfo, "watchCallback() restarted select for toolkit user events")
select {
case a := <-me.guiChan:
if (a.ActionType == toolkit.UserQuit) {
- log(logNow, "doUserEvent() User sent Quit()")
+ log(logInfo, "doUserEvent() User sent Quit()")
me.rootNode.doCustom()
exit("wit/gui toolkit.UserQuit")
break
}
if (a.ActionType == toolkit.EnableDebug) {
- log(logNow, "doUserEvent() Enable Debugging Window")
+ log(logInfo, "doUserEvent() Enable Debugging Window")
DebugWindow()
break
}
@@ -56,7 +56,7 @@ func watchCallback() {
if (n == nil) {
log(logError, "watchCallback() UNKNOWN widget id =", a.WidgetId, a.Name)
} else {
- log(logNow, "watchCallback() FOUND widget id =", n.id, n.Name)
+ log(logInfo, "watchCallback() FOUND widget id =", n.id, n.Name)
n.doUserEvent(a)
}
// this maybe a good idea?
@@ -67,7 +67,7 @@ func watchCallback() {
}
func (n *Node) doCustom() {
- log(logNow, "doUserEvent() widget =", n.id, n.Name, n.WidgetType, n.B)
+ log(logInfo, "doUserEvent() widget =", n.id, n.Name, n.WidgetType, n.B)
if (n.Custom == nil) {
log(debugError, "Custom() = nil. SKIPPING")
return
@@ -76,40 +76,40 @@ func (n *Node) doCustom() {
}
func (n *Node) doUserEvent(a toolkit.Action) {
- log(logNow, "doUserEvent() node =", n.id, n.Name)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name)
switch n.WidgetType {
case toolkit.Checkbox:
n.B = a.B
- log(logNow, "doUserEvent() node =", n.id, n.Name, "set to:", n.B)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.B)
n.doCustom()
case toolkit.Button:
- log(logNow, "doUserEvent() node =", n.id, n.Name, "button clicked")
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "button clicked")
n.doCustom()
case toolkit.Combobox:
n.S = a.S
- log(logNow, "doUserEvent() node =", n.id, n.Name, "set to:", n.S)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.S)
n.doCustom()
case toolkit.Dropdown:
n.S = a.S
- log(logNow, "doUserEvent() node =", n.id, n.Name, "set to:", n.S)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.S)
n.doCustom()
case toolkit.Textbox:
n.S = a.S
- log(logNow, "doUserEvent() node =", n.id, n.Name, "set to:", n.S)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.S)
n.doCustom()
case toolkit.Spinner:
n.I = a.I
- log(logNow, "doUserEvent() node =", n.id, n.Name, "set to:", n.I)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.I)
n.doCustom()
case toolkit.Slider:
n.I = a.I
- log(logNow, "doUserEvent() node =", n.id, n.Name, "set to:", n.I)
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "set to:", n.I)
n.doCustom()
case toolkit.Window:
- log(logNow, "doUserEvent() node =", n.id, n.Name, "window closed")
+ log(logInfo, "doUserEvent() node =", n.id, n.Name, "window closed")
n.doCustom()
default:
- log(logNow, "doUserEvent() type =", n.WidgetType)
+ log(logInfo, "doUserEvent() type =", n.WidgetType)
}
}
diff --git a/protobuf/Makefile b/protobuf/Makefile
new file mode 100644
index 0000000..7dd70be
--- /dev/null
+++ b/protobuf/Makefile
@@ -0,0 +1,34 @@
+all:
+ # You must use the current protoc-gen-go
+ # protoc --version 3.6++ does not mean that protoc will generate version3 .go files
+ #
+ # apt remove golang-goprotobuf-dev
+ # apt install protobuf-compiler
+ #
+ # Then:
+ # go get -u github.com/golang/protobuf/protoc-gen-go
+ # cd ~/go/src/github.com/golang/protobuf/protoc-gen-go
+ # go install
+ #
+ # Then:
+ protoc --version
+ make widget.pb.go
+
+clean:
+ rm -f *.pb.go
+
+widget.pb.go: widget.proto
+ protoc --go_out=. widget.proto
+
+compile:
+ protoc --go_out=. *.proto
+
+deps:
+ apt install golang-goprotobuf-dev
+ apt install protobuf-compiler
+
+push:
+ git pull
+ git add --all
+ git commit -a -s
+ git push
diff --git a/protobuf/widget.proto b/protobuf/widget.proto
new file mode 100644
index 0000000..e20354b
--- /dev/null
+++ b/protobuf/widget.proto
@@ -0,0 +1,117 @@
+syntax = "proto3";
+package guiProtobuf;
+
+message Action {
+ WidgetType widgetType = 1;
+ ActionType actionType = 2;
+ int64 widgetId = 3;
+ int64 parentId = 4;
+ string text = 5; // what is visable to the user
+ string name = 6; // a name useful for programming
+
+ // This is how the values are passed back and forth
+ // values from things like checkboxes & dropdown's
+ bool b = 7;
+ int64 i = 8;
+ string s = 9;
+
+ // This is used for things like a slider(0,100)
+ int64 x = 10;
+ int64 y = 11;
+
+ // This is for the grid size & widget position
+ int64 w = 12;
+ int64 h = 13;
+ int64 atw = 14;
+ int64 ath = 15;
+
+ bool margin = 16; // Put space around elements to improve look & feel
+ bool expand = 17; // Make widgets fill up the space available
+
+ repeated Response results = 18;
+ repeated Network networks = 19;
+ repeated VM vms = 20;
+
+ enum WidgetType {
+ Unknown = 0;
+ Root = 1; // the master 'root' node of the binary tree
+ Flag = 2; // used to send configuration values to plugins
+ Window = 3; // in certain gui's (ncurses), these are tabs
+ Tab = 4; // internally, this is a window
+ Frame = 5; // deprecate?
+ Grid = 6; // like drawers in a chest
+ Group = 7; // like the 'Appetizers' section on a menu
+ Box = 8; // a vertical or horizontal stack of widgets
+ Button = 9;
+ Checkbox = 10; // select 'on' or 'off'
+ Dropdown = 11;
+ Combobox = 12; // dropdown with edit=true
+ Label = 13;
+ Textbox = 14; // is this a Label with edit=true
+ Slider = 15; // like a progress bar
+ Spinner = 16; // like setting the oven temperature
+ Separator = 17; // TODO
+ Image = 18; // TODO
+ Area = 19; // TODO
+ Form = 20; // TODO
+ Font = 21; // TODO
+ Color = 22; // TODO
+ Dialog = 23; // TODO
+ Stdout = 24; // can be used to capture and display log output
+ }
+
+ enum ActionType {
+ Health = 0;
+ Add = 1;
+ Delete = 2;
+ Get = 3;
+ Set = 4;
+ GetText = 5;
+ SetText = 6;
+ AddText = 7;
+ Show = 8;
+ Hide = 9;
+ Enable = 10;
+ Disable = 11;
+ Margin = 12;
+ Unmargin = 13;
+ Pad = 14;
+ Unpad = 15;
+ Append = 16;
+ Move = 17;
+ Dump = 18;
+ User = 19; // the user did something (mouse, keyboard, etc)
+ InitToolkit = 20; // initializes the toolkit
+ CloseToolkit = 21; // closes the toolkit
+ UserQuit = 22; // the user closed the GUI
+ EnableDebug = 23; // open the debugging window
+ }
+
+ message Response {
+ // ActionType type = 1;
+ int64 id = 2;
+ string name = 3;
+ string error = 4;
+ repeated string snippets = 5;
+ }
+
+ message Network {
+ int64 id = 1;
+ string name = 2;
+ int64 total_cpu = 3;
+ int64 total_mem = 4;
+ string login_url = 5;
+ }
+
+ message VM {
+ int64 id = 1;
+ string name = 2;
+ string hostname = 3;
+ int64 cpus = 4;
+ int64 memory = 5;
+ int64 disk = 6;
+ string IPv6 = 7;
+ string role = 8;
+ string baseImage = 9;
+ }
+}
diff --git a/toolkit/andlabs/action.go b/toolkit/andlabs/action.go
index 29b797a..5352fc8 100644
--- a/toolkit/andlabs/action.go
+++ b/toolkit/andlabs/action.go
@@ -38,11 +38,11 @@ func (n *node) enable(b bool) {
}
func (n *node) pad(at toolkit.ActionType) {
- log(debugError, "pad()")
+ log(logInfo, "pad() on WidgetId =", n.WidgetId)
t := n.tk
if (t == nil) {
- log(debugError, "pad() toolkit struct == nil. for", n.WidgetId)
+ log(logError, "pad() toolkit struct == nil. for", n.WidgetId)
return
}
diff --git a/toolkit/andlabs/add.go b/toolkit/andlabs/add.go
index 9963b79..82d962f 100644
--- a/toolkit/andlabs/add.go
+++ b/toolkit/andlabs/add.go
@@ -127,15 +127,16 @@ func (p *node) place(n *node) bool {
return true
case toolkit.Tab:
if (p.tk.uiTab == nil) {
- log(logError, "p.tk.uiTab == nil", p.tk)
+ log(logError, "p.tk.uiTab == nil for n.WidgetId =", n.WidgetId, "p.tk =", p.tk)
panic("p.tk.uiTab == nil")
}
if (n.tk.uiControl == nil) {
- log(logError, "n.tk.uiControl == nil", n.tk)
+ log(logError, "n.tk.uiControl == nil for n.WidgetId =", n.WidgetId, "n.tk =", n.tk)
panic("n.tk.uiControl == nil")
}
- log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() node=", n.WidgetId, n.Name, n.Text, n.WidgetType)
- log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.Name, p.Text, p.WidgetType)
+ log(logError, "CHECK LOGIC ON THIS. APPENDING directly into a window without a tab")
+ // log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() node=", n.WidgetId, n.Name, n.Text, n.WidgetType)
+ // log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.Name, p.Text, p.WidgetType)
// panic("n.tk.uiControl == nil")
p.tk.uiTab.Append(n.Text, n.tk.uiControl)
p.tk.boxC += 1
diff --git a/toolkit/andlabs/debug.go b/toolkit/andlabs/debug.go
index 33f8c44..d9f8e58 100644
--- a/toolkit/andlabs/debug.go
+++ b/toolkit/andlabs/debug.go
@@ -14,12 +14,12 @@ var stretchy bool // expand things like buttons to the maximum size
var padded bool // add space between things like buttons
var margin bool // add space around the frames of windows
-var debugToolkit bool = true
-var debugChange bool = true
-var debugPlugin bool = true
-var debugAction bool = true
-var debugFlags bool = true
-var debugGrid bool = true
+var debugToolkit bool = false
+var debugChange bool = false
+var debugPlugin bool = false
+var debugAction bool = false
+var debugFlags bool = false
+var debugGrid bool = false
var debugNow bool = true
var debugError bool = true
diff --git a/toolkit/andlabs/main.go b/toolkit/andlabs/main.go
index e2d34a3..3430769 100644
--- a/toolkit/andlabs/main.go
+++ b/toolkit/andlabs/main.go
@@ -40,13 +40,18 @@ func init() {
// log(debugToolkit, "init() Setting defaultBehavior = true")
setDefaultBehavior(true)
- // andlabs = make(map[int]*andlabsT)
- pluginChan = make(chan toolkit.Action, 1)
- log(logNow, "Init() start channel reciever")
+ // TODO: this is messed up. run ui.Main() from the first add? Initialize it with an empty thing first?
+ // fake out the OS toolkit by making a fake window. This is probably needed for macos & windows
+ // actually, this probably breaks the macos build
go ui.Main(func() {
demoUI()
})
+
+ // andlabs = make(map[int]*andlabsT)
+ pluginChan = make(chan toolkit.Action, 1)
+
+ log(logNow, "Init() start channel reciever")
go catchActionChannel()
log(logNow, "Init() END")
}
diff --git a/toolkit/andlabs/updateui.go b/toolkit/andlabs/updateui.go
index 4752d67..c43e15f 100644
--- a/toolkit/andlabs/updateui.go
+++ b/toolkit/andlabs/updateui.go
@@ -86,7 +86,8 @@ func demoUI() {
messageLabel.SetText("")
})
- mainWindow.Show()
+ // this is messed up.
+ // mainWindow.Show()
}
/*
diff --git a/toolkit/gocui/debug.go b/toolkit/gocui/debug.go
index 7512c1e..2669067 100644
--- a/toolkit/gocui/debug.go
+++ b/toolkit/gocui/debug.go
@@ -45,7 +45,8 @@ func (n *node) showWidgetPlacement(b bool, s string) {
s1 += fmt.Sprintf("At(%2d,%2d) ", n.AtW, n.AtH)
}
}
- log(b, s1, s, n.WidgetType, ",", n.Name) // , "text=", w.text)
+ tmp := "." + n.Name + "."
+ log(b, s1, s, n.WidgetType, ",", tmp) // , "text=", w.text)
}
func (n *node) dumpWidget(pad string) {
diff --git a/toolkit/gocui/main.go b/toolkit/gocui/main.go
index 04e1255..11f525a 100644
--- a/toolkit/gocui/main.go
+++ b/toolkit/gocui/main.go
@@ -43,7 +43,7 @@ func catchActionChannel() {
log(logError,"ERROR: console did not initialize")
continue
}
- log(logNow, "catchActionChannel()", a.WidgetId, a.ActionType, a.WidgetType, a.Name)
+ log(logInfo, "catchActionChannel()", a.WidgetId, a.ActionType, a.WidgetType, a.Name)
action(&a)
}
}
diff --git a/toolkit/gocui/plugin.go b/toolkit/gocui/plugin.go
index eae811d..18cb71f 100644
--- a/toolkit/gocui/plugin.go
+++ b/toolkit/gocui/plugin.go
@@ -51,8 +51,22 @@ func action(a *toolkit.Action) {
case toolkit.CloseToolkit:
log(logNow, "attempting to close the plugin and release stdout and stderr")
standardExit()
+ case toolkit.Enable:
+ if n.Visible() {
+ // widget was already shown
+ } else {
+ log(logInfo, "Setting Visable to true", a.Name)
+ n.SetVisible(true)
+ }
+ case toolkit.Disable:
+ if n.Visible() {
+ log(logInfo, "Setting Visable to false", a.Name)
+ n.SetVisible(false)
+ } else {
+ // widget was already hidden
+ }
default:
- log(logError, "action() Unknown =", a.ActionType, a.WidgetType, a.Name)
+ log(logError, "action() ActionType =", a.ActionType, "WidgetType =", a.WidgetType, "Name =", a.Name)
}
log(logInfo, "action() END")
}
@@ -70,16 +84,28 @@ func (n *node) AddText(text string) {
}
func (n *node) SetText(text string) {
+ var changed bool = false
if (n == nil) {
log(logNow, "widget is nil")
return
}
- n.S = text
- n.Text = text
+ if (n.Text != text) {
+ n.Text = text
+ changed = true
+ }
+ if (n.S != text) {
+ n.S = text
+ changed = true
+ }
+ if (! changed) {
+ return
+ }
- n.textResize()
- n.deleteView()
- n.showView()
+ if (n.Visible()) {
+ n.textResize()
+ n.deleteView()
+ n.showView()
+ }
}
func (n *node) Set(val any) {
diff --git a/toolkit/gocui/view.go b/toolkit/gocui/view.go
index e69bf7c..28b80e0 100644
--- a/toolkit/gocui/view.go
+++ b/toolkit/gocui/view.go
@@ -20,20 +20,30 @@ func splitLines(s string) []string {
return lines
}
-func (n *node) textResize() {
+func (n *node) textResize() bool {
w := n.tk
var width, height int = 0, 0
+ var changed bool = false
for i, s := range splitLines(n.Text) {
- log(logNow, "textResize() len =", len(s), i, s)
+ log(logInfo, "textResize() len =", len(s), i, s)
if (width < len(s)) {
width = len(s)
}
height += 1
}
- w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW
- w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH
- n.showWidgetPlacement(logNow, "textResize()")
+ if (w.gocuiSize.w1 != w.gocuiSize.w0 + width + me.FramePadW) {
+ w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW
+ changed = true
+ }
+ if (w.gocuiSize.h1 != w.gocuiSize.h0 + height + me.FramePadH) {
+ w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH
+ changed = true
+ }
+ if (changed) {
+ n.showWidgetPlacement(logNow, "textResize() changed")
+ }
+ return changed
}
func (n *node) hideView() {
@@ -58,17 +68,38 @@ func (n *node) showView() {
x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName)
log(logInfo, "showView() w.v already defined for widget", n.Name, err)
+ // n.smartGocuiSize()
+ changed := n.textResize()
+
+ if (changed) {
+ log(logNow, "showView() textResize() changed. Should recreateView here wId =", w.cuiName)
+ } else {
+ log(logNow, "showView() Clear() and Fprint() here wId =", w.cuiName)
+ w.v.Clear()
+ fmt.Fprint(w.v, n.Text)
+ n.SetVisible(false)
+ n.SetVisible(true)
+ return
+ }
+
// if the gocui element has changed where it is supposed to be on the screen
// recreate it
- 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)
+ if (x0 != w.gocuiSize.w0) {
+ n.recreateView()
+ return
+ }
+ if (y0 != w.gocuiSize.h0) {
+ log(logError, "showView() start hight mismatch id=", w.cuiName, "gocui h vs computed h =", w.gocuiSize.h0, y0)
+ n.recreateView()
+ return
+ }
+ if (x1 != w.gocuiSize.w1) {
+ log(logError, "showView() too wide", w.cuiName, "w,w", w.gocuiSize.w1, x1)
n.recreateView()
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)
+ if (y1 != w.gocuiSize.h1) {
+ log(logError, "showView() too high", w.cuiName, "h,h", w.gocuiSize.h1, y1)
n.recreateView()
return
}