From 24ee239baa845bf918a8552242b0dc26e18c9cc2 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 5 May 2019 16:02:37 +0200 Subject: ui: use context menus for all shortcuts --- ui/logpage.go | 58 +++++++++++++++++++++++++++++---------------- ui/tunnelspage.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 21 deletions(-) diff --git a/ui/logpage.go b/ui/logpage.go index c0d4cd2a..ddd0a70e 100644 --- a/ui/logpage.go +++ b/ui/logpage.go @@ -46,7 +46,29 @@ func NewLogPage() (*LogPage, error) { } lp.logView.SetAlternatingRowBGColor(walk.Color(win.GetSysColor(win.COLOR_BTNFACE))) lp.logView.SetLastColumnStretched(true) - lp.logView.KeyPress().Attach(lp.onCopyLogLines) + + contextMenu, _ := walk.NewMenu() + copyAction := walk.NewAction() + copyAction.SetText("&Copy") + copyAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyC}) + copyAction.Triggered().Attach(lp.onCopy) + contextMenu.Actions().Add(copyAction) + selectAllAction := walk.NewAction() + selectAllAction.SetText("Select &all") + selectAllAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyA}) + selectAllAction.Triggered().Attach(lp.onSelectAll) + contextMenu.Actions().Add(selectAllAction) + saveAction := walk.NewAction() + saveAction.SetText("&Save to file") + saveAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyS}) + saveAction.Triggered().Attach(lp.onSave) + contextMenu.Actions().Add(saveAction) + lp.logView.SetContextMenu(contextMenu) + setSelectionStatus := func() { + copyAction.SetEnabled(len(lp.logView.SelectedIndexes()) > 0) + selectAllAction.SetEnabled(len(lp.logView.SelectedIndexes()) < len(lp.model.items)) + } + lp.logView.SelectedIndexesChanged().Attach(setSelectionStatus) stampCol := walk.NewTableViewColumn() stampCol.SetName("Stamp") @@ -62,6 +84,7 @@ func NewLogPage() (*LogPage, error) { lp.model = newLogModel(lp) lp.logView.SetModel(lp.model) + setSelectionStatus() buttonsContainer, err := walk.NewComposite(lp) if err != nil { @@ -77,7 +100,7 @@ func NewLogPage() (*LogPage, error) { return nil, err } saveButton.SetText("Save") - saveButton.Clicked().Attach(lp.onSaveButtonClicked) + saveButton.Clicked().Attach(lp.onSave) disposables.Spare() @@ -98,29 +121,24 @@ func (lp *LogPage) scrollToBottom() { lp.logView.EnsureItemVisible(len(lp.model.items) - 1) } -func (lp *LogPage) onCopyLogLines(key walk.Key) { - if !walk.ControlDown() { +func (lp *LogPage) onCopy() { + var logLines strings.Builder + selectedItemIndexes := lp.logView.SelectedIndexes() + if len(selectedItemIndexes) == 0 { return } - - switch key { - case walk.KeyC: - var logLines strings.Builder - selectedItemIndexes := lp.logView.SelectedIndexes() - if len(selectedItemIndexes) == 0 { - return - } - for i := 0; i < len(selectedItemIndexes); i++ { - logItem := lp.model.items[selectedItemIndexes[i]] - logLines.WriteString(fmt.Sprintf("%s: %s\r\n", logItem.Stamp.Format("2006-01-02 15:04:05.000"), logItem.Line)) - } - walk.Clipboard().SetText(logLines.String()) - case walk.KeyA: - lp.logView.SetSelectedIndexes([]int{-1}) + for i := 0; i < len(selectedItemIndexes); i++ { + logItem := lp.model.items[selectedItemIndexes[i]] + logLines.WriteString(fmt.Sprintf("%s: %s\r\n", logItem.Stamp.Format("2006-01-02 15:04:05.000"), logItem.Line)) } + walk.Clipboard().SetText(logLines.String()) +} + +func (lp *LogPage) onSelectAll() { + lp.logView.SetSelectedIndexes([]int{-1}) } -func (lp *LogPage) onSaveButtonClicked() { +func (lp *LogPage) onSave() { fd := walk.FileDialog{ Filter: "Text Files (*.txt)|*.txt|All Files (*.*)|*.*", FilePath: fmt.Sprintf("wireguard-log-%s.txt", time.Now().Format("2006-01-02T150405")), diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go index a4bbcd79..6069aee2 100644 --- a/ui/tunnelspage.go +++ b/ui/tunnelspage.go @@ -137,7 +137,7 @@ func (tp *TunnelsPage) CreateToolbar() { importAction.SetDefault(true) importAction.Triggered().Attach(tp.onImport) addAction := walk.NewAction() - addAction.SetText("Add empty tunnel") + addAction.SetText("Add empty tunnel...") addActionIcon, _ := loadSystemIcon("imageres", 2) addActionImage, _ := walk.NewBitmapFromIcon(addActionIcon, imageSize) addAction.SetImage(addActionImage) @@ -171,12 +171,76 @@ func (tp *TunnelsPage) CreateToolbar() { exportActionImage, _ := walk.NewBitmapFromIcon(exportActionIcon, imageSize) exportAction.SetImage(exportActionImage) exportAction.SetToolTip("Export all tunnels to zip...") + exportAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyS}) exportAction.Triggered().Attach(tp.onExportTunnels) tp.listToolbar.Actions().Add(exportAction) var size win.SIZE tp.listToolbar.SendMessage(win.TB_GETIDEALSIZE, win.FALSE, uintptr(unsafe.Pointer(&size))) tp.listContainer.SetMinMaxSize(walk.Size{int(size.CX), 0}, walk.Size{int(size.CX), 0}) + + contextMenu, _ := walk.NewMenu() + toggleAction := walk.NewAction() + toggleAction.SetText("&Toggle") + toggleAction.SetDefault(true) + toggleAction.Triggered().Attach(tp.onTunnelsViewItemActivated) + contextMenu.Actions().Add(toggleAction) + contextMenu.Actions().Add(walk.NewSeparatorAction()) + importAction2 := walk.NewAction() + importAction2.SetText("Import tunnel(s) from file...") + importAction2.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyO}) + importAction2.Triggered().Attach(tp.onImport) + contextMenu.Actions().Add(importAction2) + addAction2 := walk.NewAction() + addAction2.SetText("Add empty tunnel...") + addAction2.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyN}) + addAction2.Triggered().Attach(tp.onAddTunnel) + contextMenu.Actions().Add(addAction2) + exportAction2 := walk.NewAction() + exportAction2.SetText("Export all tunnels to zip...") + exportAction2.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyS}) + exportAction2.Triggered().Attach(tp.onExportTunnels) + contextMenu.Actions().Add(exportAction2) + contextMenu.Actions().Add(walk.NewSeparatorAction()) + editAction := walk.NewAction() + editAction.SetText("Edit selected tunnel") + editAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyE}) + editAction.Triggered().Attach(tp.onEditTunnel) + contextMenu.Actions().Add(editAction) + deleteAction2 := walk.NewAction() + deleteAction2.SetText("Remove selected tunnel(s)") + deleteAction2.SetShortcut(walk.Shortcut{0, walk.KeyDelete}) + deleteAction2.Triggered().Attach(tp.onDelete) + contextMenu.Actions().Add(deleteAction2) + tp.listView.SetContextMenu(contextMenu) + selectAllAction := walk.NewAction() + selectAllAction.SetText("Select all") + selectAllAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyA}) + selectAllAction.Triggered().Attach(tp.onSelectAll) + contextMenu.Actions().Add(selectAllAction) + tp.listView.SetContextMenu(contextMenu) + + setSelectionOrientedOptions := func() { + selected := len(tp.listView.SelectedIndexes()) + all := len(tp.listView.model.tunnels) + deleteAction.SetEnabled(selected > 0) + deleteAction2.SetEnabled(selected > 0) + toggleAction.SetEnabled(selected == 1) + selectAllAction.SetEnabled(selected < all) + editAction.SetEnabled(selected == 1) + } + tp.listView.SelectedIndexesChanged().Attach(setSelectionOrientedOptions) + setSelectionOrientedOptions() + setExport := func() { + all := len(tp.listView.model.tunnels) + exportAction.SetEnabled(all > 0) + exportAction2.SetEnabled(all > 0) + } + setExportRange := func(from, to int) { setExport() } + tp.listView.model.RowsInserted().Attach(setExportRange) + tp.listView.model.RowsRemoved().Attach(setExportRange) + tp.listView.model.RowsReset().Attach(setExport) + setExport() } func (tp *TunnelsPage) updateConfView() { @@ -443,6 +507,10 @@ func (tp *TunnelsPage) onDelete() { }() } +func (tp *TunnelsPage) onSelectAll() { + tp.listView.SetSelectedIndexes([]int{-1}) +} + func (tp *TunnelsPage) onImport() { dlg := walk.FileDialog{ Filter: "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*", -- cgit v1.2.3-59-g8ed1b