large change to track the window everywhere

Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
Jeff Carr 2019-05-29 19:57:15 -07:00
parent 0009d89fd5
commit bd3c5bfef5
8 changed files with 193 additions and 80 deletions

View File

@ -5,23 +5,23 @@ import "log"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
func AddAccountQuestionBox() *ui.Box {
func AddAccountQuestionBox(wm *WindowMap) *ui.Box {
newbox := ui.NewVerticalBox()
newbox.SetPadded(true)
newButton := CreateButton(nil, nil, "Create New Account", "AREA", nil)
newButton := CreateButton(wm, nil, nil, "Create New Account", "AREA", nil)
newbox.Append(newButton, false)
newbox.Append(ui.NewHorizontalSeparator(), false)
okButton := CreateButton(nil, nil, "I Have an Account", "AREA", nil)
okButton := CreateButton(wm, nil, nil, "I Have an Account", "AREA", nil)
newbox.Append(okButton, false)
return newbox
}
// func AddAccountBox(aTab *GuiTabStructure) {
func AddAccountBox() *ui.Box {
func AddAccountBox(wm *WindowMap) *ui.Box {
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
// aTab.firstBox = vbox
@ -121,10 +121,10 @@ func AddAccountBox() *ui.Box {
hboxButtons.SetPadded(true)
vbox.Append(hboxButtons, false)
okButton := CreateButton(nil, nil, "Add Account", "ADD", nil)
okButton := CreateButton(wm, nil, nil, "Add Account", "ADD", nil)
hboxButtons.Append(okButton, false)
backButton := CreateButton(nil, nil, "Back", "BACK", nil)
backButton := CreateButton(wm, nil, nil, "Back", "BACK", nil)
hboxButtons.Append(backButton, false)
return vbox

View File

@ -23,7 +23,8 @@ func findFB(button *ButtonMap) *ButtonMap {
func makeSplashArea(ah *AreaHandler) {
// make this button just to get the default font (but don't display the button)
// There should be another way to do this (?)
newB := CreateFontButton("AREA")
wm := ah.WM
newB := CreateFontButton(wm, "AREA")
// ah.Attrstr = makeAttributedString()
ah.Area = ui.NewArea(ah)

View File

@ -15,6 +15,7 @@ import "github.com/davecgh/go-spew/spew"
// import pb "git.wit.com/wit/witProtobuf"
// can not pass any args to this (?)
/*
func setupCloudUI() {
Data.Window1.W = ui.NewWindow("Cloud Control Panel", Data.Width, Data.Height, false)
Data.Window1.W.OnClosing(func(*ui.Window) bool {
@ -36,6 +37,7 @@ func setupCloudUI() {
Data.Window1.W.Show()
}
*/
func addTableTab() {
var parts []TableColumnData
@ -51,15 +53,15 @@ func addTableTab() {
log.Println("Sleep for 2 seconds, then try to add new tabs")
time.Sleep(1 * 1000 * 1000 * 1000)
AddTableTab(Data.Window1.T, 1, "test seven", 7, parts, nil)
// AddTableTab(Data.Window1.T, 1, "test seven", 7, parts, nil)
}
func addDebuggingButtons(vbox *ui.Box) {
func addDebuggingButtons(wm *WindowMap, vbox *ui.Box) {
vbox.Append(ui.NewLabel("Debugging:"), false)
vbox.Append(ui.NewColorButton(), false)
vbox.Append(CreateButton(nil, nil, "Add Account", "ADD", nil), false)
vbox.Append(CreateButton(nil, nil, "Quit", "QUIT", nil), false)
vbox.Append(CreateButton(wm, nil, nil, "Add Account", "ADD", nil), false)
vbox.Append(CreateButton(wm, nil, nil, "Quit", "QUIT", nil), false)
// ATTEMPT TO ADD THE TABLE HERE
add2button := ui.NewButton("Add a Test Table")
@ -70,21 +72,23 @@ func addDebuggingButtons(vbox *ui.Box) {
vbox.Append(add2button, false)
// ATTEMPT TO ADD THE TABLE HERE END
vbox.Append(CreateButton(nil, nil, "Hide & Show Box1&2", "HIDE", runTestHide), false)
vbox.Append(CreateButton(wm, nil, nil, "Hide & Show Box1&2", "HIDE", runTestHide), false)
vbox.Append(CreateButton(nil, nil, "Close GUI", "QUIT", nil), false)
vbox.Append(CreateButton(nil, nil, "DEBUG goroutines", "DEBUG", nil), false)
vbox.Append(CreateButton(nil, nil, "xterm", "XTERM", runTestExecClick), false)
vbox.Append(CreateButton(nil, nil, "Load test.json config file", "CONFIG", nil), false)
vbox.Append(CreateButton(wm, nil, nil, "Close GUI", "QUIT", nil), false)
vbox.Append(CreateButton(wm, nil, nil, "DEBUG goroutines", "DEBUG", nil), false)
vbox.Append(CreateButton(wm, nil, nil, "xterm", "XTERM", runTestExecClick), false)
vbox.Append(CreateButton(wm, nil, nil, "Load test.json config file", "CONFIG", nil), false)
}
func runTestHide(b *ButtonMap) {
/*
log.Println("runTestHide START")
Data.Window1.Box1.Hide()
Data.Window1.Box2.Hide()
// time.Sleep(2000 * time.Millisecond)
Data.State = "HIDE"
log.Println("runTestHide END")
*/
}
func runPingClick(b *ButtonMap) {

29
gui.go
View File

@ -41,7 +41,7 @@ func InitColumns(mh *TableData, parts []TableColumnData) {
}
}
func AddTableTab(mytab *ui.Tab, junk int, name string, rowcount int, parts []TableColumnData, account *pb.Account) *TableData {
func AddTableTab(wm *WindowMap, mytab *ui.Tab, junk int, name string, rowcount int, parts []TableColumnData, account *pb.Account) *TableData {
mh := new(TableData)
mh.RowCount = rowcount
@ -90,26 +90,26 @@ func AddTableTab(mytab *ui.Tab, junk int, name string, rowcount int, parts []Tab
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
hbox.Append(CreateButton(account, nil, "Add Virtual Machine", "createAddVmBox", nil), false)
hbox.Append(CreateButton(account, nil, "Close", "CLOSE", nil), false)
hbox.Append(CreateButton(wm, account, nil, "Add Virtual Machine", "createAddVmBox", nil), false)
hbox.Append(CreateButton(wm, account, nil, "Close", "CLOSE", nil), false)
vbox.Append(hbox, false)
return mh
}
func SocketError() {
ui.MsgBoxError(Data.Window1.W,
func SocketError(wm *WindowMap) {
ui.MsgBoxError(wm.W,
"There was a socket error",
"More detailed information can be shown here.")
}
func MessageWindow(msg1 string, msg2 string) {
ui.MsgBox(Data.Window1.W, msg1, msg2)
func MessageWindow(wm *WindowMap, msg1 string, msg2 string) {
ui.MsgBox(wm.W, msg1, msg2)
}
func ErrorWindow(msg1 string, msg2 string) {
ui.MsgBoxError(Data.Window1.W, msg1, msg2)
func ErrorWindow(wm *WindowMap, msg1 string, msg2 string) {
ui.MsgBoxError(wm.W, msg1, msg2)
}
// This is the default mouse click handler
@ -131,7 +131,7 @@ func mouseClick(b *ButtonMap) {
log.Println("\tgui.mouseClick() START b.Action =", b.Action)
if (b.Action == "createAddVmBox") {
log.Println("\tgui.mouseClick() createAddVmBox for b =", b)
createAddVmBox(Data.Window1.T, "Create New Virtual Machine", b)
createAddVmBox(b.WM, b.T, "Create New Virtual Machine", b)
return
}
/*
@ -208,16 +208,17 @@ func AddButton(b *ButtonMap, name string) *ui.Button {
return newB
}
func CreateButton(a *pb.Account, vm *pb.Event_VM,
func CreateButton(wm *WindowMap, a *pb.Account, vm *pb.Event_VM,
name string, action string, custom func(*ButtonMap)) *ui.Button {
newB := ui.NewButton(name)
newB.OnClicked(defaultButtonClick)
var newmap ButtonMap
newmap.B = newB
newmap.T = Data.Window1.T
newmap.T = wm.T
newmap.Account = a
newmap.VM = vm
newmap.WM = wm
newmap.Action = action
newmap.custom = custom
Data.AllButtons = append(Data.AllButtons, newmap)
@ -225,14 +226,14 @@ func CreateButton(a *pb.Account, vm *pb.Event_VM,
return newB
}
func CreateFontButton(action string) *ButtonMap {
func CreateFontButton(wm *WindowMap, action string) *ButtonMap {
newB := ui.NewFontButton()
// create a 'fake' button entry for the mouse clicks
var newBM ButtonMap
newBM.Action = action
newBM.FB = newB
newBM.AH = Data.Window1.AH
newBM.AH = wm.AH
Data.AllButtons = append(Data.AllButtons, newBM)
newB.OnChanged(func (*ui.FontButton) {

View File

@ -11,7 +11,7 @@ import pb "git.wit.com/wit/witProtobuf"
// import "github.com/davecgh/go-spew/spew"
func makeCloudInfoBox() *ui.Box {
func makeCloudInfoBox(wm *WindowMap) *ui.Box {
hbox := ui.NewHorizontalBox()
hbox.SetPadded(true)
@ -21,7 +21,7 @@ func makeCloudInfoBox() *ui.Box {
vbox.SetPadded(true)
hbox.Append(vbox, false)
addDebuggingButtons(vbox)
addDebuggingButtons(wm, vbox)
hbox.Append(ui.NewVerticalSeparator(), false)
}
@ -44,7 +44,7 @@ func makeCloudInfoBox() *ui.Box {
hostnameEntry.SetText(tmp)
hostnameEntry.SetReadOnly(true)
hostnamebox.Append(CreateButton(nil, nil, "Edit", "EDIT", nil), false)
hostnamebox.Append(CreateButton(wm, nil, nil, "Edit", "EDIT", nil), false)
vbox.Append(ui.NewHorizontalSeparator(), false)
@ -70,11 +70,11 @@ func makeCloudInfoBox() *ui.Box {
agrid.Append(ui.NewLabel(Data.Config.Accounts[key].Domain), 3, row, 1, 1, true, ui.AlignFill, false, ui.AlignFill)
name := "Login " + Data.Config.Accounts[key].Nick
l := CreateButton(Data.Config.Accounts[key], nil, name, "LOGIN", nil)
l := CreateButton(wm, Data.Config.Accounts[key], nil, name, "LOGIN", nil)
agrid.Append(l, 4, row, 1, 1, true, ui.AlignFill, false, ui.AlignFill)
name = "Show " + Data.Config.Accounts[key].Nick
b := CreateButton(Data.Config.Accounts[key], nil, name, "SHOW", nil)
b := CreateButton(wm, Data.Config.Accounts[key], nil, name, "SHOW", nil)
agrid.Append(b, 5, row, 1, 1, true, ui.AlignFill, false, ui.AlignFill)
row += 1
@ -83,9 +83,9 @@ func makeCloudInfoBox() *ui.Box {
row += 1
agrid.Append(ui.NewLabel(""), 1, row, 1, 1, true, ui.AlignFill, false, ui.AlignFill)
row += 1
a := CreateButton(nil, nil, "Add Account", "ADD TAB", nil)
a := CreateButton(wm, nil, nil, "Add Account", "ADD TAB", nil)
agrid.Append(a, 4, row, 1, 1, true, ui.AlignFill, false, ui.AlignFill)
q := CreateButton(nil, nil, "Quit", "QUIT", nil)
q := CreateButton(wm, nil, nil, "Quit", "QUIT", nil)
agrid.Append(q, 5, row, 1, 1, true, ui.AlignFill, false, ui.AlignFill)
vbox.Append(agrid, false)
@ -101,7 +101,7 @@ func makeCloudInfoBox() *ui.Box {
// which could be anything since TEXTCOLOR, TEXT, BG, etc
// fields use between 1 and 3 values internally
//
func AddVmsTab(name string, count int, a *pb.Account) *TableData {
func AddVmsTab(wm *WindowMap, name string, count int, a *pb.Account) *TableData {
var parts []TableColumnData
human := 0
@ -155,63 +155,145 @@ func AddVmsTab(name string, count int, a *pb.Account) *TableData {
parts = append(parts, tmp)
human += 1
mh := AddTableTab(Data.Window1.T, 1, name, count, parts, a)
mh := AddTableTab(wm, wm.T, 1, name, count, parts, a)
return mh
}
func ShowAccountQuestionTab() {
Data.Window1.T.Delete(0)
func ShowAccountQuestionTab(wm *WindowMap) {
wm.T.Delete(0)
log.Println("Sleep(200)")
time.Sleep(200 * time.Millisecond)
Data.Window1.Box2 = AddAccountQuestionBox()
Data.Window1.T.InsertAt("New Account?", 0, Data.Window1.Box2)
Data.Window1.T.SetMargined(0, true)
wm.Box2 = AddAccountQuestionBox(wm)
wm.T.InsertAt("New Account?", 0, wm.Box2)
wm.T.SetMargined(0, true)
}
func ShowAccountTab(i int) {
func ShowAccountTab(wm *WindowMap, i int) {
log.Println("ShowAccountTab() START")
log.Println("Sleep(200)")
time.Sleep(200 * time.Millisecond)
// Create the things for the Account Tab
abox := AddAccountBox()
abox := AddAccountBox(wm)
// Set the parents and data structure links
// aTab.me = Data.Window1.T
// aTab.me = wm.T
// aTab.parentWindow = Data.Window1.W
// aTab.tabOffset = 0
if (i >= 0) {
log.Println("ShowAccountTab() InsertAt i=", i)
Data.Window1.T.Delete(0)
Data.Window1.T.InsertAt("Add Account", i, abox)
Data.Window1.T.SetMargined(0, true)
wm.T.Delete(0)
wm.T.InsertAt("Add Account", i, abox)
wm.T.SetMargined(0, true)
} else {
// TODO: After append try to discover the tab index #
log.Println("ShowAccountTab() Append")
AddBoxToTab("Create New Account", Data.Window1.T, abox)
AddBoxToTab("Create New Account", wm.T, abox)
}
}
func ShowMainTab() {
Data.Window1.T.Delete(0)
func ShowMainTab(wm *WindowMap) {
log.Println("ShowMainTab() wm =", wm)
log.Println("ShowMainTab() wm.T =", wm.T)
log.Println("ShowMainTab() wm.T =", wm.T)
wm.T.Delete(0)
log.Println("Sleep(200)")
time.Sleep(200 * time.Millisecond)
Data.Window1.Box2 = makeCloudInfoBox()
Data.Window1.T.InsertAt("Main", 0, Data.Window1.Box2)
Data.Window1.T.SetMargined(0, true)
wm.Box2 = makeCloudInfoBox(wm)
wm.T.InsertAt("Main", 0, wm.Box2)
wm.T.SetMargined(0, true)
}
/*
func GoMainWindow() {
// Data.Window1 = new(WindowMap)
ui.Main(makeCloudWindow)
}
*/
func ShowWindow() {
// Data.Window1 = new(WindowMap)
for i, aWM := range(Data.Windows) {
log.Println(aWM)
if (aWM.W == nil) {
log.Println("ShowWindow() THIS WINDOW IS NOT YET SHOWN")
// Data.NewWindow = &aWM
Data.NewWindow = i
ui.Main(InitWindow)
}
}
}
func InitNewWindow(c *pb.Config, action string) *WindowMap {
log.Println("InitNewWindow() Create a new window")
var newWindowMap WindowMap
newWindowMap.C = c
newWindowMap.Action = action
Data.Windows = append(Data.Windows, &newWindowMap)
return &newWindowMap
// NEED TO INIT THIS HERE
// ui.OnShouldQuit(func() bool {
// mouseClick(&newBM)
// return true
// })
}
func getSplashText() *ui.AttributedString {
var aText *ui.AttributedString
aText = ui.NewAttributedString("Click to continue")
return aText
}
func InitWindow() {
i := Data.NewWindow
c := Data.Windows[i].C
Data.Windows[i].W = ui.NewWindow("", int(c.Width), int(c.Height), true)
Data.Windows[i].W.SetBorderless(false)
// create a 'fake' button entry for the mouse clicks
var newBM ButtonMap
newBM.Action = "QUIT"
newBM.W = Data.Windows[i].W
Data.AllButtons = append(Data.AllButtons, newBM)
Data.Windows[i].W.OnClosing(func(*ui.Window) bool {
mouseClick(&newBM)
ui.Quit()
return true
})
Data.Windows[i].T = ui.NewTab()
Data.Windows[i].W.SetChild(Data.Windows[i].T)
Data.Windows[i].W.SetMargined(true)
log.Println("InitWindow() Data.Windows[i] =", Data.Windows[i])
log.Println("InitWindow() Data.Windows[i].Action =", Data.Windows[i].Action)
if (Data.Windows[i].Action == "SPLASH") {
log.Println("InitWindow() TRYING SPLASH")
tmp := getSplashText()
log.Println("InitWindow() TRYING SPLASH tmp =", tmp)
Data.Windows[i].Box1 = ShowSplashBox(Data.Windows[i], i, tmp)
Data.Windows[i].T.Append("WIT Splash", Data.Windows[i].Box1)
Data.Windows[i].T.SetMargined(0, true)
}
Data.Windows[i].W.Show()
Data.State = "splash"
}
/*
func makeCloudWindow() {
Data.Window1.W = ui.NewWindow("", Data.Width, Data.Height, true)
// Window1.W.SetBorderless(true)
@ -236,7 +318,7 @@ func makeCloudWindow() {
Data.Window1.W.SetMargined(true)
// text := makeAttributedString()
Data.Window1.Box1 = ShowSplashBox(Data.Window1.AreaText)
// Data.Window1.Box1 = ShowSplashBox(Data.Window1.AreaText)
Data.Window1.T.Append("WIT Splash", Data.Window1.Box1)
Data.Window1.T.SetMargined(0, true)
@ -244,6 +326,7 @@ func makeCloudWindow() {
Data.Window1.W.Show()
Data.State = "splash"
}
*/
/*
func AddVmConfigureTab(name string, pbVM *pb.Event_VM) {

View File

@ -4,22 +4,31 @@ package gui
// import "time"
// import "fmt"
// import "log"
import "os"
import "log"
import "runtime"
import "github.com/andlabs/ui"
import _ "github.com/andlabs/ui/winmanifest"
func ShowSplashBox(newText *ui.AttributedString) *ui.Box {
func ShowSplashBox(wm *WindowMap, i int, newText *ui.AttributedString) *ui.Box {
log.Println("ShowSplashBox() START")
log.Println("ShowSplashBox() START wm =", wm)
if (wm == nil) {
log.Println("ShowSplashBox() WE ARE FUCKED BECAUSE WE DON'T KNOW WHAT WINDOW TO DO THIS IN")
os.Exit(0)
return nil
}
newbox := ui.NewVerticalBox()
newbox.SetPadded(true)
// initialize the AreaHandler{}
Data.Window1.AH = new(AreaHandler)
Data.Window1.AH.Attrstr = newText
makeSplashArea(Data.Window1.AH)
Data.Windows[i].AH = new(AreaHandler)
Data.Windows[i].AH.WM = wm
Data.Windows[i].AH.Attrstr = newText
makeSplashArea(Data.Windows[i].AH)
newbox.Append(Data.Window1.AH.Area, true)
newbox.Append(Data.Windows[i].AH.Area, true)
if runtime.GOOS == "linux" {
newbox.Append(ui.NewLabel("OS: Linux"), false)
@ -47,9 +56,11 @@ func ShowSplashBox(newText *ui.AttributedString) *ui.Box {
}
}
okButton := CreateButton(nil, nil, "OK", "AREA", nil)
log.Println("ShowSplashBox() START wm =", wm)
okButton := CreateButton(wm, nil, nil, "OK", "AREA", nil)
newbox.Append(okButton, false)
newbox.Append(CreateButton(nil, nil, "NEWTEXT", "NEWTEXT", nil), false)
newbox.Append(CreateButton(wm, nil, nil, "NEWTEXT", "NEWTEXT", nil), false)
// os.Exit(0)
return newbox
}

View File

@ -53,7 +53,9 @@ type GuiDataStructure struct {
// pass it in
CurrentVM *pb.Event_VM
Window1 *WindowMap
Windows []*WindowMap
NewWindow int
// Window1 *WindowMap
Window2 *WindowMap
EntryNick *ui.Entry
@ -92,8 +94,11 @@ type WindowMap struct {
Box1 *ui.Box
Box2 *ui.Box
C *pb.Config
AH *AreaHandler
AreaText *ui.AttributedString
// AreaText *ui.AttributedString
Action string
}
type FontString struct {
@ -104,17 +109,22 @@ type FontString struct {
}
type ButtonMap struct {
// andlabs/ui stuff
B *ui.Button
FB *ui.FontButton
A *ui.Area
W *ui.Window
T *ui.Tab
AH *AreaHandler
// git.wit.com/wit/gui stuff
WM *WindowMap
Account *pb.Account
VM *pb.Event_VM
AH *AreaHandler
Action string // what type of button
// a callback function for the main application
custom func (*ButtonMap)
}
@ -124,6 +134,7 @@ type AreaHandler struct{
Button *ButtonMap
Attrstr *ui.AttributedString
Area *ui.Area
WM *WindowMap
}
// AREA STRUCTURES END

View File

@ -10,6 +10,7 @@ import pb "git.wit.com/wit/witProtobuf"
import "github.com/davecgh/go-spew/spew"
/*
func GoShowVM() {
ui.Main(ShowVM)
}
@ -41,12 +42,13 @@ func ShowVM() {
CreateVmBox(VMtab, Data.CurrentVM)
VMwin.Show()
}
*/
func AddVmConfigureTab(name string, pbVM *pb.Event_VM) {
CreateVmBox(Data.Window1.T, Data.CurrentVM)
func AddVmConfigureTab(wm *WindowMap, name string, pbVM *pb.Event_VM) {
CreateVmBox(wm, wm.T, Data.CurrentVM)
}
func CreateVmBox(tab *ui.Tab, vm *pb.Event_VM) {
func CreateVmBox(wm *WindowMap, tab *ui.Tab, vm *pb.Event_VM) {
log.Println("CreateVmBox() START")
log.Println("CreateVmBox() vm.Name", vm.Name)
spew.Dump(vm)
@ -74,18 +76,18 @@ func CreateVmBox(tab *ui.Tab, vm *pb.Event_VM) {
hboxButtons.SetPadded(true)
vbox.Append(hboxButtons, false)
hboxButtons.Append(CreateButton(nil, vm, "Power On", "POWERON", nil), false)
hboxButtons.Append(CreateButton(nil, vm, "Power Off", "POWEROFF", nil), false)
hboxButtons.Append(CreateButton(nil, vm, "Destroy", "DESTROY", nil), false)
hboxButtons.Append(CreateButton(nil, vm, "ping", "PING", runPingClick), false)
hboxButtons.Append(CreateButton(nil, vm, "Console", "XTERM", runTestExecClick), false)
hboxButtons.Append(CreateButton(nil, vm, "Save", "SAVE", nil), false)
hboxButtons.Append(CreateButton(nil, vm, "Done", "DONE", nil), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "Power On", "POWERON", nil), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "Power Off", "POWEROFF", nil), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "Destroy", "DESTROY", nil), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "ping", "PING", runPingClick), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "Console", "XTERM", runTestExecClick), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "Save", "SAVE", nil), false)
hboxButtons.Append(CreateButton(wm, nil, vm, "Done", "DONE", nil), false)
AddBoxToTab(Data.CurrentVM.Name, tab, vbox)
}
func createAddVmBox(tab *ui.Tab, name string, b *ButtonMap) {
func createAddVmBox(wm *WindowMap, tab *ui.Tab, name string, b *ButtonMap) {
log.Println("createAddVmBox() START")
vbox := ui.NewVerticalBox()
vbox.SetPadded(true)
@ -118,7 +120,7 @@ func createAddVmBox(tab *ui.Tab, name string, b *ButtonMap) {
hboxButtons.Append(AddButton(&newb, "Add Virtual Machine"), false)
// hboxButtons.Append(CreateButton(nil, nil, "Add Virtual Machine","CREATE",nil), false)
hboxButtons.Append(CreateButton(nil, nil, "Cancel", "CLOSE", nil), false)
hboxButtons.Append(CreateButton(wm, nil, nil, "Cancel", "CLOSE", nil), false)
name += " (" + b.Account.Nick + ")"
AddBoxToTab(name, tab, vbox)