From 57ff7c4ef4ee45ac876ebf590618c65beb170b19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 29 May 2024 15:22:32 +0200 Subject: [PATCH] RangeSelect/MultiSelect: add GetMultiSelectState() + store LastSelectionSize as provided by user, convenient for quick debugging and testing. --- imgui_internal.h | 7 ++++--- imgui_widgets.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index e59587c4..2e43c8f1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1759,7 +1759,6 @@ struct IMGUI_API ImGuiMultiSelectTempData bool IsEndIO; // Set when switching IO from BeginMultiSelect() to EndMultiSelect() state. bool IsFocused; // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection. bool IsKeyboardSetRange; // Set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation. - bool IsSelectionEmpty; // Set by BeginMultiSelect() based on optional info provided by user. May be false positive, never false negative. bool NavIdPassedBy; bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem. bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set. @@ -1776,12 +1775,13 @@ struct IMGUI_API ImGuiMultiSelectState ImGuiWindow* Window; ImGuiID ID; int LastFrameActive; // Last used frame-count, for GC. + int LastSelectionSize; // Set by BeginMultiSelect() based on optional info provided by user. May be -1 if unknown. ImS8 RangeSelected; // -1 (don't have) or true/false ImS8 NavIdSelected; // -1 (don't have) or true/false ImGuiSelectionUserData RangeSrcItem; // ImGuiSelectionUserData NavIdItem; // SetNextItemSelectionUserData() value for NavId (if part of submitted items) - ImGuiMultiSelectState() { Window = NULL; ID = 0; LastFrameActive = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; } + ImGuiMultiSelectState() { Window = NULL; ID = 0; LastFrameActive = LastSelectionSize = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; } }; #endif // #ifdef IMGUI_HAS_MULTI_SELECT @@ -3401,7 +3401,8 @@ namespace ImGui // Multi-Select API IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags); IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed); - inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; } + inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; } + inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); } // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index dd68b5ef..083b6099 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7213,7 +7213,6 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int cur ms->FocusScopeId = id; ms->Flags = flags; ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId); - ms->IsSelectionEmpty = (current_selection_size == 0); ms->BackupCursorMaxPos = window->DC.CursorMaxPos; ms->ScopeRectMin = window->DC.CursorMaxPos = window->DC.CursorPos; PushFocusScope(ms->FocusScopeId); @@ -7227,6 +7226,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int cur ImGuiMultiSelectState* storage = g.MultiSelectStorage.GetOrAddByKey(id); storage->ID = id; storage->LastFrameActive = g.FrameCount; + storage->LastSelectionSize = current_selection_size; storage->Window = window; ms->Storage = storage; @@ -7283,7 +7283,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int cur { ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, request_select_all, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; if (!request_select_all) - ms->IsSelectionEmpty = true; + storage->LastSelectionSize = 0; ms->IO.Requests.push_back(req); } ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1; @@ -7541,13 +7541,13 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) selected = !selected; ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, item_data, item_data }; ImGuiSelectionRequest* prev_req = (ms->IO.Requests.Size > 0) ? &ms->IO.Requests.Data[ms->IO.Requests.Size - 1] : NULL; - if (ms->IsSelectionEmpty && bs->IsStartedFromVoid) + if (storage->LastSelectionSize == 0 && bs->IsStartedFromVoid) pressed = true; // First item act as a pressed: code below will emit selection request and set NavId (whatever we emit here will be overriden anyway) else if (prev_req && prev_req->Type == ImGuiSelectionRequestType_SetRange && prev_req->RangeLastItem == ms->BoxSelectLastitem && prev_req->Selected == selected) prev_req->RangeLastItem = item_data; // Merge span into same request else ms->IO.Requests.push_back(req); - ms->IsSelectionEmpty = false; + storage->LastSelectionSize++; } ms->BoxSelectLastitem = item_data; } @@ -7682,6 +7682,7 @@ void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage) return; Text("RangeSrcItem = %" IM_PRId64 " (0x%" IM_PRIX64 "), RangeSelected = %d", storage->RangeSrcItem, storage->RangeSrcItem, storage->RangeSelected); Text("NavIdItem = %" IM_PRId64 " (0x%" IM_PRIX64 "), NavIdSelected = %d", storage->NavIdItem, storage->NavIdItem, storage->NavIdSelected); + Text("LastSelectionSize = %d", storage->LastSelectionSize); // Provided by user TreePop(); #else IM_UNUSED(storage);