reapack

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

commit f114102df35b299ab6c9dd832894093b9f83da95
parent 96c2dd41a8f6294df75c0d0833a914f310f449e6
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Mon, 23 Oct 2017 06:25:53 -0400

listview: move filtering responsability, optimize

This commit implements the prerequisites for #11.

Diffstat:
Msrc/browser.cpp | 39+++++++++++++++++----------------------
Msrc/browser.hpp | 4+---
Msrc/listview.cpp | 82++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/listview.hpp | 20++++++++++++++++----
4 files changed, 107 insertions(+), 38 deletions(-)

diff --git a/src/browser.cpp b/src/browser.cpp @@ -41,7 +41,7 @@ Browser::Browser() void Browser::onInit() { m_applyBtn = getControl(IDAPPLY); - m_filterHandle = getControl(IDC_FILTER); + m_filter = getControl(IDC_FILTER); m_view = getControl(IDC_TABS); m_displayBtn = getControl(IDC_DISPLAY); m_actionsBtn = getControl(IDC_ACTION); @@ -59,13 +59,13 @@ void Browser::onInit() SendMessage(m_view, CB_SETCURSEL, 0, 0); m_list = createControl<ListView>(IDC_LIST, ListView::Columns{ - {"Status", 23, ListView::NoLabelFlag}, - {"Package", 345}, - {"Category", 105}, - {"Version", 55, 0, ListView::VersionType}, - {"Author", 95}, - {"Type", 70}, - {"Repository", 120, ListView::CollapseFlag}, + {"Status", 23, ListView::NoLabelFlag}, + {"Package", 345, ListView::FilterFlag}, + {"Category", 105, ListView::FilterFlag}, + {"Version", 55, 0, ListView::VersionType}, + {"Author", 95, ListView::FilterFlag}, + {"Type", 70}, + {"Repository", 120, ListView::CollapseFlag | ListView::FilterFlag}, {"Last Update", 105, 0, ListView::TimeType}, }); @@ -77,7 +77,7 @@ void Browser::onInit() Dialog::onInit(); setMinimumSize({600, 250}); - setAnchor(m_filterHandle, AnchorRight); + setAnchor(m_filter, AnchorRight); setAnchor(getControl(IDC_CLEAR), AnchorLeftRight); setAnchor(getControl(IDC_LABEL2), AnchorLeftRight); setAnchor(m_view, AnchorLeftRight); @@ -366,12 +366,8 @@ void Browser::updateFilter() { stopTimer(TIMER_FILTER); - const string &filter = Win32::getWindowText(m_filterHandle); - - if(m_filter != filter) { - m_filter = filter; - fillList(); - } + m_list->setFilter(Win32::getWindowText(m_filter)); + updateDisplayLabel(); } void Browser::updateAbout() @@ -474,9 +470,9 @@ void Browser::populate(const vector<IndexPtr> &indexes, const Registry *reg) void Browser::setFilter(const string &newFilter) { - Win32::setWindowText(m_filterHandle, newFilter.c_str()); + Win32::setWindowText(m_filter, newFilter.c_str()); updateFilter(); // don't wait for the timer, update now! - SetFocus(m_filterHandle); + SetFocus(m_filter); } void Browser::transferActions() @@ -553,6 +549,9 @@ void Browser::fillList() bool Browser::match(const Entry &entry) const { + if(isFiltered(entry.type())) + return false; + switch(currentView()) { case AllView: break; @@ -578,11 +577,7 @@ bool Browser::match(const Entry &entry) const break; } - if(isFiltered(entry.type())) - return false; - - return m_filter.match({entry.displayName(), entry.categoryName(), - entry.displayAuthor(), entry.indexName()}); + return true; } auto Browser::getEntry(const int index) -> Entry * diff --git a/src/browser.hpp b/src/browser.hpp @@ -20,7 +20,6 @@ #include "dialog.hpp" -#include "filter.hpp" #include "package.hpp" #include <boost/optional.hpp> @@ -125,12 +124,11 @@ private: LoadState m_loadState; int m_currentIndex; - Filter m_filter; boost::optional<Package::Type> m_typeFilter; std::vector<Entry> m_entries; std::list<Entry *> m_actions; - HWND m_filterHandle; + HWND m_filter; HWND m_view; HWND m_displayBtn; HWND m_actionsBtn; diff --git a/src/listview.cpp b/src/listview.cpp @@ -76,18 +76,24 @@ int ListView::addColumn(const Column &col) auto ListView::createRow(void *data) -> RowPtr { + const int index = rowCount(); + insertItem(index, index); + + RowPtr row = make_shared<Row>(data, this); + m_rows.push_back(row); + + return row; +} + +void ListView::insertItem(const int viewIndex, const int rowIndex) +{ LVITEM item{}; - item.iItem = rowCount(); + item.iItem = viewIndex; item.mask |= LVIF_PARAM; - item.lParam = item.iItem; + item.lParam = rowIndex; ListView_InsertItem(handle(), &item); - - RowPtr row = make_shared<Row>(m_cols.size(), data, this); - m_rows.push_back(row); - - return row; } void ListView::updateCell(int row, int cell) @@ -100,6 +106,8 @@ void ListView::updateCell(int row, int cell) if(m_sort && m_sort->column == cell) m_dirty |= NeedSortFlag; + + m_dirty |= NeedFilterFlag; } void ListView::removeRow(const int userIndex) @@ -207,6 +215,48 @@ void ListView::setSortArrow(const bool set) Header_SetItem(header, m_sort->column, &item); } +void ListView::filter() +{ + vector<int> hide; + + for(int ri = 0; ri < rowCount(); ++ri) { + RowPtr &row = m_rows[ri]; + + if(m_filter.match(row->filterValues())) { + if(row->viewIndex == -1) { + row->viewIndex = visibleRowCount(); + insertItem(row->viewIndex, ri); + + for(int ci = 0; ci < columnCount(); ++ci) + updateCell(ri, ci); + + m_dirty |= NeedSortFlag; + } + } + else if(row->viewIndex > -1) { + hide.emplace_back(row->viewIndex); + row->viewIndex = -1; + } + } + + std::sort(hide.begin(), hide.end()); + for(int i = 0; i < (int)hide.size(); ++i) { + ListView_DeleteItem(handle(), hide[i] - i); + m_dirty |= NeedReindexFlag; + } + + m_dirty &= ~NeedFilterFlag; +} + +void ListView::setFilter(const string &newFilter) +{ + if(m_filter != newFilter) { + m_filter = newFilter; + m_dirty |= NeedFilterFlag; + endEdit(); + } +} + void ListView::reindexVisible() { const int visibleCount = visibleRowCount(); @@ -224,6 +274,8 @@ void ListView::reindexVisible() void ListView::endEdit() { + if(m_dirty & NeedFilterFlag) + filter(); // filter may set NeedSortFlag if(m_dirty & NeedSortFlag) sort(); // sort may set NeedReindexFlag if(m_dirty & NeedReindexFlag) @@ -593,9 +645,9 @@ int ListView::Column::compare(const ListView::Cell &cl, const ListView::Cell &cr return 0; // to make MSVC happy } -ListView::Row::Row(const size_t size, void *data, ListView *list) +ListView::Row::Row(void *data, ListView *list) : userData(data), viewIndex(list->rowCount()), m_userIndex(viewIndex), - m_list(list), m_cells(new Cell[size]) + m_list(list), m_cells(new Cell[m_list->columnCount()]) { } @@ -607,3 +659,15 @@ void ListView::Row::setCell(const int i, const string &val, void *data) m_list->updateCell(m_userIndex, i); } + +vector<string> ListView::Row::filterValues() const +{ + vector<string> values; + + for(int ci = 0; ci < m_list->columnCount(); ++ci) { + if(m_list->column(ci).test(FilterFlag)) + values.push_back(m_cells[ci].value); + } + + return values; +} diff --git a/src/listview.hpp b/src/listview.hpp @@ -20,6 +20,7 @@ #include "control.hpp" +#include "filter.hpp" #include "serializer.hpp" #include <boost/optional.hpp> @@ -36,6 +37,7 @@ public: enum ColumnFlag { NoLabelFlag = 1<<0, CollapseFlag = 1<<1, + FilterFlag = 1<<2, }; enum ColumnDataType { @@ -54,7 +56,7 @@ public: class Row { public: - Row(size_t size, void *data, ListView *); + Row(void *data, ListView *); Row(const Row &) = delete; ~Row() { delete[] m_cells; } @@ -65,6 +67,8 @@ public: const Cell &cell(const int i) const { return m_cells[i]; } void setCell(const int i, const std::string &, void *data = nullptr); + std::vector<std::string> filterValues() const; + protected: friend ListView; int viewIndex; @@ -97,7 +101,6 @@ public: void reserveRows(size_t count) { m_rows.reserve(count); } RowPtr createRow(void *data = nullptr); const RowPtr &row(size_t index) const { return m_rows[index]; } - void updateCell(int row, int cell); void removeRow(int index); int rowCount() const { return (int)m_rows.size(); } int visibleRowCount() const; @@ -123,11 +126,13 @@ public: std::vector<int> selection(bool sort = true) const; int addColumn(const Column &); + const Column &column(int index) const { return m_cols[index]; } void resizeColumn(int index, int width); int columnWidth(int index) const; int columnCount() const { return (int)m_cols.size(); } void sortByColumn(int index, SortOrder order = AscendingOrder, bool user = false); + void setFilter(const std::string &); void endEdit(); void restoreState(Serializer::Data &); @@ -139,8 +144,8 @@ public: void onContextMenu(const MenuSignal::slot_type &slot) { m_onContextMenu.connect(slot); } protected: - void onNotify(LPNMHDR, LPARAM) override; - bool onContextMenu(HWND, int, int) override; + friend Row; + void updateCell(int row, int cell); private: struct Sort { @@ -154,8 +159,12 @@ private: enum DirtyFlag { NeedSortFlag = 1<<0, NeedReindexFlag = 1<<1, + NeedFilterFlag = 1<<2, }; + void onNotify(LPNMHDR, LPARAM) override; + bool onContextMenu(HWND, int, int) override; + static int adjustWidth(int); void setExStyle(int style, bool enable); void setSortArrow(bool); @@ -164,8 +173,10 @@ private: int translate(int userIndex) const; int translateBack(int internalIndex) const; void headerMenu(int x, int y); + void insertItem(int viewIndex, int rowIndex); void sort(); void reindexVisible(); + void filter(); bool m_customizable; std::vector<Column> m_cols; @@ -173,6 +184,7 @@ private: boost::optional<Sort> m_sort; boost::optional<Sort> m_defaultSort; + Filter m_filter; int m_dirty; VoidSignal m_onSelect;