MultiSelect: use a single ImGuiMultiSelectIO buffer.
+ using local storage var in EndMultiSelect(), should be no-op.
diff --git a/imgui_internal.h b/imgui_internal.h
index 9df3b01..6377220 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1720,10 +1720,10 @@
ImGuiID FocusScopeId; // Copied from g.CurrentFocusScopeId (unless another selection scope was pushed manually)
ImGuiMultiSelectFlags Flags;
ImGuiKeyChord KeyMods;
- ImGuiMultiSelectIO BeginIO; // Requests are set and returned by BeginMultiSelect(), written to by user during the loop.
- ImGuiMultiSelectIO EndIO; // Requests are set during the loop and returned by EndMultiSelect().
+ ImGuiMultiSelectIO IO; // Requests are set and returned by BeginMultiSelect()/EndMultiSelect() + written to by user during the loop.
bool LoopRequestClear;
bool LoopRequestSelectAll;
+ 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 IsSetRange; // Set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
bool NavIdPassedBy;
@@ -1732,7 +1732,7 @@
//ImRect Rect; // Extent of selection scope between BeginMultiSelect() / EndMultiSelect(), used by ImGuiMultiSelectFlags_ClearOnClickRectVoid.
ImGuiMultiSelectTempData() { Clear(); }
- void Clear() { Storage = NULL; FocusScopeId = 0; Flags = 0; KeyMods = 0; BeginIO.Clear(); EndIO.Clear(); LoopRequestClear = LoopRequestSelectAll = IsFocused = IsSetRange = NavIdPassedBy = RangeSrcPassedBy = RangeDstPassedBy = false; }
+ void Clear() { Storage = NULL; FocusScopeId = 0; Flags = 0; KeyMods = 0; IO.Clear(); IsEndIO = LoopRequestClear = LoopRequestSelectAll = IsFocused = IsSetRange = NavIdPassedBy = RangeSrcPassedBy = RangeDstPassedBy = false; }
};
// Persistent storage for multi-select (as long as selection is alive)
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index a3f06f3..edf48aa 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7149,10 +7149,10 @@
storage->Window = window;
ms->Storage = storage;
- // We want EndIO's NavIdItem/NavIdSelected to match BeginIO's one, so the value never changes after EndMultiSelect()
- ms->BeginIO.RangeSrcItem = ms->EndIO.RangeSrcItem = storage->RangeSrcItem;
- ms->BeginIO.NavIdItem = ms->EndIO.NavIdItem = storage->NavIdItem;
- ms->BeginIO.NavIdSelected = ms->EndIO.NavIdSelected = (storage->NavIdSelected == 1) ? true : false;
+ ms->IO.RangeSrcItem = storage->RangeSrcItem;
+ ms->IO.NavIdItem = storage->NavIdItem;
+ ms->IO.NavIdSelected = (storage->NavIdSelected == 1) ? true : false;
+ ms->IO.Requests.resize(0);
bool request_clear = false;
bool request_select_all = false;
@@ -7191,14 +7191,14 @@
}
if (request_clear || request_select_all)
- ms->BeginIO.Requests.push_back(ImGuiSelectionRequest(request_select_all ? ImGuiSelectionRequestType_SelectAll : ImGuiSelectionRequestType_Clear));
+ ms->IO.Requests.push_back(ImGuiSelectionRequest(request_select_all ? ImGuiSelectionRequestType_SelectAll : ImGuiSelectionRequestType_Clear));
ms->LoopRequestClear = request_clear;
ms->LoopRequestSelectAll = request_select_all;
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
- DebugLogMultiSelectRequests("BeginMultiSelect", &ms->BeginIO);
+ DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO);
- return &ms->BeginIO;
+ return &ms->IO;
}
// Return updated ImGuiMultiSelectIO structure. Lifetime: until EndFrame() or next BeginMultiSelect() call.
@@ -7206,46 +7206,49 @@
{
ImGuiContext& g = *GImGui;
ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect;
+ ImGuiMultiSelectState* storage = ms->Storage;
IM_ASSERT(ms->FocusScopeId == g.CurrentFocusScopeId);
- IM_ASSERT(g.CurrentMultiSelect != NULL && ms->Storage->Window == g.CurrentWindow);
+ IM_ASSERT(g.CurrentMultiSelect != NULL && storage->Window == g.CurrentWindow);
if (ms->IsFocused)
{
// We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here.
- if (ms->BeginIO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->BeginIO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at begining of the scope (see tests for easy failure)
+ if (ms->IO.RangeSrcReset || (ms->RangeSrcPassedBy == false && ms->IO.RangeSrcItem != ImGuiSelectionUserData_Invalid)) // Can't read storage->RangeSrcItem here -> we want the state at begining of the scope (see tests for easy failure)
{
IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset RangeSrcItem.\n"); // Will set be to NavId.
- ms->Storage->RangeSrcItem = ImGuiSelectionUserData_Invalid;
+ storage->RangeSrcItem = ImGuiSelectionUserData_Invalid;
}
- if (ms->NavIdPassedBy == false && ms->Storage->NavIdItem != ImGuiSelectionUserData_Invalid)
+ if (ms->NavIdPassedBy == false && storage->NavIdItem != ImGuiSelectionUserData_Invalid)
{
IMGUI_DEBUG_LOG_SELECTION("[selection] EndMultiSelect: Reset NavIdItem.\n");
- ms->Storage->NavIdItem = ImGuiSelectionUserData_Invalid;
- ms->Storage->NavIdSelected = -1;
+ storage->NavIdItem = ImGuiSelectionUserData_Invalid;
+ storage->NavIdSelected = -1;
}
}
+ if (ms->IsEndIO == false)
+ ms->IO.Requests.resize(0);
+
// Clear selection when clicking void?
// We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection!
if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickWindowVoid)
if (IsWindowHovered() && g.HoveredId == 0)
if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None)
{
- ms->EndIO.Requests.resize(0);
- ms->EndIO.Requests.push_back(ImGuiSelectionRequest(ImGuiSelectionRequestType_Clear));
+ ms->IO.Requests.resize(0);
+ ms->IO.Requests.push_back(ImGuiSelectionRequest(ImGuiSelectionRequestType_Clear));
}
// Unwind
ms->FocusScopeId = 0;
ms->Flags = ImGuiMultiSelectFlags_None;
- ms->BeginIO.Clear(); // Invalidate contents of BeginMultiSelect() to enforce scope.
PopFocusScope();
g.CurrentMultiSelect = NULL;
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
- DebugLogMultiSelectRequests("EndMultiSelect", &ms->EndIO);
+ DebugLogMultiSelectRequests("EndMultiSelect", &ms->IO);
- return &ms->EndIO;
+ return &ms->IO;
}
void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data)
@@ -7260,7 +7263,7 @@
{
// Auto updating RangeSrcPassedBy for cases were clipper is not used (done before ItemAdd() clipping)
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
- if (ms->BeginIO.RangeSrcItem == selection_user_data)
+ if (ms->IO.RangeSrcItem == selection_user_data)
ms->RangeSrcPassedBy = true;
}
else
@@ -7357,6 +7360,11 @@
storage->RangeSrcItem = item_data;
storage->RangeSelected = selected; // Will be updated at the end of this function anyway.
}
+ if (ms->IsEndIO == false)
+ {
+ ms->IO.Requests.resize(0);
+ ms->IsEndIO = true;
+ }
// Auto-select as you navigate a list
if (g.NavJustMovedToId == id)
@@ -7416,8 +7424,8 @@
request_clear = true; // With is_shift==false the RequestClear was done in BeginIO, not necessary to do again.
if (request_clear)
{
- ms->EndIO.Requests.resize(0);
- ms->EndIO.Requests.push_back(ImGuiSelectionRequest(ImGuiSelectionRequestType_Clear));
+ ms->IO.Requests.resize(0);
+ ms->IO.Requests.push_back(ImGuiSelectionRequest(ImGuiSelectionRequestType_Clear));
}
int range_direction;
@@ -7443,7 +7451,7 @@
ImGuiSelectionUserData range_dst_item = item_data;
req.RangeFirstItem = (range_direction > 0) ? storage->RangeSrcItem : range_dst_item;
req.RangeLastItem = (range_direction > 0) ? range_dst_item : storage->RangeSrcItem;
- ms->EndIO.Requests.push_back(req);
+ ms->IO.Requests.push_back(req);
}
// Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)