parent
d73ae31eb2
commit
c3ad3ce793
|
@ -0,0 +1,8 @@
|
||||||
|
GNU Lesser General Public License (LGPL)
|
||||||
|
|
||||||
|
I don't want it to be possible to make closed source forks of this.
|
||||||
|
If you need to use this in a proprietary GO application, then
|
||||||
|
compile this as a plugin. The BSD license is bad for core GO libraries.
|
||||||
|
|
||||||
|
(GO now supports plugins as of version 1.8)
|
||||||
|
https://medium.com/@henvic/opensource-and-go-what-license-f6b36c201854
|
|
@ -0,0 +1,14 @@
|
||||||
|
This is an abstraction layer around the excellent
|
||||||
|
cross platform UI toolkit from andlabs/ui
|
||||||
|
|
||||||
|
This abstraction layer makes it easier to write
|
||||||
|
simple interfaces for like our cloud control panel
|
||||||
|
|
||||||
|
The cross platform UI has 'quirks' due to it being
|
||||||
|
cross platform. Some of the abstraction layer here
|
||||||
|
attemps to obfuscate the ui objects so that it is
|
||||||
|
more difficult to trigger inconsistancies.
|
||||||
|
|
||||||
|
In this regard, this is an attempt to restrict
|
||||||
|
all andlabs/ui (and andlabs/libui) interaction to
|
||||||
|
the calls within this library.
|
|
@ -1,13 +1,12 @@
|
||||||
package gui
|
package gui
|
||||||
|
|
||||||
import "log"
|
import "log"
|
||||||
import "fmt"
|
// import "fmt"
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
import "github.com/andlabs/ui"
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
import _ "github.com/andlabs/ui/winmanifest"
|
||||||
|
|
||||||
import "github.com/davecgh/go-spew/spew"
|
// import "github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
// var subdomain *ui.Entry
|
// var subdomain *ui.Entry
|
||||||
|
|
||||||
func AddEntry(box *GuiBox, name string) *GuiEntry {
|
func AddEntry(box *GuiBox, name string) *GuiEntry {
|
||||||
|
@ -27,16 +26,16 @@ func AddEntry(box *GuiBox, name string) *GuiEntry {
|
||||||
return ge
|
return ge
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddAccountQuestionBox(wm *GuiWindow) *ui.Box {
|
func AddAccountQuestionBox(gw *GuiWindow) *GuiBox {
|
||||||
var gb *GuiBox
|
var gb *GuiBox
|
||||||
gb = new(GuiBox)
|
gb = new(GuiBox)
|
||||||
gb.EntryMap = make(map[string]*GuiEntry)
|
|
||||||
|
|
||||||
|
gb.EntryMap = make(map[string]*GuiEntry)
|
||||||
gb.EntryMap["test"] = nil
|
gb.EntryMap["test"] = nil
|
||||||
|
|
||||||
vbox := ui.NewVerticalBox()
|
vbox := ui.NewVerticalBox()
|
||||||
vbox.SetPadded(true)
|
vbox.SetPadded(true)
|
||||||
wm.Box1 = vbox
|
gw.Box1 = vbox
|
||||||
gb.UiBox = vbox
|
gb.UiBox = vbox
|
||||||
|
|
||||||
hbox := ui.NewHorizontalBox()
|
hbox := ui.NewHorizontalBox()
|
||||||
|
@ -45,7 +44,7 @@ func AddAccountQuestionBox(wm *GuiWindow) *ui.Box {
|
||||||
|
|
||||||
hbox.Append(ui.NewLabel("Enter your Subdomain or"), false)
|
hbox.Append(ui.NewLabel("Enter your Subdomain or"), false)
|
||||||
|
|
||||||
button1 := CreateButton(wm, nil, nil, "Generate", "SUBDOMAIN", generateSubdomain)
|
button1 := CreateButton(gw, nil, nil, "Generate", "SUBDOMAIN", generateSubdomain)
|
||||||
button1.Box = gb
|
button1.Box = gb
|
||||||
hbox.Append(button1.B, false)
|
hbox.Append(button1.B, false)
|
||||||
|
|
||||||
|
@ -54,50 +53,11 @@ func AddAccountQuestionBox(wm *GuiWindow) *ui.Box {
|
||||||
|
|
||||||
vbox.Append(ui.NewHorizontalSeparator(), false)
|
vbox.Append(ui.NewHorizontalSeparator(), false)
|
||||||
|
|
||||||
button2 := CreateButton(wm, nil, nil, "Create Subdomain Account", "ADD", nil)
|
button2 := CreateButton(gw, nil, nil, "Create Subdomain Account", "ADD", nil)
|
||||||
button2.Box = gb
|
button2.Box = gb
|
||||||
vbox.Append(button2.B, false)
|
vbox.Append(button2.B, false)
|
||||||
|
|
||||||
return vbox
|
return gb
|
||||||
}
|
|
||||||
|
|
||||||
func GetText(box *GuiBox, name string) string {
|
|
||||||
if (box == nil) {
|
|
||||||
log.Println("gui.GetText() ERROR box == nil")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if (box.EntryMap == nil) {
|
|
||||||
log.Println("gui.GetText() ERROR b.Box.EntryMap == nil")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
spew.Dump(box.EntryMap)
|
|
||||||
if (box.EntryMap[name] == nil) {
|
|
||||||
log.Println("gui.GetText() ERROR box.EntryMap[", name, "] == nil ")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
e := box.EntryMap[name]
|
|
||||||
log.Println("gui.GetText() box.EntryMap[", name, "] = ", e.E.Text())
|
|
||||||
log.Println("gui.GetText() END")
|
|
||||||
return e.E.Text()
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetText(box *GuiBox, name string, value string) error {
|
|
||||||
if (box == nil) {
|
|
||||||
return fmt.Errorf("gui.SetText() ERROR box == nil")
|
|
||||||
}
|
|
||||||
if (box.EntryMap == nil) {
|
|
||||||
return fmt.Errorf("gui.SetText() ERROR b.Box.EntryMap == nil")
|
|
||||||
}
|
|
||||||
spew.Dump(box.EntryMap)
|
|
||||||
if (box.EntryMap[name] == nil) {
|
|
||||||
return fmt.Errorf("gui.SetText() ERROR box.EntryMap[", name, "] == nil ")
|
|
||||||
}
|
|
||||||
e := box.EntryMap[name]
|
|
||||||
log.Println("gui.SetText() box.EntryMap[", name, "] = ", e.E.Text())
|
|
||||||
e.E.SetText(value)
|
|
||||||
log.Println("gui.SetText() box.EntryMap[", name, "] = ", e.E.Text())
|
|
||||||
log.Println("gui.SetText() END")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSubdomain(b *GuiButton) {
|
func generateSubdomain(b *GuiButton) {
|
||||||
|
@ -113,16 +73,26 @@ func generateSubdomain(b *GuiButton) {
|
||||||
log.Println("generateSubdomain END")
|
log.Println("generateSubdomain END")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func addSubdomain(b *GuiButton) {
|
func addSubdomain(b *GuiButton) {
|
||||||
log.Println("addSubdomain START")
|
log.Println("addSubdomain START")
|
||||||
// sub := subdomain.Text()
|
// sub := subdomain.Text()
|
||||||
// log.Println("generateSubdomain subdomain =", sub)
|
// log.Println("generateSubdomain subdomain =", sub)
|
||||||
log.Println("addSubdomain END")
|
log.Println("addSubdomain END")
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func AddAccountBox(gw *GuiWindow) *GuiBox {
|
||||||
|
var gb *GuiBox
|
||||||
|
gb = new(GuiBox)
|
||||||
|
|
||||||
|
gb.EntryMap = make(map[string]*GuiEntry)
|
||||||
|
gb.EntryMap["test"] = nil
|
||||||
|
|
||||||
func AddAccountBox(wm *GuiWindow) *ui.Box {
|
|
||||||
vbox := ui.NewVerticalBox()
|
vbox := ui.NewVerticalBox()
|
||||||
vbox.SetPadded(true)
|
vbox.SetPadded(true)
|
||||||
|
gw.Box1 = vbox
|
||||||
|
gb.UiBox = vbox
|
||||||
|
|
||||||
hboxAccount := ui.NewHorizontalBox()
|
hboxAccount := ui.NewHorizontalBox()
|
||||||
hboxAccount.SetPadded(true)
|
hboxAccount.SetPadded(true)
|
||||||
|
@ -219,11 +189,11 @@ func AddAccountBox(wm *GuiWindow) *ui.Box {
|
||||||
hboxButtons.SetPadded(true)
|
hboxButtons.SetPadded(true)
|
||||||
vbox.Append(hboxButtons, false)
|
vbox.Append(hboxButtons, false)
|
||||||
|
|
||||||
okButton := CreateButton(wm, nil, nil, "Add Account", "ADD", nil)
|
okButton := CreateButton(gw, nil, nil, "Add Account", "ADD", nil)
|
||||||
hboxButtons.Append(okButton.B, false)
|
hboxButtons.Append(okButton.B, false)
|
||||||
|
|
||||||
backButton := CreateButton(wm, nil, nil, "Back", "BACK", nil)
|
backButton := CreateButton(gw, nil, nil, "Back", "BACK", nil)
|
||||||
hboxButtons.Append(backButton.B, false)
|
hboxButtons.Append(backButton.B, false)
|
||||||
|
|
||||||
return vbox
|
return gb
|
||||||
}
|
}
|
||||||
|
|
68
gui.go
68
gui.go
|
@ -1,6 +1,7 @@
|
||||||
package gui
|
package gui
|
||||||
|
|
||||||
import "log"
|
import "log"
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
import "github.com/andlabs/ui"
|
import "github.com/andlabs/ui"
|
||||||
import _ "github.com/andlabs/ui/winmanifest"
|
import _ "github.com/andlabs/ui/winmanifest"
|
||||||
|
@ -41,7 +42,7 @@ func InitColumns(mh *TableData, parts []TableColumnData) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddTableTab(wm *GuiWindow, mytab *ui.Tab, junk int, name string, rowcount int, parts []TableColumnData, account *pb.Account) *TableData {
|
func AddTableTab(gw *GuiWindow, mytab *ui.Tab, junk int, name string, rowcount int, parts []TableColumnData, account *pb.Account) *TableData {
|
||||||
mh := new(TableData)
|
mh := new(TableData)
|
||||||
|
|
||||||
mh.RowCount = rowcount
|
mh.RowCount = rowcount
|
||||||
|
@ -90,9 +91,9 @@ func AddTableTab(wm *GuiWindow, mytab *ui.Tab, junk int, name string, rowcount i
|
||||||
hbox := ui.NewHorizontalBox()
|
hbox := ui.NewHorizontalBox()
|
||||||
hbox.SetPadded(true)
|
hbox.SetPadded(true)
|
||||||
|
|
||||||
a := CreateButton(wm, account, nil, "Add Virtual Machine", "createAddVmBox", nil)
|
a := CreateButton(gw, account, nil, "Add Virtual Machine", "createAddVmBox", nil)
|
||||||
hbox.Append(a.B, false)
|
hbox.Append(a.B, false)
|
||||||
b := CreateButton(wm, account, nil, "Add Virtual Machine", "createAddVmBox", nil)
|
b := CreateButton(gw, account, nil, "Add Virtual Machine", "createAddVmBox", nil)
|
||||||
hbox.Append(b.B, false)
|
hbox.Append(b.B, false)
|
||||||
|
|
||||||
vbox.Append(hbox, false)
|
vbox.Append(hbox, false)
|
||||||
|
@ -100,18 +101,18 @@ func AddTableTab(wm *GuiWindow, mytab *ui.Tab, junk int, name string, rowcount i
|
||||||
return mh
|
return mh
|
||||||
}
|
}
|
||||||
|
|
||||||
func SocketError(wm *GuiWindow) {
|
func SocketError(gw *GuiWindow) {
|
||||||
ui.MsgBoxError(wm.W,
|
ui.MsgBoxError(gw.W,
|
||||||
"There was a socket error",
|
"There was a socket error",
|
||||||
"More detailed information can be shown here.")
|
"More detailed information can be shown here.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func MessageWindow(wm *GuiWindow, msg1 string, msg2 string) {
|
func MessageWindow(gw *GuiWindow, msg1 string, msg2 string) {
|
||||||
ui.MsgBox(wm.W, msg1, msg2)
|
ui.MsgBox(gw.W, msg1, msg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrorWindow(wm *GuiWindow, msg1 string, msg2 string) {
|
func ErrorWindow(gw *GuiWindow, msg1 string, msg2 string) {
|
||||||
ui.MsgBoxError(wm.W, msg1, msg2)
|
ui.MsgBoxError(gw.W, msg1, msg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the default mouse click handler
|
// This is the default mouse click handler
|
||||||
|
@ -211,7 +212,7 @@ func AddButton(b *GuiButton, name string) *ui.Button {
|
||||||
return newB
|
return newB
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateButton(wm *GuiWindow, a *pb.Account, vm *pb.Event_VM,
|
func CreateButton(gw *GuiWindow, a *pb.Account, vm *pb.Event_VM,
|
||||||
name string, action string, custom func(*GuiButton)) *GuiButton {
|
name string, action string, custom func(*GuiButton)) *GuiButton {
|
||||||
newUiB := ui.NewButton(name)
|
newUiB := ui.NewButton(name)
|
||||||
newUiB.OnClicked(defaultButtonClick)
|
newUiB.OnClicked(defaultButtonClick)
|
||||||
|
@ -219,10 +220,10 @@ func CreateButton(wm *GuiWindow, a *pb.Account, vm *pb.Event_VM,
|
||||||
var newB *GuiButton
|
var newB *GuiButton
|
||||||
newB = new(GuiButton)
|
newB = new(GuiButton)
|
||||||
newB.B = newUiB
|
newB.B = newUiB
|
||||||
newB.T = wm.T
|
newB.T = gw.T
|
||||||
newB.Account = a
|
newB.Account = a
|
||||||
newB.VM = vm
|
newB.VM = vm
|
||||||
newB.WM = wm
|
newB.WM = gw
|
||||||
newB.Action = action
|
newB.Action = action
|
||||||
newB.custom = custom
|
newB.custom = custom
|
||||||
Data.AllButtons = append(Data.AllButtons, newB)
|
Data.AllButtons = append(Data.AllButtons, newB)
|
||||||
|
@ -230,14 +231,14 @@ func CreateButton(wm *GuiWindow, a *pb.Account, vm *pb.Event_VM,
|
||||||
return newB
|
return newB
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateFontButton(wm *GuiWindow, action string) *GuiButton {
|
func CreateFontButton(gw *GuiWindow, action string) *GuiButton {
|
||||||
newB := ui.NewFontButton()
|
newB := ui.NewFontButton()
|
||||||
|
|
||||||
// create a 'fake' button entry for the mouse clicks
|
// create a 'fake' button entry for the mouse clicks
|
||||||
var newBM GuiButton
|
var newBM GuiButton
|
||||||
newBM.Action = action
|
newBM.Action = action
|
||||||
newBM.FB = newB
|
newBM.FB = newB
|
||||||
newBM.Area = wm.Area
|
newBM.Area = gw.Area
|
||||||
Data.AllButtons = append(Data.AllButtons, &newBM)
|
Data.AllButtons = append(Data.AllButtons, &newBM)
|
||||||
|
|
||||||
newB.OnChanged(func (*ui.FontButton) {
|
newB.OnChanged(func (*ui.FontButton) {
|
||||||
|
@ -246,3 +247,42 @@ func CreateFontButton(wm *GuiWindow, action string) *GuiButton {
|
||||||
})
|
})
|
||||||
return &newBM
|
return &newBM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetText(box *GuiBox, name string) string {
|
||||||
|
if (box == nil) {
|
||||||
|
log.Println("gui.GetText() ERROR box == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if (box.EntryMap == nil) {
|
||||||
|
log.Println("gui.GetText() ERROR b.Box.EntryMap == nil")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
spew.Dump(box.EntryMap)
|
||||||
|
if (box.EntryMap[name] == nil) {
|
||||||
|
log.Println("gui.GetText() ERROR box.EntryMap[", name, "] == nil ")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
e := box.EntryMap[name]
|
||||||
|
log.Println("gui.GetText() box.EntryMap[", name, "] = ", e.E.Text())
|
||||||
|
log.Println("gui.GetText() END")
|
||||||
|
return e.E.Text()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetText(box *GuiBox, name string, value string) error {
|
||||||
|
if (box == nil) {
|
||||||
|
return fmt.Errorf("gui.SetText() ERROR box == nil")
|
||||||
|
}
|
||||||
|
if (box.EntryMap == nil) {
|
||||||
|
return fmt.Errorf("gui.SetText() ERROR b.Box.EntryMap == nil")
|
||||||
|
}
|
||||||
|
spew.Dump(box.EntryMap)
|
||||||
|
if (box.EntryMap[name] == nil) {
|
||||||
|
return fmt.Errorf("gui.SetText() ERROR box.EntryMap[", name, "] == nil ")
|
||||||
|
}
|
||||||
|
e := box.EntryMap[name]
|
||||||
|
log.Println("gui.SetText() box.EntryMap[", name, "] = ", e.E.Text())
|
||||||
|
e.E.SetText(value)
|
||||||
|
log.Println("gui.SetText() box.EntryMap[", name, "] = ", e.E.Text())
|
||||||
|
log.Println("gui.SetText() END")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -171,8 +171,10 @@ func ShowAccountQuestionTab(gw *GuiWindow) {
|
||||||
log.Println("Sleep(200)")
|
log.Println("Sleep(200)")
|
||||||
time.Sleep(200 * time.Millisecond)
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
|
||||||
gw.Box2 = AddAccountQuestionBox(gw)
|
abox := AddAccountQuestionBox(gw)
|
||||||
gw.T.InsertAt("New Account?", 0, gw.Box2)
|
gw.BoxMap["MAIN"] = abox
|
||||||
|
// gw.Box2 = AddAccountQuestionBox(gw)
|
||||||
|
gw.T.InsertAt("New Account?", 0, abox.UiBox)
|
||||||
gw.T.SetMargined(0, true)
|
gw.T.SetMargined(0, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,12 +195,12 @@ func ShowAccountTab(gw *GuiWindow, i int) {
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
log.Println("ShowAccountTab() InsertAt i=", i)
|
log.Println("ShowAccountTab() InsertAt i=", i)
|
||||||
gw.T.Delete(0)
|
gw.T.Delete(0)
|
||||||
gw.T.InsertAt("Add Account", i, abox)
|
gw.T.InsertAt("Add Account", i, abox.UiBox)
|
||||||
gw.T.SetMargined(0, true)
|
gw.T.SetMargined(0, true)
|
||||||
} else {
|
} else {
|
||||||
// TODO: After append try to discover the tab index #
|
// TODO: After append try to discover the tab index #
|
||||||
log.Println("ShowAccountTab() Append")
|
log.Println("ShowAccountTab() Append")
|
||||||
AddBoxToTab("Create New Account", gw.T, abox)
|
AddBoxToTab("Create New Account", gw.T, abox.UiBox)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +232,9 @@ func StartNewWindow(c *pb.Config, bg bool, action string) {
|
||||||
newGuiWindow.Action = action
|
newGuiWindow.Action = action
|
||||||
Data.Windows = append(Data.Windows, &newGuiWindow)
|
Data.Windows = append(Data.Windows, &newGuiWindow)
|
||||||
|
|
||||||
|
// make(newGuiWindow.BoxMap)
|
||||||
|
newGuiWindow.BoxMap = make(map[string]*GuiBox)
|
||||||
|
|
||||||
if (bg) {
|
if (bg) {
|
||||||
log.Println("ShowWindow() IN NEW GOROUTINE")
|
log.Println("ShowWindow() IN NEW GOROUTINE")
|
||||||
go ui.Main(func() {
|
go ui.Main(func() {
|
||||||
|
|
40
structs.go
40
structs.go
|
@ -55,6 +55,34 @@ type GuiData struct {
|
||||||
EntryPass *ui.Entry
|
EntryPass *ui.Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stores information on 'the' window
|
||||||
|
|
||||||
|
// More than one Window is not supported in a cross platform
|
||||||
|
// sense & may never be. On Windows and MacOS, you have to have
|
||||||
|
// 'tabs'. Even under Linux, more than one Window is currently
|
||||||
|
// unstable
|
||||||
|
//
|
||||||
|
// This code will keep track of if the windows is 'tabbed' or
|
||||||
|
// not. You can draw one thing in the window, then destroy
|
||||||
|
// that, then redraw the window with something else
|
||||||
|
//
|
||||||
|
// This struct keeps track of what is in the window so you
|
||||||
|
// can destroy and replace it with something else
|
||||||
|
//
|
||||||
|
type GuiWindow struct {
|
||||||
|
Action string
|
||||||
|
Area *GuiArea // should be moved to GuiBox
|
||||||
|
|
||||||
|
C *pb.Config
|
||||||
|
|
||||||
|
W *ui.Window
|
||||||
|
T *ui.Tab // if this != nil, the window is 'tabbed'
|
||||||
|
BoxMap map[string]*GuiBox
|
||||||
|
Box1 *ui.Box
|
||||||
|
Box2 *ui.Box
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Note: every mouse click is handled
|
// Note: every mouse click is handled
|
||||||
// as a 'Button' regardless of where
|
// as a 'Button' regardless of where
|
||||||
// the user clicks it. You could probably
|
// the user clicks it. You could probably
|
||||||
|
@ -103,18 +131,6 @@ type GuiEntry struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type GuiWindow struct {
|
|
||||||
Action string
|
|
||||||
Area *GuiArea // should be moved to GuiBox
|
|
||||||
|
|
||||||
C *pb.Config
|
|
||||||
|
|
||||||
W *ui.Window
|
|
||||||
T *ui.Tab
|
|
||||||
Box1 *ui.Box
|
|
||||||
Box2 *ui.Box
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// AREA STRUCTURES START
|
// AREA STRUCTURES START
|
||||||
// AREA STRUCTURES START
|
// AREA STRUCTURES START
|
||||||
|
|
Loading…
Reference in New Issue