code moved to the cloudflare package
use the cloudflare package add a protobuf attempt better change detection, but formatting is broken don't redraw widgets if they are not visible create new dns entry worked attempting a DNS RR create attempt a create API call use cloudflare recommended ENV vars turn off debugging Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
f67e03db16
commit
2d147a9115
|
@ -11,6 +11,9 @@ examples/textbox/textbox
|
||||||
examples/cloudflare/cloudflare
|
examples/cloudflare/cloudflare
|
||||||
examples/*/helloconsole
|
examples/*/helloconsole
|
||||||
|
|
||||||
|
# protobuf compiled files
|
||||||
|
protobuf/*.pb.go
|
||||||
|
|
||||||
# temporary files when building debian packages
|
# temporary files when building debian packages
|
||||||
/*.deb
|
/*.deb
|
||||||
/files
|
/files
|
||||||
|
|
11
common.go
11
common.go
|
@ -170,6 +170,13 @@ func (n *Node) Unpad() *Node {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Node) Expand() *Node {
|
||||||
|
a := newAction(n, toolkit.Pad)
|
||||||
|
a.Expand = true
|
||||||
|
sendAction(a)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
// is this better?
|
// is this better?
|
||||||
// yes, this is better. it allows Internationalization very easily
|
// yes, this is better. it allows Internationalization very easily
|
||||||
// me.window = myGui.New2().Window("DNS and IPv6 Control Panel").Standard()
|
// 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
|
// This should not really do anything. as per the docs, the "Standard()" way
|
||||||
// should be the default way
|
// should be the default way
|
||||||
|
/*
|
||||||
func (n *Node) Standard() *Node {
|
func (n *Node) Standard() *Node {
|
||||||
log(debugError, "Standard() not implemented yet")
|
log(debugInfo, "Standard() not implemented yet")
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,3 +199,4 @@ func (n *Node) SetMargin() *Node {
|
||||||
log(debugError, "DoMargin() not implemented yet")
|
log(debugError, "DoMargin() not implemented yet")
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -4,10 +4,11 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"log"
|
"log"
|
||||||
|
"fmt"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
// "strconv"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
@ -19,7 +20,17 @@ func doChange(dnsRow *RRT) {
|
||||||
log.Println("Content", dnsRow.Content, "vs", dnsRow.valueNode.S)
|
log.Println("Content", dnsRow.Content, "vs", dnsRow.valueNode.S)
|
||||||
if (dnsRow.Content != dnsRow.valueNode.S) {
|
if (dnsRow.Content != dnsRow.valueNode.S) {
|
||||||
log.Println("UPDATE VALUE", dnsRow.nameNode.Name, dnsRow.typeNode.Name, "to", 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()
|
dnsRow.saveNode.Disable()
|
||||||
}
|
}
|
||||||
|
@ -73,24 +84,26 @@ func getZonefile(c *configT) *DNSRecords {
|
||||||
go.wit.com. 3600 IN A 1.1.1.9
|
go.wit.com. 3600 IN A 1.1.1.9
|
||||||
test.wit.com. 3600 IN NS ns1.wit.com.
|
test.wit.com. 3600 IN NS ns1.wit.com.
|
||||||
*/
|
*/
|
||||||
func httpPut(dnsRow *RRT) {
|
func httpPut(dnsRow *RRT) (string, string) {
|
||||||
var url string = cloudflareURL + os.Getenv("CLOUDFLARE_ZONEID") + "/dns_records/" + dnsRow.ID
|
var url string = cloudflareURL + os.Getenv("CF_API_ZONEID") + "/dns_records/" + dnsRow.ID
|
||||||
var authKey string = os.Getenv("CLOUDFLARE_AUTHKEY")
|
var authKey string = os.Getenv("CF_API_KEY")
|
||||||
var email string = os.Getenv("CLOUDFLARE_EMAIL")
|
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
|
var tmp string
|
||||||
tmp = `{"content": "` + dnsRow.valueNode.S + `", `
|
tmp = `{"content": "` + dnsRow.valueNode.S + `", `
|
||||||
tmp += `"name": "` + dnsRow.Name + `", `
|
tmp += `"name": "` + dnsRow.Name + `", `
|
||||||
tmp += `"type": "` + dnsRow.Type + `", `
|
tmp += `"type": "` + dnsRow.Type + `", `
|
||||||
tmp+= `"ttl": "` + strconv.Itoa(dnsRow.TTL) + `", `
|
tmp+= `"ttl": "` + "1" + `", `
|
||||||
tmp += `"comment": "WIT DNS Control Panel"`
|
tmp += `"comment": "WIT DNS Control Panel"`
|
||||||
tmp += `}`
|
tmp += `}`
|
||||||
data := []byte(tmp)
|
data := []byte(tmp)
|
||||||
|
|
||||||
log.Println("http PUT url =", url)
|
log.Println("http PUT url =", url)
|
||||||
log.Println("http PUT data =", data)
|
// log.Println("http PUT data =", data)
|
||||||
spew.Dump(data)
|
// spew.Dump(data)
|
||||||
|
pretty, _ := formatJSON(string(data))
|
||||||
|
log.Println("http PUT data =", pretty)
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(data))
|
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(data))
|
||||||
|
|
||||||
|
@ -103,19 +116,19 @@ func httpPut(dnsRow *RRT) {
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return tmp, fmt.Sprintf("blah err =", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return tmp, fmt.Sprintf("blah err =", err)
|
||||||
}
|
}
|
||||||
log.Println("http PUT body =", body)
|
// log.Println("http PUT body =", body)
|
||||||
spew.Dump(body)
|
// spew.Dump(body)
|
||||||
|
|
||||||
return
|
return tmp, string(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://api.cloudflare.com/client/v4/zones
|
// https://api.cloudflare.com/client/v4/zones
|
||||||
|
@ -185,3 +198,22 @@ func getZones(auth, email string) *DNSRecords {
|
||||||
|
|
||||||
return &records
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,28 @@
|
||||||
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
|
#curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
|
||||||
-H "Authorization: Bearer AAAPutYourTokenInHereSoYouCanTestItL5Cl3" \
|
# -H "Authorization: Bearer AAAPutYourTokenInHereSoYouCanTestItL5Cl3" \
|
||||||
-H "Content-Type:application/json"
|
# -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: basilarchia@gmail.com' \
|
||||||
|
--data '{
|
||||||
|
"comment": "WIT DNS Control Panel",
|
||||||
|
"content": "2001:4860:4860::5555",
|
||||||
|
"name": "www5",
|
||||||
|
"proxied": false,
|
||||||
|
"ttl": 3600,
|
||||||
|
"type": "AAAA"
|
||||||
|
}'
|
||||||
|
|
|
@ -4,6 +4,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"git.wit.org/jcarr/control-panel-dns/cloudflare"
|
||||||
)
|
)
|
||||||
|
|
||||||
func loadDNS(c *configT) {
|
func loadDNS(c *configT) {
|
||||||
|
@ -11,7 +13,8 @@ func loadDNS(c *configT) {
|
||||||
log.Println("adding DNS record", hostname)
|
log.Println("adding DNS record", hostname)
|
||||||
|
|
||||||
newt := mainWindow.NewTab(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
|
// make a grid 6 things wide
|
||||||
grid := newg.NewGrid("gridnuts", 6, gridH)
|
grid := newg.NewGrid("gridnuts", 6, gridH)
|
||||||
|
@ -19,41 +22,22 @@ func loadDNS(c *configT) {
|
||||||
// grid.NewButton("Type", func () {
|
// grid.NewButton("Type", func () {
|
||||||
// log.Println("sort by Type")
|
// log.Println("sort by Type")
|
||||||
// })
|
// })
|
||||||
typedrop := grid.NewDropdown("type")
|
grid.NewLabel("RR type")
|
||||||
typedrop.AddText("A")
|
grid.NewLabel("hostname")
|
||||||
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.NewButton("Protection", func () {
|
grid.NewLabel("Proxy")
|
||||||
log.Println("sort proxied")
|
grid.NewLabel("TTL")
|
||||||
})
|
grid.NewLabel("Value")
|
||||||
grid.NewButton("TTL", func () {
|
grid.NewLabel("Save")
|
||||||
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()
|
|
||||||
|
|
||||||
masterSave = newt.NewButton("Master Save", func () {
|
masterSave = vb.NewButton("Master Save", func () {
|
||||||
log.Println("save stuff to cloudflare")
|
log.Println("save stuff to cloudflare")
|
||||||
})
|
})
|
||||||
masterSave.Disable()
|
masterSave.Disable()
|
||||||
|
|
||||||
records := getZonefile(c)
|
records := getZonefile(c)
|
||||||
for _, record := range records.Result {
|
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.
|
// copy all the JSON values into the row record.
|
||||||
rr.ID = record.ID
|
rr.ID = record.ID
|
||||||
|
@ -62,59 +46,34 @@ func loadDNS(c *configT) {
|
||||||
rr.Content = record.Content
|
rr.Content = record.Content
|
||||||
rr.Proxied = record.Proxied
|
rr.Proxied = record.Proxied
|
||||||
rr.Proxiable = record.Proxiable
|
rr.Proxiable = record.Proxiable
|
||||||
rr.TTL = record.TTL
|
// rr.Ttl = record.TTL
|
||||||
|
|
||||||
rr.typeNode = grid.NewLabel(record.Type)
|
grid.NewLabel(record.Type)
|
||||||
rr.nameNode = grid.NewEntryLine(record.Name)
|
grid.NewLabel(record.Name)
|
||||||
rr.nameNode.SetText(record.Name)
|
|
||||||
rr.nameNode.Disable()
|
|
||||||
|
|
||||||
// set proxy or unproxied
|
proxy := grid.NewLabel("proxy")
|
||||||
rr.proxyNode = grid.NewDropdown("proxy")
|
|
||||||
if (record.Proxied) {
|
if (record.Proxied) {
|
||||||
rr.proxyNode.AddText("Proxied")
|
proxy.SetText("On")
|
||||||
rr.proxyNode.AddText("DNS")
|
|
||||||
} else {
|
} else {
|
||||||
rr.proxyNode.AddText("DNS")
|
proxy.SetText("Off")
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ttl, short string
|
var ttl string
|
||||||
if (record.TTL == 1) {
|
if (record.TTL == 1) {
|
||||||
ttl = "Auto"
|
ttl = "Auto"
|
||||||
} else {
|
} else {
|
||||||
ttl = strconv.Itoa(record.TTL)
|
ttl = strconv.Itoa(record.TTL)
|
||||||
}
|
}
|
||||||
rr.ttlNode = grid.NewLabel(ttl)
|
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)
|
val := grid.NewLabel("Value")
|
||||||
rr.valueNode.SetText(record.Content)
|
val.SetText(record.Content)
|
||||||
|
|
||||||
rr.valueNode.Custom = func () {
|
load := grid.NewButton("Load", nil)
|
||||||
log.Println("value changed =", rr.valueNode.Name, rr.proxyNode.S, rr.ID)
|
load.Custom = func () {
|
||||||
rr.saveNode.Enable()
|
|
||||||
masterSave.Enable()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
|
|
||||||
rr.saveNode = grid.NewButton("Save", nil)
|
|
||||||
rr.saveNode.Disable()
|
|
||||||
rr.saveNode.Custom = func () {
|
|
||||||
name := "save stuff to cloudflare for " + rr.ID
|
name := "save stuff to cloudflare for " + rr.ID
|
||||||
log.Println(name)
|
log.Println(name)
|
||||||
doChange(&rr)
|
// doChange(&rr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"bufio"
|
"bufio"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.wit.org/wit/gui"
|
"git.wit.org/wit/gui"
|
||||||
|
"git.wit.org/jcarr/control-panel-dns/cloudflare"
|
||||||
)
|
)
|
||||||
|
|
||||||
var title string = "Cloudflare DNS Control Panel"
|
var title string = "Cloudflare DNS Control Panel"
|
||||||
|
@ -44,7 +46,8 @@ func makeCloudflareWindow() {
|
||||||
makeConfigTab(mainWindow)
|
makeConfigTab(mainWindow)
|
||||||
|
|
||||||
t = mainWindow.NewTab("Zones")
|
t = mainWindow.NewTab("Zones")
|
||||||
g1 := t.NewGroup("zones")
|
vb := t.NewBox("vBox", false)
|
||||||
|
g1 := vb.NewGroup("zones")
|
||||||
|
|
||||||
// make dropdown list of zones
|
// make dropdown list of zones
|
||||||
zonedrop = g1.NewDropdown("zone")
|
zonedrop = g1.NewDropdown("zone")
|
||||||
|
@ -52,6 +55,7 @@ func makeCloudflareWindow() {
|
||||||
for d, _ := range config {
|
for d, _ := range config {
|
||||||
zonedrop.AddText(d)
|
zonedrop.AddText(d)
|
||||||
}
|
}
|
||||||
|
zonedrop.AddText("stablesid.org")
|
||||||
|
|
||||||
zonedrop.Custom = func () {
|
zonedrop.Custom = func () {
|
||||||
domain := zonedrop.S
|
domain := zonedrop.S
|
||||||
|
@ -82,18 +86,18 @@ func makeConfigTab(window *gui.Node) {
|
||||||
vb := t.NewBox("vBox", false)
|
vb := t.NewBox("vBox", false)
|
||||||
g1 := vb.NewGroup("Cloudflare API Config")
|
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
|
// make grid to display credentials
|
||||||
grid := g1.NewGrid("credsGrid", 2, 4) // width = 2
|
grid := g1.NewGrid("credsGrid", 2, 4) // width = 2
|
||||||
|
|
||||||
grid.NewLabel("Auth Key")
|
grid.NewLabel("Auth Key")
|
||||||
aw := grid.NewEntryLine("CLOUDFLARE_AUTHKEY")
|
aw := grid.NewEntryLine("CF_API_KEY")
|
||||||
aw.SetText(os.Getenv("CLOUDFLARE_AUTHKEY"))
|
aw.SetText(os.Getenv("CF_API_KEY"))
|
||||||
|
|
||||||
grid.NewLabel("Email")
|
grid.NewLabel("Email")
|
||||||
ew := grid.NewEntryLine("CLOUDFLARE_EMAIL")
|
ew := grid.NewEntryLine("CF_API_EMAIL")
|
||||||
ew.SetText(os.Getenv("CLOUDFLARE_EMAIL"))
|
ew.SetText(os.Getenv("CF_API_EMAIL"))
|
||||||
|
|
||||||
var url string = "https://api.cloudflare.com/client/v4/zones/"
|
var url string = "https://api.cloudflare.com/client/v4/zones/"
|
||||||
grid.NewLabel("Cloudflare API")
|
grid.NewLabel("Cloudflare API")
|
||||||
|
@ -106,6 +110,10 @@ func makeConfigTab(window *gui.Node) {
|
||||||
getZones(aw.S, ew.S)
|
getZones(aw.S, ew.S)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
vb.NewButton("cloudflare wit.com", func () {
|
||||||
|
cloudflare.CreateRR(myGui, "wit.com", "3777302ac4a78cd7fa4f6d3f72086d06")
|
||||||
|
})
|
||||||
|
|
||||||
t.Pad()
|
t.Pad()
|
||||||
t.Margin()
|
t.Margin()
|
||||||
vb.Pad()
|
vb.Pad()
|
||||||
|
@ -144,16 +152,16 @@ func showCloudflareCredentials(box *gui.Node) {
|
||||||
grid := box.NewGrid("credsGrid", 2, 4) // width = 2
|
grid := box.NewGrid("credsGrid", 2, 4) // width = 2
|
||||||
|
|
||||||
grid.NewLabel("Domain")
|
grid.NewLabel("Domain")
|
||||||
domainWidget = grid.NewEntryLine("CLOUDFLARE_DOMAIN")
|
domainWidget = grid.NewEntryLine("CF_API_DOMAIN")
|
||||||
|
|
||||||
grid.NewLabel("Zone ID")
|
grid.NewLabel("Zone ID")
|
||||||
zoneWidget = grid.NewEntryLine("CLOUDFLARE_ZONEID")
|
zoneWidget = grid.NewEntryLine("CF_API_ZONEID")
|
||||||
|
|
||||||
grid.NewLabel("Auth Key")
|
grid.NewLabel("Auth Key")
|
||||||
authWidget = grid.NewEntryLine("CLOUDFLARE_AUTHKEY")
|
authWidget = grid.NewEntryLine("CF_API_KEY")
|
||||||
|
|
||||||
grid.NewLabel("Email")
|
grid.NewLabel("Email")
|
||||||
emailWidget = grid.NewEntryLine("CLOUDFLARE_EMAIL")
|
emailWidget = grid.NewEntryLine("CF_API_EMAIL")
|
||||||
|
|
||||||
var url string = "https://api.cloudflare.com/client/v4/zones/"
|
var url string = "https://api.cloudflare.com/client/v4/zones/"
|
||||||
grid.NewLabel("Cloudflare API")
|
grid.NewLabel("Cloudflare API")
|
||||||
|
@ -161,10 +169,6 @@ func showCloudflareCredentials(box *gui.Node) {
|
||||||
|
|
||||||
grid.Pad()
|
grid.Pad()
|
||||||
|
|
||||||
saveButton = box.NewButton("Save to config", func () {
|
|
||||||
})
|
|
||||||
saveButton.Disable()
|
|
||||||
|
|
||||||
loadButton = box.NewButton("Load Cloudflare DNS zonefile", func () {
|
loadButton = box.NewButton("Load Cloudflare DNS zonefile", func () {
|
||||||
var domain configT
|
var domain configT
|
||||||
domain.domain = domainWidget.S
|
domain.domain = domainWidget.S
|
||||||
|
|
|
@ -34,20 +34,23 @@ var zonedrop *gui.Node
|
||||||
|
|
||||||
// Resource Record (used in a DNS zonefile)
|
// Resource Record (used in a DNS zonefile)
|
||||||
type RRT struct {
|
type RRT struct {
|
||||||
typeNode *gui.Node
|
typeNode *gui.Node // CNAME, A, AAAA, ...
|
||||||
nameNode *gui.Node
|
nameNode *gui.Node // www, mail, ...
|
||||||
proxyNode *gui.Node
|
proxyNode *gui.Node // If cloudflare is a port 80 & 443 proxy
|
||||||
ttlNode *gui.Node
|
ttlNode *gui.Node // just set to 1 which means automatic to cloudflare
|
||||||
valueNode *gui.Node
|
valueNode *gui.Node // 4.2.2.2, "dkim stuff", etc
|
||||||
saveNode *gui.Node
|
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
|
ID string
|
||||||
Type string
|
Type string
|
||||||
Name string
|
Name string
|
||||||
Content string
|
Content string
|
||||||
|
ProxyS string
|
||||||
Proxied bool
|
Proxied bool
|
||||||
Proxiable bool
|
Proxiable bool
|
||||||
TTL int
|
Ttl string
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
30
main.go
30
main.go
|
@ -37,17 +37,17 @@ func init() {
|
||||||
func watchCallback() {
|
func watchCallback() {
|
||||||
log(logInfo, "watchCallback() START")
|
log(logInfo, "watchCallback() START")
|
||||||
for {
|
for {
|
||||||
log(logNow, "watchCallback() restarted select for toolkit user events")
|
log(logInfo, "watchCallback() restarted select for toolkit user events")
|
||||||
select {
|
select {
|
||||||
case a := <-me.guiChan:
|
case a := <-me.guiChan:
|
||||||
if (a.ActionType == toolkit.UserQuit) {
|
if (a.ActionType == toolkit.UserQuit) {
|
||||||
log(logNow, "doUserEvent() User sent Quit()")
|
log(logInfo, "doUserEvent() User sent Quit()")
|
||||||
me.rootNode.doCustom()
|
me.rootNode.doCustom()
|
||||||
exit("wit/gui toolkit.UserQuit")
|
exit("wit/gui toolkit.UserQuit")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (a.ActionType == toolkit.EnableDebug) {
|
if (a.ActionType == toolkit.EnableDebug) {
|
||||||
log(logNow, "doUserEvent() Enable Debugging Window")
|
log(logInfo, "doUserEvent() Enable Debugging Window")
|
||||||
DebugWindow()
|
DebugWindow()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ func watchCallback() {
|
||||||
if (n == nil) {
|
if (n == nil) {
|
||||||
log(logError, "watchCallback() UNKNOWN widget id =", a.WidgetId, a.Name)
|
log(logError, "watchCallback() UNKNOWN widget id =", a.WidgetId, a.Name)
|
||||||
} else {
|
} else {
|
||||||
log(logNow, "watchCallback() FOUND widget id =", n.id, n.Name)
|
log(logInfo, "watchCallback() FOUND widget id =", n.id, n.Name)
|
||||||
n.doUserEvent(a)
|
n.doUserEvent(a)
|
||||||
}
|
}
|
||||||
// this maybe a good idea?
|
// this maybe a good idea?
|
||||||
|
@ -67,7 +67,7 @@ func watchCallback() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) doCustom() {
|
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) {
|
if (n.Custom == nil) {
|
||||||
log(debugError, "Custom() = nil. SKIPPING")
|
log(debugError, "Custom() = nil. SKIPPING")
|
||||||
return
|
return
|
||||||
|
@ -76,40 +76,40 @@ func (n *Node) doCustom() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) doUserEvent(a toolkit.Action) {
|
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 {
|
switch n.WidgetType {
|
||||||
case toolkit.Checkbox:
|
case toolkit.Checkbox:
|
||||||
n.B = a.B
|
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()
|
n.doCustom()
|
||||||
case toolkit.Button:
|
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()
|
n.doCustom()
|
||||||
case toolkit.Combobox:
|
case toolkit.Combobox:
|
||||||
n.S = a.S
|
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()
|
n.doCustom()
|
||||||
case toolkit.Dropdown:
|
case toolkit.Dropdown:
|
||||||
n.S = a.S
|
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()
|
n.doCustom()
|
||||||
case toolkit.Textbox:
|
case toolkit.Textbox:
|
||||||
n.S = a.S
|
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()
|
n.doCustom()
|
||||||
case toolkit.Spinner:
|
case toolkit.Spinner:
|
||||||
n.I = a.I
|
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()
|
n.doCustom()
|
||||||
case toolkit.Slider:
|
case toolkit.Slider:
|
||||||
n.I = a.I
|
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()
|
n.doCustom()
|
||||||
case toolkit.Window:
|
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()
|
n.doCustom()
|
||||||
default:
|
default:
|
||||||
log(logNow, "doUserEvent() type =", n.WidgetType)
|
log(logInfo, "doUserEvent() type =", n.WidgetType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,11 +38,11 @@ func (n *node) enable(b bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) pad(at toolkit.ActionType) {
|
func (n *node) pad(at toolkit.ActionType) {
|
||||||
log(debugError, "pad()")
|
log(logInfo, "pad() on WidgetId =", n.WidgetId)
|
||||||
|
|
||||||
t := n.tk
|
t := n.tk
|
||||||
if (t == nil) {
|
if (t == nil) {
|
||||||
log(debugError, "pad() toolkit struct == nil. for", n.WidgetId)
|
log(logError, "pad() toolkit struct == nil. for", n.WidgetId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,15 +127,16 @@ func (p *node) place(n *node) bool {
|
||||||
return true
|
return true
|
||||||
case toolkit.Tab:
|
case toolkit.Tab:
|
||||||
if (p.tk.uiTab == nil) {
|
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")
|
panic("p.tk.uiTab == nil")
|
||||||
}
|
}
|
||||||
if (n.tk.uiControl == 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")
|
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, "CHECK LOGIC ON THIS. APPENDING directly into a window without a tab")
|
||||||
log(logError, "THIS SHOULD NEVER HAPPEN ??????? trying to place() on parent=", p.WidgetId, p.Name, p.Text, p.WidgetType)
|
// 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")
|
// panic("n.tk.uiControl == nil")
|
||||||
p.tk.uiTab.Append(n.Text, n.tk.uiControl)
|
p.tk.uiTab.Append(n.Text, n.tk.uiControl)
|
||||||
p.tk.boxC += 1
|
p.tk.boxC += 1
|
||||||
|
|
|
@ -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 padded bool // add space between things like buttons
|
||||||
var margin bool // add space around the frames of windows
|
var margin bool // add space around the frames of windows
|
||||||
|
|
||||||
var debugToolkit bool = true
|
var debugToolkit bool = false
|
||||||
var debugChange bool = true
|
var debugChange bool = false
|
||||||
var debugPlugin bool = true
|
var debugPlugin bool = false
|
||||||
var debugAction bool = true
|
var debugAction bool = false
|
||||||
var debugFlags bool = true
|
var debugFlags bool = false
|
||||||
var debugGrid bool = true
|
var debugGrid bool = false
|
||||||
var debugNow bool = true
|
var debugNow bool = true
|
||||||
var debugError bool = true
|
var debugError bool = true
|
||||||
|
|
||||||
|
|
|
@ -40,13 +40,18 @@ func init() {
|
||||||
// log(debugToolkit, "init() Setting defaultBehavior = true")
|
// log(debugToolkit, "init() Setting defaultBehavior = true")
|
||||||
setDefaultBehavior(true)
|
setDefaultBehavior(true)
|
||||||
|
|
||||||
|
|
||||||
|
// 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)
|
// andlabs = make(map[int]*andlabsT)
|
||||||
pluginChan = make(chan toolkit.Action, 1)
|
pluginChan = make(chan toolkit.Action, 1)
|
||||||
|
|
||||||
log(logNow, "Init() start channel reciever")
|
log(logNow, "Init() start channel reciever")
|
||||||
go ui.Main(func() {
|
|
||||||
demoUI()
|
|
||||||
})
|
|
||||||
go catchActionChannel()
|
go catchActionChannel()
|
||||||
log(logNow, "Init() END")
|
log(logNow, "Init() END")
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,8 @@ func demoUI() {
|
||||||
messageLabel.SetText("")
|
messageLabel.SetText("")
|
||||||
})
|
})
|
||||||
|
|
||||||
mainWindow.Show()
|
// this is messed up.
|
||||||
|
// mainWindow.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -45,7 +45,8 @@ func (n *node) showWidgetPlacement(b bool, s string) {
|
||||||
s1 += fmt.Sprintf("At(%2d,%2d) ", n.AtW, n.AtH)
|
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) {
|
func (n *node) dumpWidget(pad string) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ func catchActionChannel() {
|
||||||
log(logError,"ERROR: console did not initialize")
|
log(logError,"ERROR: console did not initialize")
|
||||||
continue
|
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)
|
action(&a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,22 @@ func action(a *toolkit.Action) {
|
||||||
case toolkit.CloseToolkit:
|
case toolkit.CloseToolkit:
|
||||||
log(logNow, "attempting to close the plugin and release stdout and stderr")
|
log(logNow, "attempting to close the plugin and release stdout and stderr")
|
||||||
standardExit()
|
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:
|
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")
|
log(logInfo, "action() END")
|
||||||
}
|
}
|
||||||
|
@ -70,16 +84,28 @@ func (n *node) AddText(text string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) SetText(text string) {
|
func (n *node) SetText(text string) {
|
||||||
|
var changed bool = false
|
||||||
if (n == nil) {
|
if (n == nil) {
|
||||||
log(logNow, "widget is nil")
|
log(logNow, "widget is nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n.S = text
|
if (n.Text != text) {
|
||||||
n.Text = text
|
n.Text = text
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if (n.S != text) {
|
||||||
|
n.S = text
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
if (! changed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
n.textResize()
|
if (n.Visible()) {
|
||||||
n.deleteView()
|
n.textResize()
|
||||||
n.showView()
|
n.deleteView()
|
||||||
|
n.showView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) Set(val any) {
|
func (n *node) Set(val any) {
|
||||||
|
|
|
@ -20,20 +20,30 @@ func splitLines(s string) []string {
|
||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) textResize() {
|
func (n *node) textResize() bool {
|
||||||
w := n.tk
|
w := n.tk
|
||||||
var width, height int = 0, 0
|
var width, height int = 0, 0
|
||||||
|
var changed bool = false
|
||||||
|
|
||||||
for i, s := range splitLines(n.Text) {
|
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)) {
|
if (width < len(s)) {
|
||||||
width = len(s)
|
width = len(s)
|
||||||
}
|
}
|
||||||
height += 1
|
height += 1
|
||||||
}
|
}
|
||||||
w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW
|
if (w.gocuiSize.w1 != w.gocuiSize.w0 + width + me.FramePadW) {
|
||||||
w.gocuiSize.h1 = w.gocuiSize.h0 + height + me.FramePadH
|
w.gocuiSize.w1 = w.gocuiSize.w0 + width + me.FramePadW
|
||||||
n.showWidgetPlacement(logNow, "textResize()")
|
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() {
|
func (n *node) hideView() {
|
||||||
|
@ -58,17 +68,38 @@ func (n *node) showView() {
|
||||||
x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName)
|
x0, y0, x1, y1, err := me.baseGui.ViewPosition(w.cuiName)
|
||||||
log(logInfo, "showView() w.v already defined for widget", n.Name, err)
|
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
|
// if the gocui element has changed where it is supposed to be on the screen
|
||||||
// recreate it
|
// recreate it
|
||||||
if (x0 != w.gocuiSize.w0) || (y0 != w.gocuiSize.h0) {
|
if (x0 != w.gocuiSize.w0) {
|
||||||
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.recreateView()
|
n.recreateView()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (x1 != w.gocuiSize.w1) || (y1 != w.gocuiSize.h1) {
|
if (y0 != w.gocuiSize.h0) {
|
||||||
log(logError, "showView() w.v.w1 != x1", n.Name, w.gocuiSize.w1, x1)
|
log(logError, "showView() start hight mismatch id=", w.cuiName, "gocui h vs computed h =", w.gocuiSize.h0, y0)
|
||||||
log(logError, "showView() w.v.h1 != y1", n.Name, w.gocuiSize.h1, y1)
|
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 (y1 != w.gocuiSize.h1) {
|
||||||
|
log(logError, "showView() too high", w.cuiName, "h,h", w.gocuiSize.h1, y1)
|
||||||
n.recreateView()
|
n.recreateView()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue