Added multi-column sorting to data tables.
This commit is contained in:
parent
9d02d97af3
commit
da8d1589b3
@ -5,6 +5,7 @@
|
||||
#define RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED 1
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
@ -73,8 +74,13 @@ inline bool BeginPopupButton(const char* label)
|
||||
struct DataTableState
|
||||
{
|
||||
std::vector<std::size_t> sortedIndices;
|
||||
std::size_t sortColumn = 0;
|
||||
|
||||
struct SortColumn
|
||||
{
|
||||
std::size_t index;
|
||||
bool sortDescending = false;
|
||||
};
|
||||
std::vector<SortColumn> sortColumns;
|
||||
bool dirty = true;
|
||||
};
|
||||
|
||||
@ -97,7 +103,8 @@ template<typename TObject>
|
||||
struct DataTableOptions
|
||||
{
|
||||
std::span<const DataTableColumn<TObject>> columns;
|
||||
ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable | ImGuiTableFlags_ScrollY;
|
||||
ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable
|
||||
| ImGuiTableFlags_ScrollY | ImGuiTableFlags_SortMulti;
|
||||
};
|
||||
|
||||
template<typename TObject,typename TData>
|
||||
@ -128,10 +135,23 @@ inline void DataTable(const char* strId, const DataTableOptions<TObject>& option
|
||||
{
|
||||
sortSpecs->SpecsDirty = false;
|
||||
|
||||
const ImGuiTableColumnSortSpecs& specs = *sortSpecs->Specs;
|
||||
state.dirty |= (specs.ColumnIndex != static_cast<ImS16>(state.sortColumn));
|
||||
state.sortColumn = specs.ColumnIndex;
|
||||
state.sortDescending = specs.SortDirection == ImGuiSortDirection_Descending;
|
||||
if (state.sortColumns.size() != static_cast<std::size_t>(sortSpecs->SpecsCount))
|
||||
{
|
||||
state.dirty = true;
|
||||
state.sortColumns.resize(sortSpecs->SpecsCount);
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < sortSpecs->SpecsCount; ++idx)
|
||||
{
|
||||
const ImGuiTableColumnSortSpecs& specs = sortSpecs->Specs[idx];
|
||||
DataTableState::SortColumn& column = state.sortColumns[idx];
|
||||
state.dirty |= (static_cast<std::size_t>(specs.ColumnIndex) != column.index);
|
||||
state.dirty |= column.sortDescending != (specs.SortDirection == ImGuiSortDirection_Descending);
|
||||
column = {
|
||||
.index = static_cast<std::size_t>(specs.ColumnIndex),
|
||||
.sortDescending = (specs.SortDirection == ImGuiSortDirection_Descending)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (state.sortedIndices.size() != data.size())
|
||||
@ -145,16 +165,28 @@ inline void DataTable(const char* strId, const DataTableOptions<TObject>& option
|
||||
for (std::size_t idx = 0; idx < data.size(); ++idx) {
|
||||
state.sortedIndices[idx] = idx;
|
||||
}
|
||||
std::ranges::sort(state.sortedIndices, [&](std::size_t leftIdx, std::size_t rightIdx) {
|
||||
return options.columns[state.sortColumn].comparator(data[leftIdx], data[rightIdx]);
|
||||
std::ranges::sort(state.sortedIndices, [&](std::size_t leftIdx, std::size_t rightIdx)
|
||||
{
|
||||
for (const DataTableState::SortColumn& column : state.sortColumns)
|
||||
{
|
||||
const bool less = options.columns[column.index].comparator(data[leftIdx], data[rightIdx]);
|
||||
if (less)
|
||||
{ // left < right
|
||||
return !column.sortDescending;
|
||||
}
|
||||
if (options.columns[column.index].comparator(data[rightIdx], data[leftIdx]))
|
||||
{ // left > right
|
||||
return column.sortDescending;
|
||||
}
|
||||
}
|
||||
// left == right
|
||||
return false;
|
||||
});
|
||||
state.dirty = false;
|
||||
}
|
||||
|
||||
for (std::size_t indexIdx = 0; indexIdx < state.sortedIndices.size(); ++indexIdx)
|
||||
for (const std::size_t dataIdx : state.sortedIndices)
|
||||
{
|
||||
const std::size_t dataIdx = state.sortDescending ? state.sortedIndices[state.sortedIndices.size() - indexIdx - 1]
|
||||
: state.sortedIndices[indexIdx];
|
||||
const TObject& object = data[dataIdx];
|
||||
ImGui::TableNextRow();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user