mirror of
https://github.com/VladimirMarkelov/clui.git
synced 2025-04-26 13:49:01 +08:00
160 lines
4.7 KiB
Go
160 lines
4.7 KiB
Go
package clui
|
|
|
|
const (
|
|
LoginOk = iota
|
|
LoginCanceled
|
|
LoginInvalid
|
|
)
|
|
|
|
// LoginDialog is a login dialog with fields to enter user name and password
|
|
// Public properties:
|
|
// * Username - login entered by a user
|
|
// * Password - password entered by a user
|
|
// * Action - how the dialog was closed:
|
|
// - LoginOk - button "OK" was clicked
|
|
// - LoginCanceled - button "Cancel" was clicked or dialog was dismissed
|
|
// - LoginInvalid - invalid credentials were entered. This value appears
|
|
// only in case of callback is used and button "OK" is clicked
|
|
// while entered username or password is incorrect
|
|
type LoginDialog struct {
|
|
View *Window
|
|
Username string
|
|
Password string
|
|
Action int
|
|
|
|
result int
|
|
onClose func()
|
|
onCheck func(string, string) bool
|
|
}
|
|
|
|
// LoginDialog creates a new login dialog
|
|
// * title - custom dialog title
|
|
// * userName - initial username. Maybe useful if you want to implement
|
|
// a feature "remember me"
|
|
// The active control depends on userName: if it is empty then the cursor is
|
|
// in Username field, and in Password field otherwise.
|
|
// By default the dialog is closed when button "OK" is clicked. But if you set
|
|
// OnCheck callback the dialog closes only if callback returns true or
|
|
// button "Cancel" is clicked. This is helpful if you do not want to recreate
|
|
// the dialog after every incorrect credentials. So, you define a callback
|
|
// that checks whether pair of Usename and Password is correct and then the
|
|
// button "OK" closed the dialog only if the callback returns true. If the
|
|
// credentials are not valid, then the dialog shows a warning. The warning
|
|
// automatically disappears when a user starts typing in Password or Username
|
|
// field.
|
|
func CreateLoginDialog(title, userName string) *LoginDialog {
|
|
dlg := new(LoginDialog)
|
|
|
|
dlg.View = AddWindow(15, 8, 10, 4, title)
|
|
WindowManager().BeginUpdate()
|
|
defer WindowManager().EndUpdate()
|
|
|
|
dlg.View.SetModal(true)
|
|
dlg.View.SetPack(Vertical)
|
|
|
|
userfrm := CreateFrame(dlg.View, 1, 1, BorderNone, Fixed)
|
|
userfrm.SetPaddings(1, 1)
|
|
userfrm.SetPack(Horizontal)
|
|
userfrm.SetGaps(1, 0)
|
|
CreateLabel(userfrm, AutoSize, AutoSize, "User name", Fixed)
|
|
edUser := CreateEditField(userfrm, 20, userName, 1)
|
|
|
|
passfrm := CreateFrame(dlg.View, 1, 1, BorderNone, 1)
|
|
passfrm.SetPaddings(1, 1)
|
|
passfrm.SetPack(Horizontal)
|
|
passfrm.SetGaps(1, 0)
|
|
CreateLabel(passfrm, AutoSize, AutoSize, "Password", Fixed)
|
|
edPass := CreateEditField(passfrm, 20, "", 1)
|
|
edPass.SetPasswordMode(true)
|
|
|
|
filler := CreateFrame(dlg.View, 1, 1, BorderNone, 1)
|
|
filler.SetPack(Horizontal)
|
|
lbRes := CreateLabel(filler, AutoSize, AutoSize, "", 1)
|
|
|
|
blist := CreateFrame(dlg.View, 1, 1, BorderNone, Fixed)
|
|
blist.SetPack(Horizontal)
|
|
blist.SetPaddings(1, 1)
|
|
btnOk := CreateButton(blist, 10, 4, "OK", Fixed)
|
|
btnCancel := CreateButton(blist, 10, 4, "Cancel", Fixed)
|
|
|
|
btnCancel.OnClick(func(ev Event) {
|
|
WindowManager().DestroyWindow(dlg.View)
|
|
WindowManager().BeginUpdate()
|
|
dlg.Action = LoginCanceled
|
|
closeFunc := dlg.onClose
|
|
WindowManager().EndUpdate()
|
|
if closeFunc != nil {
|
|
closeFunc()
|
|
}
|
|
})
|
|
|
|
btnOk.OnClick(func(ev Event) {
|
|
if dlg.onCheck != nil && !dlg.onCheck(edUser.Title(), edPass.Title()) {
|
|
lbRes.SetTitle("Invalid username or password")
|
|
dlg.Action = LoginInvalid
|
|
return
|
|
}
|
|
|
|
dlg.Action = LoginOk
|
|
if dlg.onCheck == nil {
|
|
dlg.Username = edUser.Title()
|
|
dlg.Password = edPass.Title()
|
|
}
|
|
|
|
WindowManager().DestroyWindow(dlg.View)
|
|
WindowManager().BeginUpdate()
|
|
|
|
closeFunc := dlg.onClose
|
|
WindowManager().EndUpdate()
|
|
if closeFunc != nil {
|
|
closeFunc()
|
|
}
|
|
})
|
|
|
|
dlg.View.OnClose(func(ev Event) bool {
|
|
if dlg.result == DialogAlive {
|
|
dlg.result = DialogClosed
|
|
if ev.X != 1 {
|
|
WindowManager().DestroyWindow(dlg.View)
|
|
}
|
|
if dlg.onClose != nil {
|
|
dlg.onClose()
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
|
|
edUser.OnChange(func(ev Event) {
|
|
lbRes.SetTitle("")
|
|
})
|
|
edPass.OnChange(func(ev Event) {
|
|
lbRes.SetTitle("")
|
|
})
|
|
|
|
if userName == "" {
|
|
ActivateControl(dlg.View, edUser)
|
|
} else {
|
|
ActivateControl(dlg.View, edPass)
|
|
}
|
|
return dlg
|
|
}
|
|
|
|
// OnClose sets the callback that is called when the
|
|
// dialog is closed
|
|
func (d *LoginDialog) OnClose(fn func()) {
|
|
WindowManager().BeginUpdate()
|
|
defer WindowManager().EndUpdate()
|
|
d.onClose = fn
|
|
}
|
|
|
|
// OnCheck sets the callback that is called when the
|
|
// button "OK" is clicked. The dialog sends to the callback two arguments:
|
|
// username and password. The callback validates the arguments and if
|
|
// the credentials are valid it returns true. That means the dialog can be
|
|
// closed. If the callback returns false then the dialog remains on the screen.
|
|
func (d *LoginDialog) OnCheck(fn func(string, string) bool) {
|
|
WindowManager().BeginUpdate()
|
|
defer WindowManager().EndUpdate()
|
|
d.onCheck = fn
|
|
}
|