[PATCH setup 4/4] Add double-click for a 'default action' to ListView
Jon Turney
jon.turney@dronecode.org.uk
Thu Mar 21 15:36:00 GMT 2019
Add support for a double-click in the ListView to invoke a 'default
action'.
Because we receive both NM_CLICK and then NM_DBCLK, reduce the area of a
pop-up column which is sensitive to a click to the drop-down button
(which opens a focus-stealing pop-up menu), so the rest of the area can
receive a click (which does nothing) or a double-click (which does the
default action).
For a package, this default action is to toggle between the currently
installed version (or uninstalled, if not installed), and the highest
non-test version.
There is no keyboard acceleration for this action currently.
Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
---
ListView.cc | 38 +++++++++++++++++++++++++++++++++++++-
ListView.h | 1 +
PickCategoryLine.cc | 6 ++++++
PickCategoryLine.h | 1 +
PickPackageLine.cc | 11 +++++++++++
PickPackageLine.h | 1 +
package_meta.cc | 21 +++++++++++++++++++++
package_meta.h | 1 +
8 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/ListView.cc b/ListView.cc
index d58780b..a6dc56d 100644
--- a/ListView.cc
+++ b/ListView.cc
@@ -345,9 +345,19 @@ ListView::OnNotify (NMHDR *pNmHdr, LRESULT *pResult)
if (headers[iCol].type == ListView::ControlType::popup)
{
POINT p;
- // position pop-up menu at the location of the click
GetCursorPos(&p);
+ RECT r;
+ ListView_GetSubItemRect(hWndListView, iRow, iCol, LVIR_BOUNDS, &r);
+ POINT cp = p;
+ ::ScreenToClient(hWndListView, &cp);
+
+ // if the click isn't over the pop-up button, do nothing yet (but this
+ // might be followed by a NM_DBLCLK)
+ if (cp.x < r.right - GetSystemMetrics(SM_CXVSCROLL))
+ return true;
+
+ // position pop-up menu at the location of the click
update = popup_menu(iRow, iCol, p);
}
else
@@ -366,6 +376,32 @@ ListView::OnNotify (NMHDR *pNmHdr, LRESULT *pResult)
}
break;
+ case NM_DBLCLK:
+ {
+ NMITEMACTIVATE *pNmItemAct = (NMITEMACTIVATE *) pNmHdr;
+#if DEBUG
+ Log (LOG_BABBLE) << "NM_DBLCLICK: pnmitem->iItem " << pNmItemAct->iItem << " pNmItemAct->iSubItem " << pNmItemAct->iSubItem << endLog;
+#endif
+ int iRow = pNmItemAct->iItem;
+ int iCol = pNmItemAct->iSubItem;
+ if (iRow < 0)
+ return false;
+
+ int update = 0;
+
+ // Inform the item of the double-click
+ update = (*contents)[iRow]->do_default_action(iCol );
+
+ // Update items, if needed
+ if (update > 0)
+ {
+ ListView_RedrawItems(hWndListView, iRow, iRow + update -1);
+ }
+
+ return true;
+ }
+ break;
+
case NM_CUSTOMDRAW:
{
NMLVCUSTOMDRAW *pNmLvCustomDraw = (NMLVCUSTOMDRAW *)pNmHdr;
diff --git a/ListView.h b/ListView.h
index 97b138a..519b61a 100644
--- a/ListView.h
+++ b/ListView.h
@@ -37,6 +37,7 @@ class ListViewLine
virtual int get_indent() const = 0;
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;
};
diff --git a/PickCategoryLine.cc b/PickCategoryLine.cc
index c088cd4..7aa1f28 100644
--- a/PickCategoryLine.cc
+++ b/PickCategoryLine.cc
@@ -56,6 +56,12 @@ PickCategoryLine::do_action(int col_num, int action_id)
return 1;
}
+int
+PickCategoryLine::do_default_action(int col_num)
+{
+ return 0;
+}
+
ActionList *
PickCategoryLine::get_actions(int col) const
{
diff --git a/PickCategoryLine.h b/PickCategoryLine.h
index 9486904..35b90e6 100644
--- a/PickCategoryLine.h
+++ b/PickCategoryLine.h
@@ -40,6 +40,7 @@ public:
int get_indent() const;
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;
private:
diff --git a/PickPackageLine.cc b/PickPackageLine.cc
index 1f884be..685d632 100644
--- a/PickPackageLine.cc
+++ b/PickPackageLine.cc
@@ -144,6 +144,17 @@ PickPackageLine::do_action(int col_num, int action_id)
return 0;
}
+int
+PickPackageLine::do_default_action(int col_num)
+{
+ if (col_num == new_col)
+ {
+ pkg.toggle_action();
+ return 1;
+ }
+ return 0;
+}
+
ActionList *
PickPackageLine::get_actions(int col_num) const
{
diff --git a/PickPackageLine.h b/PickPackageLine.h
index a35f399..3877a4b 100644
--- a/PickPackageLine.h
+++ b/PickPackageLine.h
@@ -36,6 +36,7 @@ public:
int get_indent() const;
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;
private:
packagemeta & pkg;
diff --git a/package_meta.cc b/package_meta.cc
index cbb7388..3509f05 100644
--- a/package_meta.cc
+++ b/package_meta.cc
@@ -465,6 +465,27 @@ packagemeta::select_action (int id, trusts const deftrust)
user_picked = true;
}
+// toggle between the currently installed version (or uninstalled, if not
+// installed), and the naively preferred version (the highest non-test version)
+void
+packagemeta::toggle_action ()
+{
+ if (desired != installed)
+ {
+ set_action(Default_action, installed);
+ }
+ else
+ {
+ packageversion naively_preferred;
+ std::set<packageversion>::iterator i = versions.begin ();
+ for (i = versions.begin (); i != versions.end (); ++i)
+ if (!packagedb::solver.is_test_package(*i))
+ naively_preferred = *i;
+
+ set_action(Install_action, naively_preferred);
+ }
+}
+
ActionList *
packagemeta::list_actions(trusts const trust)
{
diff --git a/package_meta.h b/package_meta.h
index 0eff8d0..c9bfe7c 100644
--- a/package_meta.h
+++ b/package_meta.h
@@ -63,6 +63,7 @@ public:
void set_action (_actions, packageversion const & default_version);
ActionList *list_actions(trusts const trust);
void select_action (int id, trusts const deftrust);
+ void toggle_action ();
void set_message (const std::string& message_id, const std::string& message_string)
{
--
2.17.0
More information about the Cygwin-apps
mailing list