RangeSelect/MultiSelect: (breaking) Added 'items_count' parameter to BeginMultiSelect(). Will enable extra features, and remove equivalent param from ImGuiSelectionBasicStorage::ApplyRequests(.

features/range_select
ocornut ago%!(EXTRA string=11 months)
parent 431caec3da
commit deedb600f2
  1. 12
      imgui.h
  2. 40
      imgui_demo.cpp
  3. 29
      imgui_widgets.cpp

@ -179,7 +179,7 @@ struct ImGuiMultiSelectIO; // Structure to interact with a BeginMultiSe
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiPayload; // User data payload for drag and drop operations
struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function. struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function.
struct ImGuiSelectionBasicStorage; // Helper struct to store multi-selection state + apply multi-selection requests. struct ImGuiSelectionBasicStorage; // Optional helper to store multi-selection state + apply multi-selection requests.
struct ImGuiSelectionRequest; // A selection request (stored in ImGuiMultiSelectIO) struct ImGuiSelectionRequest; // A selection request (stored in ImGuiMultiSelectIO)
struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
struct ImGuiStorage; // Helper for key->value storage (container sorted by key) struct ImGuiStorage; // Helper for key->value storage (container sorted by key)
@ -672,9 +672,10 @@ namespace ImGui
// Multi-selection system for Selectable() and TreeNode() functions. // Multi-selection system for Selectable() and TreeNode() functions.
// - This enables standard multi-selection/range-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used. // - This enables standard multi-selection/range-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used.
// - ImGuiSelectionUserData is often used to store your item index. // - ImGuiSelectionUserData is often used to store your item index within the current view (but may store something else).
// - Read comments near ImGuiMultiSelectIO for instructions/details and see 'Demo->Widgets->Selection State & Multi-Select' for demo. // - Read comments near ImGuiMultiSelectIO for instructions/details and see 'Demo->Widgets->Selection State & Multi-Select' for demo.
IMGUI_API ImGuiMultiSelectIO* BeginMultiSelect(ImGuiMultiSelectFlags flags, int current_selection_size = -1); // - 'selection_size' and 'items_count' parameters are optional and used by a few features. If they are costly for you to compute, you may avoid them.
IMGUI_API ImGuiMultiSelectIO* BeginMultiSelect(ImGuiMultiSelectFlags flags, int selection_size = -1, int items_count = -1);
IMGUI_API ImGuiMultiSelectIO* EndMultiSelect(); IMGUI_API ImGuiMultiSelectIO* EndMultiSelect();
IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data);
IMGUI_API bool IsItemToggledSelection(); // Was the last item selection state toggled? Useful if you need the per-item information _before_ reaching EndMultiSelect(). We only returns toggle _event_ in order to handle clipping correctly. IMGUI_API bool IsItemToggledSelection(); // Was the last item selection state toggled? Useful if you need the per-item information _before_ reaching EndMultiSelect(). We only returns toggle _event_ in order to handle clipping correctly.
@ -2736,6 +2737,7 @@ struct ImGuiMultiSelectIO
ImGuiSelectionUserData NavIdItem; // ms:w, app:r / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items). ImGuiSelectionUserData NavIdItem; // ms:w, app:r / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items).
bool NavIdSelected; // ms:w, app:r / app:r // (If using deletion) Last known selection state for NavId (if part of submitted items). bool NavIdSelected; // ms:w, app:r / app:r // (If using deletion) Last known selection state for NavId (if part of submitted items).
bool RangeSrcReset; // app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection). bool RangeSrcReset; // app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
int ItemsCount; // ms:w, app:r / app:r // 'int items_count' parameter to BeginMultiSelect() is copied here for convenience, allowing simpler calls to your ApplyRequests handler. Not used internally.
}; };
// Selection request type // Selection request type
@ -2783,8 +2785,8 @@ struct ImGuiSelectionBasicStorage
ImGuiID (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx); // e.g. selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((MyItems**)self->AdapterData)[idx]->ID; }; ImGuiID (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx); // e.g. selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((MyItems**)self->AdapterData)[idx]->ID; };
void* UserData; // User data for use by adapter function // e.g. selection.UserData = (void*)my_items; void* UserData; // User data for use by adapter function // e.g. selection.UserData = (void*)my_items;
// Methods: apply selection requests coming from BeginMultiSelect() and EndMultiSelect() functions // Methods: apply selection requests coming from BeginMultiSelect() and EndMultiSelect() functions. Uses 'items_count' based to BeginMultiSelect()
IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io, int items_count); IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io);
// Methods: selection storage // Methods: selection storage
ImGuiSelectionBasicStorage() { Clear(); UserData = NULL; AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage*, int idx) { return (ImGuiID)idx; }; } ImGuiSelectionBasicStorage() { Clear(); UserData = NULL; AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage*, int idx) { return (ImGuiID)idx; }; }

