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:
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;