reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/CMakeLists.txt | 2+-
Msrc/browser.cpp | 3+--
Msrc/listview.cpp | 12++++++++++++
Msrc/listview.hpp | 9+++++----
Asrc/listview.mm | 33+++++++++++++++++++++++++++++++++
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]; +}