MultiSelect: Demo: added simpler demo using Clipper. Clarify RangeSrcPassedBy doc.

This commit is contained in:
ocornut 2023-08-23 19:47:24 +02:00
parent c3753809b1
commit 6ddc5f38af
2 changed files with 52 additions and 8 deletions

12
imgui.h
View File

@ -2774,11 +2774,13 @@ enum ImGuiMultiSelectFlags_
// Usage flow: // Usage flow:
// BEGIN - (1) Call BeginMultiSelect() and retrieve the ImGuiMultiSelectIO* result. // BEGIN - (1) Call BeginMultiSelect() and retrieve the ImGuiMultiSelectIO* result.
// - (2) [If using clipper] Honor Clear/SelectAll/SetRange requests by updating your selection data. Same code as Step 6. // - (2) [If using clipper] Honor Clear/SelectAll/SetRange requests by updating your selection data. Same code as Step 6.
// LOOP - (3) [If using clipper] Set RangeSrcPassedBy=true if the RangeSrcItem item is part of the items clipped before the first submitted/visible item. // LOOP - (3) [If using clipper] Set RangeSrcPassedBy=true if the RangeSrcItem item was already passed by.
// This is because for range-selection we need to know if we are currently "inside" or "outside" the range. // 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 in ImGuiSelectionUserData, this is easy to compute: if (clipper.DisplayStart > data->RangeSrcItem) { data->RangeSrcPassedBy = true; } // - If you are using integer indices in ImGuiSelectionUserData, this is easy to compute:
// - If you are using pointers in ImGuiSelectionUserData, you may need additional processing in each clipper step to tell if current DisplayStart comes after RangeSrcItem.. // if (clipper.DisplayStart > data->RangeSrcItem) { data->RangeSrcPassedBy = true; }
// - (4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls. (optionally call IsItemToggledSelection() if you need that info immediately for displaying your item, before EndMultiSelect()) // - If you are using pointers in ImGuiSelectionUserData, you may need additional processing, e.g. find the index of RangeSrcItem before applying the above operation.
// - This also needs to be done at the end of the clipper loop, otherwise we can't tell if the item still exist.
// - (4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls.
// END - (5) Call EndMultiSelect() and retrieve the ImGuiMultiSelectIO* result. // END - (5) Call EndMultiSelect() and retrieve the ImGuiMultiSelectIO* result.
// - (6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Same code as Step 2. // - (6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Same code as Step 2.
// If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable()/TreeNode on a per-item basis. // If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable()/TreeNode on a per-item basis.
@ -2801,7 +2803,7 @@ struct ImGuiMultiSelectIO
ImGuiSelectionUserData RangeFirstItem; // / / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom) ImGuiSelectionUserData RangeFirstItem; // / / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom)
ImGuiSelectionUserData RangeLastItem; // / / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top) ImGuiSelectionUserData RangeLastItem; // / / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top)
bool RangeSelected; // / / ms:w, app:r // End: parameter for RequestSetRange request. true = Select Range, false = Unselect Range. bool RangeSelected; // / / ms:w, app:r // End: parameter for RequestSetRange request. true = Select Range, false = Unselect Range.
bool RangeSrcPassedBy; // / ms:rw app:w / ms:r // (If using clipper) Need to be set by app/user if RangeSrcItem was part of the clipped set before submitting the visible items. Ignore if not clipping. bool RangeSrcPassedBy; // / ms:rw app:w / ms:r // (If using clipper) Need to be set by app/user if RangeSrcItem was passed by. Ignore if not clipping.
bool RangeSrcReset; // app:w / app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection). bool RangeSrcReset; // app:w / app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
bool NavIdSelected; // ms:w, app:r / / // (If using deletion) Last known selection state for NavId (if part of submitted items). bool NavIdSelected; // ms:w, app:r / / // (If using deletion) Last known selection state 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). ImGuiSelectionUserData NavIdItem; // ms:w, app:r / / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items).

View File

@ -2911,7 +2911,7 @@ static void ShowDemoWindowMultiSelect()
ImGui::TreePop(); ImGui::TreePop();
} }
const char* random_names[] = static const char* random_names[] =
{ {
"Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper", "Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper",
"Bitter Gourd", "Bok Choy", "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", "Calabash", "Capers", "Carrot", "Cassava", "Bitter Gourd", "Bok Choy", "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", "Calabash", "Capers", "Carrot", "Cassava",
@ -2935,7 +2935,7 @@ static void ShowDemoWindowMultiSelect()
// The BeginListBox() has no actual purpose for selection logic (other that offering a scrolling region). // The BeginListBox() has no actual purpose for selection logic (other that offering a scrolling region).
const int ITEMS_COUNT = 50; const int ITEMS_COUNT = 50;
ImGui::Text("Selection size: %d", selection.GetSize()); ImGui::Text("Selection: %d/%d", selection.GetSize(), ITEMS_COUNT);
if (ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20))) if (ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20)))
{ {
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape; ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape;
@ -2951,7 +2951,49 @@ static void ShowDemoWindowMultiSelect()
ImGui::Selectable(label, item_is_selected); ImGui::Selectable(label, item_is_selected);
} }
// Apply multi-select requests ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, ITEMS_COUNT);
ImGui::EndListBox();
}
ImGui::TreePop();
}
// Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect()
IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with clipper)");
if (ImGui::TreeNode("Multi-Select (with clipper)"))
{
static ExampleSelection selection;
ImGui::Text("Added features:");
ImGui::BulletText("Using ImGuiListClipper.");
const int ITEMS_COUNT = 10000;
ImGui::Text("Selection: %d/%d", selection.GetSize(), ITEMS_COUNT);
if (ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20)))
{
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags);
selection.ApplyRequests(ms_io, ITEMS_COUNT);
ImGuiListClipper clipper;
clipper.Begin(ITEMS_COUNT);
while (clipper.Step())
{
if (!ms_io->RangeSrcPassedBy && clipper.DisplayStart > ms_io->RangeSrcItem)
ms_io->RangeSrcPassedBy = true;
for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
{
char label[64];
sprintf(label, "Object %05d: %s", n, random_names[n % IM_ARRAYSIZE(random_names)]);
bool item_is_selected = selection.Contains(n);
ImGui::SetNextItemSelectionUserData(n);
ImGui::Selectable(label, item_is_selected);
}
}
if (!ms_io->RangeSrcPassedBy && ITEMS_COUNT > ms_io->RangeSrcItem)
ms_io->RangeSrcPassedBy = true;
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io, ITEMS_COUNT); selection.ApplyRequests(ms_io, ITEMS_COUNT);