From 895f5510731bec0b161ba9b651b5a77dd8cb96a4 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Mon, 22 Aug 2022 16:39:21 +0200 Subject: [PATCH] Keyboard accelerators for install/reinstall/uninstall Ctrl+I/R/U select install/reinstall/uninstall and then move selection to next row. --- ListView.cc | 64 +++++++++++++++++++++++++++++++-------------- ListView.h | 10 ++++++- PickCategoryLine.cc | 21 +++++++-------- PickCategoryLine.h | 2 +- PickPackageLine.cc | 27 ++++++++++++++----- PickPackageLine.h | 2 +- package_meta.cc | 11 ++++++++ 7 files changed, 97 insertions(+), 40 deletions(-) diff --git a/ListView.cc b/ListView.cc index 62a37ab..7cc7f0f 100644 --- a/ListView.cc +++ b/ListView.cc @@ -24,6 +24,18 @@ // ListView Common Control // --------------------------------------------------------------------------- +int ModifierKeys::get() +{ + int keys = 0; + if (GetKeyState(VK_SHIFT) & 0x8000) + keys |= Shift; + if (GetKeyState(VK_CONTROL) & 0x8000) + keys |= Control; + if (GetKeyState(VK_MENU) & 0x8000) + keys |= Alt; + return keys; +} + void ListView::init(HWND parent, int id, HeaderList headers) { @@ -563,33 +575,47 @@ ListView::OnNotify (NMHDR *pNmHdr, LRESULT *pResult) { NMLVKEYDOWN *pNmLvKeyDown = (NMLVKEYDOWN *)pNmHdr; int iRow = ListView_GetSelectionMark(hWndListView); + int modkeys = ModifierKeys::get(); #if DEBUG - Log (LOG_PLAIN) << "LVN_KEYDOWN vkey " << pNmLvKeyDown->wVKey << " on row " << iRow << endLog; + Log (LOG_PLAIN) << "LVN_KEYDOWN vkey " << pNmLvKeyDown->wVKey << " on row " << iRow + << " Shift:" << !!(modkeys & ModifierKeys::Shift) + << " Ctrl:" << !!(modkeys & ModifierKeys::Control) + << " Alt:" << !!(modkeys & ModifierKeys::Alt) << endLog; #endif if (contents && iRow >= 0) { - int col_num; - int action_id; - if ((*contents)[iRow]->map_key_to_action(pNmLvKeyDown->wVKey, &col_num, &action_id)) + int col_num = 0; + int action_id = 0; + int todo = (*contents)[iRow]->map_key_to_action(pNmLvKeyDown->wVKey, modkeys, + col_num, action_id); + int update = 0; + if (todo & ListViewLine::Action::Direct) + update = (*contents)[iRow]->do_action(col_num, action_id); + else if (todo & ListViewLine::Action::PopUp) { - int update; - if (action_id >= 0) - update = (*contents)[iRow]->do_action(col_num, action_id); - else - { - POINT p; - RECT r; - ListView_GetSubItemRect(hWndListView, iRow, col_num, LVIR_BOUNDS, &r); - p.x = r.left; - p.y = r.top; - ClientToScreen(hWndListView, &p); + POINT p; + RECT r; + ListView_GetSubItemRect(hWndListView, iRow, col_num, LVIR_BOUNDS, &r); + p.x = r.left; + p.y = r.top; + ClientToScreen(hWndListView, &p); + + update = popup_menu(iRow, col_num, p); + } - update = popup_menu(iRow, col_num, p); - } + if (update > 0) + ListView_RedrawItems(hWndListView, iRow, iRow + update -1); - if (update > 0) - ListView_RedrawItems(hWndListView, iRow, iRow + update -1); + if ((todo & ListViewLine::Action::NextRow) + && iRow + 1 < ListView_GetItemCount(hWndListView)) + { + // move selection to next row + ListView_SetItemState(hWndListView, -1, 0, LVIS_SELECTED | LVIS_FOCUSED); + ListView_SetItemState(hWndListView, iRow + 1, LVIS_SELECTED | LVIS_FOCUSED, + LVIS_SELECTED | LVIS_FOCUSED); + ListView_SetSelectionMark(hWndListView, iRow + 1); + ListView_EnsureVisible(hWndListView, iRow + 1, false); } } } diff --git a/ListView.h b/ListView.h index 95dd9ee..6a1be0b 100644 --- a/ListView.h +++ b/ListView.h @@ -25,10 +25,17 @@ // ListView Common Control // --------------------------------------------------------------------------- +struct ModifierKeys +{ + enum { Shift = 0x01, Control = 0x02, Alt = 0x04 }; + static int get(); // get bitmask of currently pressed keys +}; + class ListViewLine { public: enum class State { collapsed, expanded, nothing=-1 }; + enum Action { None = 0x00, Direct = 0x01, PopUp = 0x02, NextRow = 0x04 }; virtual ~ListViewLine() {}; virtual const std::wstring get_text(int col) const = 0; @@ -38,7 +45,8 @@ class ListViewLine virtual ActionList *get_actions(int col) const = 0; virtual int do_action(int col, int id) = 0; virtual int do_default_action(int col) = 0; - virtual bool map_key_to_action(WORD vkey, int *col_num, int *action_id) const = 0; + virtual int map_key_to_action(WORD vkey, int modkeys, int & col_num, + int & action_id) const = 0; }; typedef std::vector ListViewContents; diff --git a/PickCategoryLine.cc b/PickCategoryLine.cc index d2ac899..b13dbe4 100644 --- a/PickCategoryLine.cc +++ b/PickCategoryLine.cc @@ -96,20 +96,19 @@ PickCategoryLine::get_tooltip(int col_num) const return ""; } -bool -PickCategoryLine::map_key_to_action(WORD vkey, int *col_num, int *action_id) const +int +PickCategoryLine::map_key_to_action(WORD vkey, int modkeys, int & col_num, + int & action_id) const { switch (vkey) { - case VK_SPACE: - *col_num = pkgname_col; - *action_id = 0; - return true; - case VK_APPS: - *col_num = new_col; - *action_id = -1; - return true; + case VK_SPACE: // expand <> collapse category + col_num = pkgname_col; + return Action::Direct; + case VK_APPS: // install/reinstall/uninstall context menu for category + col_num = new_col; + return Action::PopUp; } - return false; + return Action::None; } diff --git a/PickCategoryLine.h b/PickCategoryLine.h index 6a7321d..7616b15 100644 --- a/PickCategoryLine.h +++ b/PickCategoryLine.h @@ -41,7 +41,7 @@ public: ActionList *get_actions(int col) const; int do_action(int col, int action_id); int do_default_action(int col); - bool map_key_to_action(WORD vkey, int *col_num, int *action_id) const; + int map_key_to_action(WORD vkey, int modkeys, int & col_num, int & action_id) const; private: CategoryTree * cat_tree; diff --git a/PickPackageLine.cc b/PickPackageLine.cc index ae1e520..c1e2a15 100644 --- a/PickPackageLine.cc +++ b/PickPackageLine.cc @@ -144,17 +144,30 @@ PickPackageLine::get_indent() const return indent; } -bool -PickPackageLine::map_key_to_action(WORD vkey, int *col_num, int *action_id) const +int +PickPackageLine::map_key_to_action(WORD vkey, int modkeys, int & col_num, + int & action_id) const { switch (vkey) { - case VK_SPACE: + case VK_SPACE: // install/reinstall/uninstall context menu for package case VK_APPS: - *col_num = new_col; - *action_id = -1; - return true; + col_num = new_col; + return Action::PopUp; + case 'I': // Ctrl+I: select install default version and move to next row + case 'R': // Ctrl+R: select reinstall and move to next row + case 'U': // Ctrl+U: select uninstall and move to next row + if (modkeys != ModifierKeys::Control) + break; + col_num = new_col; + switch (vkey) + { + case 'I': action_id = packagemeta::Install_action; break; + case 'R': action_id = packagemeta::Reinstall_action; break; + default: action_id = packagemeta::Uninstall_action; break; + } + return Action::Direct | Action::NextRow; } - return false; + return Action::None; } diff --git a/PickPackageLine.h b/PickPackageLine.h index 2c59e90..0bf4ae6 100644 --- a/PickPackageLine.h +++ b/PickPackageLine.h @@ -37,7 +37,7 @@ public: ActionList *get_actions(int col_num) const; int do_action(int col, int action_id); int do_default_action(int col); - bool map_key_to_action(WORD vkey, int *col_num, int *action_id) const; + int map_key_to_action(WORD vkey, int modkeys, int & col_num, int & action_id) const; private: packagemeta & pkg; PickView & theView; diff --git a/package_meta.cc b/package_meta.cc index 8a69525..a5dc436 100644 --- a/package_meta.cc +++ b/package_meta.cc @@ -651,6 +651,13 @@ packagemeta::set_action (_actions action, packageversion const &default_version, srcpick (false); } } + else + { + action = NoChange_action; + desired = installed; + pick (false); + srcpick (false); + } } else if (action == Reinstall_action) { @@ -670,6 +677,10 @@ packagemeta::set_action (_actions action, packageversion const &default_version, else if (action == Uninstall_action) { desired = packageversion (); + pick (false); + srcpick (false); + if (!installed) + action = NoChange_action; } _action = action; -- 2.37.1