Compare commits
2 Commits
d74474a042
...
d3b56d3fd0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3b56d3fd0 | ||
|
|
7470878f9c |
@ -97,7 +97,15 @@ int Application::run(int argc, char** argv)
|
|||||||
ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size);
|
ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size);
|
||||||
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
||||||
|
|
||||||
|
for (const auto& [variable, value] : mMainWindowStyles) {
|
||||||
|
std::visit([&](auto val) {
|
||||||
|
ImGui::PushStyleVar(variable, val);
|
||||||
|
}, value);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Begin("##main", nullptr, mMainWindowFlags);
|
ImGui::Begin("##main", nullptr, mMainWindowFlags);
|
||||||
|
ImGui::PopStyleVar(static_cast<int>(mMainWindowStyles.size()));
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
|
||||||
mTaskLoop.tick();
|
mTaskLoop.tick();
|
||||||
|
|||||||
@ -4,7 +4,14 @@
|
|||||||
#if !defined(RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED)
|
#if !defined(RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED)
|
||||||
#define RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED 1
|
#define RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include <mijin/debug/assert.hpp>
|
||||||
|
|
||||||
namespace ImRaid
|
namespace ImRaid
|
||||||
{
|
{
|
||||||
@ -47,6 +54,106 @@ inline bool ToggleImageButton(const char* strId, ImTextureID textureId, const Im
|
|||||||
}
|
}
|
||||||
return clicked;
|
return clicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DataTableState
|
||||||
|
{
|
||||||
|
std::vector<std::size_t> sortedIndices;
|
||||||
|
std::size_t sortColumn = 0;
|
||||||
|
bool sortDescending = false;
|
||||||
|
bool dirty = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TObject>
|
||||||
|
struct DataTableColumn
|
||||||
|
{
|
||||||
|
struct CellRendererArgs
|
||||||
|
{
|
||||||
|
const TObject& object;
|
||||||
|
};
|
||||||
|
using renderer_t = std::function<void(const CellRendererArgs&)>;
|
||||||
|
using comparator_t = std::function<bool(const TObject&, const TObject&)>;
|
||||||
|
|
||||||
|
std::string header;
|
||||||
|
renderer_t renderer;
|
||||||
|
comparator_t comparator;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TObject>
|
||||||
|
struct DataTableOptions
|
||||||
|
{
|
||||||
|
std::span<const DataTableColumn<TObject>> columns;
|
||||||
|
ImGuiTableFlags tableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable | ImGuiTableFlags_ScrollY;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TData, typename TObject>
|
||||||
|
inline void DataTable(const char* strId, const DataTableOptions<TObject>& options, const TData& data, DataTableState& state, ImVec2 outerSize = {})
|
||||||
|
{
|
||||||
|
if (outerSize.y <= 0.f) {
|
||||||
|
outerSize.y = ImGui::GetContentRegionAvail().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui::BeginTable(strId, static_cast<int>(options.columns.size()), options.tableFlags, outerSize)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const DataTableColumn<TObject>& column : options.columns)
|
||||||
|
{
|
||||||
|
ImGuiTableColumnFlags flags = 0;
|
||||||
|
MIJIN_ASSERT(column.renderer, "Missing column renderer.");
|
||||||
|
if (!column.comparator) {
|
||||||
|
flags |= ImGuiTableColumnFlags_NoSort;
|
||||||
|
}
|
||||||
|
ImGui::TableSetupColumn(column.header.c_str(), flags);
|
||||||
|
}
|
||||||
|
ImGui::TableSetupScrollFreeze(0, 1);
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs();
|
||||||
|
if (sortSpecs != nullptr && sortSpecs->SpecsDirty)
|
||||||
|
{
|
||||||
|
sortSpecs->SpecsDirty = false;
|
||||||
|
|
||||||
|
const ImGuiTableColumnSortSpecs& specs = *sortSpecs->Specs;
|
||||||
|
state.dirty |= (specs.ColumnIndex != state.sortColumn);
|
||||||
|
state.sortColumn = specs.ColumnIndex;
|
||||||
|
state.sortDescending = specs.SortDirection == ImGuiSortDirection_Descending;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.sortedIndices.size() != data.size())
|
||||||
|
{
|
||||||
|
state.dirty = true;
|
||||||
|
state.sortedIndices.resize(data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.dirty)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
});
|
||||||
|
state.dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t indexIdx = 0; indexIdx < state.sortedIndices.size(); ++indexIdx)
|
||||||
|
{
|
||||||
|
const std::size_t dataIdx = state.sortDescending ? state.sortedIndices[state.sortedIndices.size() - indexIdx - 1]
|
||||||
|
: state.sortedIndices[indexIdx];
|
||||||
|
const TObject& object = data[dataIdx];
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
for (const DataTableColumn<TObject>& column : options.columns)
|
||||||
|
{
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
column.renderer({
|
||||||
|
.object = object
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
} // namespace ImRaid
|
} // namespace ImRaid
|
||||||
|
|
||||||
#endif // !defined(RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED)
|
#endif // !defined(RAID_PUBLIC_RAID_IMRAID_HPP_INCLUDED)
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <variant>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <mijin/async/coroutine.hpp>
|
#include <mijin/async/coroutine.hpp>
|
||||||
@ -63,6 +64,7 @@ private:
|
|||||||
|
|
||||||
bool mRunning = true;
|
bool mRunning = true;
|
||||||
ImGuiWindowFlags mMainWindowFlags = DEFAULT_MAIN_WINDOW_FLAGS;
|
ImGuiWindowFlags mMainWindowFlags = DEFAULT_MAIN_WINDOW_FLAGS;
|
||||||
|
std::unordered_map<ImGuiStyleVar, std::variant<float, ImVec2>> mMainWindowStyles;
|
||||||
|
|
||||||
using GLbitfield = std::uint32_t;
|
using GLbitfield = std::uint32_t;
|
||||||
using GLint = std::int32_t;
|
using GLint = std::int32_t;
|
||||||
@ -108,6 +110,8 @@ public:
|
|||||||
ImGuiWindowFlags getMainWindowFlags() const { return mMainWindowFlags; }
|
ImGuiWindowFlags getMainWindowFlags() const { return mMainWindowFlags; }
|
||||||
|
|
||||||
void setMainWindowFlags(ImGuiWindowFlags flags) { mMainWindowFlags = flags; }
|
void setMainWindowFlags(ImGuiWindowFlags flags) { mMainWindowFlags = flags; }
|
||||||
|
void setMainWindowStyle(ImGuiStyleVar variable, std::variant<float, ImVec2> value) { mMainWindowStyles.emplace(variable, value); }
|
||||||
|
void unsetMainWindowStyle(ImGuiStyleVar variable) { mMainWindowStyles.erase(variable); }
|
||||||
void requestQuit() { mRunning = false; }
|
void requestQuit() { mRunning = false; }
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user