@ -2854,7 +2854,7 @@ struct ExampleDualListBox
// In this example we store item id in selection (instead of item index) // In this example we store item id in selection (instead of item index)
Selections[side].UserData = Items[side].Data; Selections[side].UserData = Items[side].Data;
Selections[side].AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImGuiID* items = (ImGuiID*)self->UserData; return items[idx]; }; Selections[side].AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImGuiID* items = (ImGuiID*)self->UserData; return items[idx]; };
Selections[side].ApplyRequests(ms_io, Items[side].Size); Selections[side].ApplyRequests(ms_io);
} }
static int IMGUI_CDECL CompareItemsByValue(const void* lhs, const void* rhs) static int IMGUI_CDECL CompareItemsByValue(const void* lhs, const void* rhs)
{ {
@ -2909,7 +2909,7 @@ struct ExampleDualListBox
if (child_visible) if (child_visible)
{ {
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None; ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
ApplySelectionRequests(ms_io, side); ApplySelectionRequests(ms_io, side);
for (int item_n = 0; item_n < items.Size; item_n++) for (int item_n = 0; item_n < items.Size; item_n++)
@ -3040,8 +3040,8 @@ static void ShowDemoWindowMultiSelect()
if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
{ {
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
selection.ApplyRequests(ms_io, ITEMS_COUNT); selection.ApplyRequests(ms_io);
for (int n = 0; n < ITEMS_COUNT; n++) for (int n = 0; n < ITEMS_COUNT; n++)
{ {
@ -3053,7 +3053,7 @@ static void ShowDemoWindowMultiSelect()
} }
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, ITEMS_COUNT); selection.ApplyRequests(ms_io);
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::TreePop(); ImGui::TreePop();
@ -3074,8 +3074,8 @@ static void ShowDemoWindowMultiSelect()
if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
{ {
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
selection.ApplyRequests(ms_io, ITEMS_COUNT); selection.ApplyRequests(ms_io);
ImGuiListClipper clipper; ImGuiListClipper clipper;
clipper.Begin(ITEMS_COUNT); clipper.Begin(ITEMS_COUNT);
@ -3094,7 +3094,7 @@ static void ShowDemoWindowMultiSelect()
} }
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, ITEMS_COUNT); selection.ApplyRequests(ms_io);
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::TreePop(); ImGui::TreePop();
@ -3138,8 +3138,8 @@ static void ShowDemoWindowMultiSelect()
if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
{ {
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
selection.ApplyRequests(ms_io, items.Size); selection.ApplyRequests(ms_io);
const bool want_delete = ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0); const bool want_delete = ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0);
const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1; const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1;
@ -3159,7 +3159,7 @@ static void ShowDemoWindowMultiSelect()
// Apply multi-select requests // Apply multi-select requests
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, items.Size); selection.ApplyRequests(ms_io);
if (want_delete) if (want_delete)
selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus); selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus);
} }
@ -3255,8 +3255,8 @@ static void ShowDemoWindowMultiSelect()
{ {
ImGui::PushID(selection_scope_n); ImGui::PushID(selection_scope_n);
ImGuiSelectionBasicStorage* selection = &selections_data[selection_scope_n]; ImGuiSelectionBasicStorage* selection = &selections_data[selection_scope_n];
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection->Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection->Size, ITEMS_COUNT);
selection->ApplyRequests(ms_io, ITEMS_COUNT); selection->ApplyRequests(ms_io);
ImGui::SeparatorText("Selection scope"); ImGui::SeparatorText("Selection scope");
ImGui::Text("Selection size: %d/%d", selection->Size, ITEMS_COUNT); ImGui::Text("Selection size: %d/%d", selection->Size, ITEMS_COUNT);
@ -3272,7 +3272,7 @@ static void ShowDemoWindowMultiSelect()
// Apply multi-select requests // Apply multi-select requests
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection->ApplyRequests(ms_io, ITEMS_COUNT); selection->ApplyRequests(ms_io);
ImGui::PopID(); ImGui::PopID();
} }
ImGui::TreePop(); ImGui::TreePop();
@ -3355,8 +3355,8 @@ static void ShowDemoWindowMultiSelect()
if (widget_type == WidgetType_TreeNode) if (widget_type == WidgetType_TreeNode)
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
selection.ApplyRequests(ms_io, items.Size); selection.ApplyRequests(ms_io);
const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0)) || request_deletion_from_menu; const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0)) || request_deletion_from_menu;
const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1; const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1;
@ -3500,7 +3500,7 @@ static void ShowDemoWindowMultiSelect()
// Apply multi-select requests // Apply multi-select requests
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, items.Size); selection.ApplyRequests(ms_io);
if (want_delete) if (want_delete)
selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus); selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus);
@ -9700,12 +9700,12 @@ struct ExampleAssetsBrowser
ms_flags |= ImGuiMultiSelectFlags_SelectOnClickRelease; // To allow dragging an unselected item without altering selection. ms_flags |= ImGuiMultiSelectFlags_SelectOnClickRelease; // To allow dragging an unselected item without altering selection.
if (AllowBoxSelect) if (AllowBoxSelect)
ms_flags |= ImGuiMultiSelectFlags_BoxSelect; // Enable box-select in 2D mode. ms_flags |= ImGuiMultiSelectFlags_BoxSelect; // Enable box-select in 2D mode.
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, Selection.Size); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, Selection.Size, Items.Size);
// Use custom selection adapter: store ID in selection (recommended) // Use custom selection adapter: store ID in selection (recommended)
Selection.UserData = this; Selection.UserData = this;
Selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self_, int idx) { ExampleAssetsBrowser* self = (ExampleAssetsBrowser*)self_->UserData; return self->Items[idx].ID; }; Selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self_, int idx) { ExampleAssetsBrowser* self = (ExampleAssetsBrowser*)self_->UserData; return self->Items[idx].ID; };
Selection.ApplyRequests(ms_io, Items.Size); Selection.ApplyRequests(ms_io);
const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (Selection.Size > 0)) || RequestDelete; const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (Selection.Size > 0)) || RequestDelete;
const int item_curr_idx_to_focus = want_delete ? Selection.ApplyDeletionPreLoop(ms_io, Items.Size) : -1; const int item_curr_idx_to_focus = want_delete ? Selection.ApplyDeletionPreLoop(ms_io, Items.Size) : -1;
@ -9813,7 +9813,7 @@ struct ExampleAssetsBrowser
} }
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
Selection.ApplyRequests(ms_io, Items.Size); Selection.ApplyRequests(ms_io);
if (want_delete) if (want_delete)
Selection.ApplyDeletionPostLoop(ms_io, Items, item_curr_idx_to_focus); Selection.ApplyDeletionPostLoop(ms_io, Items, item_curr_idx_to_focus);

