diff --git a/public/raid/imraid.hpp b/public/raid/imraid.hpp index 5cd46f9..a5d32e1 100644 --- a/public/raid/imraid.hpp +++ b/public/raid/imraid.hpp @@ -5,6 +5,7 @@ #define RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED 1 #include +#include #include #include #include @@ -73,8 +74,13 @@ inline bool BeginPopupButton(const char* label) struct DataTableState { std::vector sortedIndices; - std::size_t sortColumn = 0; - bool sortDescending = false; + + struct SortColumn + { + std::size_t index; + bool sortDescending = false; + }; + std::vector sortColumns; bool dirty = true; }; @@ -97,7 +103,8 @@ template struct DataTableOptions { std::span> columns; - ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable | ImGuiTableFlags_ScrollY; + ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable + | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SortMulti; }; template @@ -128,10 +135,23 @@ inline void DataTable(const char* strId, const DataTableOptions& option { sortSpecs->SpecsDirty = false; - const ImGuiTableColumnSortSpecs& specs = *sortSpecs->Specs; - state.dirty |= (specs.ColumnIndex != static_cast(state.sortColumn)); - state.sortColumn = specs.ColumnIndex; - state.sortDescending = specs.SortDirection == ImGuiSortDirection_Descending; + if (state.sortColumns.size() != static_cast(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(specs.ColumnIndex) != column.index); + state.dirty |= column.sortDescending != (specs.SortDirection == ImGuiSortDirection_Descending); + column = { + .index = static_cast(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& 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();