RangeSelect/MultiSelect: Shallow tweaks/refactors.
Including moving IsFocused back internally for now.
diff --git a/imgui.h b/imgui.h
index 556cc20..cd50da5 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2475,6 +2475,7 @@
// you may as well not bother with clipping, as the cost should be negligible (as least on Dear ImGui side).
// If you are not sure, always start without clipping and you can work your way to the more optimized version afterwards.
// - The void* RangeSrc/RangeDst value represent a selectable object. They are the values you pass to SetNextItemSelectionData().
+// Most likely you will want to store an index here.
// Storing an integer index is the easiest thing to do, as SetRange requests will give you two end points and you will need to interpolate
// between them to honor range selection. But the code never assume that sortable integers are used (you may store pointers to your object,
// and then from the pointer have your own way of iterating from RangeSrc to RangeDst).
@@ -2482,36 +2483,37 @@
// e.g. instructive selection (store a bool inside each object), external array (store an array aside from your objects),
// hash/map/set (store only selected items in a hash/map/set), or other structures (store indices in an interval tree), etc.
// Usage flow:
-// 1) Call BeginMultiSelect() with the last saved value of ->RangeSrc and its selection state.
-// It is because you need to pass its selection state (and you own selection) that we don't store this value in Dear ImGui.
-// (For the initial frame or when resetting your selection state: you may use the value for your first item or a "null" value that matches the type stored in your void*).
-// 2) Honor Clear/SelectAll requests by updating your selection data. [Only required if you are using a clipper in step 4]
-// 3) Set RangeSrcPassedBy=true if the RangeSrc item is part of the items clipped before the first submitted/visible item. [Only required if you are using a clipper in step 4]
-// This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
-// If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrc) { data->RangeSrcPassedBy = true; }
-// 4) Submit your items with SetNextItemSelectionData() + Selectable()/TreeNode() calls.
-// Call IsItemToggledSelection() to query if the selection state has been toggled, if you need the info immediately for your display (before EndMultiSelect()).
-// When cannot return a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggle" event instead.
-// 5) Call EndMultiSelect(). Save the value of ->RangeSrc for the next frame (you may convert the value in a format that is safe for persistance)
-// 6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)
+// Begin
+// 1) Call BeginMultiSelect() with the last saved value of ->RangeSrc and its selection state.
+// It is because you need to pass its selection state (and you own selection) that we don't store this value in Dear ImGui.
+// (For the initial frame or when resetting your selection state: you may use the value for your first item or a "null" value that matches the type stored in your void*).
+// 2) Honor Clear/SelectAll requests by updating your selection data. Only required if you are using a clipper in step 4: but you can use same code as step 6 anyway.
+// Loop
+// 3) Set RangeSrcPassedBy=true if the RangeSrc item is part of the items clipped before the first submitted/visible item. [Only required if you are using a clipper in step 4]
+// This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
+// If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrc) { data->RangeSrcPassedBy = true; }
+// 4) Submit your items with SetNextItemSelectionData() + Selectable()/TreeNode() calls.
+// Call IsItemToggledSelection() to query if the selection state has been toggled, if you need the info immediately for your display (before EndMultiSelect()).
+// When cannot return a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggle" event instead.
+// End
+// 5) Call EndMultiSelect(). Save the value of ->RangeSrc for the next frame (you may convert the value in a format that is safe for persistance)
+// 6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)
// If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable() on a per-item basis.
#define IMGUI_HAS_MULTI_SELECT // Multi-Select/Range-Select WIP branch // <-- This is currently _not_ in the top of imgui.h to prevent merge conflicts.
struct ImGuiMultiSelectData
{
- bool IsFocused; // Begin // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection.
- bool RequestClear; // Begin, End // Request user to clear selection
- bool RequestSelectAll; // Begin, End // Request user to select all
- bool RequestSetRange; // End // Request user to set or clear selection in the [RangeSrc..RangeDst] range
- bool RangeSrcPassedBy; // In loop // (If clipping) Need to be set by user if RangeSrc was part of the clipped set before submitting the visible items. Ignore if not clipping.
- bool RangeValue; // End // End: parameter from RequestSetRange request. True = Select Range, False = Unselect range.
- void* RangeSrc; // Begin, End // End: parameter from RequestSetRange request + you need to save this value so you can pass it again next frame. / Begin: this is the value you passed to BeginMultiSelect()
- void* RangeDst; // End // End: parameter from RequestSetRange request.
- int RangeDirection; // End // End: parameter from RequestSetRange request. +1 if RangeSrc came before RangeDst, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values.
+ bool RequestClear; // Begin, End // 1. Request user to clear selection
+ bool RequestSelectAll; // Begin, End // 2. Request user to select all
+ bool RequestSetRange; // End // 3. Request user to set or clear selection in the [RangeSrc..RangeDst] range
+ bool RangeSrcPassedBy; // Loop // (If clipping) Need to be set by user if RangeSrc was part of the clipped set before submitting the visible items. Ignore if not clipping.
+ bool RangeValue; // End // End: parameter from RequestSetRange request. true = Select Range, false = Unselect Range.
+ void* RangeSrc; // Begin, End // End: parameter from RequestSetRange request + you need to save this value so you can pass it again next frame. / Begin: this is the value you passed to BeginMultiSelect()
+ void* RangeDst; // End // End: parameter from RequestSetRange request.
+ int RangeDirection; // End // End: parameter from RequestSetRange request. +1 if RangeSrc came before RangeDst, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values.
ImGuiMultiSelectData() { Clear(); }
void Clear()
{
- IsFocused = false;
RequestClear = RequestSelectAll = RequestSetRange = RangeSrcPassedBy = RangeValue = false;
RangeSrc = RangeDst = NULL;
RangeDirection = 0;
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index e334d44..f0b9d5d 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -565,6 +565,7 @@
static void ShowDemoWindowWidgets()
{
IMGUI_DEMO_MARKER("Widgets");
+ //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (!ImGui::CollapsingHeader("Widgets"))
return;
@@ -1254,6 +1255,7 @@
}
IMGUI_DEMO_MARKER("Widgets/Selectables");
+ //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode("Selectables"))
{
// Selectable() has 2 overloads:
@@ -2605,26 +2607,28 @@
}
}
-// [Advanced] Helper class to simulate storage of a multi-selection state, used by the advanced multi-selection demos.
+// [Advanced] Helper class to simulate storage of a multi-selection state, used by the BeginMultiSelect() demos.
// We use ImGuiStorage (simple key->value storage) to avoid external dependencies but it's probably not optimal.
// To store a single-selection:
// - You only need a single variable and don't need any of this!
// To store a multi-selection, in your real application you could:
// - Use intrusively stored selection (e.g. 'bool IsSelected' inside your object). This is by far the simplest
// way to store your selection data, but it means you cannot have multiple simultaneous views over your objects.
-// This is what may of the simpler demos in this file are using (so they are not using this class).
-// - Otherwise, any externally stored unordered_set/set/hash/map/interval trees (storing indices, objects id, etc.)
+// This is what many of the simpler demos in this file are using (so they are not using this class).
+// - Use external storage: e.g. unordered_set/set/hash/map/interval trees (storing indices, objects id, etc.)
// are generally appropriate. Even a large array of bool might work for you...
// - If you need to handle extremely large selections, it might be advantageous to support a "negative" mode in
-// your storage, so "Select All" becomes "Negative=1, Clear" and then sparse unselect can add to the storage.
+// your storage, so "Select All" becomes "Negative=1 + Clear" and then sparse unselect can add to the storage.
// About RefItem:
-// - The MultiSelect API requires you to store information about the reference/pivot item (generally the last clicked item).
+// - The BeginMultiSelect() API requires you to store information about the reference/pivot item (generally the last clicked item).
struct ExampleSelection
{
- ImGuiStorage Storage;
+ // Data
+ ImGuiStorage Storage; // Selection set
int SelectionSize; // Number of selected items (== number of 1 in the Storage, maintained by this class)
int RangeRef; // Reference/pivot item (generally last clicked item)
+ // Functions
ExampleSelection() { RangeRef = 0; Clear(); }
void Clear() { Storage.Clear(); SelectionSize = 0; }
bool GetSelected(int n) const { return Storage.GetInt((ImGuiID)n, 0) != 0; }
@@ -2637,11 +2641,20 @@
// you will need a way to iterate from one object to another given the ID you use.
// You are likely to need some kind of data structure to convert 'view index' <> 'object ID'.
// FIXME-MULTISELECT: Would be worth providing a demo of doing this.
- // FIXME-MULTISELECT: SetRange() is currently very inefficient since it doesn't take advantage of the fact that ImGuiStorage stores sorted key.
- void SetRange(int n1, int n2, bool v) { if (n2 < n1) { int tmp = n2; n2 = n1; n1 = tmp; } for (int n = n1; n <= n2; n++) SetSelected(n, v); }
- void SelectAll(int count) { Storage.Data.resize(count); for (int idx = 0; idx < count; idx++) Storage.Data[idx] = ImGuiStorage::ImGuiStoragePair((ImGuiID)idx, 1); SelectionSize = count; } // This could be using SetRange(), but it this way is faster.
+ // FIXME-MULTISELECT: This implementation of SetRange() is inefficient because it doesn't take advantage of the fact that ImGuiStorage stores sorted key.
+ void SetRange(int a, int b, bool v) { if (b < a) { int tmp = b; b = a; a = tmp; } for (int n = a; n <= b; n++) SetSelected(n, v); }
+ void SelectAll(int count) { Storage.Data.resize(count); for (int idx = 0; idx < count; idx++) Storage.Data[idx] = ImGuiStorage::ImGuiStoragePair((ImGuiID)idx, 1); SelectionSize = count; } // This could be using SetRange(), but it this way is faster.
+
+ // Apply requests coming from BeginMultiSelect() and EndMultiSelect(). Must be done in this order! Order->SelectAll->SetRange.
+ void ApplyRequests(ImGuiMultiSelectData* ms_data, int items_count)
+ {
+ if (ms_data->RequestClear) { Clear(); }
+ if (ms_data->RequestSelectAll) { SelectAll(items_count); }
+ if (ms_data->RequestSetRange) { SetRange((int)(intptr_t)ms_data->RangeSrc, (int)(intptr_t)ms_data->RangeDst, ms_data->RangeValue ? 1 : 0); }
+ }
};
+
static void ShowDemoWindowMultiSelect()
{
IMGUI_DEMO_MARKER("Widgets/Selection State");
@@ -2710,8 +2723,7 @@
{
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape;
ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(flags, (void*)(intptr_t)selection.RangeRef, selection.GetSelected(selection.RangeRef));
- if (multi_select_data->RequestClear) { selection.Clear(); }
- if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
+ selection.ApplyRequests(multi_select_data, ITEMS_COUNT);
for (int n = 0; n < ITEMS_COUNT; n++)
{
@@ -2732,9 +2744,7 @@
// Apply multi-select requests
multi_select_data = ImGui::EndMultiSelect();
selection.RangeRef = (int)(intptr_t)multi_select_data->RangeSrc;
- if (multi_select_data->RequestClear) { selection.Clear(); }
- if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
- if (multi_select_data->RequestSetRange) { selection.SetRange((int)(intptr_t)multi_select_data->RangeSrc, (int)(intptr_t)multi_select_data->RangeDst, multi_select_data->RangeValue ? 1 : 0); }
+ selection.ApplyRequests(multi_select_data, ITEMS_COUNT);
ImGui::EndListBox();
}
@@ -2749,7 +2759,7 @@
// - Showcase having multiple multi-selection scopes in the same window.
// - Showcase using inside a table.
IMGUI_DEMO_MARKER("Widgets/Selection State/Multiple Selection (using BeginMultiSelect, advanced)");
- ImGui::SetNextItemOpen(true, ImGuiCond_Once);
+ //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode("Multiple Selection (using BeginMultiSelect, advanced)"))
{
// Options
@@ -2798,8 +2808,7 @@
else
flags |= ImGuiMultiSelectFlags_ClearOnClickWindowVoid;
ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(flags, (void*)(intptr_t)selection->RangeRef, selection->GetSelected(selection->RangeRef));
- if (multi_select_data->RequestClear) { selection->Clear(); }
- if (multi_select_data->RequestSelectAll) { selection->SelectAll(ITEMS_COUNT); }
+ selection->ApplyRequests(multi_select_data, ITEMS_COUNT);
if (multiple_selection_scopes)
ImGui::Text("Selection size: %d", selection->GetSelectionSize()); // Draw counter below Separator and after BeginMultiSelect()
@@ -2817,8 +2826,8 @@
clipper.Begin(ITEMS_COUNT);
while (clipper.Step())
{
- // IF clipping is used you need to set 'RangeSrcPassedBy = true' if RangeRef was passed over.
- if (clipper.DisplayStart > selection->RangeRef)
+ // IF clipping is used you need to set 'RangeSrcPassedBy = true' if RangeSrc was passed over.
+ if ((int)(intptr_t)multi_select_data->RangeSrc <= clipper.DisplayStart)
multi_select_data->RangeSrcPassedBy = true;
for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
@@ -2898,9 +2907,7 @@
// Apply multi-select requests
multi_select_data = ImGui::EndMultiSelect();
selection->RangeRef = (int)(intptr_t)multi_select_data->RangeSrc;
- if (multi_select_data->RequestClear) { selection->Clear(); }
- if (multi_select_data->RequestSelectAll) { selection->SelectAll(ITEMS_COUNT); }
- if (multi_select_data->RequestSetRange) { selection->SetRange((int)(intptr_t)multi_select_data->RangeSrc, (int)(intptr_t)multi_select_data->RangeDst, multi_select_data->RangeValue ? 1 : 0); }
+ selection->ApplyRequests(multi_select_data, ITEMS_COUNT);
if (widget_type == WidgetType_TreeNode)
ImGui::PopStyleVar();
diff --git a/imgui_internal.h b/imgui_internal.h
index 96ba7bd..47b3b9a 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1588,15 +1588,19 @@
struct IMGUI_API ImGuiMultiSelectState
{
- ImGuiID FocusScopeId; // Same as g.CurrentFocusScopeId (unless another selection scope was pushed manually)
+ ImGuiID FocusScopeId; // Copied from g.CurrentFocusScopeId (unless another selection scope was pushed manually)
+ ImGuiMultiSelectFlags Flags;
+ ImGuiKeyChord KeyMods;
+ ImGuiWindow* Window;
ImGuiMultiSelectData In; // The In requests are set and returned by BeginMultiSelect()
ImGuiMultiSelectData Out; // The Out requests are finalized and returned by EndMultiSelect()
+ 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 InRangeDstPassedBy; // (Internal) set by the the item that match NavJustMovedToId when InRequestRangeSetNav is set.
bool InRequestSetRangeNav; // (Internal) set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
//ImRect Rect; // Extent of selection scope between BeginMultiSelect() / EndMultiSelect(), used by ImGuiMultiSelectFlags_ClearOnClickRectVoid.
ImGuiMultiSelectState() { Clear(); }
- void Clear() { FocusScopeId = 0; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
+ void Clear() { FocusScopeId = 0; Flags = ImGuiMultiSelectFlags_None; KeyMods = ImGuiMod_None; Window = NULL; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
};
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
@@ -1945,10 +1949,7 @@
ImVec2 NavWindowingAccumDeltaSize;
// Range-Select/Multi-Select
- ImGuiWindow* MultiSelectEnabledWindow; // FIXME-MULTISELECT: We currently don't support recursing/stacking multi-select
- ImGuiMultiSelectFlags MultiSelectFlags;
- ImGuiMultiSelectState MultiSelectState;
- ImGuiKeyChord MultiSelectKeyMods;
+ ImGuiMultiSelectState MultiSelectState; // FIXME-MULTISELECT: We currently don't support recursing/stacking multi-select
// Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
@@ -2180,10 +2181,6 @@
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
NavWindowingToggleLayer = false;
- MultiSelectEnabledWindow = NULL;
- MultiSelectFlags = ImGuiMultiSelectFlags_None;
- MultiSelectKeyMods = ImGuiMod_None;
-
DimBgRatio = 0.0f;
DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index d4362e3..5f7a286 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -6212,7 +6212,7 @@
const bool was_selected = selected;
// Multi-selection support (header)
- const bool is_multi_select = (g.MultiSelectEnabledWindow == window);
+ const bool is_multi_select = (g.MultiSelectState.Window == window);
if (is_multi_select)
{
MultiSelectItemHeader(id, &selected);
@@ -6545,7 +6545,7 @@
if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemflags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
// Multi-selection support (header)
- const bool is_multi_select = (g.MultiSelectEnabledWindow == window);
+ const bool is_multi_select = (g.MultiSelectState.Window == window);
const bool was_selected = selected;
if (is_multi_select)
{
@@ -6660,23 +6660,19 @@
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
- IM_ASSERT(g.MultiSelectEnabledWindow == NULL); // No recursion allowed yet (we could allow it if we deem it useful)
- IM_ASSERT(g.MultiSelectFlags == 0);
- IM_ASSERT(g.MultiSelectState.FocusScopeId == 0);
+ ImGuiMultiSelectState* ms = &g.MultiSelectState;
+ IM_ASSERT(ms->Window == NULL && ms->Flags == 0 && ms->FocusScopeId == 0); // No recursion allowed yet (we could allow it if we deem it useful)
// FIXME: BeginFocusScope()
- ImGuiMultiSelectState* ms = &g.MultiSelectState;
ms->Clear();
ms->FocusScopeId = window->IDStack.back();
+ ms->Flags = flags;
+ ms->Window = window;
+ ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
PushFocusScope(ms->FocusScopeId);
- g.MultiSelectEnabledWindow = window;
- g.MultiSelectFlags = flags;
-
- // Report focus
- ms->In.IsFocused = ms->Out.IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
// Use copy of keyboard mods at the time of the request, otherwise we would requires mods to be held for an extra frame.
- g.MultiSelectKeyMods = g.NavJustMovedToId ? g.NavJustMovedToKeyMods : g.IO.KeyMods;
+ ms->KeyMods = g.NavJustMovedToId ? g.NavJustMovedToKeyMods : g.IO.KeyMods;
if ((flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0)
{
@@ -6688,14 +6684,14 @@
// FIXME: Polling key mods after the fact (frame following the move request) is incorrect, but latching it would requires non-trivial change in MultiSelectItemFooter()
if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == ms->FocusScopeId && g.NavJustMovedToHasSelectionData)
{
- if (g.MultiSelectKeyMods & ImGuiMod_Shift)
+ if (ms->KeyMods & ImGuiMod_Shift)
ms->InRequestSetRangeNav = true;
- if ((g.MultiSelectKeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0)
+ if ((ms->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0)
ms->In.RequestClear = true;
}
// Shortcuts
- if (ms->In.IsFocused)
+ if (ms->IsFocused)
{
// Select All helper shortcut (CTRL+A)
// Note: we are comparing FocusScope so we don't need to be testing for IsWindowFocused()
@@ -6708,10 +6704,8 @@
ms->In.RequestClear = true;
}
-#ifdef IMGUI_DEBUG_MULTISELECT
- if (ms->In.RequestClear) IMGUI_DEBUG_LOG("BeginMultiSelect: RequestClear\n");
- if (ms->In.RequestSelectAll) IMGUI_DEBUG_LOG("BeginMultiSelect: RequestSelectAll\n");
-#endif
+ //if (ms->In.RequestClear) IMGUI_DEBUG_LOG("BeginMultiSelect: RequestClear\n");
+ //if (ms->In.RequestSelectAll) IMGUI_DEBUG_LOG("BeginMultiSelect: RequestSelectAll\n");
return &ms->In;
}
@@ -6724,27 +6718,25 @@
// Clear selection when clicking void?
// We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection!
- if (g.MultiSelectFlags & ImGuiMultiSelectFlags_ClearOnClickWindowVoid)
+ if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickWindowVoid)
if (IsWindowHovered() && g.HoveredId == 0)
if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None)
{
- state->Out.RequestClear = true;
- state->Out.RequestSelectAll = state->Out.RequestSetRange = false;
+ ms->Out.RequestClear = true;
+ ms->Out.RequestSelectAll = ms->Out.RequestSetRange = false;
}
// Unwind
- if (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)
+ if (ms->Flags & ImGuiMultiSelectFlags_NoUnselect)
ms->Out.RangeValue = true;
- g.MultiSelectState.FocusScopeId = 0;
+ ms->FocusScopeId = 0;
+ ms->Window = NULL;
+ ms->Flags = ImGuiMultiSelectFlags_None;
PopFocusScope();
- g.MultiSelectEnabledWindow = NULL;
- g.MultiSelectFlags = ImGuiMultiSelectFlags_None;
-#ifdef IMGUI_DEBUG_MULTISELECT
- if (ms->Out.RequestClear) IMGUI_DEBUG_LOG("EndMultiSelect: RequestClear\n");
- if (ms->Out.RequestSelectAll) IMGUI_DEBUG_LOG("EndMultiSelect: RequestSelectAll\n");
- if (ms->Out.RequestSetRange) IMGUI_DEBUG_LOG("EndMultiSelect: RequestSetRange %p..%p = %d\n", ms->Out.RangeSrc, ms->Out.RangeDst, ms->Out.RangeValue);
-#endif
+ //if (ms->Out.RequestClear) IMGUI_DEBUG_LOG("EndMultiSelect: RequestClear\n");
+ //if (ms->Out.RequestSelectAll) IMGUI_DEBUG_LOG("EndMultiSelect: RequestSelectAll\n");
+ //if (ms->Out.RequestSetRange) IMGUI_DEBUG_LOG("EndMultiSelect: RequestSetRange %p..%p = %d\n", ms->Out.RangeSrc, ms->Out.RangeDst, ms->Out.RangeValue);
return &ms->Out;
}
@@ -6788,13 +6780,13 @@
if (ms->InRequestSetRangeNav)
{
IM_ASSERT(id != 0);
- IM_ASSERT((g.MultiSelectKeyMods & ImGuiMod_Shift) != 0);
+ IM_ASSERT((ms->KeyMods & ImGuiMod_Shift) != 0);
const bool is_range_dst = !ms->InRangeDstPassedBy && g.NavJustMovedToId == id; // Assume that g.NavJustMovedToId is not clipped.
if (is_range_dst)
ms->InRangeDstPassedBy = true;
if (is_range_src || is_range_dst || ms->In.RangeSrcPassedBy != ms->InRangeDstPassedBy)
selected = ms->In.RangeValue;
- else if ((g.MultiSelectKeyMods & ImGuiMod_Ctrl) == 0)
+ else if ((ms->KeyMods & ImGuiMod_Ctrl) == 0)
selected = false;
}
@@ -6810,11 +6802,11 @@
void* item_data = g.NextItemData.SelectionData;
g.NextItemData.FocusScopeId = 0;
+ const bool is_multiselect = (ms->Flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0;
bool selected = *p_selected;
bool pressed = *p_pressed;
- const bool is_multiselect = (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoMultiSelect) == 0;
- bool is_ctrl = (g.MultiSelectKeyMods & ImGuiMod_Ctrl) != 0;
- bool is_shift = (g.MultiSelectKeyMods & ImGuiMod_Shift) != 0;
+ bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0;
+ bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0;
// Auto-select as you navigate a list
if (g.NavJustMovedToId == id)
@@ -6866,7 +6858,7 @@
}
else
{
- selected = (!is_ctrl || (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)) ? true : !selected;
+ selected = (!is_ctrl || (ms->Flags & ImGuiMultiSelectFlags_NoUnselect)) ? true : !selected;
ms->Out.RangeSrc = ms->Out.RangeDst = item_data;
ms->Out.RangeValue = selected;
}
@@ -6903,7 +6895,7 @@
}
// Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)
- if (ms->Out.RangeSrc == item_data && is_ctrl && is_shift && is_multiselect && !(g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect))
+ if (ms->Out.RangeSrc == item_data && is_ctrl && is_shift && is_multiselect && !(ms->Flags & ImGuiMultiSelectFlags_NoUnselect))
ms->Out.RangeValue = selected;
*p_selected = selected;