@ -7183,10 +7183,13 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe
// Return ImGuiMultiSelectIO structure. // Return ImGuiMultiSelectIO structure.
// Lifetime: don't hold on ImGuiMultiSelectIO* pointers over multiple frames or past any subsequent call to BeginMultiSelect() or EndMultiSelect(). // Lifetime: don't hold on ImGuiMultiSelectIO* pointers over multiple frames or past any subsequent call to BeginMultiSelect() or EndMultiSelect().
// Passing 'current_selection_size' is currently optional: // Passing 'selection_size' and 'items_count' parameters is currently optional.
// - it is useful for shortcut routing with ImGuiMultiSelectFlags_ClearOnEscape: so we can have Escape be used to clear selection THEN to exit child window. // - 'selection_size' is useful to disable some shortcut routing: e.g. ImGuiMultiSelectFlags_ClearOnEscape won't claim Escape key when selection_size 0,
// - if it is costly for you to compute, but can easily tell if your selection is empty or not, you may pass 1, or use the ImGuiMultiSelectFlags_ClearOnEscape flag dynamically. // allowing a first press to clear selection THEN the second press to leave child window and return to parent.
ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int current_selection_size) // - 'items_count' is stored in ImGuiMultiSelectIO which makes it a convenient way to pass the information to your ApplyRequest() handler (but you may pass it differently).
// - If they are costly for you to compute (e.g. external intrusive selection without maintaining size), you may avoid them and pass -1.
// - If you can easily tell if your selection is empty or not, you may pass 0/1, or you may enable ImGuiMultiSelectFlags_ClearOnEscape flag dynamically.
ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int selection_size, int items_count)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
@ -7224,15 +7227,16 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int cur
ImGuiMultiSelectState* storage = g.MultiSelectStorage.GetOrAddByKey(id); ImGuiMultiSelectState* storage = g.MultiSelectStorage.GetOrAddByKey(id);
storage->ID = id; storage->ID = id;
storage->LastFrameActive = g.FrameCount; storage->LastFrameActive = g.FrameCount;
storage->LastSelectionSize = current_selection_size; storage->LastSelectionSize = selection_size;
storage->Window = window; storage->Window = window;
ms->Storage = storage; ms->Storage = storage;
// Output to user // Output to user
ms->IO.Requests.resize(0);
ms->IO.RangeSrcItem = storage->RangeSrcItem; ms->IO.RangeSrcItem = storage->RangeSrcItem;
ms->IO.NavIdItem = storage->NavIdItem; ms->IO.NavIdItem = storage->NavIdItem;
ms->IO.NavIdSelected = (storage->NavIdSelected == 1) ? true : false; ms->IO.NavIdSelected = (storage->NavIdSelected == 1) ? true : false;
ms->IO.Requests.resize(0); ms->IO.ItemsCount = items_count;
// Clear when using Navigation to move within the scope // Clear when using Navigation to move within the scope
// (we compare FocusScopeId so it possible to use multiple selections inside a same window) // (we compare FocusScopeId so it possible to use multiple selections inside a same window)
@ -7258,7 +7262,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int cur
{ {
// Shortcut: Clear selection (Escape) // Shortcut: Clear selection (Escape)
// Only claim shortcut if selection is not empty, allowing further presses on Escape to e.g. leave current child window. // Only claim shortcut if selection is not empty, allowing further presses on Escape to e.g. leave current child window.
if ((flags & ImGuiMultiSelectFlags_ClearOnEscape) && (current_selection_size != 0)) if ((flags & ImGuiMultiSelectFlags_ClearOnEscape) && (selection_size != 0))
if (Shortcut(ImGuiKey_Escape)) if (Shortcut(ImGuiKey_Escape))
request_clear = true; request_clear = true;
@ -7709,17 +7713,22 @@ void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage)
// if (req.Type == ImGuiSelectionRequestType_SetAll) { Clear(); if (req.Selected) { for (int n = 0; n < items_count; n++) { AddItem(n); } } // if (req.Type == ImGuiSelectionRequestType_SetAll) { Clear(); if (req.Selected) { for (int n = 0; n < items_count; n++) { AddItem(n); } }
// if (req.Type == ImGuiSelectionRequestType_SetRange) { for (int n = (int)ms_io->RangeFirstItem; n <= (int)ms_io->RangeLastItem; n++) { UpdateItem(n, ms_io->Selected); } } // if (req.Type == ImGuiSelectionRequestType_SetRange) { for (int n = (int)ms_io->RangeFirstItem; n <= (int)ms_io->RangeLastItem; n++) { UpdateItem(n, ms_io->Selected); } }
// } // }
void ImGuiSelectionBasicStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io, int items_count) void ImGuiSelectionBasicStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io)
{ {
// For convenience we obtain ItemsCount as passed to BeginMultiSelect(), which is optional.
// It makes sense when using ImGuiSelectionBasicStorage to simply pass your items count to BeginMultiSelect().
// Other scheme may handle SetAll differently.
IM_ASSERT(ms_io->ItemsCount != -1 && "Missing value for items_count in BeginMultiSelect() call!");
IM_ASSERT(AdapterIndexToStorageId != NULL); IM_ASSERT(AdapterIndexToStorageId != NULL);
for (ImGuiSelectionRequest& req : ms_io->Requests) for (ImGuiSelectionRequest& req : ms_io->Requests)
{ {
if (req.Type == ImGuiSelectionRequestType_SetAll) if (req.Type == ImGuiSelectionRequestType_SetAll)
Clear(); Clear();
if (req.Type == ImGuiSelectionRequestType_SetAll && req.Selected) if (req.Type == ImGuiSelectionRequestType_SetAll && req.Selected)
{ {
Storage.Data.reserve(items_count); Storage.Data.reserve(ms_io->ItemsCount);
for (int idx = 0; idx < items_count; idx++) for (int idx = 0; idx < ms_io->ItemsCount; idx++)
SetItemSelected(AdapterIndexToStorageId(this, idx), true); SetItemSelected(AdapterIndexToStorageId(this, idx), true);
} }
if (req.Type == ImGuiSelectionRequestType_SetRange) if (req.Type == ImGuiSelectionRequestType_SetRange)

Loading…
Cancel
Save