diff --git a/main.go b/main.go index f9dcc48..a36fdfb 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,10 @@ package main import "log" -import "fmt" import "os" import "time" import "os/user" -import "runtime" -import "runtime/debug" +import "reflect" // this is the king of dns libraries import "github.com/miekg/dns" @@ -99,7 +97,7 @@ func main() { go processEvents() go gorillaDial("v000185.testing.com.customers.wprod.wit.com:9000") - go watchGUI() + go gui.WatchGUI() user, err := user.Current() if err != nil { @@ -144,257 +142,6 @@ func main() { gui.StartNewWindow(config, false, "SPLASH", showSplashBox) } -// This is the handler for all mosue clicks (buttons, areas, etc)) -// -// This is massive for a reason. EVERY MOUSE CLICK COMES HERE -// the 'gui' code is kinda just a holder. It will pass everything -// here and we have to sort out what to do with the click -// at least, that is the current design because I thought it -// might be a good approach. Time will tell... -// -func mainMouseClick(b *gui.GuiButton) { - defer r() // a golang trick to try to not crash on certain errors - - if (b == nil) { - log.Println("mainMouseClick() BACK IN MAIN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?") - log.Println("mainMouseClick() BACK IN MAIN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?") - onExit(fmt.Errorf("mainMouseClick() got b = nil")) - } - spew.Dump(b.Account) - log.Println("mainMouseClick() b.Action =", b.Action) - log.Println("mainMouseClick() b.Account =", b.Account) - log.Println("mainMouseClick() b.Box =", b.Box) - - var gw *gui.GuiWindow - if (b.GW != nil) { - gw = b.GW - } else { - if (b.Box != nil) { - gw = b.Box.Window - } - } - if (gw == nil) { - log.Println("THIS BUTTON IS BROKEN gw = nil") - log.Println("THIS BUTTON IS BROKEN gw = nil") - log.Println("THIS BUTTON IS BROKEN gw = nil") - panic("something") - } - -// gui.Data.Current = b.Account - log.Println("mainMouseClick() BACK IN CONTROL PANEL CODE b =", b) - if (b.Account != nil) { - log.Println("\tmainMouseClick() setting current account = ", b.Account.Nick) - } - if (b.Action == "NEWTEXT") { - if (b.Box == nil) { - log.Println("\tmainMouseClick() b.Box = nil") - os.Exit(-1) - } - if (gw.Area == nil) { - log.Println("\tmainMouseClick() gw.Area = nil") - os.Exit(-1) - } - gw.Area.UiAttrstr = getNEWTEXT() - log.Println("Area.UiAttrstr = ", gw.Area.UiAttrstr) - gw.Area.UiArea.QueueRedrawAll() - } else if (b.Action == "AREA") { - if (config == nil) { - log.Println("gui.State = splash BUT SOMETHING HAS GONE VERY WRONG") - log.Println("gui.State = splash BUT SOMETHING HAS GONE VERY WRONG") - log.Println("gui.State = splash config = nil") - os.Exit(-1) - } - for key, _ := range config.Accounts { - log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Account = ", config.Accounts[key]) - // log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Username = ", config.Accounts[key]) - log.Println("SETTING gui.State = main") - gui.Data.State = "main"; - if (config.Accounts[key] == nil) { - log.Println("THIS IS LAME. CONFIG FILE MADE NULL ACCOUNTS key =", key) - } - } - if (gui.Data.State == "splash") { - gw.MakeWindow = addSubdomainQuestionBox - gw = gui.ShowTab(gw, "Box2", "New Account?") - gui.Data.State = "account1" - return - } - if (gui.Data.State == "main") { - log.Println("gui.Data.State == main b =", b) - log.Println("gui.Data.State == main gw =", gw) - makeCloudInfoBox(gw) - // gw.MakeWindow = makeCloudInfoBox - // gui.ShowMainTab(gw) - gui.Data.State = "done" - return - } else if (gui.Data.State == "account1") { - // gui.ShowAccountTab(gw, 0) - gui.Data.State = "main" - return - } - } else if (b.Action == "ADD TAB") { - log.Println("\tADD TAB TRY b.Action = ", b.Action) - log.Println("\tADD TAB TRY gui.ShowAccountTab(-1)") - // gui.ShowAccountTab(gw, -1) - gui.Data.State = "done" - return - } else if (b.Action == "QUIT") { - onExit(nil) - } else if (b.Action == "CREATE") { - log.Println("\tTRY TO ADD A NEW VIRTUAL MACHINE") - log.Println("\tTRIGGER CREATE VM") - gui.Data.State = "CREATE" - event := pb.MakeAddVmEvent() - for key, entry := range gui.Data.AllEntries { - log.Println("\tdefaultEntryChange() Data.AllEntries =", key, entry) - log.Println("\tdefaultEntryChange() Data.AllEntries[key].Action =", entry.Action) - if (entry.Action == "Hostname") { - event.Vms[0].Hostname = entry.UiEntry.Text() - } - if (entry.Action == "Memory") { - event.Vms[0].Memory = pint64(entry.UiEntry.Text()) - } - log.Println("\tdefaultEntryChange() Data.AllEntries[key].E =", entry.UiEntry.Text()) - log.Println("\tdefaultEntryChange() Data.AllEntries[key].B =", entry.B) - if entry.B == b { - log.Println("defaultEntryChange() FOUND. Entry assigned to Button", b) - } - } - event.Account = b.Account - log.Println("\tTRIGGERING CREATE event=", event) - log.Println("\tTRIGGERING CREATE event.Account=", event.Account) - prepareAndSend(event) - } else if (b.Action == "CONFIG") { - newConfig := loadDefaultConfig() - config.Accounts = newConfig.Accounts - gui.Data.State = "done" - } else if (b.Action == "DEBUG") { - log.Println("\tdebug.PrintStack() (SHOULD BE JUST THIS goroutine)") - debug.PrintStack() - } else if (b.Action == "DEBUG FULL") { - log.Println("\tATTEMPT FULL STACK DUMP") - buf := make([]byte, 1<<16) - runtime.Stack(buf, true) - log.Printf("%s", buf) - log.Println("\tFINISHED FULL STACK DUMP") - } else if (b.Action == "LOGIN") { -/* - log.Println("\tTRIGGER LOGIN ACCOUNT") - gui.Data.State = "SEND LOGIN" - - // TODO: move this into a seperate goroutine - event := pb.MakeLoginEvent() - event.Account = b.Account - prepareAndSend(event) - - count := 0 - for { - log.Println("\tSleep() in buttonClick() gui.Data.State =", gui.Data.State) - time.Sleep(200 * time.Millisecond) - if (gui.Data.State == "NEW PROTOBUF") { - if (currentMessage == nil) { - gui.ErrorWindow(gw, - "There was a socket error", - "More detailed information can be shown here.") - gui.Data.State = "done" - } else { - log.Println("LOGIN currentMessage =", currentMessage) - if (currentMessage.Type == pb.Event_OK) { - msg := "On account " + b.Account.Nick + "\n" - log.Println("\tLOGIN WAS OK!", msg) - log.Println("\tLOGIN WAS OK! old button.Account was =", b.Account) - log.Println("\tLOGIN WAS OK! currentMessage.Account =", currentMessage.Account) - if (b.Account.Id == currentMessage.Account.Id) { - if (b.Account.Token != currentMessage.Account.Token) { - log.Println("\tLOGIN SENT NEW TOKEN") - b.Account.Token = currentMessage.Account.Token - log.Println("\tLOGIN WAS OK! old button.Account is now =", b.Account) - } - } - log.Println("\tLOGIN WAS OK!") - gui.MessageWindow(gw, "Login OK", msg) - } else if (currentMessage.Type == pb.Event_FAIL) { - log.Println("\tLOGIN FAILED") - log.Println("\tLOGIN FAILED") - log.Println("\tLOGIN FAILED") - msg := "On account " + b.Account.Nick + "\n" - msg += "pb.Comment = " + currentMessage.Comment + "\n" - msg += "pb.Id = " + fmt.Sprintf("%d", currentMessage.Id) + "\n" - msg += "pb.Email = " + b.Account.Email + "\n" - msg += "pb.Username = " + b.Account.Username + "\n" - gui.ErrorWindow(gw, "Login Failed", msg) - } - currentMessage = nil - gui.Data.State = "done" - } - return - } - // TODO: fix this with an actual timeout - count += 1 - if (count > 10) { - log.Println("\tERROR: waited too long for a resposne") - currentMessage = nil - gui.Data.State = "done" - return - } - } -*/ - } else if (b.Action == "SHOW VM") { - // gui.Data.CurrentVM = b.VM - if (gui.Data.Debug) { - // log.Println("\tATTEMPTING TO SHOW VM IN WINDOW") - // go gui.GoShowVM() - - log.Println("\tATTEMPTING TO SHOW VM TAB gw = ", gw) - createVmBox(gw, b.VM) - } else { - log.Println("\tATTEMPTING TO SHOW VM TAB gw = ", gw) - createVmBox(gw, b.VM) - } - } else if (b.Action == "SHOW") { - log.Println("\tTRIGGER DISPLAY ACCOUNT") - gui.Data.State = "SEND WEBSOCKET" - - event := pb.MakeGetEvent() - event.Account = b.Account - prepareAndSend(event) - - count := 0 - for { - log.Println("\tSleep() in buttonClick() gui.Data.State =", gui.Data.State) - time.Sleep(200 * time.Millisecond) - if (gui.Data.State == "NEW PROTOBUF") { - if (currentMessage == nil) { - gui.ErrorWindow(gw, - "There was a socket error", - "More detailed information can be shown here.") - gui.Data.State = "done" - } else { - count := countVMS(currentMessage) - log.Println("\tSHOW VMS currentMessage =", currentMessage) - log.Println("\tSHOW VMS count =", count) - // TODO: make sure login worked & the account really has zero VMs - // if (count != 0) { - name := "Virtual Machines (" + b.Account.Nick + ")" - mh := addVmsTab(gw, name, count, b.Account) - ReadReceivedData(currentMessage, mh, b.GW) - // } - currentMessage = nil - gui.Data.State = "done" - } - return - } - count += 1 - if (count > 10) { - log.Println("\tERROR: waited too long for a resposne") - currentMessage = nil - gui.Data.State = "done" - return - } - } - } -} - // // This is GO language concept for 'recover' to keep an app from completely crashing // @@ -427,6 +174,19 @@ func prepareAndSend(event *pb.Event) { gui.Data.State = "READ PROTOBUF" } +func splashClick(b *gui.GuiButton) { + gw := b.Box.Window + // if there is already an account, skip straight to the main screen + for key, _ := range config.Accounts { + log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Account = ", config.Accounts[key]) + makeCloudInfoBox(gw) + return + } + // if there is not an account, then go to 'make account' + gw.MakeWindow = addSubdomainQuestionBox + gw = gui.ShowTab(gw, "Box2", "New Account?") +} + // this watches the GUI primarily to process protobuf's // maybe this is pointless or wrong func watchGUI() { @@ -437,8 +197,19 @@ func watchGUI() { log.Println("Sleep() in watchGUI() gui.Data.State =", gui.Data.State) for i, window := range gui.Data.Windows { log.Println("watchGUI() gui.Data.Windows i =", i, "Action =", window.Action) - for name, _ := range window.BoxMap { - log.Println("\twatchGUI() name =", name) + for name, abox := range window.BoxMap { + log.Println("\twatchGUI() BOX name =", name) + if (name == "SplashArea3") { + log.Println("\twatchGUI() BOX abox =", reflect.TypeOf(abox)) + win := abox.Window + log.Println("\twatchGUI() BOX win =", reflect.TypeOf(win)) + area := win.Area + log.Println("\twatchGUI() BOX area =", reflect.TypeOf(area)) + spew.Dump(area.UiArea) + area.UiArea.Show() + time.Sleep(20000 * time.Millisecond) + os.Exit(0) + } } } count = 0 diff --git a/mouseClick.go b/mouseClick.go new file mode 100644 index 0000000..d2a6c12 --- /dev/null +++ b/mouseClick.go @@ -0,0 +1,128 @@ +package main + +import "log" +import "fmt" +import "time" +import "runtime" +import "runtime/debug" + +import "git.wit.com/wit/gui" +import pb "git.wit.com/wit/witProtobuf" + +// import "github.com/davecgh/go-spew/spew" + +// This is the handler for all mosue clicks (buttons, areas, etc)) +// +// This is massive for a reason. EVERY MOUSE CLICK COMES HERE +// the 'gui' code is kinda just a holder. It will pass everything +// here and we have to sort out what to do with the click +// at least, that is the current design because I thought it +// might be a good approach. Time will tell... +// +func mainMouseClick(b *gui.GuiButton) { + defer r() // a golang trick to try to not crash on certain errors + + if (b == nil) { + log.Println("mainMouseClick() BACK IN MAIN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?") + onExit(fmt.Errorf("mainMouseClick() got b = nil")) + } + log.Println("mainMouseClick() BACK IN CONTROL PANEL CODE b.Action =", b.Action) + + var gw *gui.GuiWindow + gw = b.Box.Window + + if (gw == nil) { + log.Println("THIS BUTTON IS BROKEN gw = nil") + panic("something") + } + + if (b.Action == "QUIT") { + onExit(nil) + } else if (b.Action == "CREATE") { + log.Println("\tTRY TO ADD A NEW VIRTUAL MACHINE") + log.Println("\tTRIGGER CREATE VM") + gui.Data.State = "CREATE" + event := pb.MakeAddVmEvent() + for key, entry := range gui.Data.AllEntries { + log.Println("\tdefaultEntryChange() Data.AllEntries =", key, entry) + log.Println("\tdefaultEntryChange() Data.AllEntries[key].Action =", entry.Action) + if (entry.Action == "Hostname") { + event.Vms[0].Hostname = entry.UiEntry.Text() + } + if (entry.Action == "Memory") { + event.Vms[0].Memory = pint64(entry.UiEntry.Text()) + } + log.Println("\tdefaultEntryChange() Data.AllEntries[key].E =", entry.UiEntry.Text()) + log.Println("\tdefaultEntryChange() Data.AllEntries[key].B =", entry.B) + if entry.B == b { + log.Println("defaultEntryChange() FOUND. Entry assigned to Button", b) + } + } + event.Account = b.Account + log.Println("\tTRIGGERING CREATE event=", event) + log.Println("\tTRIGGERING CREATE event.Account=", event.Account) + prepareAndSend(event) + } else if (b.Action == "CONFIG") { + newConfig := loadDefaultConfig() + config.Accounts = newConfig.Accounts + gui.Data.State = "done" + } else if (b.Action == "DEBUG") { + log.Println("\tdebug.PrintStack() (SHOULD BE JUST THIS goroutine)") + debug.PrintStack() + } else if (b.Action == "DEBUG FULL") { + log.Println("\tATTEMPT FULL STACK DUMP") + buf := make([]byte, 1<<16) + runtime.Stack(buf, true) + log.Printf("%s", buf) + log.Println("\tFINISHED FULL STACK DUMP") + } else if (b.Action == "SHOW VM") { + if (gui.Data.Debug) { + log.Println("\tATTEMPTING TO SHOW VM TAB gw = ", gw) + createVmBox(gw, b.VM) + } else { + log.Println("\tATTEMPTING TO SHOW VM TAB gw = ", gw) + createVmBox(gw, b.VM) + } + } else if (b.Action == "SHOW") { + log.Println("\tTRIGGER DISPLAY ACCOUNT") + gui.Data.State = "SEND WEBSOCKET" + + event := pb.MakeGetEvent() + event.Account = b.Account + prepareAndSend(event) + + count := 0 + for { + log.Println("\tSleep() in buttonClick() gui.Data.State =", gui.Data.State) + time.Sleep(200 * time.Millisecond) + if (gui.Data.State == "NEW PROTOBUF") { + if (currentMessage == nil) { + gui.ErrorWindow(gw, + "There was a socket error", + "More detailed information can be shown here.") + gui.Data.State = "done" + } else { + count := countVMS(currentMessage) + log.Println("\tSHOW VMS currentMessage =", currentMessage) + log.Println("\tSHOW VMS count =", count) + // TODO: make sure login worked & the account really has zero VMs + // if (count != 0) { + name := "Virtual Machines (" + b.Account.Nick + ")" + mh := addVmsTab(gw, name, count, b.Account) + ReadReceivedData(currentMessage, mh, b.GW) + // } + currentMessage = nil + gui.Data.State = "done" + } + return + } + count += 1 + if (count > 10) { + log.Println("\tERROR: waited too long for a resposne") + currentMessage = nil + gui.Data.State = "done" + return + } + } + } +} diff --git a/splash.go b/splash.go index 62fbf4c..b3bd5ce 100644 --- a/splash.go +++ b/splash.go @@ -31,7 +31,7 @@ func showSplashBox(gw *gui.GuiWindow) *gui.GuiBox { gui.NewLabel(box, "build date: " + BUILDTIME) } - okButton := gui.CreateButton(box, nil, nil, "OK", "AREA", nil) + okButton := gui.CreateButton(box, nil, nil, "OK", "AREA", splashClick) gui.AddButtonToBox(box, okButton) log.Println("ShowSplashBox() END box =", box) diff --git a/test4/Makefile b/test4/Makefile new file mode 100644 index 0000000..52515aa --- /dev/null +++ b/test4/Makefile @@ -0,0 +1,3 @@ +run: + go build + ./test4 diff --git a/test4/main.go b/test4/main.go new file mode 100644 index 0000000..52e9938 --- /dev/null +++ b/test4/main.go @@ -0,0 +1,144 @@ +package main + +import "log" +// import "os" +// import "time" +// import "os/user" +// import "reflect" +import "runtime" + +import "git.wit.com/wit/gui" + +import "github.com/andlabs/ui" +import _ "github.com/andlabs/ui/winmanifest" + +import pb "git.wit.com/wit/witProtobuf" + +// import "github.com/davecgh/go-spew/spew" + +var config *pb.Config + +func main() { + go gui.WatchGUI() + config = pb.MakeDefaultConfig() + gui.StartNewWindow(config, false, "SPLASH", showSplashBox) +} + +func splashClick(b *gui.GuiButton) { + gw := b.Box.Window + // if there is already an account, skip straight to the main screen + for key, _ := range config.Accounts { + log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Account = ", config.Accounts[key]) + // makeCloudInfoBox(gw) + return + } + // if there is not an account, then go to 'make account' + // gw.MakeWindow = addSubdomainQuestionBox + gw = gui.ShowTab(gw, "Box2", "New Account?") +} + +func showSplashBox(gw *gui.GuiWindow) *gui.GuiBox { + log.Println("ShowSplashBox() START") + text := getNEWTEXT() + box := gui.ShowTextBox(gw, text) + + if runtime.GOOS == "linux" { + gui.NewLabel(box,"OS: Linux") + } else if runtime.GOOS == "windows" { + gui.NewLabel(box,"OS: Windows") + } else { + gui.NewLabel(box,"OS: " + runtime.GOOS) + } + + gui.NewLabel(box, "Version: " + "test") + + okButton := gui.CreateButton(box, nil, nil, "OK", "AREA", splashClick) + gui.AddButtonToBox(box, okButton) + + log.Println("ShowSplashBox() END box =", box) + return box +} + +func getNEWTEXT() *ui.AttributedString { + var aText *ui.AttributedString + aText = ui.NewAttributedString("") + + gui.AreaAppendText(aText, "Welcome to the Cloud Control Panel\n", ui.TextSize(16), ui.TextColor{0.0, 0.0, 0.8, .8}) + gui.AreaAppendText(aText, "(alpha)\n\n", ui.TextSize(10)) + + gui.AreaAppendText(aText, "This control panel was designed to be an interface to your 'private' cloud. ", ui.TextWeightBold) + gui.AreaAppendText(aText, "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) + + aText.AppendUnattributed("\n") + aText.AppendUnattributed("\n") + gui.AreaAppendText(aText, "This control panel requires:\n") + aText.AppendUnattributed("\n") + gui.AreaAppendText(aText, "IPv6\n") + gui.AreaAppendText(aText, "Your hostname in DNS\n") + aText.AppendUnattributed("\n\n\n\n\n") + + gui.AreaAppendText(aText, "\n", ui.TextSize(10)) + + return aText +} + +/* +func addSubdomainQuestionBox(gw *gui.GuiWindow) *gui.GuiBox { + log.Println("addSubdomainQuestionBox() START") + box := gui.AddGenericBox(gw) + + gui.NewLabel(box, "Enter your Subdomain or") + + button := gui.CreateButton(box, nil, nil, "Generate", "SUBDOMAIN", generateSubdomain) + gui.AddButtonToBox(box, button) + + gui.AddEntry(box, "SUBDOMAIN") + + gui.HorizontalBreak(box) + + button2 := gui.CreateButton(box, nil, nil, "Create Subdomain Account", "ADD", addSubdomainButton) + gui.AddButtonToBox(box, button2) + + log.Println("addSubdomainQuestionBox() END box =", box) + return box +} + +// curl -vv -X POST -H "X-Wit-Auth: $TOKEN" 'http://stackapi-api1.stackapi.customers.wit.com:4000/vms/toby?count=1&cpu=2&ram=512&disk=25' + + +func addSubdomainButton(b *gui.GuiButton) { + log.Println("addSubdomainButton() START") + subdomain := gui.GetText(b.Box, "SUBDOMAIN") + if (subdomain == "") { + gui.ErrorWindow(b.GW, "Blank Name", "You must have a valid subdomain") + return + } + log.Println("\tsubdomain =", subdomain) + + acc := new(pb.Account) + acc.Nick = subdomain + acc.Domain = subdomain + acc.Username = "jcarr@wit.com" + acc.Email = "jcarr@wit.com" + acc.Password = "badpass" + acc.URL = "http://stackapi-api1.stackapi.customers.dev.wit.com:4000/" + config.Accounts = append(config.Accounts, acc) + + makeCloudInfoBox(b.GW) + gui.Data.State = "done" + log.Println("addSubdomainButton() END") +} + +func generateSubdomain(b *gui.GuiButton) { + log.Println("generateSubdomain START") + if (b == nil) { + log.Println("generateSubdomain ERROR b == nil") + return + } + // subdomain.SetText("cust00013.wit.dev") + + txt := gui.SetText(b.Box, "SUBDOMAIN", "cust001.testing.com.customers.wprod.wit.com") + log.Println("generateSubdomain subdomain = ", txt) + log.Println("generateSubdomain END") +} +*/