commit 4cb302522651af034834c78e77d6df238eb51b7f
parent b3db16a1b6e1096d374ab0003ed8dca5de8ccd18
Author: cfillion <cfillion@users.noreply.github.com>
Date: Mon, 13 Jan 2020 15:30:03 -0500
optimize (un)selecting many listview items at once on macOS
Diffstat:
5 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -77,7 +77,7 @@ add_library(reapack OBJECT
index.cpp
index_v1.cpp
install.cpp
- listview.cpp
+ listview.cpp $<IF:$<BOOL:${APPLE}>,listview.mm,>
main.cpp
manager.cpp
menu.cpp
diff --git a/src/browser.cpp b/src/browser.cpp
@@ -564,8 +564,7 @@ void Browser::fillList()
// restore selection only after having sorted the table
// in order to get the same scroll position as before if possible
- for(const int index : selectIndexes)
- m_list->select(index);
+ m_list->select(selectIndexes);
m_list->endEdit(); // filter before calling updateDisplayLabel
updateDisplayLabel();
diff --git a/src/listview.cpp b/src/listview.cpp
@@ -342,6 +342,18 @@ void ListView::setSelected(const int index, const bool select)
select ? LVIS_SELECTED : 0, LVIS_SELECTED);
}
+#ifndef __APPLE__
+// optimized macOS implementations in listview.mm
+void ListView::setSelected(const std::vector<int> &indexes, const bool select)
+{
+ for(const int index : indexes)
+ setSelected(index, select);
+}
+
+void ListView::selectAll() { select(-1); }
+void ListView::unselectAll() { unselect(-1); }
+#endif
+
int ListView::visibleRowCount() const
{
return ListView_GetItemCount(handle());
diff --git a/src/listview.hpp b/src/listview.hpp
@@ -128,10 +128,11 @@ public:
void setScroll(int);
void setSelected(int index, bool select);
- void select(int index) { setSelected(index, true); }
- void unselect(int index) { setSelected(index, false); }
- void selectAll() { select(-1); }
- void unselectAll() { unselect(-1); }
+ void setSelected(const std::vector<int> &indexes, bool select);
+ template<typename T> void select(T index) { setSelected(index, true); }
+ template<typename T> void unselect(T index) { setSelected(index, false); }
+ void selectAll();
+ void unselectAll();
int selectionSize() const;
bool hasSelection() const { return selectionSize() > 0; }
std::vector<int> selection(bool sort = true) const;
diff --git a/src/listview.mm b/src/listview.mm
@@ -0,0 +1,33 @@
+#include "listview.hpp"
+
+#include <Cocoa/Cocoa.h>
+
+// NSTableView::selectRowIndexes is an expansive operation so selecting
+// thousands of items individually can take seconds on macOS
+// (observed on 10.10 and 10.15).
+//
+// As a side effect of the optimizations below, SWELL will post a single
+// LVN_ITEMCHANGED notification instead of one per item.
+
+void ListView::setSelected(const std::vector<int> &indexes, const bool select)
+{
+ auto indexSet = [NSMutableIndexSet indexSet];
+
+ for(const int index : indexes)
+ [indexSet addIndex: index];
+
+ auto tableView = reinterpret_cast<NSTableView *>(handle());
+ [tableView selectRowIndexes: indexSet byExtendingSelection: select];
+}
+
+void ListView::selectAll()
+{
+ auto tableView = reinterpret_cast<NSTableView *>(handle());
+ [tableView selectAll: tableView];
+}
+
+void ListView::unselectAll()
+{
+ auto tableView = reinterpret_cast<NSTableView *>(handle());
+ [tableView deselectAll: tableView];
+}