From 806a1461989bdcc87162cb99a764845689b81911 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 28 May 2016 17:12:13 +0200 Subject: [PATCH] TreeNodeEx(): ImGuiTreeNodeFlags_AlwaysOpen->ImGuiTreeNodeFlags_Leaf, + added ImGuiTreeNodeFlags_Bullet (#324, #581) --- imgui.cpp | 8 ++++---- imgui.h | 9 +++++---- imgui_demo.cpp | 39 ++++++++++++++++++++++++++------------- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d677f2a6..1ec4cd2d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5776,7 +5776,7 @@ void ImGui::LogButtons() bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { - if (flags & ImGuiTreeNodeFlags_AlwaysOpen) + if (flags & ImGuiTreeNodeFlags_Leaf) return true; // We only write to the tree storage if the user clicks (or explicitely use SetNextTreeNode*** functions) @@ -5871,7 +5871,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - if (pressed && !(flags & ImGuiTreeNodeFlags_AlwaysOpen)) + if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) { bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) @@ -5915,9 +5915,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) RenderFrame(bb.Min, bb.Max, col, false); - if (flags & ImGuiTreeNodeFlags_AlwaysOpen) + if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); - else + else if (!(flags & ImGuiTreeNodeFlags_Leaf)) RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f, false); if (g.LogEnabled) LogRenderedText(text_pos, ">"); diff --git a/imgui.h b/imgui.h index 3a0426b8..15af60fd 100644 --- a/imgui.h +++ b/imgui.h @@ -541,10 +541,11 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. - ImGuiTreeNodeFlags_AlwaysOpen = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). - //ImGuiTreeNodeFlags_UnindentArrow = 1 << 9, // FIXME: TODO: Unindent tree so that Label is aligned to current X position - //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 10, // FIXME: TODO: Extend hit box horizontally even if not framed - //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 11, // FIXME: TODO: Automatically scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). + ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow + //ImGuiTreeNodeFlags_UnindentArrow = 1 << 10, // FIXME: TODO: Unindent tree so that Label is aligned to current X position + //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed + //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Automatically scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6fb75a9c..c78f6965 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -253,22 +253,34 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("With selectable nodes")) { - ShowHelpMarker("Click to select, CTRL+Click to toggle, click on arrows to open"); - static int selection_mask = 0x02; // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. - int node_clicked = -1; + ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open."); + ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents. + static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit. + int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc. for (int i = 0; i < 6; i++) { + // Disable the default open on single-click behavior and pass in Selected flag according to our selection state. ImGuiTreeNodeFlags node_flags = ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; - if (i >= 3) - node_flags |= ImGuiTreeNodeFlags_AlwaysOpen; - bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable %s %d", (i >= 3) ? "Leaf" : "Node", i); - if (ImGui::IsItemClicked()) - node_clicked = i; - if (node_open) + if (i < 3) { - ImGui::Text("Selectable Blah blah"); - ImGui::Text("Blah blah"); - ImGui::TreePop(); + // Node + bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; + if (node_open) + { + ImGui::Text("Blah blah\nBlah Blah"); + ImGui::TreePop(); + } + } + else + { + // Leaf: Here we use the ImGuiTreeNodeFlags_Leaf functionality + ImGuiTreeNodeFlags_NoTreePushOnOpen to avoid testing return value and doing a TreePop + // The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or a simple Text() element offset by GetTreeNodeToLabelSpacing() + node_flags |= ImGuiTreeNodeFlags_Leaf|ImGuiTreeNodeFlags_NoTreePushOnOpen; + ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); + if (ImGui::IsItemClicked()) + node_clicked = i; } } if (node_clicked != -1) @@ -276,9 +288,10 @@ void ImGui::ShowTestWindow(bool* p_open) // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame. if (ImGui::GetIO().KeyCtrl) selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else if (!(selection_mask & (1 << node_clicked))) // If there is already a selection don't replace we clicked node is part of it + else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection selection_mask = (1 << node_clicked); // Click to single-select } + ImGui::PopStyleVar(); ImGui::TreePop(); } ImGui::TreePop();