have to remove all test code so 'packr build' works
Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
995878382e
commit
30be403d03
2
Makefile
2
Makefile
|
@ -10,7 +10,7 @@ GO111MODULE=on
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@echo your version of go must be greater than 2.10. Your version is ${GOVERSION}
|
@echo your version of go must be greater than 2.10. Your version is ${GOVERSION}
|
||||||
go build
|
packr build
|
||||||
./cloud-control-panel
|
./cloud-control-panel
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
|
|
@ -101,7 +101,7 @@ func build(tag string) *bool {
|
||||||
|
|
||||||
// rebuild the binary (always remove the old one
|
// rebuild the binary (always remove the old one
|
||||||
shell.Run("rm " + filename)
|
shell.Run("rm " + filename)
|
||||||
shell.Run("go build")
|
shell.Run("packr build")
|
||||||
md5sum = shell.Run("md5sum " + filename)
|
md5sum = shell.Run("md5sum " + filename)
|
||||||
log.Println("\tmd5sum =", md5sum)
|
log.Println("\tmd5sum =", md5sum)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
all:
|
|
||||||
go test --race
|
|
||||||
# go test bench=.
|
|
|
@ -1,193 +0,0 @@
|
||||||
package benchmark
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var result interface{}
|
|
||||||
//BenchmarkBytesToStrings convert a []bytes in a string
|
|
||||||
//https://golang.org/pkg/bytes/#Compare
|
|
||||||
func BenchmarkBytesToStrings(b *testing.B) {
|
|
||||||
s1 := []byte("string to convert")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r string
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = string(s1)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkBytesCompare compare 2 []bytes.
|
|
||||||
//https://golang.org/pkg/bytes/#Compare
|
|
||||||
func BenchmarkBytesCompare(b *testing.B) {
|
|
||||||
s1 := []byte("string to compare")
|
|
||||||
s2 := []byte("string to compare")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r int
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = bytes.Compare(s1, s2)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkStringsCompare compare 2 strings.
|
|
||||||
//https://golang.org/pkg/strings/#Compare
|
|
||||||
func BenchmarkStringsCompare(b *testing.B) {
|
|
||||||
s1 := "string to compare"
|
|
||||||
s2 := "string to compare"
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r int
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = strings.Compare(s1, s2)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkBytesContains check contains method
|
|
||||||
//https://golang.org/pkg/bytes/#Contains
|
|
||||||
func BenchmarkBytesContains(b *testing.B) {
|
|
||||||
s1 := []byte("string to compare")
|
|
||||||
s2 := []byte("comparc")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r bool
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = bytes.Contains(s1, s2)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkStringsContains check contains method
|
|
||||||
//https://golang.org/pkg/strings/#Contains
|
|
||||||
func BenchmarkStringsContains(b *testing.B) {
|
|
||||||
s1 := "string to compare"
|
|
||||||
s2 := "comparc"
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r bool
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = strings.Contains(s1, s2)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkBytesIndex check contains index
|
|
||||||
//https://golang.org/pkg/bytes/#Index
|
|
||||||
func BenchmarkBytesIndex(b *testing.B) {
|
|
||||||
s1 := []byte("string to compare")
|
|
||||||
s2 := []byte("e")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r int
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = bytes.Index(s1, s2)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkStringIndex check contains index
|
|
||||||
//https://golang.org/pkg/strings/#Index
|
|
||||||
func BenchmarkStringIndex(b *testing.B) {
|
|
||||||
s1 := "string to compare"
|
|
||||||
s2 := "e"
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r int
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = strings.Index(s1, s2)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkBytesReplace check replace method
|
|
||||||
//https://golang.org/pkg/bytes/#Replace
|
|
||||||
func BenchmarkBytesReplace(b *testing.B) {
|
|
||||||
s1 := []byte("string to comparc")
|
|
||||||
s2 := []byte("comparc")
|
|
||||||
s3 := []byte("compare")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r []byte
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = bytes.Replace(s1, s2, s3, -1)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkStringsReplace check replace method
|
|
||||||
//https://golang.org/pkg/strings/#Replace
|
|
||||||
func BenchmarkStringsReplace(b *testing.B) {
|
|
||||||
s1 := "string to comparc"
|
|
||||||
s2 := "comparc"
|
|
||||||
s3 := "compare"
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r string
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = strings.Replace(s1, s2, s3, -1)
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkBytesConcat concats 2 bytes
|
|
||||||
func BenchmarkBytesConcat2(b *testing.B) {
|
|
||||||
s1 := []byte("string to compare")
|
|
||||||
s2 := []byte("string to add")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r := make([]byte, 0, len(s1)+len(s2))
|
|
||||||
r = append(r, s1...)
|
|
||||||
r = append(r, s2...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//BenchmarkStringsConcat concats 2 strings
|
|
||||||
func BenchmarkStringsConcat2(b *testing.B) {
|
|
||||||
s1 := "string to compare"
|
|
||||||
s2 := "string to add"
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r string
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
r = s1 + s2
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkStringsJoin joins 2 strings
|
|
||||||
//https://golang.org/pkg/strings/#Join
|
|
||||||
func BenchmarkStringsJoin2(b *testing.B) {
|
|
||||||
s1 := "string to compare"
|
|
||||||
s2 := "string to add"
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var r string
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
j := []string{s1, s2}
|
|
||||||
r = strings.Join(j, "")
|
|
||||||
}
|
|
||||||
result = r
|
|
||||||
}
|
|
||||||
//BenchmarkMapHints bench mymap[string(abytes)]
|
|
||||||
func BenchmarkMapHints(b *testing.B) {
|
|
||||||
mymap := make(map[string]string)
|
|
||||||
mymap["key"] = "value"
|
|
||||||
abytes := []byte("key")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var v string
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
v, _ = mymap[string(abytes)]
|
|
||||||
}
|
|
||||||
result = v
|
|
||||||
}
|
|
||||||
//BenchmarkMapsHints_Dont bench key := string(abytes)
|
|
||||||
//v, _ = mymap[key]
|
|
||||||
func BenchmarkMapsHints_Dont(b *testing.B) {
|
|
||||||
mymap := make(map[string]string)
|
|
||||||
mymap["key"] = "value"
|
|
||||||
abytes := []byte("key")
|
|
||||||
b.ResetTimer()
|
|
||||||
b.ReportAllocs()
|
|
||||||
var v string
|
|
||||||
for n := 0; n < b.N; n++ {
|
|
||||||
key := string(abytes)
|
|
||||||
v, _ = mymap[key]
|
|
||||||
}
|
|
||||||
result = v
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var start time.Time
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
start = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println("main() started", time.Since(start))
|
|
||||||
chan1 := make(chan string, 2)
|
|
||||||
chan2 := make(chan string, 2)
|
|
||||||
|
|
||||||
chan1 <- "Value 1"
|
|
||||||
chan1 <- "Value 2"
|
|
||||||
chan2 <- "Value 1"
|
|
||||||
chan2 <- "Value 2"
|
|
||||||
|
|
||||||
select {
|
|
||||||
case res := <-chan1:
|
|
||||||
fmt.Println("Response from chan1", res, time.Since(start))
|
|
||||||
case res := <-chan2:
|
|
||||||
fmt.Println("Response from chan2", res, time.Since(start))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("main() stopped", time.Since(start))
|
|
||||||
for {}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
// In the previous example we used explicit locking with
|
|
||||||
// [mutexes](mutexes) to synchronize access to shared state
|
|
||||||
// across multiple goroutines. Another option is to use the
|
|
||||||
// built-in synchronization features of goroutines and
|
|
||||||
// channels to achieve the same result. This channel-based
|
|
||||||
// approach aligns with Go's ideas of sharing memory by
|
|
||||||
// communicating and having each piece of data owned
|
|
||||||
// by exactly 1 goroutine.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// In this example our state will be owned by a single
|
|
||||||
// goroutine. This will guarantee that the data is never
|
|
||||||
// corrupted with concurrent access. In order to read or
|
|
||||||
// write that state, other goroutines will send messages
|
|
||||||
// to the owning goroutine and receive corresponding
|
|
||||||
// replies. These `readOp` and `writeOp` `struct`s
|
|
||||||
// encapsulate those requests and a way for the owning
|
|
||||||
// goroutine to respond.
|
|
||||||
type readOp struct {
|
|
||||||
key int
|
|
||||||
resp chan int
|
|
||||||
}
|
|
||||||
type writeOp struct {
|
|
||||||
key int
|
|
||||||
val int
|
|
||||||
resp chan bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// As before we'll count how many operations we perform.
|
|
||||||
var readOps uint64
|
|
||||||
var writeOps uint64
|
|
||||||
|
|
||||||
// The `reads` and `writes` channels will be used by
|
|
||||||
// other goroutines to issue read and write requests,
|
|
||||||
// respectively.
|
|
||||||
reads := make(chan readOp)
|
|
||||||
writes := make(chan writeOp)
|
|
||||||
|
|
||||||
// Here is the goroutine that owns the `state`, which
|
|
||||||
// is a map as in the previous example but now private
|
|
||||||
// to the stateful goroutine. This goroutine repeatedly
|
|
||||||
// selects on the `reads` and `writes` channels,
|
|
||||||
// responding to requests as they arrive. A response
|
|
||||||
// is executed by first performing the requested
|
|
||||||
// operation and then sending a value on the response
|
|
||||||
// channel `resp` to indicate success (and the desired
|
|
||||||
// value in the case of `reads`).
|
|
||||||
go func() {
|
|
||||||
var state = make(map[int]int)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case read := <-reads:
|
|
||||||
read.resp <- state[read.key]
|
|
||||||
case write := <-writes:
|
|
||||||
state[write.key] = write.val
|
|
||||||
write.resp <- true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// This starts 100 goroutines to issue reads to the
|
|
||||||
// state-owning goroutine via the `reads` channel.
|
|
||||||
// Each read requires constructing a `readOp`, sending
|
|
||||||
// it over the `reads` channel, and the receiving the
|
|
||||||
// result over the provided `resp` channel.
|
|
||||||
for r := 0; r < 100; r++ {
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
read := readOp{
|
|
||||||
key: rand.Intn(5),
|
|
||||||
resp: make(chan int)}
|
|
||||||
reads <- read
|
|
||||||
<-read.resp
|
|
||||||
atomic.AddUint64(&readOps, 1)
|
|
||||||
time.Sleep(time.Millisecond)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// We start 10 writes as well, using a similar
|
|
||||||
// approach.
|
|
||||||
for w := 0; w < 10; w++ {
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
write := writeOp{
|
|
||||||
key: rand.Intn(5),
|
|
||||||
val: rand.Intn(100),
|
|
||||||
resp: make(chan bool)}
|
|
||||||
writes <- write
|
|
||||||
<-write.resp
|
|
||||||
atomic.AddUint64(&writeOps, 1)
|
|
||||||
time.Sleep(time.Millisecond)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the goroutines work for a second.
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
|
|
||||||
// Finally, capture and report the op counts.
|
|
||||||
readOpsFinal := atomic.LoadUint64(&readOps)
|
|
||||||
fmt.Println("readOps:", readOpsFinal)
|
|
||||||
writeOpsFinal := atomic.LoadUint64(&writeOps)
|
|
||||||
fmt.Println("writeOps:", writeOpsFinal)
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
28b6130e98b0740cb724da6464361e3a cloud-control-panel
|
|
|
@ -1,7 +0,0 @@
|
||||||
build:
|
|
||||||
go build
|
|
||||||
./example-aminal
|
|
||||||
|
|
||||||
|
|
||||||
build-windows:
|
|
||||||
env GOOS=windows GOARCH=amd64 go build
|
|
|
@ -1,122 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/liamg/aminal/config"
|
|
||||||
"github.com/liamg/aminal/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getActuallyProvidedFlags() map[string]bool {
|
|
||||||
result := make(map[string]bool)
|
|
||||||
|
|
||||||
flag.Visit(func(f *flag.Flag) {
|
|
||||||
result[f.Name] = true
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func getConfig() *config.Config {
|
|
||||||
showVersion := false
|
|
||||||
ignoreConfig := false
|
|
||||||
shell := ""
|
|
||||||
debugMode := false
|
|
||||||
slomo := false
|
|
||||||
|
|
||||||
if flag.Parsed() == false {
|
|
||||||
flag.BoolVar(&showVersion, "version", showVersion, "Output version information")
|
|
||||||
flag.BoolVar(&ignoreConfig, "ignore-config", ignoreConfig, "Ignore user config files and use defaults")
|
|
||||||
flag.StringVar(&shell, "shell", shell, "Specify the shell to use")
|
|
||||||
flag.BoolVar(&debugMode, "debug", debugMode, "Enable debug logging")
|
|
||||||
flag.BoolVar(&slomo, "slomo", slomo, "Render in slow motion (useful for debugging)")
|
|
||||||
|
|
||||||
flag.Parse() // actual parsing and fetching flags from the command line
|
|
||||||
}
|
|
||||||
actuallyProvidedFlags := getActuallyProvidedFlags()
|
|
||||||
|
|
||||||
if showVersion {
|
|
||||||
v := version.Version
|
|
||||||
if v == "" {
|
|
||||||
v = "development"
|
|
||||||
}
|
|
||||||
fmt.Println(v)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
var conf *config.Config
|
|
||||||
if ignoreConfig {
|
|
||||||
conf = &config.DefaultConfig
|
|
||||||
} else {
|
|
||||||
conf = loadConfigFile()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override values in the configuration file with the values specified in the command line, if any.
|
|
||||||
if actuallyProvidedFlags["shell"] {
|
|
||||||
conf.Shell = shell
|
|
||||||
}
|
|
||||||
|
|
||||||
if actuallyProvidedFlags["debug"] {
|
|
||||||
conf.DebugMode = debugMode
|
|
||||||
}
|
|
||||||
|
|
||||||
if actuallyProvidedFlags["slomo"] {
|
|
||||||
conf.Slomo = slomo
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadConfigFile() *config.Config {
|
|
||||||
|
|
||||||
usr, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to get current user information: %s\n", err)
|
|
||||||
return &config.DefaultConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
home := usr.HomeDir
|
|
||||||
if home == "" {
|
|
||||||
return &config.DefaultConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
places := []string{}
|
|
||||||
|
|
||||||
xdgHome := os.Getenv("XDG_CONFIG_HOME")
|
|
||||||
if xdgHome != "" {
|
|
||||||
places = append(places, filepath.Join(xdgHome, "aminal/config.toml"))
|
|
||||||
}
|
|
||||||
|
|
||||||
places = append(places, filepath.Join(home, ".config/aminal/config.toml"))
|
|
||||||
places = append(places, filepath.Join(home, ".aminal.toml"))
|
|
||||||
|
|
||||||
for _, place := range places {
|
|
||||||
if b, err := ioutil.ReadFile(place); err == nil {
|
|
||||||
if c, err := config.Parse(b); err == nil {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Invalid config at %s: %s\n", place, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if b, err := config.DefaultConfig.Encode(); err != nil {
|
|
||||||
fmt.Printf("Failed to encode config file: %s\n", err)
|
|
||||||
} else {
|
|
||||||
err = os.MkdirAll(filepath.Dir(places[0]), 0744)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to create config file directory: %s\n", err)
|
|
||||||
} else {
|
|
||||||
if err = ioutil.WriteFile(places[0], b, 0644); err != nil {
|
|
||||||
fmt.Printf("Failed to encode config file: %s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &config.DefaultConfig
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/liamg/aminal/config"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLogger(conf *config.Config) (*zap.SugaredLogger, error) {
|
|
||||||
|
|
||||||
var logger *zap.Logger
|
|
||||||
var err error
|
|
||||||
if conf.DebugMode {
|
|
||||||
logger, err = zap.NewDevelopment()
|
|
||||||
} else {
|
|
||||||
loggerConfig := zap.NewProductionConfig()
|
|
||||||
loggerConfig.Encoding = "console"
|
|
||||||
logger, err = loggerConfig.Build()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to create logger: %s", err)
|
|
||||||
}
|
|
||||||
return logger.Sugar(), nil
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/liamg/aminal/gui"
|
|
||||||
"github.com/liamg/aminal/platform"
|
|
||||||
"github.com/liamg/aminal/terminal"
|
|
||||||
"github.com/riywo/loginshell"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
type callback func(terminal *terminal.Terminal, g *gui.GUI)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
runtime.LockOSThread()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
initialize(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initialize(unitTestfunc callback) {
|
|
||||||
conf := getConfig()
|
|
||||||
logger, err := getLogger(conf)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to create logger: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer logger.Sync()
|
|
||||||
|
|
||||||
logger.Infof("Allocating pty...")
|
|
||||||
|
|
||||||
pty, err := platform.NewPty(80, 25)
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatalf("Failed to allocate pty: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
shellStr := conf.Shell
|
|
||||||
if shellStr == "" {
|
|
||||||
loginShell, err := loginshell.Shell()
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatalf("Failed to ascertain your shell: %s", err)
|
|
||||||
}
|
|
||||||
shellStr = loginShell
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Setenv("TERM", "xterm-256color") // controversial! easier than installing terminfo everywhere, but obviously going to be slightly different to xterm functionality, so we'll see...
|
|
||||||
os.Setenv("COLORTERM", "truecolor")
|
|
||||||
|
|
||||||
guestProcess, err := pty.CreateGuestProcess(shellStr)
|
|
||||||
if err != nil {
|
|
||||||
pty.Close()
|
|
||||||
logger.Fatalf("Failed to start your shell: %s", err)
|
|
||||||
}
|
|
||||||
defer guestProcess.Close()
|
|
||||||
|
|
||||||
logger.Infof("Creating terminal...")
|
|
||||||
terminal := terminal.New(pty, logger, conf)
|
|
||||||
|
|
||||||
g, err := gui.New(conf, terminal, logger)
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatalf("Cannot start: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if unitTestfunc != nil {
|
|
||||||
go unitTestfunc(terminal, g)
|
|
||||||
} else {
|
|
||||||
go func() {
|
|
||||||
if err := guestProcess.Wait(); err != nil {
|
|
||||||
logger.Fatalf("Failed to wait for guest process: %s", err)
|
|
||||||
}
|
|
||||||
g.Close()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := g.Render(); err != nil {
|
|
||||||
logger.Fatalf("Render error: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
run:
|
|
||||||
go run *.go
|
|
|
@ -1,92 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
var mainwin *ui.Window
|
|
||||||
|
|
||||||
func makeNumbersPage() ui.Control {
|
|
||||||
hbox := ui.NewHorizontalBox()
|
|
||||||
hbox.SetPadded(true)
|
|
||||||
|
|
||||||
group := ui.NewGroup("Numbers")
|
|
||||||
group.SetMargined(true)
|
|
||||||
hbox.Append(group, true)
|
|
||||||
|
|
||||||
vbox := ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
group.SetChild(vbox)
|
|
||||||
|
|
||||||
spinbox := ui.NewSpinbox(47, 100)
|
|
||||||
slider := ui.NewSlider(21, 100)
|
|
||||||
pbar := ui.NewProgressBar()
|
|
||||||
|
|
||||||
spinbox.OnChanged(func(*ui.Spinbox) {
|
|
||||||
slider.SetValue(spinbox.Value())
|
|
||||||
pbar.SetValue(spinbox.Value())
|
|
||||||
})
|
|
||||||
slider.OnChanged(func(*ui.Slider) {
|
|
||||||
spinbox.SetValue(slider.Value())
|
|
||||||
pbar.SetValue(slider.Value())
|
|
||||||
})
|
|
||||||
vbox.Append(spinbox, false)
|
|
||||||
vbox.Append(slider, false)
|
|
||||||
vbox.Append(pbar, false)
|
|
||||||
|
|
||||||
ip := ui.NewProgressBar()
|
|
||||||
ip.SetValue(-1)
|
|
||||||
vbox.Append(ip, false)
|
|
||||||
|
|
||||||
group = ui.NewGroup("Lists")
|
|
||||||
group.SetMargined(true)
|
|
||||||
hbox.Append(group, true)
|
|
||||||
|
|
||||||
vbox = ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
group.SetChild(vbox)
|
|
||||||
|
|
||||||
cbox := ui.NewCombobox()
|
|
||||||
cbox.Append("Combobox Item 1")
|
|
||||||
cbox.Append("Combobox Item 2")
|
|
||||||
cbox.Append("Combobox Item 3")
|
|
||||||
vbox.Append(cbox, false)
|
|
||||||
|
|
||||||
ecbox := ui.NewEditableCombobox()
|
|
||||||
ecbox.Append("Editable Item 1")
|
|
||||||
ecbox.Append("Editable Item 2")
|
|
||||||
ecbox.Append("Editable Item 3")
|
|
||||||
vbox.Append(ecbox, false)
|
|
||||||
|
|
||||||
rb := ui.NewRadioButtons()
|
|
||||||
rb.Append("Radio Button 1")
|
|
||||||
rb.Append("Radio Button 2")
|
|
||||||
rb.Append("Radio Button 3")
|
|
||||||
vbox.Append(rb, false)
|
|
||||||
|
|
||||||
return hbox
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupUI() {
|
|
||||||
mainwin = ui.NewWindow("gui-example1", 300, 200, false)
|
|
||||||
mainwin.OnClosing(func(*ui.Window) bool {
|
|
||||||
ui.Quit()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
mainwin.Destroy()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
tab := ui.NewTab()
|
|
||||||
mainwin.SetChild(tab)
|
|
||||||
mainwin.SetMargined(true)
|
|
||||||
|
|
||||||
tab.Append("example1", makeNumbersPage())
|
|
||||||
tab.SetMargined(0, true)
|
|
||||||
|
|
||||||
mainwin.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ui.Main(setupUI)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./example-lookupAAAA
|
|
|
@ -1,28 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
import "github.com/miekg/dns"
|
|
||||||
|
|
||||||
import "git.wit.com/jcarr/dnssecsocket"
|
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
|
||||||
// import "github.com/Showmax/go-fqdn"
|
|
||||||
|
|
||||||
func lookupAAAA(hostname string) string {
|
|
||||||
// lookup the IP address from DNS
|
|
||||||
dnsRR := dnssecsocket.Dnstrace(hostname, "AAAA")
|
|
||||||
spew.Dump(dnsRR)
|
|
||||||
if (dnsRR == nil) {
|
|
||||||
return "BROKEN"
|
|
||||||
}
|
|
||||||
ipaddr := dns.Field(dnsRR, 1)
|
|
||||||
log.Println("ipaddr", ipaddr)
|
|
||||||
return ipaddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
hostname := "v000185.testing.com.customers.wprod.wit.com"
|
|
||||||
// 2604:bbc0:2:248:5054:f0ff:fe00:156
|
|
||||||
|
|
||||||
lookupAAAA(hostname)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./example-multiple-windows
|
|
|
@ -1,123 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
// import "os"
|
|
||||||
import "log"
|
|
||||||
import "fmt"
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
import "git.wit.com/wit/gui"
|
|
||||||
import pb "git.wit.com/wit/witProtobuf"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
var first *gui.GuiWindow
|
|
||||||
var config *pb.Config
|
|
||||||
|
|
||||||
// This sometimes crashes on the most recent window
|
|
||||||
// under linux. but it doesn't always crash
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
config = pb.MakeDefaultConfig()
|
|
||||||
// gui.Data.Config = c
|
|
||||||
|
|
||||||
i := 1
|
|
||||||
|
|
||||||
config.Width = int32(400 + 50 * i)
|
|
||||||
config.Height = int32(400 + 50 * i)
|
|
||||||
config.Hostname = fmt.Sprintf("splash %d", i)
|
|
||||||
first = StartNewWindow(config, true, "SPLASH")
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
config.Width = int32(400 + 50 * i)
|
|
||||||
config.Hostname = fmt.Sprintf("splash %d", i)
|
|
||||||
StartNewWindow(config, true, "BLAH")
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
config.Width = int32(400 + 50 * i)
|
|
||||||
config.Hostname = fmt.Sprintf("splash %d", i)
|
|
||||||
StartNewWindow(config, false, "BLAH")
|
|
||||||
|
|
||||||
for {
|
|
||||||
i += 1
|
|
||||||
config.Width = int32(400 + 50 * i)
|
|
||||||
config.Hostname = fmt.Sprintf("splash %d", i)
|
|
||||||
StartNewWindow(config, false, "SPLASH")
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
config.Width = int32(400 + 50 * i)
|
|
||||||
config.Hostname = fmt.Sprintf("splash %d", i)
|
|
||||||
StartNewWindow(config, false, "BLAH")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartNewWindow(c *pb.Config, bg bool, action string) *gui.GuiWindow {
|
|
||||||
log.Println("InitNewWindow() Create a new window")
|
|
||||||
|
|
||||||
var newGuiWindow *gui.GuiWindow
|
|
||||||
newGuiWindow = new(gui.GuiWindow)
|
|
||||||
// newGuiWindow.Config = c
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
// mouseClick(&newBM)
|
|
||||||
ui.Quit()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
if (bg) {
|
|
||||||
log.Println("ShowWindow() IN NEW GOROUTINE")
|
|
||||||
go ui.Main(func() {
|
|
||||||
InitWindow(newGuiWindow)
|
|
||||||
})
|
|
||||||
time.Sleep(2000 * time.Millisecond)
|
|
||||||
} else {
|
|
||||||
log.Println("ShowWindow() WAITING for ui.Main()")
|
|
||||||
ui.Main(func() {
|
|
||||||
InitWindow(newGuiWindow)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return newGuiWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitWindow(gw *gui.GuiWindow) {
|
|
||||||
log.Println("InitWindow() NEW WINDOW gw =", gw)
|
|
||||||
|
|
||||||
c := config
|
|
||||||
gw.UiWindow = ui.NewWindow("", int(c.Width), int(c.Height), true)
|
|
||||||
// gw.UiWindow.SetBorderless(false)
|
|
||||||
|
|
||||||
blah := gw
|
|
||||||
gw.UiWindow.OnClosing(func(*ui.Window) bool {
|
|
||||||
log.Println("InitWindow() OnClosing() blah")
|
|
||||||
log.Println("InitWindow() OnClosing() blah")
|
|
||||||
log.Println("InitWindow() OnClosing() blah")
|
|
||||||
log.Println("InitWindow() OnClosing() blah")
|
|
||||||
spew.Dump(blah)
|
|
||||||
spew.Dump(gw)
|
|
||||||
log.Println("InitWindow() OnClosing() THIS WINDOW IS CLOSING gw=", gw)
|
|
||||||
spew.Dump(gw)
|
|
||||||
spew.Dump(gw.UiWindow)
|
|
||||||
// mouseClick(&newBM)
|
|
||||||
if (gw.UiWindow != nil) {
|
|
||||||
gw.UiWindow.Hide()
|
|
||||||
}
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
spew.Dump(gw)
|
|
||||||
// gw.UiWindow.Destroy()
|
|
||||||
ui.Quit()
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
// gw.UiWindow.SetChild(gw.T)
|
|
||||||
// gw.UiWindow.SetMargined(true)
|
|
||||||
|
|
||||||
log.Println("InitWindow() Show() gw.Name =", gw.Name)
|
|
||||||
gw.UiWindow.Show()
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
// import "os/exec"
|
|
||||||
import "log"
|
|
||||||
import "github.com/go-cmd/cmd"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
p := cmd.NewCmdOptions(
|
|
||||||
cmd.Options{
|
|
||||||
Buffered: false,
|
|
||||||
Streaming: false,
|
|
||||||
},
|
|
||||||
"/bin/bash",
|
|
||||||
"ping",
|
|
||||||
"localhost",
|
|
||||||
)
|
|
||||||
log.Println("cmd p = ", p)
|
|
||||||
p.Start()
|
|
||||||
// for {}
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
// run this and then hit:
|
|
||||||
// http://localhost:6060/debug/pprof/
|
|
||||||
//
|
|
||||||
// Also run from the command line:
|
|
||||||
// go tool pprof 'localhost:6060/debug/pprof/wit_pprof_experiment_thing?debug=1'
|
|
||||||
//
|
|
||||||
// https://medium.com/@cep21/creating-custom-go-profiles-with-pprof-b737dfc58e11
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "log"
|
|
||||||
import "net/http"
|
|
||||||
import _ "net/http/pprof" // the _ means only the init() is needed
|
|
||||||
import "os"
|
|
||||||
import "runtime/pprof"
|
|
||||||
import "sync/atomic"
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
var libProfile *pprof.Profile
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
profName := "wit_pprof_experiment_thing" // this ends up in the URL
|
|
||||||
libProfile = pprof.Lookup(profName)
|
|
||||||
if libProfile == nil {
|
|
||||||
libProfile = pprof.NewProfile(profName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type someResource struct {
|
|
||||||
*os.File
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileIndex = int64(0)
|
|
||||||
|
|
||||||
func MustResource() *someResource {
|
|
||||||
f, err := os.Create(fmt.Sprintf("/tmp/%d.txt", atomic.AddInt64(&fileIndex, 1)))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
r := &someResource{f}
|
|
||||||
libProfile.Add(r, 1)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *someResource) Close() error {
|
|
||||||
libProfile.Remove(r)
|
|
||||||
return r.File.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func trackAFunction() {
|
|
||||||
tracked := new(byte)
|
|
||||||
libProfile.Add(tracked, 1)
|
|
||||||
defer libProfile.Remove(tracked)
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
func usesAResource() {
|
|
||||||
res := MustResource()
|
|
||||||
defer res.Close()
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
http.HandleFunc("/nonblock", func(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
go usesAResource()
|
|
||||||
})
|
|
||||||
http.HandleFunc("/functiontrack", func(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
trackAFunction()
|
|
||||||
})
|
|
||||||
http.HandleFunc("/block", func(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
usesAResource()
|
|
||||||
})
|
|
||||||
log.Println("Running!")
|
|
||||||
log.Println(http.ListenAndServe("localhost:6060", nil))
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
run:
|
|
||||||
go run *.go
|
|
|
@ -1,140 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
// import "github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
func addAccountWindow() {
|
|
||||||
accounthWin := ui.NewWindow("Add Account", 400, 300, false)
|
|
||||||
accounthWin.OnClosing(func(*ui.Window) bool {
|
|
||||||
ui.Quit()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
accounthWin.Destroy()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
vbox := ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
accounthWin.SetChild(vbox)
|
|
||||||
accounthWin.SetMargined(true)
|
|
||||||
|
|
||||||
// This displays the window
|
|
||||||
accounthWin.Show()
|
|
||||||
|
|
||||||
// START create new account button
|
|
||||||
newAccountButton := ui.NewButton("Create New Account")
|
|
||||||
newAccountButton.OnClicked(func(*ui.Button) {
|
|
||||||
log.Println("OK. Closing window.")
|
|
||||||
accounthWin.Destroy()
|
|
||||||
ui.Quit()
|
|
||||||
})
|
|
||||||
vbox.Append(newAccountButton, false)
|
|
||||||
// END create new account button
|
|
||||||
|
|
||||||
vbox.Append(ui.NewHorizontalSeparator(), false)
|
|
||||||
vbox.Append(ui.NewLabel("or"), false)
|
|
||||||
vbox.Append(ui.NewHorizontalSeparator(), false)
|
|
||||||
|
|
||||||
// START add account hbox
|
|
||||||
hboxAccount := ui.NewHorizontalBox()
|
|
||||||
hboxAccount.SetPadded(true)
|
|
||||||
vbox.Append(hboxAccount, false)
|
|
||||||
|
|
||||||
// Start 'Provider' vertical box
|
|
||||||
vboxC := ui.NewVerticalBox()
|
|
||||||
vboxC.SetPadded(true)
|
|
||||||
vboxC.Append(ui.NewLabel("Cloud Provider:"), false)
|
|
||||||
|
|
||||||
cbox := ui.NewCombobox()
|
|
||||||
cbox.Append("WIT")
|
|
||||||
cbox.Append("Evocative")
|
|
||||||
vboxC.Append(cbox, false)
|
|
||||||
cbox.SetSelected(0)
|
|
||||||
|
|
||||||
cbox.OnSelected(func(*ui.Combobox) {
|
|
||||||
log.Println("OK. Selected Cloud Provider =", cbox.Selected())
|
|
||||||
})
|
|
||||||
hboxAccount.Append(vboxC, false)
|
|
||||||
// End 'Cloud Provider' vertical box
|
|
||||||
|
|
||||||
// Start 'Region' vertical box
|
|
||||||
vboxR := ui.NewVerticalBox()
|
|
||||||
vboxR.SetPadded(true)
|
|
||||||
vboxR.Append(ui.NewLabel("Region:"), false)
|
|
||||||
|
|
||||||
regbox := ui.NewCombobox()
|
|
||||||
regbox.Append("Any")
|
|
||||||
regbox.Append("SF")
|
|
||||||
vboxR.Append(regbox, false)
|
|
||||||
regbox.SetSelected(0)
|
|
||||||
|
|
||||||
regbox.OnSelected(func(*ui.Combobox) {
|
|
||||||
log.Println("OK. Selected something =", regbox.Selected())
|
|
||||||
})
|
|
||||||
hboxAccount.Append(vboxR, false)
|
|
||||||
// End 'Region' vertical box
|
|
||||||
|
|
||||||
// Start 'Nickname' vertical box
|
|
||||||
vboxN := ui.NewVerticalBox()
|
|
||||||
vboxN.SetPadded(true)
|
|
||||||
vboxN.Append(ui.NewLabel("Account Nickname:"), false)
|
|
||||||
|
|
||||||
entryNick := ui.NewEntry()
|
|
||||||
entryNick.SetReadOnly(false)
|
|
||||||
|
|
||||||
vboxN.Append(entryNick, false)
|
|
||||||
|
|
||||||
entryNick.OnChanged(func(*ui.Entry) {
|
|
||||||
log.Println("OK. nickname =", entryNick.Text())
|
|
||||||
})
|
|
||||||
hboxAccount.Append(vboxN, false)
|
|
||||||
// End 'Nickname' vertical box
|
|
||||||
|
|
||||||
// Start 'Username' vertical box
|
|
||||||
vboxU := ui.NewVerticalBox()
|
|
||||||
vboxU.SetPadded(true)
|
|
||||||
vboxU.Append(ui.NewLabel("Account Username:"), false)
|
|
||||||
|
|
||||||
entryUser := ui.NewEntry()
|
|
||||||
entryUser.SetReadOnly(false)
|
|
||||||
|
|
||||||
vboxU.Append(entryUser, false)
|
|
||||||
|
|
||||||
entryUser.OnChanged(func(*ui.Entry) {
|
|
||||||
log.Println("OK. username =", entryUser.Text())
|
|
||||||
})
|
|
||||||
hboxAccount.Append(vboxU, false)
|
|
||||||
// End 'Username' vertical box
|
|
||||||
|
|
||||||
// Start 'Password' vertical box
|
|
||||||
vboxP := ui.NewVerticalBox()
|
|
||||||
vboxP.SetPadded(true)
|
|
||||||
vboxP.Append(ui.NewLabel("Account Password:"), false)
|
|
||||||
|
|
||||||
entryPass := ui.NewEntry()
|
|
||||||
entryPass.SetReadOnly(false)
|
|
||||||
|
|
||||||
vboxP.Append(entryPass, false)
|
|
||||||
|
|
||||||
entryPass.OnChanged(func(*ui.Entry) {
|
|
||||||
log.Println("OK. password =", entryPass.Text())
|
|
||||||
})
|
|
||||||
hboxAccount.Append(vboxP, false)
|
|
||||||
// End 'Password' vertical box
|
|
||||||
|
|
||||||
vbox.Append(ui.NewHorizontalSeparator(), false)
|
|
||||||
|
|
||||||
okButton := ui.NewButton("Add Account")
|
|
||||||
okButton.OnClicked(func(*ui.Button) {
|
|
||||||
log.Println("OK. Closing window.")
|
|
||||||
accounthWin.Destroy()
|
|
||||||
ui.Quit()
|
|
||||||
})
|
|
||||||
vbox.Append(okButton, false)
|
|
||||||
// END add account hbox
|
|
||||||
}
|
|
|
@ -1,117 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
// import "time"
|
|
||||||
import "log"
|
|
||||||
// import "fmt"
|
|
||||||
// import "runtime"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
var fontButton *ui.FontButton
|
|
||||||
var attrstr *ui.AttributedString
|
|
||||||
var splashArea *ui.Area
|
|
||||||
|
|
||||||
func makeSplashArea() *ui.Area {
|
|
||||||
fontButton = ui.NewFontButton()
|
|
||||||
fontButton.OnChanged(func(*ui.FontButton) {
|
|
||||||
spew.Dump(fontButton.Font())
|
|
||||||
// SplashArea.QueueRedrawAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
spew.Dump(fontButton.Font())
|
|
||||||
|
|
||||||
makeAttributedString()
|
|
||||||
splashArea = ui.NewArea(areaHandler{})
|
|
||||||
|
|
||||||
spew.Dump(splashArea)
|
|
||||||
return splashArea
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendWithAttributes(what string, attrs ...ui.Attribute) {
|
|
||||||
start := len(attrstr.String())
|
|
||||||
end := start + len(what)
|
|
||||||
attrstr.AppendUnattributed(what)
|
|
||||||
for _, a := range attrs {
|
|
||||||
attrstr.SetAttribute(a, start, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeAttributedString() {
|
|
||||||
attrstr = ui.NewAttributedString("")
|
|
||||||
|
|
||||||
appendWithAttributes("Welcome to the Cloud Control Panel\n", ui.TextSize(16), ui.TextColor{0.0, 0.0, 0.8, .8}) // "RGBT"
|
|
||||||
|
|
||||||
appendWithAttributes("(alpha)\n\n", ui.TextSize(10))
|
|
||||||
|
|
||||||
appendWithAttributes("This control panel was designed to be an interface to your 'private' cloud. ", ui.TextWeightBold)
|
|
||||||
appendWithAttributes("The concept of a private cloud means that you can use a providers system, or, seemlessly, use your own hardware in your own datacenter. ", ui.TextWeightBold)
|
|
||||||
|
|
||||||
attrstr.AppendUnattributed("\n")
|
|
||||||
attrstr.AppendUnattributed("\n")
|
|
||||||
appendWithAttributes("This control panel requires:\n")
|
|
||||||
attrstr.AppendUnattributed("\n")
|
|
||||||
appendWithAttributes("IPv6\n")
|
|
||||||
appendWithAttributes("Your hostname in DNS\n")
|
|
||||||
attrstr.AppendUnattributed("\n\n\n\n\n")
|
|
||||||
|
|
||||||
appendWithAttributes("<click or press any key>\n", ui.TextSize(10))
|
|
||||||
}
|
|
||||||
|
|
||||||
type areaHandler struct{}
|
|
||||||
|
|
||||||
func (areaHandler) Draw(a *ui.Area, p *ui.AreaDrawParams) {
|
|
||||||
tl := ui.DrawNewTextLayout(&ui.DrawTextLayoutParams{
|
|
||||||
String: attrstr,
|
|
||||||
DefaultFont: fontButton.Font(),
|
|
||||||
Width: p.AreaWidth,
|
|
||||||
Align: ui.DrawTextAlign(1),
|
|
||||||
})
|
|
||||||
defer tl.Free()
|
|
||||||
p.Context.Text(tl, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (areaHandler) MouseEvent(a *ui.Area, me *ui.AreaMouseEvent) {
|
|
||||||
log.Println("GOT MouseEvent()")
|
|
||||||
spew.Dump(me)
|
|
||||||
if (me.Down == 1) {
|
|
||||||
log.Println("GOT MOUSE DOWN")
|
|
||||||
log.Println("GOT MOUSE DOWN")
|
|
||||||
log.Println("GOT MOUSE DOWN")
|
|
||||||
}
|
|
||||||
if (me.Up == 1) {
|
|
||||||
log.Println("GOT MOUSE UP")
|
|
||||||
log.Println("GOT MOUSE UP")
|
|
||||||
log.Println("GOT MOUSE UP")
|
|
||||||
splashWin.Destroy()
|
|
||||||
ui.Quit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (areaHandler) MouseCrossed(a *ui.Area, left bool) {
|
|
||||||
log.Println("GOT MouseCrossed()")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (areaHandler) DragBroken(a *ui.Area) {
|
|
||||||
log.Println("GOT DragBroken()")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (areaHandler) KeyEvent(a *ui.Area, ke *ui.AreaKeyEvent) (handled bool) {
|
|
||||||
log.Println("GOT KeyEvent()")
|
|
||||||
if (ke.Key == 10) {
|
|
||||||
log.Println("GOT ENTER")
|
|
||||||
log.Println("GOT ENTER")
|
|
||||||
log.Println("GOT ENTER")
|
|
||||||
}
|
|
||||||
if (ke.Key == 32) {
|
|
||||||
log.Println("GOT ENTER")
|
|
||||||
log.Println("GOT ENTER")
|
|
||||||
log.Println("GOT ENTER")
|
|
||||||
}
|
|
||||||
spew.Dump(ke)
|
|
||||||
splashWin.Destroy()
|
|
||||||
ui.Quit()
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
import "log"
|
|
||||||
import "fmt"
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
var mainwin *ui.Window
|
|
||||||
var hbox *ui.Box
|
|
||||||
|
|
||||||
func makeSplashPage() ui.Control {
|
|
||||||
hbox = ui.NewHorizontalBox()
|
|
||||||
hbox.SetPadded(true)
|
|
||||||
|
|
||||||
group := ui.NewGroup("Numbers")
|
|
||||||
group.SetMargined(true)
|
|
||||||
hbox.Append(group, true)
|
|
||||||
|
|
||||||
vbox := ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
group.SetChild(vbox)
|
|
||||||
|
|
||||||
spinbox := ui.NewSpinbox(47, 100)
|
|
||||||
slider := ui.NewSlider(21, 100)
|
|
||||||
pbar := ui.NewProgressBar()
|
|
||||||
|
|
||||||
spinbox.OnChanged(func(*ui.Spinbox) {
|
|
||||||
slider.SetValue(spinbox.Value())
|
|
||||||
pbar.SetValue(spinbox.Value())
|
|
||||||
})
|
|
||||||
slider.OnChanged(func(*ui.Slider) {
|
|
||||||
spinbox.SetValue(slider.Value())
|
|
||||||
pbar.SetValue(slider.Value())
|
|
||||||
})
|
|
||||||
vbox.Append(spinbox, false)
|
|
||||||
vbox.Append(slider, false)
|
|
||||||
vbox.Append(pbar, false)
|
|
||||||
|
|
||||||
return hbox
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupUI() {
|
|
||||||
mainwin := ui.NewWindow("gui-example1", 300, 200, true)
|
|
||||||
mainwin.OnClosing(func(*ui.Window) bool {
|
|
||||||
ui.Quit()
|
|
||||||
os.Exit(0)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
mainwin.Destroy()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
tab := ui.NewTab()
|
|
||||||
mainwin.SetChild(tab)
|
|
||||||
mainwin.SetMargined(true)
|
|
||||||
|
|
||||||
tab.Append("WIT Splash", makeSplashPage())
|
|
||||||
tab.SetMargined(0, true)
|
|
||||||
|
|
||||||
mainwin.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ui.Main(addAccountWindow)
|
|
||||||
|
|
||||||
ui.Main(showSplash)
|
|
||||||
|
|
||||||
go ui.Main(setupUI)
|
|
||||||
|
|
||||||
// locks up GTK after a while (50 times)
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
count := 0
|
|
||||||
|
|
||||||
var newgroup *ui.Group
|
|
||||||
|
|
||||||
name := "Test " + fmt.Sprintf("%d", count)
|
|
||||||
log.Println("name=",name)
|
|
||||||
newgroup = ui.NewGroup(name)
|
|
||||||
newgroup.SetMargined(true)
|
|
||||||
hbox.Append(newgroup, false)
|
|
||||||
|
|
||||||
// display the splash screen info
|
|
||||||
log.Println("sleep for 3")
|
|
||||||
time.Sleep(3000 * time.Millisecond)
|
|
||||||
|
|
||||||
hbox.Delete(1)
|
|
||||||
// newgroup.Delete()
|
|
||||||
// can't destroy when there is a parent
|
|
||||||
newgroup.Destroy()
|
|
||||||
newgroup = nil
|
|
||||||
|
|
||||||
// wait forever here
|
|
||||||
for {
|
|
||||||
log.Println("sleep for 3 forever here")
|
|
||||||
time.Sleep(3000 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
// import "github.com/davecgh/go-spew/spew"
|
|
||||||
// import "time"
|
|
||||||
// import "fmt"
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
import "runtime"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
var splashWin *ui.Window
|
|
||||||
|
|
||||||
func showSplash() {
|
|
||||||
splashWin = ui.NewWindow("", 640, 480, true)
|
|
||||||
splashWin.SetBorderless(true)
|
|
||||||
splashWin.OnClosing(func(*ui.Window) bool {
|
|
||||||
ui.Quit()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
splashWin.Destroy()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
vbox := ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
splashWin.SetChild(vbox)
|
|
||||||
splashWin.SetMargined(true)
|
|
||||||
|
|
||||||
// This displays the window
|
|
||||||
splashWin.Show()
|
|
||||||
|
|
||||||
makeAttributedString()
|
|
||||||
myArea := makeSplashArea()
|
|
||||||
|
|
||||||
vbox.Append(myArea, true)
|
|
||||||
|
|
||||||
if runtime.GOOS == "linux" {
|
|
||||||
vbox.Append(ui.NewLabel("OS: Linux"), false)
|
|
||||||
} else if runtime.GOOS == "windows" {
|
|
||||||
vbox.Append(ui.NewLabel("OS: Windows"), false)
|
|
||||||
} else {
|
|
||||||
vbox.Append(ui.NewLabel("OS: " + runtime.GOOS), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
vbox.Append(ui.NewLabel("Version: v0.3"), false)
|
|
||||||
|
|
||||||
okButton := ui.NewButton("OK")
|
|
||||||
okButton.OnClicked(func(*ui.Button) {
|
|
||||||
log.Println("OK. Closing window.")
|
|
||||||
splashWin.Destroy()
|
|
||||||
ui.Quit()
|
|
||||||
})
|
|
||||||
vbox.Append(okButton, false)
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
// "code.google.com/p/go.crypto/ssh"
|
|
||||||
// "code.google.com/p/go.crypto/ssh/terminal"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// An SSH server is represented by a ServerConfig, which holds
|
|
||||||
// certificate details and handles authentication of ServerConns.
|
|
||||||
config := &ssh.ServerConfig{
|
|
||||||
PasswordCallback: func(conn *ssh.ServerConn, user, pass string) bool {
|
|
||||||
return user == "testuser" && pass == "tiger"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pemBytes, err := ioutil.ReadFile("id_rsa")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to load private key:", err)
|
|
||||||
}
|
|
||||||
if err = config.SetRSAPrivateKey(pemBytes); err != nil {
|
|
||||||
log.Fatal("Failed to parse private key:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Once a ServerConfig has been configured, connections can be
|
|
||||||
// accepted.
|
|
||||||
conn, err := ssh.Listen("tcp", "0.0.0.0:2022", config)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("failed to listen for connection")
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
// A ServerConn multiplexes several channels, which must
|
|
||||||
// themselves be Accepted.
|
|
||||||
log.Println("accept")
|
|
||||||
sConn, err := conn.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("failed to accept incoming connection")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := sConn.Handshake(); err != nil {
|
|
||||||
log.Println("failed to handshake")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
go handleServerConn(sConn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleServerConn(sConn *ssh.ServerConn) {
|
|
||||||
defer sConn.Close()
|
|
||||||
for {
|
|
||||||
// Accept reads from the connection, demultiplexes packets
|
|
||||||
// to their corresponding channels and returns when a new
|
|
||||||
// channel request is seen. Some goroutine must always be
|
|
||||||
// calling Accept; otherwise no messages will be forwarded
|
|
||||||
// to the channels.
|
|
||||||
ch, err := sConn.Accept()
|
|
||||||
if err == io.EOF {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Println("handleServerConn Accept:", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// Channels have a type, depending on the application level
|
|
||||||
// protocol intended. In the case of a shell, the type is
|
|
||||||
// "session" and ServerShell may be used to present a simple
|
|
||||||
// terminal interface.
|
|
||||||
if ch.ChannelType() != "session" {
|
|
||||||
ch.Reject(ssh.UnknownChannelType, "unknown channel type")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
go handleChannel(ch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleChannel(ch ssh.Channel) {
|
|
||||||
term := terminal.NewTerminal(ch, "> ")
|
|
||||||
serverTerm := &ssh.ServerTerminal{
|
|
||||||
Term: term,
|
|
||||||
Channel: ch,
|
|
||||||
}
|
|
||||||
ch.Accept()
|
|
||||||
defer ch.Close()
|
|
||||||
for {
|
|
||||||
line, err := serverTerm.ReadLine()
|
|
||||||
if err == io.EOF {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Println("handleChannel readLine err:", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Println(line)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,202 +0,0 @@
|
||||||
// A small SSH daemon providing bash sessions
|
|
||||||
//
|
|
||||||
// Server:
|
|
||||||
// cd my/new/dir/
|
|
||||||
// #generate server keypair
|
|
||||||
// ssh-keygen -t rsa
|
|
||||||
// go get -v .
|
|
||||||
// go run sshd.go
|
|
||||||
//
|
|
||||||
// Client:
|
|
||||||
// ssh foo@localhost -p 2200 #pass=bar
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os/exec"
|
|
||||||
"sync"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/kr/pty"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// In the latest version of crypto/ssh (after Go 1.3), the SSH server type has been removed
|
|
||||||
// in favour of an SSH connection type. A ssh.ServerConn is created by passing an existing
|
|
||||||
// net.Conn and a ssh.ServerConfig to ssh.NewServerConn, in effect, upgrading the net.Conn
|
|
||||||
// into an ssh.ServerConn
|
|
||||||
|
|
||||||
config := &ssh.ServerConfig{
|
|
||||||
//Define a function to run when a client attempts a password login
|
|
||||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
|
||||||
// Should use constant-time compare (or better, salt+hash) in a production setting.
|
|
||||||
if c.User() == "foo" && string(pass) == "bar" {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("password rejected for %q", c.User())
|
|
||||||
},
|
|
||||||
// You may also explicitly allow anonymous client authentication, though anon bash
|
|
||||||
// sessions may not be a wise idea
|
|
||||||
// NoClientAuth: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// You can generate a keypair with 'ssh-keygen -t rsa'
|
|
||||||
privateBytes, err := ioutil.ReadFile("id_rsa")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to load private key (./id_rsa)")
|
|
||||||
}
|
|
||||||
|
|
||||||
private, err := ssh.ParsePrivateKey(privateBytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to parse private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
config.AddHostKey(private)
|
|
||||||
|
|
||||||
// Once a ServerConfig has been configured, connections can be accepted.
|
|
||||||
listener, err := net.Listen("tcp", "0.0.0.0:2200")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to listen on 2200 (%s)", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accept all connections
|
|
||||||
log.Print("Listening on 2200...")
|
|
||||||
for {
|
|
||||||
tcpConn, err := listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to accept incoming connection (%s)", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Before use, a handshake must be performed on the incoming net.Conn.
|
|
||||||
sshConn, chans, reqs, err := ssh.NewServerConn(tcpConn, config)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to handshake (%s)", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("New SSH connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion())
|
|
||||||
// Discard all global out-of-band Requests
|
|
||||||
go ssh.DiscardRequests(reqs)
|
|
||||||
// Accept all channels
|
|
||||||
go handleChannels(chans)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleChannels(chans <-chan ssh.NewChannel) {
|
|
||||||
// Service the incoming Channel channel in go routine
|
|
||||||
for newChannel := range chans {
|
|
||||||
go handleChannel(newChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleChannel(newChannel ssh.NewChannel) {
|
|
||||||
// Since we're handling a shell, we expect a
|
|
||||||
// channel type of "session". The also describes
|
|
||||||
// "x11", "direct-tcpip" and "forwarded-tcpip"
|
|
||||||
// channel types.
|
|
||||||
if t := newChannel.ChannelType(); t != "session" {
|
|
||||||
newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point, we have the opportunity to reject the client's
|
|
||||||
// request for another logical connection
|
|
||||||
connection, requests, err := newChannel.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Could not accept channel (%s)", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire up bash for this session
|
|
||||||
bash := exec.Command("bash")
|
|
||||||
|
|
||||||
// Prepare teardown function
|
|
||||||
close := func() {
|
|
||||||
connection.Close()
|
|
||||||
_, err := bash.Process.Wait()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to exit bash (%s)", err)
|
|
||||||
}
|
|
||||||
log.Printf("Session closed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a terminal for this channel
|
|
||||||
log.Print("Creating pty...")
|
|
||||||
bashf, err := pty.Start(bash)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Could not start pty (%s)", err)
|
|
||||||
close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//pipe session to bash and visa-versa
|
|
||||||
var once sync.Once
|
|
||||||
go func() {
|
|
||||||
io.Copy(connection, bashf)
|
|
||||||
once.Do(close)
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
io.Copy(bashf, connection)
|
|
||||||
once.Do(close)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Sessions have out-of-band requests such as "shell", "pty-req" and "env"
|
|
||||||
go func() {
|
|
||||||
for req := range requests {
|
|
||||||
switch req.Type {
|
|
||||||
case "shell":
|
|
||||||
// We only accept the default shell
|
|
||||||
// (i.e. no command in the Payload)
|
|
||||||
if len(req.Payload) == 0 {
|
|
||||||
req.Reply(true, nil)
|
|
||||||
}
|
|
||||||
case "pty-req":
|
|
||||||
termLen := req.Payload[3]
|
|
||||||
w, h := parseDims(req.Payload[termLen+4:])
|
|
||||||
SetWinsize(bashf.Fd(), w, h)
|
|
||||||
// Responding true (OK) here will let the client
|
|
||||||
// know we have a pty ready for input
|
|
||||||
req.Reply(true, nil)
|
|
||||||
case "window-change":
|
|
||||||
w, h := parseDims(req.Payload)
|
|
||||||
SetWinsize(bashf.Fd(), w, h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// =======================
|
|
||||||
|
|
||||||
// parseDims extracts terminal dimensions (width x height) from the provided buffer.
|
|
||||||
func parseDims(b []byte) (uint32, uint32) {
|
|
||||||
w := binary.BigEndian.Uint32(b)
|
|
||||||
h := binary.BigEndian.Uint32(b[4:])
|
|
||||||
return w, h
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======================
|
|
||||||
|
|
||||||
// Winsize stores the Height and Width of a terminal.
|
|
||||||
type Winsize struct {
|
|
||||||
Height uint16
|
|
||||||
Width uint16
|
|
||||||
x uint16 // unused
|
|
||||||
y uint16 // unused
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetWinsize sets the size of the given pty.
|
|
||||||
func SetWinsize(fd uintptr, w, h uint32) {
|
|
||||||
ws := &Winsize{Width: uint16(w), Height: uint16(h)}
|
|
||||||
syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Borrowed from https://github.com/creack/termios/blob/master/win/win.go
|
|
|
@ -1,202 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2014 Brave New Software Project, Inc.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
|
@ -1,6 +0,0 @@
|
||||||
build:
|
|
||||||
go build
|
|
||||||
./example-systray
|
|
||||||
|
|
||||||
run:
|
|
||||||
go run *.go
|
|
|
@ -1,88 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
import "github.com/getlantern/systray"
|
|
||||||
import "github.com/getlantern/systray/example/icon"
|
|
||||||
import "github.com/skratchdot/open-golang/open"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
onExit := func() {
|
|
||||||
fmt.Println("Starting onExit")
|
|
||||||
/*
|
|
||||||
now := time.Now()
|
|
||||||
ioutil.WriteFile(fmt.Sprintf(`on_exit_%d.txt`, now.UnixNano()), []byte(now.String()), 0644)
|
|
||||||
now = time.Now()
|
|
||||||
ioutil.WriteFile(fmt.Sprintf(`on_exit_%d.2.txt`, now.UnixNano()), []byte(now.String()), 0644)
|
|
||||||
*/
|
|
||||||
fmt.Println("Finished onExit")
|
|
||||||
}
|
|
||||||
// Should be called at the very beginning of main().
|
|
||||||
systray.Run(onReady, onExit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func onReady() {
|
|
||||||
systray.SetIcon(icon.Data)
|
|
||||||
systray.SetTitle("Awesome App")
|
|
||||||
systray.SetTooltip("Lantern")
|
|
||||||
mQuitOrig := systray.AddMenuItem("Quit", "Quit the whole app")
|
|
||||||
go func() {
|
|
||||||
<-mQuitOrig.ClickedCh
|
|
||||||
fmt.Println("Requesting quit")
|
|
||||||
systray.Quit()
|
|
||||||
fmt.Println("Finished quitting")
|
|
||||||
}()
|
|
||||||
|
|
||||||
// We can manipulate the systray in other goroutines
|
|
||||||
go func() {
|
|
||||||
systray.SetIcon(icon.Data)
|
|
||||||
systray.SetTitle("Awesome App")
|
|
||||||
systray.SetTooltip("Pretty awesome棒棒嗒")
|
|
||||||
mChange := systray.AddMenuItem("Change Me", "Change Me")
|
|
||||||
mChecked := systray.AddMenuItem("Unchecked", "Check Me")
|
|
||||||
mEnabled := systray.AddMenuItem("Enabled", "Enabled")
|
|
||||||
systray.AddMenuItem("Ignored", "Ignored")
|
|
||||||
mUrl := systray.AddMenuItem("Open Lantern.org", "my home")
|
|
||||||
mQuit := systray.AddMenuItem("退出", "Quit the whole app")
|
|
||||||
|
|
||||||
// Sets the icon of a menu item. Only available on Mac.
|
|
||||||
mQuit.SetIcon(icon.Data)
|
|
||||||
|
|
||||||
systray.AddSeparator()
|
|
||||||
mToggle := systray.AddMenuItem("Toggle", "Toggle the Quit button")
|
|
||||||
shown := true
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-mChange.ClickedCh:
|
|
||||||
mChange.SetTitle("I've Changed")
|
|
||||||
case <-mChecked.ClickedCh:
|
|
||||||
if mChecked.Checked() {
|
|
||||||
mChecked.Uncheck()
|
|
||||||
mChecked.SetTitle("Unchecked")
|
|
||||||
} else {
|
|
||||||
mChecked.Check()
|
|
||||||
mChecked.SetTitle("Checked")
|
|
||||||
}
|
|
||||||
case <-mEnabled.ClickedCh:
|
|
||||||
mEnabled.SetTitle("Disabled")
|
|
||||||
mEnabled.Disable()
|
|
||||||
case <-mUrl.ClickedCh:
|
|
||||||
open.Run("https://www.getlantern.org")
|
|
||||||
case <-mToggle.ClickedCh:
|
|
||||||
if shown {
|
|
||||||
mQuitOrig.Hide()
|
|
||||||
mEnabled.Hide()
|
|
||||||
shown = false
|
|
||||||
} else {
|
|
||||||
mQuitOrig.Show()
|
|
||||||
mEnabled.Show()
|
|
||||||
shown = true
|
|
||||||
}
|
|
||||||
case <-mQuit.ClickedCh:
|
|
||||||
systray.Quit()
|
|
||||||
fmt.Println("Quit2 now...")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
run:
|
|
||||||
go run *.go
|
|
||||||
|
|
||||||
build:
|
|
||||||
go build
|
|
||||||
|
|
||||||
build-windows:
|
|
||||||
env GOOS=windows GOARCH=amd64 go build
|
|
|
@ -1 +0,0 @@
|
||||||
This is the example directly from andlabs/ui
|
|
|
@ -1,454 +0,0 @@
|
||||||
// taken directly from the andlabs/ui/examples
|
|
||||||
// 26 august 2018
|
|
||||||
|
|
||||||
// TODO possible bugs in libui:
|
|
||||||
// - the checkboxes on macOS retain their values when they shouldn't
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
_ "image/png"
|
|
||||||
"image/draw"
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/andlabs/ui"
|
|
||||||
_ "github.com/andlabs/ui/winmanifest"
|
|
||||||
)
|
|
||||||
|
|
||||||
type modelHandler struct {
|
|
||||||
row9Text string
|
|
||||||
yellowRow int
|
|
||||||
checkStates [15]int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newModelHandler() *modelHandler {
|
|
||||||
m := new(modelHandler)
|
|
||||||
m.row9Text = "You can edit this one"
|
|
||||||
m.yellowRow = -1
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mh *modelHandler) ColumnTypes(m *ui.TableModel) []ui.TableValue {
|
|
||||||
return []ui.TableValue{
|
|
||||||
ui.TableString(""), // column 0 text
|
|
||||||
ui.TableString(""), // column 1 text
|
|
||||||
ui.TableString(""), // column 2 text
|
|
||||||
ui.TableColor{}, // row background color
|
|
||||||
ui.TableColor{}, // column 1 text color
|
|
||||||
ui.TableImage{}, // column 1 image
|
|
||||||
ui.TableString(""), // column 4 button text
|
|
||||||
ui.TableInt(0), // column 3 checkbox state
|
|
||||||
ui.TableInt(0), // column 5 progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mh *modelHandler) NumRows(m *ui.TableModel) int {
|
|
||||||
return 15
|
|
||||||
}
|
|
||||||
|
|
||||||
var img [2]*ui.Image
|
|
||||||
|
|
||||||
func (mh *modelHandler) CellValue(m *ui.TableModel, row, column int) ui.TableValue {
|
|
||||||
if column == 3 {
|
|
||||||
if row == mh.yellowRow {
|
|
||||||
return ui.TableColor{1, 1, 0, 1}
|
|
||||||
}
|
|
||||||
if row == 3 {
|
|
||||||
return ui.TableColor{1, 0, 0, 1}
|
|
||||||
}
|
|
||||||
if row == 11 {
|
|
||||||
return ui.TableColor{0, 0.5, 1, 0.5}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if column == 4 {
|
|
||||||
if (row % 2) == 1 {
|
|
||||||
return ui.TableColor{0.5, 0, 0.75, 1}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if column == 5 {
|
|
||||||
if row < 8 {
|
|
||||||
return ui.TableImage{img[0]}
|
|
||||||
}
|
|
||||||
return ui.TableImage{img[1]}
|
|
||||||
}
|
|
||||||
if column == 7 {
|
|
||||||
return ui.TableInt(mh.checkStates[row])
|
|
||||||
}
|
|
||||||
if column == 8 {
|
|
||||||
if row == 0 {
|
|
||||||
return ui.TableInt(0)
|
|
||||||
}
|
|
||||||
if row == 13 {
|
|
||||||
return ui.TableInt(100)
|
|
||||||
}
|
|
||||||
if row == 14 {
|
|
||||||
return ui.TableInt(-1)
|
|
||||||
}
|
|
||||||
return ui.TableInt(50)
|
|
||||||
}
|
|
||||||
switch column {
|
|
||||||
case 0:
|
|
||||||
return ui.TableString(fmt.Sprintf("Row %d", row))
|
|
||||||
case 2:
|
|
||||||
if row == 9 {
|
|
||||||
return ui.TableString(mh.row9Text)
|
|
||||||
}
|
|
||||||
return ui.TableString("Editing this won't change anything")
|
|
||||||
case 1:
|
|
||||||
return ui.TableString("Colors!")
|
|
||||||
case 6:
|
|
||||||
return ui.TableString("Make Yellow")
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mh *modelHandler) SetCellValue(m *ui.TableModel, row, column int, value ui.TableValue) {
|
|
||||||
if row == 9 && column == 2 {
|
|
||||||
mh.row9Text = string(value.(ui.TableString))
|
|
||||||
}
|
|
||||||
if column == 6 { // row background color
|
|
||||||
prevYellowRow := mh.yellowRow
|
|
||||||
mh.yellowRow = row
|
|
||||||
if prevYellowRow != -1 {
|
|
||||||
m.RowChanged(prevYellowRow)
|
|
||||||
}
|
|
||||||
m.RowChanged(mh.yellowRow)
|
|
||||||
}
|
|
||||||
if column == 7 { // checkboxes
|
|
||||||
mh.checkStates[row] = int(value.(ui.TableInt))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendImageNamed(i *ui.Image, which string) {
|
|
||||||
b := rawImages[which]
|
|
||||||
img, _, err := image.Decode(bytes.NewReader(b))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
nr, ok := img.(*image.RGBA)
|
|
||||||
if !ok {
|
|
||||||
i2 := image.NewRGBA(img.Bounds())
|
|
||||||
draw.Draw(i2, i2.Bounds(), img, img.Bounds().Min, draw.Src)
|
|
||||||
nr = i2
|
|
||||||
}
|
|
||||||
i.Append(nr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupUI() {
|
|
||||||
mainwin := ui.NewWindow("libui Control Gallery", 640, 480, true)
|
|
||||||
mainwin.OnClosing(func(*ui.Window) bool {
|
|
||||||
ui.Quit()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
mainwin.Destroy()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
img[0] = ui.NewImage(16, 16)
|
|
||||||
appendImageNamed(img[0], "andlabs_16x16test_24june2016.png")
|
|
||||||
appendImageNamed(img[0], "andlabs_32x32test_24june2016.png")
|
|
||||||
img[1] = ui.NewImage(16, 16)
|
|
||||||
appendImageNamed(img[1], "tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png")
|
|
||||||
appendImageNamed(img[1], "tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png")
|
|
||||||
|
|
||||||
mh := newModelHandler()
|
|
||||||
model := ui.NewTableModel(mh)
|
|
||||||
|
|
||||||
table := ui.NewTable(&ui.TableParams{
|
|
||||||
Model: model,
|
|
||||||
RowBackgroundColorModelColumn: 3,
|
|
||||||
})
|
|
||||||
|
|
||||||
vbox := ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
vbox.Append(table, true)
|
|
||||||
|
|
||||||
mainwin.SetChild(vbox)
|
|
||||||
mainwin.SetMargined(true)
|
|
||||||
|
|
||||||
table.AppendTextColumn("Column 1",
|
|
||||||
0, ui.TableModelColumnNeverEditable, nil)
|
|
||||||
|
|
||||||
table.AppendImageTextColumn("Column 2",
|
|
||||||
5,
|
|
||||||
1, ui.TableModelColumnNeverEditable, &ui.TableTextColumnOptionalParams{
|
|
||||||
ColorModelColumn: 4,
|
|
||||||
});
|
|
||||||
table.AppendTextColumn("Editable",
|
|
||||||
2, ui.TableModelColumnAlwaysEditable, nil)
|
|
||||||
|
|
||||||
table.AppendCheckboxColumn("Checkboxes",
|
|
||||||
7, ui.TableModelColumnAlwaysEditable)
|
|
||||||
table.AppendButtonColumn("Buttons",
|
|
||||||
6, ui.TableModelColumnAlwaysEditable)
|
|
||||||
|
|
||||||
table.AppendProgressBarColumn("Progress Bar",
|
|
||||||
8)
|
|
||||||
|
|
||||||
mainwin.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ui.Main(setupUI)
|
|
||||||
}
|
|
||||||
|
|
||||||
var rawImages = map[string][]byte{
|
|
||||||
"andlabs_16x16test_24june2016.png": []byte{
|
|
||||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
|
||||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
|
||||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
|
|
||||||
0x00, 0xca, 0x49, 0x44, 0x41, 0x54, 0x38, 0x11, 0xa5, 0x93, 0xb1, 0x0d,
|
|
||||||
0xc2, 0x40, 0x0c, 0x45, 0x1d, 0xc4, 0x14, 0x0c, 0x12, 0x41, 0x0f, 0x62,
|
|
||||||
0x12, 0x46, 0x80, 0x8a, 0x2e, 0x15, 0x30, 0x02, 0x93, 0x20, 0x68, 0x11,
|
|
||||||
0x51, 0x06, 0x61, 0x0d, 0x88, 0x2d, 0x7f, 0xdb, 0x07, 0x87, 0x08, 0xdc,
|
|
||||||
0x49, 0x91, 0x7d, 0xf6, 0xf7, 0xf3, 0x4f, 0xa4, 0x54, 0xbb, 0xeb, 0xf6,
|
|
||||||
0x41, 0x05, 0x67, 0xcc, 0xb3, 0x9b, 0xfa, 0xf6, 0x17, 0x62, 0xdf, 0xcd,
|
|
||||||
0x48, 0x00, 0x32, 0xbd, 0xa8, 0x1d, 0x72, 0xee, 0x3c, 0x47, 0x16, 0xfb,
|
|
||||||
0x5c, 0x53, 0x8d, 0x03, 0x30, 0x14, 0x84, 0xf7, 0xd5, 0x89, 0x26, 0xc7,
|
|
||||||
0x25, 0x10, 0x36, 0xe4, 0x05, 0xa2, 0x51, 0xbc, 0xc4, 0x1c, 0xc3, 0x1c,
|
|
||||||
0xed, 0x30, 0x1c, 0x8f, 0x16, 0x3f, 0x02, 0x78, 0x33, 0x20, 0x06, 0x60,
|
|
||||||
0x97, 0x70, 0xaa, 0x45, 0x7f, 0x85, 0x60, 0x5d, 0xb6, 0xf4, 0xc2, 0xc4,
|
|
||||||
0x3e, 0x0f, 0x44, 0xcd, 0x1b, 0x20, 0x90, 0x0f, 0xed, 0x85, 0xa8, 0x55,
|
|
||||||
0x05, 0x42, 0x43, 0xb4, 0x9e, 0xce, 0x71, 0xb3, 0xe8, 0x0e, 0xb4, 0xc4,
|
|
||||||
0xc3, 0x39, 0x21, 0xb7, 0x73, 0xbd, 0xe4, 0x1b, 0xe4, 0x04, 0xb6, 0xaa,
|
|
||||||
0x4f, 0x18, 0x2c, 0xee, 0x42, 0x31, 0x01, 0x84, 0xfa, 0xe0, 0xd4, 0x00,
|
|
||||||
0xdf, 0xb6, 0x83, 0xf8, 0xea, 0xc2, 0x00, 0x10, 0xfc, 0x1a, 0x05, 0x30,
|
|
||||||
0x74, 0x3b, 0xe0, 0xd1, 0x45, 0xb1, 0x83, 0xaa, 0xf4, 0x77, 0x7e, 0x02,
|
|
||||||
0x87, 0x1f, 0x42, 0x7f, 0x9e, 0x2b, 0xe8, 0xdf, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
|
|
||||||
},
|
|
||||||
"andlabs_32x32test_24june2016.png": []byte{
|
|
||||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
|
||||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
|
|
||||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
|
|
||||||
0x01, 0x6a, 0x49, 0x44, 0x41, 0x54, 0x58, 0x09, 0xc5, 0x97, 0xc1, 0x0d,
|
|
||||||
0xc2, 0x30, 0x0c, 0x45, 0x03, 0x62, 0x0a, 0x06, 0x41, 0x70, 0x07, 0x31,
|
|
||||||
0x09, 0x23, 0xc0, 0x89, 0x05, 0x80, 0x11, 0x98, 0x04, 0xc1, 0x15, 0x81,
|
|
||||||
0x18, 0x84, 0x35, 0x00, 0x57, 0xfd, 0x8d, 0x13, 0x92, 0x3a, 0x4e, 0x03,
|
|
||||||
0x8d, 0x54, 0x39, 0x35, 0xb1, 0xff, 0x8b, 0xed, 0x1e, 0x18, 0xec, 0xae,
|
|
||||||
0xdb, 0x97, 0xe9, 0x71, 0x8d, 0x48, 0x7b, 0x33, 0xb9, 0xf5, 0x82, 0xb0,
|
|
||||||
0x7f, 0xcc, 0x4c, 0x05, 0x50, 0xa9, 0x2f, 0x26, 0x32, 0xc4, 0xf9, 0x21,
|
|
||||||
0x9f, 0xa1, 0x13, 0x8a, 0x5c, 0x16, 0x40, 0x4a, 0x9e, 0x92, 0x14, 0x78,
|
|
||||||
0x8a, 0x5c, 0x43, 0xc4, 0xf4, 0x65, 0x3b, 0x01, 0x3c, 0x57, 0x27, 0x43,
|
|
||||||
0x4f, 0x97, 0x95, 0x0d, 0x40, 0xc2, 0xe3, 0xe3, 0xb2, 0x7a, 0xba, 0x40,
|
|
||||||
0xd8, 0x19, 0x50, 0x5c, 0x03, 0xe2, 0x08, 0x21, 0x10, 0xdf, 0xd7, 0x3a,
|
|
||||||
0x88, 0x6c, 0x46, 0xd4, 0x00, 0x5f, 0x42, 0x35, 0x85, 0x03, 0x41, 0x03,
|
|
||||||
0xcb, 0x44, 0x00, 0x1a, 0xb2, 0x2e, 0x80, 0x66, 0xd2, 0x43, 0xd9, 0x32,
|
|
||||||
0x7c, 0x2e, 0x40, 0x1b, 0x75, 0x0d, 0xe7, 0xdc, 0x94, 0x09, 0xc6, 0x2a,
|
|
||||||
0xc3, 0x8e, 0x04, 0xb7, 0x59, 0x43, 0x08, 0x08, 0x64, 0xcc, 0x15, 0xa7,
|
|
||||||
0x78, 0x5b, 0x01, 0x45, 0xdf, 0x28, 0x90, 0x43, 0xd0, 0x3e, 0x77, 0x59,
|
|
||||||
0x80, 0x8c, 0x0c, 0x5d, 0x84, 0x21, 0xe7, 0x02, 0x94, 0x1c, 0x42, 0x29,
|
|
||||||
0x57, 0x3d, 0x6f, 0x16, 0xa0, 0x6d, 0x00, 0x81, 0xcb, 0xec, 0xe1, 0x7e,
|
|
||||||
0x61, 0x6f, 0xc6, 0xac, 0xa7, 0x73, 0xfb, 0xae, 0xc8, 0x65, 0x01, 0x6c,
|
|
||||||
0xb8, 0xb8, 0x23, 0x71, 0x47, 0xf0, 0x13, 0x11, 0xf2, 0x89, 0x89, 0x3e,
|
|
||||||
0x07, 0xd4, 0x5f, 0x41, 0x4c, 0x88, 0x80, 0xfc, 0xaa, 0x14, 0x07, 0x88,
|
|
||||||
0x89, 0x43, 0x28, 0x07, 0x42, 0x5d, 0x01, 0x88, 0x95, 0xb2, 0xc9, 0x00,
|
|
||||||
0xd2, 0xed, 0x01, 0xa4, 0xad, 0x82, 0x38, 0x84, 0xe8, 0xab, 0x3f, 0x74,
|
|
||||||
0x10, 0x0c, 0x59, 0x0e, 0x21, 0xc5, 0xb5, 0x02, 0xa4, 0xde, 0x3a, 0x06,
|
|
||||||
0x41, 0x7e, 0x29, 0x47, 0x72, 0x0b, 0x42, 0x22, 0x25, 0x7c, 0x51, 0x00,
|
|
||||||
0x89, 0x3c, 0x55, 0x9c, 0xb7, 0x23, 0x14, 0xf3, 0xd5, 0x82, 0x9c, 0x9e,
|
|
||||||
0x87, 0x12, 0x73, 0x1f, 0x87, 0xf0, 0x67, 0xc2, 0x01, 0x28, 0x75, 0x6b,
|
|
||||||
0x2e, 0x8e, 0x3d, 0x84, 0x7d, 0x8d, 0x68, 0x0b, 0x10, 0xf8, 0x6b, 0xdb,
|
|
||||||
0x00, 0xf8, 0x64, 0xbf, 0x12, 0xe6, 0xed, 0x20, 0x8d, 0x0a, 0xe0, 0x5f,
|
|
||||||
0xe2, 0xb8, 0x14, 0x87, 0x68, 0x2a, 0x80, 0x1f, 0xff, 0x6d, 0x07, 0x7d,
|
|
||||||
0xff, 0x3d, 0x7f, 0x03, 0x93, 0xca, 0x91, 0xa9, 0x89, 0x2a, 0x2e, 0xd2,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
|
|
||||||
},
|
|
||||||
"tango-icon-theme-0.8.90_16x16_x-office-spreadsheet.png": []byte{
|
|
||||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
|
||||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
|
||||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
|
||||||
0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
|
|
||||||
0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00,
|
|
||||||
0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18,
|
|
||||||
0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x04, 0x16,
|
|
||||||
0x14, 0x0d, 0x09, 0xd9, 0x88, 0x44, 0xfa, 0x00, 0x00, 0x02, 0x4d, 0x49,
|
|
||||||
0x44, 0x41, 0x54, 0x38, 0xcb, 0x95, 0x92, 0xdf, 0x4b, 0x53, 0x61, 0x18,
|
|
||||||
0xc7, 0x3f, 0x67, 0x9b, 0x6e, 0x7a, 0xd6, 0xfc, 0x55, 0xe0, 0x59, 0x8a,
|
|
||||||
0x95, 0x71, 0x08, 0x52, 0x21, 0x91, 0x2c, 0x8a, 0x0a, 0x94, 0x11, 0x14,
|
|
||||||
0x78, 0x21, 0x99, 0x14, 0x81, 0xdd, 0x48, 0x7f, 0x45, 0x63, 0x5d, 0x75,
|
|
||||||
0x1b, 0x34, 0xd0, 0x9b, 0x52, 0x83, 0x0a, 0xad, 0x0b, 0x43, 0x72, 0xd0,
|
|
||||||
0x85, 0x14, 0x14, 0x68, 0x77, 0x39, 0xcd, 0x6c, 0x94, 0x0c, 0xf4, 0x48,
|
|
||||||
0x4d, 0x5b, 0x5b, 0x4b, 0xcf, 0x39, 0x3b, 0xef, 0xe9, 0x62, 0x3f, 0xec,
|
|
||||||
0xd7, 0x2e, 0x7c, 0xae, 0xbe, 0x2f, 0xef, 0xf3, 0xfd, 0xbc, 0xdf, 0xf7,
|
|
||||||
0x7d, 0x5e, 0x69, 0x78, 0x78, 0xf8, 0xc9, 0xfa, 0xfa, 0x7a, 0x2f, 0xbb,
|
|
||||||
0xab, 0xcb, 0xc1, 0x60, 0x70, 0x1c, 0x80, 0x50, 0x28, 0x64, 0xef, 0xb6,
|
|
||||||
0x42, 0xa1, 0x90, 0x5d, 0x20, 0xb9, 0x0a, 0x22, 0x12, 0x89, 0xe4, 0x95,
|
|
||||||
0x84, 0xa6, 0x69, 0xf8, 0xfd, 0x0a, 0x00, 0x9a, 0xa6, 0xa1, 0x28, 0xfe,
|
|
||||||
0xbc, 0x5e, 0x63, 0x60, 0x60, 0xe0, 0x8f, 0x28, 0x45, 0x80, 0xa6, 0x69,
|
|
||||||
0x48, 0x52, 0x0e, 0x20, 0x49, 0xb9, 0xf5, 0xce, 0xde, 0x5a, 0xc9, 0xbb,
|
|
||||||
0x14, 0x01, 0x8a, 0x5f, 0xc1, 0x2b, 0x7b, 0x01, 0x88, 0xc5, 0x62, 0xf4,
|
|
||||||
0xf4, 0xf4, 0x00, 0x10, 0x8d, 0x46, 0x69, 0x69, 0x6d, 0x41, 0xb2, 0x25,
|
|
||||||
0xe6, 0xa3, 0xf3, 0xa5, 0x01, 0x86, 0x6e, 0x90, 0x21, 0x83, 0x84, 0x04,
|
|
||||||
0x40, 0x2a, 0x95, 0x22, 0x2f, 0x49, 0x7f, 0x4f, 0x91, 0x8f, 0x57, 0x1a,
|
|
||||||
0xe0, 0x71, 0xbb, 0x91, 0xbd, 0x5e, 0x0a, 0xaf, 0xe3, 0xf3, 0x55, 0x15,
|
|
||||||
0xfc, 0xf8, 0xaa, 0x76, 0x74, 0x49, 0xc0, 0xb6, 0xae, 0xe7, 0x4f, 0xcc,
|
|
||||||
0xb5, 0x7e, 0x8c, 0x3c, 0x67, 0xf5, 0xee, 0x1d, 0xb6, 0x16, 0x16, 0x89,
|
|
||||||
0xa7, 0x33, 0xb9, 0x26, 0xb9, 0x82, 0xc9, 0xb6, 0x56, 0xbc, 0x6d, 0xed,
|
|
||||||
0xff, 0x49, 0xe0, 0xf1, 0x20, 0xcb, 0x32, 0x00, 0xf6, 0xe8, 0x3d, 0x3e,
|
|
||||||
0xcd, 0xcd, 0xd1, 0x74, 0xe5, 0x22, 0x65, 0x9d, 0x2a, 0xc2, 0x21, 0x91,
|
|
||||||
0x15, 0x02, 0xc3, 0x14, 0x48, 0x0e, 0x0f, 0x4d, 0xcf, 0xa6, 0x78, 0x74,
|
|
||||||
0xbc, 0xe3, 0x65, 0xff, 0xec, 0xdb, 0xfe, 0x22, 0x40, 0xd7, 0x75, 0x00,
|
|
||||||
0x36, 0x1e, 0x8c, 0x51, 0xb3, 0xb2, 0x4c, 0xc3, 0x8d, 0x3e, 0xb2, 0xe9,
|
|
||||||
0x24, 0xc9, 0xf8, 0x2a, 0xa6, 0x10, 0x18, 0x96, 0x8d, 0xb3, 0xaa, 0x16,
|
|
||||||
0x53, 0x08, 0xac, 0x4e, 0x15, 0xe7, 0xd2, 0xea, 0x99, 0x11, 0xf5, 0xf0,
|
|
||||||
0xed, 0x22, 0xc0, 0xed, 0x76, 0x23, 0xcb, 0x32, 0x89, 0xc8, 0x34, 0xfb,
|
|
||||||
0xaf, 0x9e, 0xe7, 0x47, 0x3c, 0x56, 0x34, 0x9a, 0x42, 0xf0, 0xa1, 0xfe,
|
|
||||||
0x10, 0x9b, 0x86, 0x0b, 0x53, 0x64, 0x31, 0x24, 0x0b, 0xef, 0xb1, 0x7a,
|
|
||||||
0xd4, 0xa7, 0x93, 0x7d, 0xff, 0x24, 0xb0, 0x37, 0xbf, 0x61, 0x19, 0x5b,
|
|
||||||
0xe8, 0xd6, 0x8e, 0x59, 0x52, 0xca, 0xd9, 0xd3, 0xe1, 0x26, 0xfc, 0xb5,
|
|
||||||
0x0b, 0xc3, 0xd4, 0x51, 0x6b, 0xbd, 0x08, 0xcb, 0xe4, 0xe8, 0xe8, 0x43,
|
|
||||||
0x8f, 0xe3, 0xef, 0x04, 0x66, 0x75, 0x0d, 0xce, 0x7d, 0x0d, 0xe0, 0xab,
|
|
||||||
0x41, 0x17, 0x16, 0xba, 0x25, 0x70, 0xaa, 0x95, 0x34, 0x37, 0xa7, 0xa9,
|
|
||||||
0xcf, 0xae, 0x71, 0xb2, 0x71, 0x2f, 0x5f, 0x52, 0x29, 0x7c, 0x2b, 0xef,
|
|
||||||
0xc9, 0x78, 0x3c, 0xdb, 0xc5, 0x04, 0x81, 0x40, 0x20, 0x37, 0x8d, 0xc1,
|
|
||||||
0x41, 0xde, 0xdd, 0x1f, 0xe3, 0xe0, 0xf5, 0x5e, 0xea, 0x0e, 0x1c, 0xc1,
|
|
||||||
0x76, 0xb9, 0xa8, 0x3e, 0x5d, 0x87, 0xa8, 0x70, 0x10, 0xec, 0x90, 0x78,
|
|
||||||
0xfc, 0x39, 0x4d, 0x63, 0x7c, 0x91, 0xf6, 0xc9, 0x09, 0x2a, 0x55, 0x75,
|
|
||||||
0x5c, 0x0a, 0x87, 0xc3, 0x53, 0x89, 0x44, 0xe2, 0xc2, 0xef, 0xb3, 0xad,
|
|
||||||
0x9d, 0x99, 0x41, 0x7e, 0xf3, 0x1a, 0xf3, 0xdc, 0x09, 0xca, 0x1a, 0xaa,
|
|
||||||
0xf1, 0x9c, 0xb5, 0xd1, 0x0d, 0x41, 0x66, 0xc3, 0x64, 0x7a, 0x4a, 0xd0,
|
|
||||||
0x33, 0xfb, 0x8a, 0x0a, 0x55, 0x7d, 0x71, 0x6d, 0x61, 0x21, 0x50, 0xea,
|
|
||||||
0x7f, 0x30, 0xd2, 0xdd, 0x7d, 0x49, 0x5f, 0x5a, 0xba, 0xe9, 0x4e, 0x26,
|
|
||||||
0x55, 0xe7, 0xcf, 0x4c, 0xb9, 0x6d, 0x83, 0x90, 0x65, 0xc3, 0xa5, 0x28,
|
|
||||||
0xcb, 0x07, 0xbb, 0xba, 0x6e, 0x9d, 0x1a, 0x1a, 0x9a, 0x00, 0xf8, 0x05,
|
|
||||||
0xf4, 0xf5, 0x23, 0xe9, 0x30, 0xeb, 0x2d, 0xf9, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
|
|
||||||
},
|
|
||||||
"tango-icon-theme-0.8.90_32x32_x-office-spreadsheet.png": []byte{
|
|
||||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
|
||||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20,
|
|
||||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x00,
|
|
||||||
0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64,
|
|
||||||
0x88, 0x00, 0x00, 0x05, 0xa5, 0x49, 0x44, 0x41, 0x54, 0x58, 0x85, 0xe5,
|
|
||||||
0x97, 0xcd, 0x6b, 0x54, 0x57, 0x18, 0xc6, 0x7f, 0xe7, 0xde, 0x3b, 0x93,
|
|
||||||
0x51, 0x67, 0x92, 0x8c, 0x66, 0x32, 0x6a, 0x26, 0x4d, 0x94, 0x18, 0x27,
|
|
||||||
0xa9, 0x50, 0xbf, 0x5a, 0x2d, 0x94, 0x76, 0xd1, 0x85, 0x05, 0x41, 0x8b,
|
|
||||||
0x60, 0x75, 0x53, 0x70, 0x21, 0x0a, 0x55, 0xba, 0x71, 0x51, 0xa8, 0xb4,
|
|
||||||
0x7f, 0x40, 0xd7, 0xd5, 0x45, 0xa5, 0x90, 0x6e, 0x5a, 0xa8, 0x20, 0x34,
|
|
||||||
0x15, 0x0a, 0x6d, 0xa1, 0x25, 0x58, 0x2c, 0xa4, 0xd6, 0x42, 0x4d, 0xa2,
|
|
||||||
0xf9, 0x20, 0xc9, 0xc4, 0x64, 0x3e, 0x4c, 0xa2, 0x13, 0x93, 0xcc, 0xdc,
|
|
||||||
0xef, 0x2e, 0x32, 0xf7, 0xf4, 0xde, 0xc9, 0x97, 0x59, 0x74, 0xd5, 0x03,
|
|
||||||
0x87, 0x7b, 0xde, 0xf3, 0x9e, 0x73, 0xde, 0xe7, 0x3c, 0xef, 0xf3, 0xde,
|
|
||||||
0xb9, 0x03, 0xff, 0xf7, 0x26, 0xaa, 0x27, 0xae, 0x5d, 0xbb, 0x76, 0x4a,
|
|
||||||
0xd3, 0xb4, 0x2e, 0x20, 0xa6, 0xaa, 0x2a, 0x8a, 0xa2, 0xe0, 0x38, 0x0e,
|
|
||||||
0xb6, 0x6d, 0xcb, 0x6e, 0x59, 0x96, 0x7c, 0xfa, 0xc7, 0x6b, 0xcd, 0x01,
|
|
||||||
0xcf, 0x2d, 0xcb, 0x3a, 0xd7, 0xd5, 0xd5, 0x75, 0xcb, 0x1f, 0x4f, 0x5b,
|
|
||||||
0x86, 0x48, 0x88, 0x2f, 0xcf, 0x9f, 0x3f, 0x1f, 0xab, 0x8c, 0xe5, 0xbc,
|
|
||||||
0xeb, 0xba, 0x81, 0x75, 0x7e, 0xfb, 0x05, 0xc7, 0xb1, 0x4b, 0x97, 0x2e,
|
|
||||||
0x7d, 0x09, 0xac, 0x0d, 0xc0, 0xb6, 0xed, 0x7a, 0x80, 0xd1, 0xd1, 0x51,
|
|
||||||
0x84, 0x10, 0x12, 0x84, 0xff, 0xe9, 0x07, 0xe6, 0x1f, 0xaf, 0x64, 0x7b,
|
|
||||||
0x40, 0x1a, 0x1b, 0x1b, 0x31, 0x0c, 0xa3, 0xbe, 0xda, 0xb7, 0x0c, 0x80,
|
|
||||||
0xeb, 0xba, 0x32, 0xc8, 0x8d, 0x1b, 0x37, 0x48, 0x24, 0x12, 0x81, 0xa0,
|
|
||||||
0xf9, 0x7c, 0x9e, 0x64, 0x32, 0x29, 0xed, 0x42, 0xa1, 0x40, 0x32, 0x99,
|
|
||||||
0x94, 0xfb, 0x0b, 0x85, 0x02, 0x8d, 0x8d, 0x8d, 0xd2, 0x9e, 0x9e, 0x9e,
|
|
||||||
0xe6, 0xc2, 0x85, 0x0b, 0xcb, 0x40, 0xad, 0x0a, 0xc0, 0x71, 0x1c, 0x79,
|
|
||||||
0x93, 0x54, 0x2a, 0x45, 0x2a, 0x95, 0x0a, 0xdc, 0xaa, 0xa6, 0xa6, 0x26,
|
|
||||||
0x30, 0x17, 0x89, 0x44, 0x48, 0xa5, 0x52, 0x72, 0x8f, 0xdf, 0xf6, 0xfc,
|
|
||||||
0xde, 0xda, 0xea, 0x34, 0xae, 0x0a, 0xc0, 0x63, 0xc1, 0x3b, 0xb4, 0xfa,
|
|
||||||
0x59, 0x9d, 0x9a, 0x95, 0x68, 0xf7, 0xb7, 0xb5, 0xfc, 0x2b, 0x69, 0x40,
|
|
||||||
0x8e, 0xa7, 0xa6, 0xa6, 0xb0, 0x6d, 0x3b, 0x10, 0xac, 0x50, 0x28, 0x04,
|
|
||||||
0xd6, 0xe4, 0xf3, 0x79, 0x4c, 0xd3, 0x94, 0xfe, 0x7c, 0x3e, 0xef, 0xa9,
|
|
||||||
0x5e, 0xfa, 0x37, 0xcc, 0x80, 0x77, 0xd8, 0xce, 0x9d, 0x3b, 0x03, 0xf4,
|
|
||||||
0x0a, 0x21, 0xd0, 0x34, 0x8d, 0xe3, 0xc7, 0x8f, 0xcb, 0x43, 0x47, 0x46,
|
|
||||||
0x46, 0x68, 0x6b, 0x6b, 0x93, 0x6b, 0x86, 0x87, 0x87, 0xa5, 0x0d, 0x30,
|
|
||||||
0x3c, 0x3c, 0x8c, 0xa2, 0x28, 0x2f, 0x0e, 0xc0, 0xbb, 0x9d, 0x10, 0x82,
|
|
||||||
0x6c, 0x36, 0x8b, 0xe3, 0x38, 0xcb, 0x44, 0x38, 0x34, 0x34, 0x24, 0xd7,
|
|
||||||
0x4f, 0x4c, 0x4c, 0x04, 0x40, 0x67, 0x32, 0x19, 0x69, 0x03, 0x64, 0x32,
|
|
||||||
0x19, 0xd2, 0xe9, 0xf4, 0xc6, 0x01, 0x00, 0xec, 0xd8, 0xb1, 0x83, 0xe6,
|
|
||||||
0xe6, 0xe6, 0x00, 0x00, 0x55, 0x55, 0xd9, 0xbb, 0x77, 0xaf, 0xb4, 0x43,
|
|
||||||
0xa1, 0x50, 0x80, 0x01, 0x4d, 0xd3, 0x02, 0x0c, 0x68, 0x9a, 0xb6, 0xb1,
|
|
||||||
0x14, 0xd8, 0xb6, 0x2d, 0x45, 0x98, 0xcb, 0xe5, 0x96, 0x6d, 0x28, 0x14,
|
|
||||||
0x0a, 0x0c, 0x0e, 0x0e, 0xca, 0x80, 0xff, 0x19, 0x03, 0x9e, 0x06, 0x9a,
|
|
||||||
0x9b, 0x9b, 0xa5, 0x4f, 0x08, 0x41, 0x28, 0x14, 0x92, 0x07, 0x7a, 0xb6,
|
|
||||||
0x9f, 0x01, 0x55, 0x55, 0xd9, 0xb3, 0x67, 0x8f, 0xdc, 0xa3, 0xaa, 0xaa,
|
|
||||||
0x64, 0xc0, 0x0f, 0x6c, 0x5d, 0x00, 0x80, 0xd4, 0x80, 0x77, 0xb8, 0xa7,
|
|
||||||
0xf2, 0x47, 0x8f, 0x1e, 0x49, 0x3b, 0x93, 0xc9, 0x04, 0x40, 0xaf, 0xc4,
|
|
||||||
0x40, 0x47, 0x47, 0xc7, 0xc6, 0x18, 0xf0, 0x52, 0xe0, 0x55, 0x81, 0xbf,
|
|
||||||
0xf6, 0x55, 0x55, 0x25, 0x9d, 0x4e, 0x07, 0xec, 0xf6, 0xf6, 0x76, 0x09,
|
|
||||||
0x40, 0xd3, 0xb4, 0x00, 0x03, 0x7e, 0x0d, 0xbc, 0x10, 0x03, 0xfe, 0x1a,
|
|
||||||
0xf6, 0xbf, 0x07, 0xbc, 0x9e, 0xcb, 0xe5, 0x02, 0x1a, 0x18, 0x1f, 0x1b,
|
|
||||||
0x23, 0x7b, 0xef, 0x1e, 0xf9, 0xfb, 0xf7, 0x79, 0x36, 0x32, 0xc2, 0x7c,
|
|
||||||
0x2e, 0x47, 0x44, 0x51, 0x70, 0x34, 0x8d, 0xf0, 0xd6, 0xad, 0x28, 0x89,
|
|
||||||
0x04, 0xe1, 0x73, 0xe7, 0xe8, 0x7c, 0xfb, 0xed, 0x8d, 0xa5, 0xc0, 0xaf,
|
|
||||||
0x81, 0xea, 0x2a, 0x48, 0xa7, 0xd3, 0xd8, 0xa6, 0x49, 0xef, 0x57, 0x5f,
|
|
||||||
0x31, 0x70, 0xfd, 0x3a, 0xfb, 0x1a, 0x1a, 0x78, 0x6b, 0xd7, 0x2e, 0x5a,
|
|
||||||
0x3a, 0x3b, 0x89, 0x1d, 0x3a, 0x84, 0xeb, 0x38, 0x38, 0xa6, 0x49, 0x71,
|
|
||||||
0x6e, 0x8e, 0xb1, 0x5c, 0x8e, 0xbe, 0x2b, 0x57, 0xe8, 0x2e, 0x97, 0x89,
|
|
||||||
0xd4, 0xd5, 0x71, 0x1a, 0xc2, 0x37, 0xc1, 0x58, 0x17, 0x80, 0xc7, 0xc0,
|
|
||||||
0x4a, 0xef, 0x81, 0x3f, 0x7b, 0x7a, 0xb8, 0xf3, 0xc9, 0x27, 0x1c, 0x88,
|
|
||||||
0x46, 0xb9, 0x7a, 0xf2, 0x24, 0x9b, 0xc3, 0x61, 0x60, 0x29, 0xc7, 0xb6,
|
|
||||||
0x61, 0xe0, 0x98, 0x26, 0x8e, 0x69, 0x12, 0x11, 0x82, 0xf6, 0x86, 0x06,
|
|
||||||
0xda, 0xea, 0xea, 0x58, 0x58, 0x5c, 0xe4, 0xa7, 0x81, 0x01, 0xee, 0xc2,
|
|
||||||
0x6f, 0x1f, 0xc0, 0xa9, 0xeb, 0x30, 0xb1, 0x2a, 0x00, 0x4f, 0x03, 0x4d,
|
|
||||||
0x4d, 0x4d, 0x92, 0x01, 0x8f, 0x15, 0x61, 0x9a, 0xdc, 0xbd, 0x7a, 0x95,
|
|
||||||
0x77, 0x3b, 0x3b, 0x39, 0xdc, 0xd6, 0x06, 0x95, 0x94, 0x39, 0xa6, 0x89,
|
|
||||||
0x6d, 0x59, 0x32, 0xb8, 0x63, 0x9a, 0xd8, 0xbe, 0x71, 0xc8, 0xb2, 0x78,
|
|
||||||
0xa7, 0xb5, 0x95, 0x44, 0x28, 0x74, 0xf8, 0xbb, 0xe1, 0xe1, 0x1f, 0x2f,
|
|
||||||
0xc0, 0xd1, 0x2f, 0xa0, 0xb8, 0xae, 0x06, 0x3c, 0x06, 0x3c, 0x00, 0x43,
|
|
||||||
0x37, 0x6f, 0x72, 0x28, 0x1e, 0xe7, 0x70, 0x47, 0x07, 0xe8, 0x3a, 0x8e,
|
|
||||||
0x6d, 0xaf, 0x18, 0x30, 0x30, 0xe7, 0x03, 0xb6, 0x2f, 0x1e, 0x67, 0x68,
|
|
||||||
0xdb, 0xb6, 0x74, 0xff, 0xcc, 0xcc, 0x47, 0xc0, 0xc7, 0x6b, 0xa6, 0xa0,
|
|
||||||
0x5a, 0x03, 0x42, 0x08, 0xfa, 0x1f, 0x3e, 0xe4, 0xf5, 0xb3, 0x67, 0x71,
|
|
||||||
0x2d, 0x0b, 0xbb, 0x54, 0x5a, 0x37, 0xe0, 0x32, 0x50, 0xae, 0xcb, 0x81,
|
|
||||||
0x44, 0x82, 0xbe, 0x99, 0x99, 0xb3, 0xab, 0x02, 0xf0, 0xea, 0x75, 0x6a,
|
|
||||||
0x6a, 0x4a, 0x8e, 0x3d, 0x16, 0xf4, 0xe9, 0x69, 0x6a, 0x6b, 0x6b, 0xb1,
|
|
||||||
0x9e, 0x3e, 0xc5, 0x29, 0x95, 0xfe, 0x0d, 0x50, 0x09, 0x6a, 0x9b, 0x26,
|
|
||||||
0xe3, 0x6f, 0xec, 0xe7, 0xdb, 0xf2, 0x6b, 0xe0, 0xba, 0x98, 0x86, 0x81,
|
|
||||||
0x6e, 0x18, 0x58, 0x86, 0x81, 0x6e, 0x98, 0x38, 0xb6, 0x49, 0xab, 0x53,
|
|
||||||
0x44, 0x3c, 0xfc, 0xf4, 0x25, 0x40, 0x59, 0x93, 0x01, 0x4f, 0x03, 0x32,
|
|
||||||
0xff, 0x42, 0x70, 0xdf, 0x75, 0x79, 0x92, 0xcd, 0xb2, 0x79, 0xcb, 0x16,
|
|
||||||
0xec, 0x72, 0x79, 0xd9, 0x0d, 0x6d, 0xd7, 0xa6, 0xfc, 0x7e, 0x03, 0xdb,
|
|
||||||
0xba, 0x8b, 0xfc, 0xb9, 0x98, 0x46, 0xd7, 0x0d, 0x0c, 0x43, 0x47, 0xd7,
|
|
||||||
0x0d, 0x74, 0xdd, 0x20, 0xa2, 0xb9, 0x44, 0x67, 0x17, 0x01, 0x54, 0x20,
|
|
||||||
0xba, 0xaa, 0x06, 0x84, 0x10, 0x4c, 0x4e, 0x4e, 0x06, 0xde, 0x84, 0x00,
|
|
||||||
0x4a, 0x2c, 0x46, 0x6f, 0x4f, 0x0f, 0xc9, 0x33, 0x67, 0x50, 0x66, 0x66,
|
|
||||||
0xb0, 0xab, 0x58, 0x28, 0xbe, 0x12, 0x27, 0x17, 0xce, 0xb2, 0x6b, 0xff,
|
|
||||||
0xdf, 0xf4, 0xf6, 0xec, 0xc2, 0xb2, 0xec, 0x4a, 0xb7, 0x08, 0x6b, 0xd0,
|
|
||||||
0x1e, 0xd1, 0xc9, 0x67, 0xc6, 0x88, 0x43, 0x1e, 0x88, 0x28, 0x6b, 0xa5,
|
|
||||||
0xa0, 0xa9, 0xa9, 0x89, 0x96, 0x96, 0x16, 0xd9, 0x5b, 0x5b, 0x5b, 0xa9,
|
|
||||||
0xdd, 0xb7, 0x8f, 0x81, 0xc9, 0x49, 0xfe, 0xf8, 0xe1, 0x07, 0x4a, 0xc9,
|
|
||||||
0x24, 0x6e, 0x32, 0xb9, 0xf4, 0xe9, 0x5d, 0x2e, 0x63, 0x95, 0x4a, 0x64,
|
|
||||||
0x0e, 0x0b, 0xa6, 0xf5, 0x31, 0x1e, 0xef, 0x78, 0xcc, 0x2b, 0xa1, 0xaf,
|
|
||||||
0x97, 0x2e, 0xe4, 0xda, 0x6c, 0x8f, 0x6f, 0xe2, 0xb5, 0x58, 0x99, 0xc1,
|
|
||||||
0xc7, 0x05, 0xe2, 0x7d, 0x3f, 0x53, 0x82, 0x3b, 0x80, 0xbd, 0x6a, 0x0a,
|
|
||||||
0x5c, 0xd7, 0x5d, 0x91, 0x01, 0xf7, 0xe0, 0x41, 0x9e, 0xf7, 0xf5, 0x71,
|
|
||||||
0x6f, 0x74, 0x94, 0x85, 0x62, 0x91, 0x9d, 0xbb, 0x77, 0xb3, 0xbd, 0xad,
|
|
||||||
0x8d, 0x70, 0xa9, 0x84, 0x3d, 0x37, 0x4b, 0xf6, 0x48, 0x84, 0xb2, 0x55,
|
|
||||||
0xc4, 0xb2, 0x75, 0xa2, 0x6f, 0x3d, 0xe0, 0xe5, 0xde, 0xd3, 0xd4, 0x1b,
|
|
||||||
0x30, 0x3d, 0xd8, 0x47, 0xcf, 0xa2, 0xc6, 0x9e, 0xde, 0x6e, 0xc8, 0x8f,
|
|
||||||
0x3c, 0xfb, 0x0b, 0x3e, 0x07, 0x16, 0xd6, 0x2c, 0xc3, 0x8b, 0x17, 0x2f,
|
|
||||||
0x06, 0x2a, 0x40, 0x08, 0x81, 0x7d, 0xe2, 0x04, 0x03, 0x6f, 0xbe, 0xc9,
|
|
||||||
0xed, 0xcb, 0x97, 0x79, 0x9e, 0xcf, 0xb3, 0xd7, 0x30, 0x98, 0xe8, 0xef,
|
|
||||||
0x67, 0x53, 0x34, 0x8a, 0x95, 0x8e, 0x32, 0xf7, 0x57, 0x8c, 0x90, 0x02,
|
|
||||||
0xb8, 0xb0, 0x50, 0xd6, 0x31, 0xfe, 0xee, 0xe2, 0xfb, 0x85, 0xa3, 0x34,
|
|
||||||
0x17, 0xb3, 0xec, 0xef, 0xbd, 0x85, 0x9e, 0x1b, 0x99, 0x7e, 0x00, 0x1f,
|
|
||||||
0x3e, 0x80, 0x7e, 0xa0, 0x5c, 0x0d, 0x20, 0xa6, 0x28, 0xca, 0x9c, 0xeb,
|
|
||||||
0xba, 0xb5, 0xf5, 0xf5, 0xff, 0x7e, 0xc2, 0x57, 0x7f, 0x54, 0x1e, 0x3a,
|
|
||||||
0x76, 0x8c, 0x86, 0xdb, 0xb7, 0xf9, 0xe5, 0xb3, 0xcf, 0xf8, 0xbd, 0xbb,
|
|
||||||
0x9b, 0x58, 0x28, 0x44, 0x52, 0xd7, 0x51, 0x1f, 0x2f, 0x30, 0x3e, 0xfe,
|
|
||||||
0x0c, 0x67, 0x93, 0xc0, 0x71, 0x5d, 0x42, 0x33, 0x16, 0x4a, 0x5f, 0x3f,
|
|
||||||
0xaf, 0x3e, 0xfc, 0x15, 0xa7, 0x58, 0xa0, 0xb0, 0x75, 0xab, 0x75, 0x07,
|
|
||||||
0x2e, 0x66, 0xa1, 0x17, 0x78, 0x02, 0xc1, 0xbf, 0x66, 0x31, 0x20, 0x71,
|
|
||||||
0xe4, 0xc8, 0x91, 0xf7, 0x5a, 0x5a, 0x5a, 0x3e, 0x05, 0x36, 0x55, 0xb3,
|
|
||||||
0xe3, 0x6f, 0xae, 0xeb, 0x62, 0x18, 0x06, 0xd6, 0xfc, 0x3c, 0x35, 0x93,
|
|
||||||
0x93, 0x44, 0x66, 0x67, 0xa9, 0x99, 0x9f, 0x47, 0x33, 0x0c, 0x14, 0xcb,
|
|
||||||
0xc2, 0xd1, 0x34, 0xcc, 0x50, 0x08, 0x3d, 0x1a, 0xa5, 0x14, 0x8f, 0x53,
|
|
||||||
0xda, 0xbe, 0xdd, 0x18, 0xcd, 0xe5, 0xbe, 0x18, 0x1c, 0x1c, 0xfc, 0x06,
|
|
||||||
0x18, 0x07, 0xb2, 0x80, 0xe3, 0x07, 0x10, 0x06, 0x92, 0xc0, 0x36, 0xa0,
|
|
||||||
0x1e, 0xa8, 0x61, 0xa9, 0x54, 0xd6, 0x6b, 0x0a, 0x10, 0x01, 0x36, 0x57,
|
|
||||||
0xf6, 0x68, 0x95, 0x39, 0x00, 0x87, 0xa5, 0x1f, 0x9e, 0xa7, 0x80, 0x0e,
|
|
||||||
0x3c, 0x03, 0x66, 0x59, 0xfa, 0x1d, 0x98, 0xaf, 0x66, 0xc0, 0x6b, 0x35,
|
|
||||||
0x95, 0x03, 0xc3, 0xab, 0xf8, 0xd7, 0x6b, 0xa2, 0xd2, 0xbd, 0xaf, 0x0f,
|
|
||||||
0xb7, 0x02, 0xc4, 0xac, 0x80, 0xd0, 0x7d, 0x3e, 0xfe, 0x01, 0x9f, 0x1e,
|
|
||||||
0x98, 0x64, 0x1e, 0x77, 0xb2, 0x47, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
|
|
||||||
0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
all:
|
|
||||||
go test --race
|
|
|
@ -1,21 +0,0 @@
|
||||||
package ex
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
type Item struct{}
|
|
||||||
|
|
||||||
func TestAppend(t *testing.T) {
|
|
||||||
var list []Item
|
|
||||||
|
|
||||||
n := 2
|
|
||||||
wg := sync.WaitGroup{}
|
|
||||||
wg.Add(n)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
list = append(list, Item{})
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./test1
|
|
|
@ -1 +0,0 @@
|
||||||
this eventually crashes (GTK / Linux)
|
|
35
test1/crash1
35
test1/crash1
|
@ -1,35 +0,0 @@
|
||||||
2019/05/17 10:59:15 name= Test 128
|
|
||||||
2019/05/17 10:59:15 sleep
|
|
||||||
2019/05/17 10:59:15 sleep
|
|
||||||
2019/05/17 10:59:15 name= Test 129
|
|
||||||
2019/05/17 10:59:16 sleep
|
|
||||||
fatal error: unexpected signal during runtime execution
|
|
||||||
[signal SIGSEGV: segmentation violation code=0x1 addr=0x7f8c000000b8 pc=0x7f8cbfb2f8e5]
|
|
||||||
|
|
||||||
runtime stack:
|
|
||||||
runtime.throw(0x50c4b8, 0x2a)
|
|
||||||
/usr/lib/go-1.11/src/runtime/panic.go:608 +0x72
|
|
||||||
runtime.sigpanic()
|
|
||||||
/usr/lib/go-1.11/src/runtime/signal_unix.go:374 +0x2f2
|
|
||||||
|
|
||||||
goroutine 19 [syscall]:
|
|
||||||
runtime.cgocall(0x4b5490, 0xc00004df78, 0xc0000ac048)
|
|
||||||
/usr/lib/go-1.11/src/runtime/cgocall.go:128 +0x5e fp=0xc00004df48 sp=0xc00004df10 pc=0x41688e
|
|
||||||
github.com/andlabs/ui._Cfunc_uiMain()
|
|
||||||
_cgo_gotypes.go:2518 +0x41 fp=0xc00004df78 sp=0xc00004df48 pc=0x4a9711
|
|
||||||
github.com/andlabs/ui.Main(0x50d890, 0xc00003a701, 0xc0000842c0)
|
|
||||||
/home/jcarr/go/src/github.com/andlabs/ui/main.go:41 +0xfd fp=0xc00004dfc8 sp=0xc00004df78 pc=0x4ad6cd
|
|
||||||
runtime.goexit()
|
|
||||||
/usr/lib/go-1.11/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc00004dfd0 sp=0xc00004dfc8 pc=0x466461
|
|
||||||
created by main.main
|
|
||||||
/home/jcarr/go/src/git.wit.com/wit/cloud-control-panel/example-splash/main.go:68 +0x53
|
|
||||||
|
|
||||||
goroutine 1 [sleep, locked to thread]:
|
|
||||||
time.Sleep(0x11e1a300)
|
|
||||||
/usr/lib/go-1.11/src/runtime/time.go:105 +0x14f
|
|
||||||
main.main()
|
|
||||||
/home/jcarr/go/src/git.wit.com/wit/cloud-control-panel/example-splash/main.go:74 +0x74
|
|
||||||
exit status 2
|
|
||||||
make: *** [Makefile:2: run] Error 1
|
|
||||||
jcarr@librem15:~/go/src/git.wit.com/wit/cloud-control-panel/example-splash$ git diff
|
|
||||||
|
|
BIN
test1/main
BIN
test1/main
Binary file not shown.
|
@ -1,93 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
import "log"
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
var mainwin *ui.Window
|
|
||||||
var hbox *ui.Box
|
|
||||||
var vbox *ui.Box
|
|
||||||
var newgroup *ui.Group
|
|
||||||
|
|
||||||
func makeSplashPage() ui.Control {
|
|
||||||
hbox = ui.NewHorizontalBox()
|
|
||||||
hbox.SetPadded(true)
|
|
||||||
|
|
||||||
group := ui.NewGroup("Numbers")
|
|
||||||
group.SetMargined(true)
|
|
||||||
hbox.Append(group, true)
|
|
||||||
|
|
||||||
vbox = ui.NewVerticalBox()
|
|
||||||
vbox.SetPadded(true)
|
|
||||||
group.SetChild(vbox)
|
|
||||||
|
|
||||||
spinbox := ui.NewSpinbox(47, 100)
|
|
||||||
slider := ui.NewSlider(21, 100)
|
|
||||||
pbar := ui.NewProgressBar()
|
|
||||||
|
|
||||||
spinbox.OnChanged(func(*ui.Spinbox) {
|
|
||||||
slider.SetValue(spinbox.Value())
|
|
||||||
pbar.SetValue(spinbox.Value())
|
|
||||||
})
|
|
||||||
slider.OnChanged(func(*ui.Slider) {
|
|
||||||
spinbox.SetValue(slider.Value())
|
|
||||||
pbar.SetValue(slider.Value())
|
|
||||||
})
|
|
||||||
vbox.Append(spinbox, false)
|
|
||||||
vbox.Append(slider, false)
|
|
||||||
vbox.Append(pbar, false)
|
|
||||||
|
|
||||||
return hbox
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupUI() {
|
|
||||||
mainwin = ui.NewWindow("gui-example1", 300, 200, false)
|
|
||||||
mainwin.OnClosing(func(*ui.Window) bool {
|
|
||||||
ui.Quit()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
ui.OnShouldQuit(func() bool {
|
|
||||||
mainwin.Destroy()
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
tab := ui.NewTab()
|
|
||||||
mainwin.SetChild(tab)
|
|
||||||
mainwin.SetMargined(true)
|
|
||||||
|
|
||||||
tab.Append("WIT Splash", makeSplashPage())
|
|
||||||
tab.SetMargined(0, true)
|
|
||||||
|
|
||||||
mainwin.Show()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
go ui.Main(setupUI)
|
|
||||||
|
|
||||||
// locks up GTK after a while (50 times)
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
count := 0
|
|
||||||
for {
|
|
||||||
time.Sleep(300 * time.Millisecond)
|
|
||||||
log.Println("sleep")
|
|
||||||
|
|
||||||
if (newgroup == nil) {
|
|
||||||
name := "Test " + fmt.Sprintf("%d", count)
|
|
||||||
log.Println("name=",name)
|
|
||||||
newgroup = ui.NewGroup(name)
|
|
||||||
newgroup.SetMargined(true)
|
|
||||||
hbox.Append(newgroup, false)
|
|
||||||
// newgroup = append(newgroup, group)
|
|
||||||
count += 1
|
|
||||||
} else {
|
|
||||||
hbox.Delete(1)
|
|
||||||
// newgroup.Delete()
|
|
||||||
// can't destroy when there is a parent
|
|
||||||
newgroup.Destroy()
|
|
||||||
newgroup = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./test2
|
|
|
@ -1,44 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
/*
|
|
||||||
This simply parses the command line arguments using the default golang
|
|
||||||
package called 'flag'. This can be used as a simple template to parse
|
|
||||||
command line arguments in other programs.
|
|
||||||
|
|
||||||
It puts everything in the 'config' package which I think is a good
|
|
||||||
wrapper around the 'flags' package and doesn't need a whole mess of
|
|
||||||
global variables
|
|
||||||
*/
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
import "strings"
|
|
||||||
import "io/ioutil"
|
|
||||||
|
|
||||||
import "github.com/golang/protobuf/jsonpb"
|
|
||||||
import pb "git.wit.com/wit/witProtobuf"
|
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
// TEST UNMARSHAL JSON TO PROTOBUF
|
|
||||||
// This is known to crash unless done exactly like this
|
|
||||||
// with strings.NewReader & 'sets'
|
|
||||||
func loadDefaultConfig(a string) pb.Config {
|
|
||||||
sets := pb.Config{}
|
|
||||||
|
|
||||||
b, err := ioutil.ReadFile("../resources/cloud-control-panel.json")
|
|
||||||
if err != nil {
|
|
||||||
log.Println("ioutil.ReadFile() ERROR =", err)
|
|
||||||
}
|
|
||||||
// log.Println("ioutil.ReadFile() b =", b)
|
|
||||||
|
|
||||||
err = jsonpb.Unmarshal(strings.NewReader(string(b)), &sets)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("jsonpb.Unmarshal() ERROR =", err)
|
|
||||||
}
|
|
||||||
spew.Dump(sets)
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
loadDefaultConfig("")
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./test3
|
|
|
@ -1,32 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
|
||||||
|
|
||||||
import "git.wit.com/wit/gui"
|
|
||||||
|
|
||||||
func TestAttributedString() *ui.AttributedString {
|
|
||||||
newText := ui.NewAttributedString("")
|
|
||||||
|
|
||||||
gui.AreaAppendText(newText, "Welcome to the Cloud Control Panel\n", ui.TextSize(16), ui.TextColor{0.0, 0.0, 0.8, .8}) // "RGBT"
|
|
||||||
return newText
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// THIS CRASHES IF YOU RUN IT HERE
|
|
||||||
// text := TestAttributedString()
|
|
||||||
// log.Println("text =", text)
|
|
||||||
|
|
||||||
ui.Main(setupUI)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupUI() {
|
|
||||||
// this doesn't crash here
|
|
||||||
text := TestAttributedString()
|
|
||||||
log.Println("text =", text)
|
|
||||||
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./test4
|
|
220
test4/config.go
220
test4/config.go
|
@ -1,220 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
/*
|
|
||||||
This simply parses the command line arguments using the default golang
|
|
||||||
package called 'flag'. This can be used as a simple template to parse
|
|
||||||
command line arguments in other programs.
|
|
||||||
|
|
||||||
It puts everything in a 'config' Protobuf which I think is a good
|
|
||||||
wrapper around the 'flags' package and doesn't need a whole mess of
|
|
||||||
global variables
|
|
||||||
*/
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
import "os"
|
|
||||||
import "os/user"
|
|
||||||
import "flag"
|
|
||||||
import "fmt"
|
|
||||||
import "runtime"
|
|
||||||
import "io/ioutil"
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
import "github.com/golang/protobuf/jsonpb"
|
|
||||||
import pb "git.wit.com/wit/witProtobuf"
|
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
var config *pb.Config
|
|
||||||
|
|
||||||
// This loads the config file and marshals it into the
|
|
||||||
// config protocol buffer definition.
|
|
||||||
// Then it is very easy to pass all the config options
|
|
||||||
// around and the re-write that JSON file when the GUI
|
|
||||||
// exits
|
|
||||||
func loadConfigFile() {
|
|
||||||
// look up the user information
|
|
||||||
user, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
onExit(err)
|
|
||||||
}
|
|
||||||
spew.Dump(user)
|
|
||||||
|
|
||||||
filename := ""
|
|
||||||
// TODO: confirm this is correct for MacOS and Windows
|
|
||||||
if runtime.GOOS == "linux" {
|
|
||||||
log.Println("loadConfigFile() OS: Linux")
|
|
||||||
filename = user.HomeDir + "/.config/cloud-control-panel.json"
|
|
||||||
} else if runtime.GOOS == "windows" {
|
|
||||||
log.Println("loadConfigFile() OS: Windows")
|
|
||||||
filename = user.HomeDir + "\\cloud-control-panel.json"
|
|
||||||
} else {
|
|
||||||
log.Println("loadConfigFile() OS: " + runtime.GOOS)
|
|
||||||
filename = user.HomeDir + "/.cloud-control-panel.json"
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp := loadConfigFromFilename(filename)
|
|
||||||
config = &tmp
|
|
||||||
|
|
||||||
config.Filename = filename
|
|
||||||
}
|
|
||||||
|
|
||||||
var customUsage = func() {
|
|
||||||
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
|
|
||||||
flag.PrintDefaults()
|
|
||||||
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println("EXAMPLES:")
|
|
||||||
fmt.Println("")
|
|
||||||
fmt.Println(os.Args[0] + " --hostname test.hostname.wit.com")
|
|
||||||
fmt.Println("")
|
|
||||||
}
|
|
||||||
var defaultconfig *bool
|
|
||||||
|
|
||||||
func parseFlags() {
|
|
||||||
var hostname string
|
|
||||||
|
|
||||||
// always override the debugging flag from the command line
|
|
||||||
var debug *bool
|
|
||||||
var debugtable *bool
|
|
||||||
|
|
||||||
flag.StringVar (&hostname, "hostname", "localhost", "Your full hostname")
|
|
||||||
|
|
||||||
height := flag.Int ("height", 0, "Height of the Window")
|
|
||||||
width := flag.Int ("width", 0, "Width of the Window")
|
|
||||||
debug = flag.Bool("debug", false, "Enable debugging")
|
|
||||||
defaultconfig = flag.Bool("defaultconfig", false, "Use the default config file")
|
|
||||||
debugtable = flag.Bool("debugtable", false, "Enable GUI table debugging")
|
|
||||||
|
|
||||||
// Set the output if something fails to stdout rather than stderr
|
|
||||||
flag.CommandLine.SetOutput(os.Stdout)
|
|
||||||
|
|
||||||
flag.Usage = customUsage
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if flag.Parsed() {
|
|
||||||
log.Println("flag.Parse() worked")
|
|
||||||
} else {
|
|
||||||
log.Println("flag.Parse() failed")
|
|
||||||
onExit(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*width > 100) {
|
|
||||||
log.Println("ENABLE width =", int32(*width))
|
|
||||||
config.Width = int32(*width)
|
|
||||||
}
|
|
||||||
if (*height > 100) {
|
|
||||||
log.Println("ENABLE height =", int32(*height))
|
|
||||||
config.Height = int32(*height)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostname == "") {
|
|
||||||
config.Hostname = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
// never allow these to be set in the config file
|
|
||||||
config.Debug = *debug
|
|
||||||
config.Debugtable = *debugtable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a Protobuf to JSON
|
|
||||||
func PBtoJSON() string {
|
|
||||||
// this makes a sample protobuf
|
|
||||||
c := pb.MakeDefaultConfig()
|
|
||||||
|
|
||||||
marshaler := &jsonpb.Marshaler{}
|
|
||||||
stuff, _ := marshaler.MarshalToString(c)
|
|
||||||
log.Println(stuff)
|
|
||||||
return stuff
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeToFile(filename string, a string) {
|
|
||||||
f, _ := os.Create(filename)
|
|
||||||
f.WriteString(a)
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveConfig() {
|
|
||||||
filename := config.Filename
|
|
||||||
if (filename == "") {
|
|
||||||
log.Println("NOT SAVING CONFIG FILE")
|
|
||||||
} else {
|
|
||||||
marshaler := &jsonpb.Marshaler{}
|
|
||||||
stuff, _ := marshaler.MarshalToString(config)
|
|
||||||
log.Println(stuff)
|
|
||||||
|
|
||||||
writeToFile(filename, stuff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// will load the default config from within the go binary
|
|
||||||
func loadConfigFromFilename(filename string) pb.Config {
|
|
||||||
sets := pb.Config{}
|
|
||||||
b, err := ioutil.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("ioutil.ReadFile() ERROR =", err)
|
|
||||||
// This probably means this is the first time the user is opening this
|
|
||||||
sets.Errors += 1
|
|
||||||
sets.Crash = "err"
|
|
||||||
sets.Counter = 1
|
|
||||||
sets.Width = 500
|
|
||||||
sets.Height = 500
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
log.Println("ioutil.ReadFile() b =", b)
|
|
||||||
|
|
||||||
err = jsonpb.Unmarshal(strings.NewReader(string(b)), &sets)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("jsonpb.Unmarshal() ERROR =", err)
|
|
||||||
}
|
|
||||||
spew.Dump(sets)
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
|
|
||||||
// will load the default config from within the go binary
|
|
||||||
func loadDefaultConfig() *pb.Config {
|
|
||||||
log.Println("TRY TO LOAD DEFAULT CONFIG")
|
|
||||||
// defaultConfig, _ := packrBox.FindString("protobuf-config.json")
|
|
||||||
b, err := packrBox.FindString("cloud-control-panel.json")
|
|
||||||
log.Println("b =", b)
|
|
||||||
log.Println("err =", err)
|
|
||||||
// var newpb *pb.Config
|
|
||||||
sets := pb.Config{}
|
|
||||||
|
|
||||||
err = jsonpb.Unmarshal(strings.NewReader(string(b)), &sets)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("jsonpb.Unmarshal() ERROR =", err)
|
|
||||||
}
|
|
||||||
spew.Dump(sets)
|
|
||||||
return &sets
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is what you call from main()
|
|
||||||
//
|
|
||||||
func parseConfig() {
|
|
||||||
// first load the config file
|
|
||||||
loadConfigFile()
|
|
||||||
|
|
||||||
// override the config file from the command line
|
|
||||||
parseFlags()
|
|
||||||
|
|
||||||
log.Println("config.width", config.Width)
|
|
||||||
log.Println("config.height", config.Height)
|
|
||||||
log.Println("config.debug", config.Debug)
|
|
||||||
|
|
||||||
// check that the config parsing worked
|
|
||||||
for key, foo := range config.Accounts {
|
|
||||||
log.Println("account = ", key, foo)
|
|
||||||
log.Println("Accounts[key] = ", config.Accounts[key])
|
|
||||||
}
|
|
||||||
if (config.Accounts == nil) {
|
|
||||||
log.Println("loadConfigFile() config.Accounts == nil")
|
|
||||||
log.Println("If debugging is on, should load default config here")
|
|
||||||
if (*defaultconfig == true) {
|
|
||||||
log.Println("Debugging is on, loading debug config accounts")
|
|
||||||
tmp := loadDefaultConfig()
|
|
||||||
config.Accounts = tmp.Accounts
|
|
||||||
log.Println("loadConfigFile() config.Accounts =", config.Accounts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
103
test4/main.go
103
test4/main.go
|
@ -1,103 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
import "os"
|
|
||||||
import "time"
|
|
||||||
// import "reflect"
|
|
||||||
|
|
||||||
// this is the king of dns libraries
|
|
||||||
// import "github.com/miekg/dns"
|
|
||||||
|
|
||||||
import "git.wit.com/wit/gui"
|
|
||||||
import pb "git.wit.com/wit/witProtobuf"
|
|
||||||
// import "git.wit.com/jcarr/dnssecsocket"
|
|
||||||
|
|
||||||
import "github.com/gobuffalo/packr"
|
|
||||||
// import "github.com/davecgh/go-spew/spew"
|
|
||||||
|
|
||||||
var GITCOMMIT string // this is passed in as an ldflag
|
|
||||||
var GOVERSION string // this is passed in as an ldflag
|
|
||||||
var BUILDTIME string // this is passed in as an ldflag
|
|
||||||
var VERSION string // this is passed in as an ldflag
|
|
||||||
|
|
||||||
var State string // used as a State machine
|
|
||||||
|
|
||||||
type myButtonInfo struct {
|
|
||||||
Account *pb.Account // associated with what account?
|
|
||||||
Accounts []*pb.Account // associated with what account?
|
|
||||||
VM *pb.Event_VM // associated with which VM?
|
|
||||||
Custom func (*gui.GuiButton)
|
|
||||||
ADD func (*gui.GuiButton)
|
|
||||||
Name string
|
|
||||||
Action string
|
|
||||||
}
|
|
||||||
|
|
||||||
var packrBox packr.Box
|
|
||||||
|
|
||||||
func onExit(err error) {
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
packrBox = packr.NewBox("./resources")
|
|
||||||
|
|
||||||
parseConfig()
|
|
||||||
|
|
||||||
go gui.WatchGUI()
|
|
||||||
|
|
||||||
config.Hostname = "localhost"
|
|
||||||
config.IPv6 = "notvalid"
|
|
||||||
|
|
||||||
gui.Data.MouseClick = func (*gui.GuiButton) {
|
|
||||||
log.Println("mainMouseClick() BACK IN CONTROL PANEL CODE")
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.Config.Width = int(config.Width)
|
|
||||||
gui.Config.Height = int(config.Height)
|
|
||||||
|
|
||||||
gui.Config.Debug = config.Debug
|
|
||||||
gui.Config.DebugTable = config.Debugtable
|
|
||||||
log.Println("gui.Config.Debug = ", gui.Config.Debug)
|
|
||||||
log.Println("gui.Config.DebugTable = ", gui.Config.DebugTable)
|
|
||||||
|
|
||||||
go gui.StartNewWindow(false, "test4", showBox)
|
|
||||||
time.Sleep(time.Second * 2)
|
|
||||||
gui.StartNewWindow(false, "test5", showBox)
|
|
||||||
}
|
|
||||||
|
|
||||||
func showBox(gw *gui.GuiWindow) *gui.GuiBox {
|
|
||||||
log.Println("ShowSplashBox() START")
|
|
||||||
|
|
||||||
box := gui.HardBox(gw, gui.Yaxis, "Cloud Accounts")
|
|
||||||
|
|
||||||
log.Println("showBox() START GW IS NOW: gw =", gw)
|
|
||||||
log.Println("showBox() box =", box)
|
|
||||||
|
|
||||||
gui.NewLabel(box, "Hostname:")
|
|
||||||
makeButton(box, nil, nil, "EMPTY", "SUBDOMAIN", nil)
|
|
||||||
makeButton(box, nil, nil, "List all windows & tabs", "SUBDOMAIN", func (*gui.GuiButton) {
|
|
||||||
log.Println("showBox() gui.DumpBoxes()")
|
|
||||||
gui.DumpBoxes()
|
|
||||||
})
|
|
||||||
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
// stores the fields we want to map into our private structure 'values'
|
|
||||||
func makeGuiButtonValues(box *gui.GuiBox, a *pb.Account, vm *pb.Event_VM,
|
|
||||||
name string, action string, custom func(*gui.GuiButton)) *myButtonInfo {
|
|
||||||
val := &myButtonInfo{}
|
|
||||||
val.Account = a
|
|
||||||
val.Accounts = config.Accounts
|
|
||||||
val.VM = vm
|
|
||||||
val.Custom = custom
|
|
||||||
val.Name = "jcarr"
|
|
||||||
val.Action = action
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeButton(box *gui.GuiBox, a *pb.Account, vm *pb.Event_VM,
|
|
||||||
name string, action string, custom func(*gui.GuiButton)) *gui.GuiButton {
|
|
||||||
val := makeGuiButtonValues(box, a, vm, name, action, custom)
|
|
||||||
return gui.CreateButton(box, custom, name, val)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
run:
|
|
||||||
go build
|
|
||||||
./test5
|
|
|
@ -1,86 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "io"
|
|
||||||
import "log"
|
|
||||||
import "reflect"
|
|
||||||
import "strings"
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
type S struct{
|
|
||||||
blah int
|
|
||||||
foo string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *S) addr() { fmt.Printf("%p\n", s) }
|
|
||||||
|
|
||||||
type Codec interface {
|
|
||||||
Encode(w io.Writer, v interface{}) error
|
|
||||||
Decode(r io.Reader, v interface{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (jsonCodec) Encode(w io.Writer, v interface{}) error {
|
|
||||||
return json.NewEncoder(w).Encode(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (jsonCodec) Decode(r io.Reader, v interface{}) error {
|
|
||||||
return json.NewDecoder(r).Decode(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
var JSON Codec = jsonCodec{}
|
|
||||||
|
|
||||||
type jsonCodec struct{}
|
|
||||||
|
|
||||||
type buttons interface {
|
|
||||||
Encode(w io.Writer, v interface{}) error
|
|
||||||
Decode(r io.Reader, v interface{}) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type foo struct{}
|
|
||||||
|
|
||||||
type goo struct{
|
|
||||||
test int
|
|
||||||
}
|
|
||||||
|
|
||||||
func bar(baz interface{}) {
|
|
||||||
log.Println("baz =", baz)
|
|
||||||
log.Println("reflect.TypeOf(baz) =", reflect.TypeOf(baz))
|
|
||||||
switch f := baz.(type) {
|
|
||||||
case int:
|
|
||||||
log.Println("baz.(type) is an int =", f * 3)
|
|
||||||
case *foo: // f is of type *foo
|
|
||||||
log.Println("baz.(type) is known as *foo")
|
|
||||||
default: // f is some other type
|
|
||||||
log.Println("baz.(type) =", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var a, b S
|
|
||||||
a.addr() // 0x1beeb0
|
|
||||||
b.addr() // 0x1beeb0
|
|
||||||
|
|
||||||
f := &foo{}
|
|
||||||
bar(f) // every type implements interface{}. Nothing special required
|
|
||||||
|
|
||||||
g := &goo{}
|
|
||||||
g.test = 4
|
|
||||||
bar(g) // every type implements interface{}. Nothing special required
|
|
||||||
|
|
||||||
bar("hello") // every type implements interface{}. Nothing special required
|
|
||||||
|
|
||||||
// what is this?
|
|
||||||
// s := &Service{
|
|
||||||
// Codec: JSON,
|
|
||||||
// }
|
|
||||||
|
|
||||||
r := strings.NewReader("Hello, Reader!")
|
|
||||||
err := JSON.Decode(r, "afjd")
|
|
||||||
log.Println("JSON.Decoder err =", err)
|
|
||||||
|
|
||||||
// err := JSON.Encode(w, obj)
|
|
||||||
// log.Println("err =", err)
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue