diff --git a/fragments/filters.cpp b/fragments/filters.cpp index 144ceda..86f2747 100644 --- a/fragments/filters.cpp +++ b/fragments/filters.cpp @@ -1,6 +1,7 @@ #include #include +#include "../misc.h" #include "../group_panel.h" #include "../filters.h" #include "ok_buttons_fragment.h" @@ -13,7 +14,8 @@ static inline void render_priority_filter(PriorityFilter* filter); static inline void render_group_filter(GroupFilter* filter); static std::unique_ptr render_add_filter_popup(); -static void render_filter(Filter* filter, std::string* title, bool* request_removal) { +static void render_filter(Filter* filter, std::string* title, bool* request_removal, + auto move_up, auto move_down, bool can_move_up, bool can_move_down) { ImGui::PushID(filter); ImGui::BeginGroupPanel(); @@ -42,6 +44,15 @@ static void render_filter(Filter* filter, std::string* title, bool* request_remo *request_removal = true; } + ImGui::SameLine(); + if (ImGui::ArrowButton("##up", ImGuiDir_Up, can_move_up)) { + move_up(); + } + ImGui::SameLine(); + if (ImGui::ArrowButton("##down", ImGuiDir_Down, can_move_down)) { + move_down(); + } + { ImGui::SameLine(); bool disabled = filter->disabled(); @@ -162,16 +173,28 @@ static inline void render_group_filter(GroupFilter* filter) { filter->type = static_cast(selected_type); } - for (std::vector>::iterator it = filter->filters.begin(); it != filter->filters.end();) { + std::vector> swaps_to_do; + std::vector removals_to_do; + for (size_t i = 0; i < filter->filters.size(); i++) { bool removal_requested = false; - render_filter(it->get(), nullptr, &removal_requested); + render_filter(filter->filters[i].get(), nullptr, &removal_requested, [&]() { + swaps_to_do.push_back(std::make_pair(i, i - 1)); + }, [&]() { + swaps_to_do.push_back(std::make_pair(i, i + 1)); + }, i != 0, i + 1 != filter->filters.size()); + if (removal_requested) { - filter->filters.erase(it); - filter->updated(); - } else { - it++; + removals_to_do.push_back(i); } } + for (auto &[lhs, rhs] : swaps_to_do) { + std::swap(filter->filters[lhs], filter->filters[rhs]); + filter->updated(); + } + for (size_t i : removals_to_do) { + filter->filters.erase(filter->filters.begin() + static_cast(i)); + filter->updated(); + } if (ImGui::Button("+ add filter")) { ImGui::OpenPopup("add_filter"); @@ -212,15 +235,26 @@ void filters_fragment(Filters& inactive_filters) { ImGui::TextWrapped("You can use regex for strings by prepending \"regex:\". " "While editing titles, press Enter to use the new title or press Escape to keep the old one"); - for (Filters::iterator it = inactive_filters.begin(); it != inactive_filters.end();) { + std::vector> swaps_to_do; + std::vector removals_to_do; + for (size_t i = 0; i < inactive_filters.size(); i++) { bool removal_requested = false; - render_filter(it->second.get(), &it->first, &removal_requested); + render_filter(inactive_filters[i].second.get(), &inactive_filters[i].first, &removal_requested, [&]() { + swaps_to_do.push_back(std::make_pair(i, i - 1)); + }, [&]() { + swaps_to_do.push_back(std::make_pair(i, i + 1)); + }, i != 0, i + 1 != inactive_filters.size()); + if (removal_requested) { - inactive_filters.erase(it); - } else { - it++; + removals_to_do.push_back(i); } } + for (auto &[lhs, rhs] : swaps_to_do) { + std::swap(inactive_filters[lhs], inactive_filters[rhs]); + } + for (size_t i : removals_to_do) { + inactive_filters.erase(inactive_filters.begin() + static_cast(i)); + } if (ImGui::Button("+ add filter")) { ImGui::OpenPopup("add_filter"); diff --git a/misc.cpp b/misc.cpp index 43b1a5f..b4abe61 100644 --- a/misc.cpp +++ b/misc.cpp @@ -62,6 +62,19 @@ bool ImGui::Button(const char* label, bool enabled) { return res; } +bool ImGui::ArrowButton(const char* label, ImGuiDir dir, bool enabled) { + if (!enabled) { + ImGui::BeginDisabled(); + } + + bool res = ImGui::ArrowButton(label, dir); + + if (!enabled) { + ImGui::EndDisabled(); + } + return res; +} + bool ImGui::BeginWithCloseShortcut(const char* label, bool* p_open, ImGuiWindowFlags flags) { bool res = ImGui::Begin(label, p_open, flags); diff --git a/misc.h b/misc.h index 1647c62..ea86ac8 100644 --- a/misc.h +++ b/misc.h @@ -3,6 +3,7 @@ #include typedef int ImGuiWindowFlags; // forward declaration from imgui/imgui.h typedef int ImGuiKeyChord; // forward declaration from imgui/imgui.h +typedef int ImGuiDir; // forward declaration from imgui/imgui.h std::string quote(const std::string& str); void throw_system_error(int err, const char* what); @@ -13,6 +14,7 @@ namespace ImGui { void TextUnformatted(const std::string& str); bool RedButton(const char* label); bool Button(const char* label, bool enabled); + bool ArrowButton(const char* label, ImGuiDir dir, bool enabled); bool BeginWithCloseShortcut(const char* label, bool* p_open, ImGuiWindowFlags flags = 0); // don't spill __all__ of imgui_internal.h bool IsKeyPressed(ImGuiKeyChord key_chord, bool repeat = true);