RangeSelect/MultiSelect: Demo tweak. Removed multi-scope from Advanced (too messy), made it a seperate mini-demo.

features/range_select
ocornut ago%!(EXTRA string=2 years)
parent 507790eeaa
commit 20e46d4180
  1. 136
      imgui_demo.cpp

@ -2850,9 +2850,10 @@ static void ShowDemoWindowMultiSelect()
ImGui::BulletText("Shift modifier for range selection."); ImGui::BulletText("Shift modifier for range selection.");
ImGui::BulletText("CTRL+A to select all."); ImGui::BulletText("CTRL+A to select all.");
// The BeginListBox() has no actual purpose for selection logic (other that offering a scrolling regions). // 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 size: %d", selection.GetSize());
ImGui::Text("RangeRef: %d", selection.RangeRef);
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;
@ -2881,11 +2882,49 @@ static void ShowDemoWindowMultiSelect()
ImGui::TreePop(); ImGui::TreePop();
} }
// Demonstrate individual selection scopes in same window
IMGUI_DEMO_MARKER("Widgets/Selection State/Multiple Selection (full, multiple scopes)");
if (ImGui::TreeNode("Multiple Selection (full, multiple scopes)"))
{
const int SCOPES_COUNT = 3;
const int ITEMS_COUNT = 8; // Per scope
static ExampleSelection selections_data[SCOPES_COUNT];
for (int selection_scope_n = 0; selection_scope_n < SCOPES_COUNT; selection_scope_n++)
{
ExampleSelection* selection = &selections_data[selection_scope_n];
ImGui::SeparatorText("Selection scope");
ImGui::Text("Selection size: %d/%d", selection->GetSize(), ITEMS_COUNT);
ImGui::PushID(selection_scope_n);
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape; // | ImGuiMultiSelectFlags_ClearOnClickRectVoid
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, (void*)(intptr_t)selection->RangeRef, selection->GetSelected(selection->RangeRef));
selection->ApplyRequests(ms_io, ITEMS_COUNT);
for (int n = 0; n < ITEMS_COUNT; n++)
{
char label[64];
sprintf(label, "Object %05d: %s", n, random_names[n % IM_ARRAYSIZE(random_names)]);
bool item_is_selected = selection->GetSelected(n);
ImGui::SetNextItemSelectionUserData(n);
ImGui::Selectable(label, item_is_selected);
if (ImGui::IsItemToggledSelection())
selection->SetSelected(n, !item_is_selected);
}
// Apply multi-select requests
ms_io = ImGui::EndMultiSelect();
selection->RangeRef = (int)(intptr_t)ms_io->RangeSrc;
selection->ApplyRequests(ms_io, ITEMS_COUNT);
ImGui::PopID();
}
ImGui::TreePop();
}
// Advanced demonstration of BeginMultiSelect() // Advanced demonstration of BeginMultiSelect()
// - Showcase clipping. // - Showcase clipping.
// - Showcase basic drag and drop. // - Showcase basic drag and drop.
// - Showcase TreeNode variant (note that tree node don't expand in the demo: supporting expanding tree nodes + clipping a separate thing). // - Showcase TreeNode variant (note that tree node don't expand in the demo: supporting expanding tree nodes + clipping a separate thing).
// - Showcase having multiple multi-selection scopes in the same window.
// - Showcase using inside a table. // - Showcase using inside a table.
IMGUI_DEMO_MARKER("Widgets/Selection State/Multiple Selection (full, advanced)"); IMGUI_DEMO_MARKER("Widgets/Selection State/Multiple Selection (full, advanced)");
//ImGui::SetNextItemOpen(true, ImGuiCond_Once); //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
@ -2893,64 +2932,42 @@ static void ShowDemoWindowMultiSelect()
{ {
// Options // Options
enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode }; enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode };
static bool use_table = false; static bool use_clipper = true;
static bool use_drag_drop = true; static bool use_drag_drop = true;
static bool use_multiple_scopes = false; static bool show_in_table = false;
static bool show_color_button = false;
static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None; static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None;
static WidgetType widget_type = WidgetType_Selectable; static WidgetType widget_type = WidgetType_Selectable;
if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; } if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; } if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; }
ImGui::Checkbox("Use table", &use_table); ImGui::Checkbox("Enable clipper", &use_clipper);
ImGui::Checkbox("Use drag & drop", &use_drag_drop); ImGui::Checkbox("Enable drag & drop", &use_drag_drop);
ImGui::Checkbox("Multiple selection scopes in same window", &use_multiple_scopes); ImGui::Checkbox("Show in a table", &show_in_table);
ImGui::Checkbox("Show color button", &show_color_button);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoMultiSelect", &flags, ImGuiMultiSelectFlags_NoMultiSelect); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoMultiSelect", &flags, ImGuiMultiSelectFlags_NoMultiSelect);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoUnselect", &flags, ImGuiMultiSelectFlags_NoUnselect); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoUnselect", &flags, ImGuiMultiSelectFlags_NoUnselect);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectAll", &flags, ImGuiMultiSelectFlags_NoSelectAll); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectAll", &flags, ImGuiMultiSelectFlags_NoSelectAll);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnEscape", &flags, ImGuiMultiSelectFlags_ClearOnEscape); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnEscape", &flags, ImGuiMultiSelectFlags_ClearOnEscape);
ImGui::BeginDisabled(use_multiple_scopes);
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickWindowVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickWindowVoid); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickWindowVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickWindowVoid);
ImGui::EndDisabled();
// When 'use_multiple_scopes' is set we show 3 selection scopes in the host window instead of 1 in a scrolling window.
static ExampleSelection selections_data[3];
const int selection_scope_count = use_multiple_scopes ? 3 : 1;
for (int selection_scope_n = 0; selection_scope_n < selection_scope_count; selection_scope_n++)
{
ExampleSelection* selection = &selections_data[selection_scope_n];
const int ITEMS_COUNT = use_multiple_scopes ? 12 : 1000; // Smaller count to make it easier to see multiple scopes in same screen. const int ITEMS_COUNT = 1000;
ImGui::PushID(selection_scope_n); static ExampleSelection selection;
// Open a scrolling region ImGui::Text("Selection size: %d/%d", selection.GetSize(), ITEMS_COUNT);
bool draw_selection = true; if (ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20)))
if (use_multiple_scopes)
{
ImGui::SeparatorText("Selection scope");
}
else
{
ImGui::Text("Selection size: %d", selection->GetSize());
draw_selection = ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20));
}
if (draw_selection)
{ {
ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize()); ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize());
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));
ImGuiMultiSelectFlags local_flags = flags; ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, (void*)(intptr_t)selection.RangeRef, selection.GetSelected(selection.RangeRef));
if (use_multiple_scopes) selection.ApplyRequests(ms_io, ITEMS_COUNT);
local_flags &= ~ImGuiMultiSelectFlags_ClearOnClickWindowVoid; // local_flags |= ImGuiMultiSelectFlags_ClearOnClickRectVoid;
ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(local_flags, (void*)(intptr_t)selection->RangeRef, selection->GetSelected(selection->RangeRef));
selection->ApplyRequests(ms_io, ITEMS_COUNT);
if (use_multiple_scopes)
ImGui::Text("Selection size: %d", selection->GetSize()); // Draw counter below Separator and after BeginMultiSelect()
if (use_table) if (show_in_table)
{ {
if (widget_type == WidgetType_TreeNode)
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f));
ImGui::BeginTable("##Split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoPadOuterX); ImGui::BeginTable("##Split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoPadOuterX);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.70f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.70f);
@ -2959,39 +2976,47 @@ static void ShowDemoWindowMultiSelect()
} }
ImGuiListClipper clipper; ImGuiListClipper clipper;
if (use_clipper)
clipper.Begin(ITEMS_COUNT); clipper.Begin(ITEMS_COUNT);
while (clipper.Step())
while (!use_clipper || clipper.Step())
{ {
// IF clipping is used you need to set 'RangeSrcPassedBy = true' if RangeSrc was passed over. // IF clipping is used you need to set 'RangeSrcPassedBy = true' if RangeSrc was passed over.
if (use_clipper)
if ((int)(intptr_t)ms_io->RangeSrc <= clipper.DisplayStart) if ((int)(intptr_t)ms_io->RangeSrc <= clipper.DisplayStart)
ms_io->RangeSrcPassedBy = true; ms_io->RangeSrcPassedBy = true;
for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) const int item_begin = use_clipper ? clipper.DisplayStart : 0;
const int item_end = use_clipper ? clipper.DisplayEnd : ITEMS_COUNT;
for (int n = item_begin; n < item_end; n++)
{ {
if (use_table) if (show_in_table)
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushID(n); ImGui::PushID(n);
const char* category = random_names[n % IM_ARRAYSIZE(random_names)]; const char* category = random_names[n % IM_ARRAYSIZE(random_names)];
char label[64]; char label[64];
sprintf(label, "Object %05d: category: %s", n, category); sprintf(label, "Object %05d: %s", n, category);
bool item_is_selected = selection->GetSelected(n);
// Emit a color button, to test that Shift+LeftArrow landing on an item that is not part // Emit a color button, to test that Shift+LeftArrow landing on an item that is not part
// of the selection scope doesn't erroneously alter our selection (FIXME-TESTS: Add a test for that!). // of the selection scope doesn't erroneously alter our selection (FIXME-TESTS: Add a test for that!).
if (show_color_button)
{
ImU32 dummy_col = (ImU32)((unsigned int)n * 0xC250B74B) | IM_COL32_A_MASK; ImU32 dummy_col = (ImU32)((unsigned int)n * 0xC250B74B) | IM_COL32_A_MASK;
ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz); ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz);
ImGui::SameLine(); ImGui::SameLine();
}
bool item_is_selected = selection.GetSelected(n);
ImGui::SetNextItemSelectionUserData(n); ImGui::SetNextItemSelectionUserData(n);
if (widget_type == WidgetType_Selectable) if (widget_type == WidgetType_Selectable)
{ {
ImGui::Selectable(label, item_is_selected); ImGui::Selectable(label, item_is_selected);
if (ImGui::IsItemToggledSelection()) if (ImGui::IsItemToggledSelection())
selection->SetSelected(n, !item_is_selected); selection.SetSelected(n, !item_is_selected);
if (use_drag_drop && ImGui::BeginDragDropSource()) if (use_drag_drop && ImGui::BeginDragDropSource())
{ {
ImGui::Text("(Dragging %d items)", selection->GetSize()); ImGui::Text("(Dragging %d items)", selection.GetSize());
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
} }
@ -3003,10 +3028,10 @@ static void ShowDemoWindowMultiSelect()
tree_node_flags |= ImGuiTreeNodeFlags_Selected; tree_node_flags |= ImGuiTreeNodeFlags_Selected;
bool open = ImGui::TreeNodeEx(label, tree_node_flags); bool open = ImGui::TreeNodeEx(label, tree_node_flags);
if (ImGui::IsItemToggledSelection()) if (ImGui::IsItemToggledSelection())
selection->SetSelected(n, !item_is_selected); selection.SetSelected(n, !item_is_selected);
if (use_drag_drop && ImGui::BeginDragDropSource()) if (use_drag_drop && ImGui::BeginDragDropSource())
{ {
ImGui::Text("(Dragging %d items)", selection->GetSize()); ImGui::Text("(Dragging %d items)", selection.GetSize());
ImGui::EndDragDropSource(); ImGui::EndDragDropSource();
} }
if (open) if (open)
@ -3022,7 +3047,7 @@ static void ShowDemoWindowMultiSelect()
} }
// Demo content within a table // Demo content within a table
if (use_table) if (show_in_table)
{ {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::SetNextItemWidth(-FLT_MIN); ImGui::SetNextItemWidth(-FLT_MIN);
@ -3033,27 +3058,26 @@ static void ShowDemoWindowMultiSelect()
ImGui::PopID(); ImGui::PopID();
} }
if (!use_clipper)
break;
} }
if (use_table) if (show_in_table)
{ {
ImGui::EndTable(); ImGui::EndTable();
if (widget_type == WidgetType_TreeNode)
ImGui::PopStyleVar(); ImGui::PopStyleVar();
} }
// Apply multi-select requests // Apply multi-select requests
ms_io = ImGui::EndMultiSelect(); ms_io = ImGui::EndMultiSelect();
selection->RangeRef = (int)(intptr_t)ms_io->RangeSrc; selection.RangeRef = (int)(intptr_t)ms_io->RangeSrc;
selection->ApplyRequests(ms_io, ITEMS_COUNT); selection.ApplyRequests(ms_io, ITEMS_COUNT);
if (widget_type == WidgetType_TreeNode) if (widget_type == WidgetType_TreeNode)
ImGui::PopStyleVar(); ImGui::PopStyleVar();
if (use_multiple_scopes == false)
ImGui::EndListBox(); ImGui::EndListBox();
} }
ImGui::PopID(); // ImGui::PushID(selection_scope_n);
} // for each selection scope (1 or 3)
ImGui::TreePop(); ImGui::TreePop();
} }

Loading…
Cancel
Save