diff --git a/connectdialog_windows.go b/connectdialog_windows.go index f5d9d43..deb58a8 100644 --- a/connectdialog_windows.go +++ b/connectdialog_windows.go @@ -9,7 +9,7 @@ type connectDialog struct { ui connectDialogUI } -func runConnectDialog(currentAddr string, currentPw string, owner walk.Form) (result bool, addr string, pw string, err error) { +func runConnectDialog(currentAddr string, currentPw string, owner walk.Form, title string) (result bool, addr string, pw string, err error) { dlg := new(connectDialog) if err = dlg.init(owner); err != nil { @@ -35,6 +35,10 @@ func runConnectDialog(currentAddr string, currentPw string, owner walk.Form) (re dlg.ui.rconAddress.SetText(currentAddr) dlg.ui.rconPassword.SetText(currentPw) + if title != "" { + dlg.SetTitle(title) + } + choice := dlg.Run() result = choice == walk.DlgCmdOK diff --git a/main_windows.go b/main_windows.go index 30bab8c..7c97266 100644 --- a/main_windows.go +++ b/main_windows.go @@ -5,8 +5,14 @@ package main //go:generate ui2walk import ( + "encoding/json" + "errors" "fmt" + "io/ioutil" "log" + "os" + "os/user" + "path" "strings" "syscall" @@ -30,11 +36,51 @@ var ( history []string historyIndex = 0 + + bookmarksFile string + bookmarks []bookmark + bookmarksMenu *walk.Menu ) +type bookmark struct { + Address string `json:"address"` + Password string `json:"password"` +} + func init() { kernel32, guiInitErr = syscall.LoadDLL("kernel32.dll") freeConsole, guiInitErr = kernel32.FindProc("FreeConsole") + + // Creates an folder in user home called "IceCon" + initStorage() + loadBookmarks() +} + +func initStorage() { + // If user found create in user home + if usr, err := user.Current(); err == nil { + directory := path.Join(usr.HomeDir, "IceCon") + bookmarksFile = path.Join(usr.HomeDir, "Icecon", "bookmarks.json") + + os.Mkdir(directory, os.ModePerm) + } +} + +func loadBookmarks() { + // Loads bookmarks.json from IceCon directory + file, err := ioutil.ReadFile(bookmarksFile) + if err != nil { + return + } + + json.Unmarshal(file, &bookmarks) +} + +func saveBookmarks() { + // Saves current bookmarks to file + if out, err := json.Marshal(bookmarks); err == nil { + ioutil.WriteFile(bookmarksFile, out, os.ModePerm) + } } func uiLogError(text string) { @@ -84,6 +130,53 @@ func addToHistory(command string) { historyIndex = len(history) } +func getBookmark(address string) (bookmark, error) { + var bookmark bookmark + + // Gets the bookmark by address + for _, item := range bookmarks { + if item.Address == address { + return item, nil + } + } + + return bookmark, errors.New("No bookmark found") +} + +func createBookmarkItem(address string) *walk.Action { + // Create bookmark item (used in init UI and add bookmark) + item := walk.NewAction() + item.SetText(address) + + // Connect to selected server + item.Triggered().Attach(func() { + // Get the right bookmark + bookmark, err := getBookmark(item.Text()) + if err != nil { + return + } + if err = initSocketAddr(bookmark.Address); err != nil { + uiLogError(fmt.Sprintf("Couldn't use that address: %s", err)) + return + } + + password = bookmark.Password + addressStr = bookmark.Address + dlg.ui.rconOutput.SetText("") + + uiUpdateAddress() + + // Uncheck other items + for i := 0; i < bookmarksMenu.Actions().Len(); i++ { + item := bookmarksMenu.Actions().At(i) + item.SetChecked(false) + } + item.SetChecked(true) + }) + + return item +} + func runGraphicalUi() (err error) { dlg = new(mainDialog) if err := dlg.init(); err != nil { @@ -116,7 +209,7 @@ func runGraphicalUi() (err error) { return } connectAction.Triggered().Attach(func() { - result, addr, pw, err := runConnectDialog(addressStr, password, dlg) + result, addr, pw, err := runConnectDialog(addressStr, password, dlg, "") if err != nil { uiLogError(fmt.Sprintf("Failed to run connect dialog: %s", err)) return @@ -135,6 +228,47 @@ func runGraphicalUi() (err error) { return } + // Bookmarks list + bookmarksMenu, _ = walk.NewMenu() + + // Add for every bookmark a menu action + for _, bookmark := range bookmarks { + item := createBookmarkItem(bookmark.Address) + bookmarksMenu.Actions().Add(item) + } + + // Add bookmark item + addBookmarkAction := walk.NewAction() + if err = addBookmarkAction.SetText("New bookmark"); err != nil { + return + } + addBookmarkAction.Triggered().Attach(func() { + // Re-use connect dialog as "add bookmark" dialog + result, addr, pw, err := runConnectDialog("", "", dlg, "Add bookmark") + if err != nil { + uiLogError(fmt.Sprintf("Failed to run connect dialog: %s", err)) + return + } + + // Add bookmark if not empty addr + if result && len(addr) > 0 { + bookmarks = append(bookmarks, bookmark{addr, pw}) + item := createBookmarkItem(addr) + // Add before "add bookmark" action + bookmarksMenu.Actions().Insert((bookmarksMenu.Actions().Len() - 1), item) + + // Save bookmarks to file + saveBookmarks() + } + }) + bookmarksMenu.Actions().Add(addBookmarkAction) + + // Bookmarks menu + bookmarksAction, _ := dlg.Menu().Actions().AddMenu(bookmarksMenu) + if err = bookmarksAction.SetText("Bookmarks"); err != nil { + return + } + // Handle input dlg.ui.rconInput.KeyPress().Attach(func(key walk.Key) { // handle history (arrow up/down)