MultiSelect: Fix for TreeNode following merge of 011d4755. Demo: basic test for tree nodes.

This commit is contained in:
ocornut 2020-03-11 21:57:18 +01:00
parent 9c7183dd04
commit 7abda179af
2 changed files with 49 additions and 17 deletions

View File

@ -2844,18 +2844,29 @@ static void ShowDemoWindowMultiSelect()
"Cauliflower", "Celery", "Celery Root", "Celcuce", "Chayote", "Celtuce", "Chayote", "Chinese Broccoli", "Corn", "Cucumber"
};
int COUNT = 1000;
HelpMarker("Hold CTRL and click to select multiple items. Hold SHIFT to select a range. Keyboard is also supported.");
// Test both Selectable() and TreeNode() widgets
enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode };
static WidgetType widget_type = WidgetType_TreeNode;
if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; }
ImGui::SameLine();
if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; }
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int*)&ImGui::GetIO().ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
ImGui::SameLine(); HelpMarker("Hold CTRL and click to select multiple items. Hold SHIFT to select a range. Keyboard is also supported.");
// Open a scrolling region
const int ITEMS_COUNT = 1000;
if (ImGui::BeginListBox("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20)))
{
ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_None, (void*)(intptr_t)selection_ref, selection.GetSelected((int)selection_ref));
if (multi_select_data->RequestClear) { selection.Clear(); }
if (multi_select_data->RequestSelectAll) { selection.SelectAll(COUNT); }
ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize());
if (widget_type == WidgetType_TreeNode)
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(ImGuiMultiSelectFlags_None, (void*)(intptr_t)selection_ref, selection.GetSelected(selection_ref));
if (multi_select_data->RequestClear) { selection.Clear(); }
if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
ImGuiListClipper clipper;
clipper.Begin(COUNT);
clipper.Begin(ITEMS_COUNT);
while (clipper.Step())
{
if (clipper.DisplayStart > (int)selection_ref)
@ -2868,23 +2879,42 @@ static void ShowDemoWindowMultiSelect()
bool item_is_selected = selection.GetSelected(n);
// 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.
ImVec4 dummy_col = ImColor((ImU32)ImGui::GetID(label));
ImGui::ColorButton("##", dummy_col, ImGuiColorEditFlags_NoTooltip, color_button_sz);
// of the selection scope doesn't erroneously alter our selection (FIXME-TESTS: Add a test for that!).
ImU32 dummy_col = (ImU32)ImGui::GetID(label);
ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz);
ImGui::SameLine();
ImGui::SetNextItemSelectionUserData(n);
if (ImGui::Selectable(label, item_is_selected))
selection.SetSelected(n, !item_is_selected);
if (widget_type == WidgetType_Selectable)
{
if (ImGui::Selectable(label, item_is_selected))
selection.SetSelected(n, !item_is_selected);
}
else if (widget_type == WidgetType_TreeNode)
{
ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnDoubleClick;
if (item_is_selected)
tree_node_flags |= ImGuiTreeNodeFlags_Selected;
ImGui::TreeNodeEx(label, tree_node_flags);
if (ImGui::IsItemToggledSelection())
selection.SetSelected(n, !item_is_selected);
}
ImGui::PopID();
}
}
// Apply multi-select requests
multi_select_data = ImGui::EndMultiSelect();
selection_ref = (int)(intptr_t)multi_select_data->RangeSrc;
ImGui::EndListBox();
if (multi_select_data->RequestClear) { selection.Clear(); }
if (multi_select_data->RequestSelectAll) { selection.SelectAll(COUNT); }
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); }
if (widget_type == WidgetType_TreeNode)
ImGui::PopStyleVar();
ImGui::EndListBox();
}
ImGui::TreePop();
}

View File

@ -6443,8 +6443,6 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x;
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
// Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags.
// Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support.
@ -6469,12 +6467,15 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
const bool is_multi_select = g.MultiSelectEnabled;
if (is_multi_select)
{
flags |= ImGuiTreeNodeFlags_OpenOnArrow;
MultiSelectItemHeader(id, &selected);
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
// We absolutely need to distinguish open vs select so this is the default when multi-select is enabled.
flags |= ImGuiTreeNodeFlags_OpenOnArrow;
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
// Enabling this test makes actions using CTRL+SHIFT delay their effect on the mouse release which is annoying, but it allows drag and drop of multiple items.
// FIXME-MULTISELECT: Consider opt-in for drag and drop behavior in ImGuiMultiSelectFlags?
if (!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore))
button_flags |= ImGuiButtonFlags_PressedOnClick;
else
@ -6482,7 +6483,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
}
else
{
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
}
bool hovered, held;