reapack

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

commit 954446b2fe51c79b5e834d0c76644753f1f01007
parent 7058021674a9f0050a461f284e5e3bf59c90f176
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Wed,  3 Feb 2016 01:57:21 -0500

implement sorting in list view

Diffstat:
Msrc/about.cpp | 5+++++
Msrc/listview.cpp | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/listview.hpp | 19++++++++++++++-----
Msrc/manager.cpp | 2+-
Msrc/resource.rc | 4++--
5 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/src/about.cpp b/src/about.cpp @@ -63,6 +63,8 @@ void About::onInit() {AUTO_STR("Author"), 90}, }); + m_packages->sortByColumn(0); + m_installedFiles = getControl(IDC_LIST); m_tabs = createControl<TabBar>(IDC_TABS, TabBar::Tabs{ @@ -132,6 +134,8 @@ void About::populate() for(Category *cat : m_index->categories()) m_cats->addRow({make_autostring(cat->name())}); + m_cats->sortByColumn(0); + updatePackages(); updateInstalledFiles(); @@ -170,6 +174,7 @@ void About::updatePackages() } m_currentCat = catIndex; + m_packages->sort(); } void About::updateInstalledFiles() diff --git a/src/listview.cpp b/src/listview.cpp @@ -24,7 +24,8 @@ using namespace std; ListView::ListView(const Columns &columns, HWND handle) - : Control(handle), m_columnSize(0), m_rowSize(0) + : Control(handle), m_columnSize(0), + m_sortColumn(-1), m_sortOrder(AscendingOrder) { for(const Column &col : columns) addColumn(col); @@ -58,10 +59,14 @@ void ListView::addColumn(const Column &col) int ListView::addRow(const Row &content) { LVITEM item{}; - item.iItem = m_rowSize++; + item.iItem = rowCount(); + + item.mask |= LVIF_PARAM; + item.lParam = item.iItem; ListView_InsertItem(handle(), &item); + m_rows.resize(item.iItem + 1); // make room for the new row replaceRow(item.iItem, content); return item.iItem; @@ -69,20 +74,30 @@ int ListView::addRow(const Row &content) void ListView::replaceRow(const int index, const Row &content) { - LVITEM item{}; - item.iItem = index; + m_rows[index] = content; const int cols = min(m_columnSize, (int)content.size()); for(int i = 0; i < cols; i++) { auto_char *text = const_cast<auto_char *>(content[i].c_str()); - ListView_SetItemText(handle(), item.iItem, i, text); + ListView_SetItemText(handle(), index, i, text); } } void ListView::removeRow(const int index) { ListView_DeleteItem(handle(), index); + m_rows.erase(m_rows.begin() + index); + + // shift lParam to reflect the new row indexes + const int size = rowCount(); + for(int i = index; i < size; i++) { + LVITEM item{}; + item.iItem = i; + item.mask |= LVIF_PARAM; + item.lParam = i; + ListView_SetItem(handle(), &item); + } } void ListView::resizeColumn(const int index, const int width) @@ -90,24 +105,73 @@ void ListView::resizeColumn(const int index, const int width) ListView_SetColumnWidth(handle(), index, width); } -ListView::Row ListView::getRow(const int rowIndex) const +void ListView::sort() +{ + if(m_sortColumn > -1) + sortByColumn(m_sortColumn, m_sortOrder); +} + +void ListView::sortByColumn(const int index, const SortOrder order) +{ + static const auto compare = [](LPARAM aRow, LPARAM bRow, LPARAM param) + { + ListView *view = reinterpret_cast<ListView *>(param); + const int column = view->m_sortColumn; + + const auto_string &a = view->m_rows[aRow][column]; + const auto_string &b = view->m_rows[bRow][column]; + + const int ret = a.compare(b); + + switch(view->m_sortOrder) { + case AscendingOrder: + return ret; + case DescendingOrder: + default: // for MSVC + return -ret; + } + }; + + if(m_sortColumn > -1) + setSortArrow(false); + + m_sortColumn = index; + m_sortOrder = order; + setSortArrow(true); + + ListView_SortItems(handle(), compare, (LPARAM)this); +} + +void ListView::setSortArrow(const bool set) { - Row row(m_columnSize); + HWND header = ListView_GetHeader(handle()); - for(int i = 0; i < m_columnSize; i++) { - auto_char buf[4096]; - ListView_GetItemText(handle(), rowIndex, i, buf, sizeof(buf)); - row[i] = buf; + HDITEM item{}; + item.mask |= HDI_FORMAT; + + if(!Header_GetItem(header, m_sortColumn, &item)) + return; + + item.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP); // clear + + if(set) { + switch(m_sortOrder) { + case AscendingOrder: + item.fmt |= HDF_SORTUP; + break; + case DescendingOrder: + item.fmt |= HDF_SORTDOWN; + } } - return row; + Header_SetItem(header, m_sortColumn, &item); } void ListView::clear() { ListView_DeleteAllItems(handle()); - m_rowSize = 0; + m_rows.clear(); } bool ListView::hasSelection() const @@ -117,10 +181,20 @@ bool ListView::hasSelection() const int ListView::currentIndex() const { - return ListView_GetNextItem(handle(), -1, LVNI_SELECTED); + const int internalIndex = ListView_GetNextItem(handle(), -1, LVNI_SELECTED); + + if(internalIndex < 0) + return -1; + + LVITEM item{}; + item.iItem = internalIndex; + item.mask |= LVIF_PARAM; + ListView_GetItem(handle(), &item); + + return (int)item.lParam; } -void ListView::onNotify(LPNMHDR info, LPARAM) +void ListView::onNotify(LPNMHDR info, LPARAM lParam) { switch(info->code) { case LVN_ITEMCHANGED: @@ -129,5 +203,28 @@ void ListView::onNotify(LPNMHDR info, LPARAM) case NM_DBLCLK: m_onDoubleClick(); break; + case LVN_COLUMNCLICK: + onColumnClick(lParam); + break; }; } + +void ListView::onColumnClick(LPARAM lParam) +{ + auto info = (LPNMLISTVIEW)lParam; + const int col = info->iSubItem; + SortOrder order = AscendingOrder; + + if(col == m_sortColumn) { + switch(m_sortOrder) { + case AscendingOrder: + order = DescendingOrder; + break; + case DescendingOrder: + order = AscendingOrder; + break; + } + } + + sortByColumn(col, order); +} diff --git a/src/listview.hpp b/src/listview.hpp @@ -27,6 +27,8 @@ class ListView : public Control { public: + enum SortOrder { AscendingOrder, DescendingOrder }; + struct Column { auto_string text; int width; }; typedef std::vector<Column> Columns; typedef std::vector<auto_string> Row; @@ -37,14 +39,17 @@ public: ListView(const Columns &, HWND handle); int addRow(const Row &); - Row getRow(const int index) const; - void replaceRow(const int index, const Row &); - void removeRow(const int index); - void resizeColumn(const int index, const int width); + const Row &row(int index) const { return m_rows[index]; } + void replaceRow(int index, const Row &); + void removeRow(int index); + void resizeColumn(int index, const int width); + void sort(); + void sortByColumn(int index, SortOrder order = AscendingOrder); void clear(); bool hasSelection() const; int currentIndex() const; + int rowCount() { return (int)m_rows.size(); } void onSelect(const Callback &callback) { m_onSelect.connect(callback); } void onDoubleClick(const Callback &callback) @@ -56,9 +61,13 @@ protected: private: void setExStyle(int style, bool enable); void addColumn(const Column &); + void setSortArrow(bool); + void onColumnClick(LPARAM lpnmlistview); int m_columnSize; - int m_rowSize; + int m_sortColumn; + SortOrder m_sortOrder; + std::vector<Row> m_rows; Signal m_onSelect; Signal m_onDoubleClick; diff --git a/src/manager.cpp b/src/manager.cpp @@ -292,7 +292,7 @@ Remote Manager::currentRemote() const if(index < 0) return {}; - const ListView::Row &row = m_list->getRow(index); + const ListView::Row &row = m_list->row(index); const string &remoteName = from_autostring(row[0]); return m_reapack->config()->remotes()->get(remoteName); diff --git a/src/resource.rc b/src/resource.rc @@ -31,8 +31,8 @@ FONT DIALOG_FONT CAPTION "ReaPack Configuration" BEGIN LTEXT "Remote repositories:", IDC_LABEL, 5, 5, 320, 10 - CONTROL "", IDC_LIST, WC_LISTVIEW, LVS_REPORT | LVS_SINGLESEL | - LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP, 5, 18, 320, 136 + CONTROL "", IDC_LIST, WC_LISTVIEW, WS_BORDER | LVS_REPORT | LVS_SINGLESEL | + LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_TABSTOP, 5, 18, 320, 136 PUSHBUTTON "&Import...", IDC_IMPORT, 5, 160, 45, 14 DEFPUSHBUTTON "&OK", IDOK, 240, 160, 40, 14 PUSHBUTTON "&Cancel", IDCANCEL, 284, 160, 40, 14