From 4405c5e015efaa9895c9bbbd9b41cfbb47de22af Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jul 2024 19:03:25 +0200 Subject: [PATCH] WIP TreeNode: todying with experimental ImGuiTreeNodeFlags_DrawTreeLines() (#2920) --- imgui_internal.h | 6 ++++-- imgui_widgets.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index ff1a8d8aca..5ea3883234 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -994,6 +994,7 @@ enum ImGuiSelectableFlagsPrivate_ // Extend ImGuiTreeNodeFlags_ enum ImGuiTreeNodeFlagsPrivate_ { + ImGuiTreeNodeFlags_DrawTreeLines = 1 << 27, // FIXME-EXPERIMENTAL: #2920 ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader() ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517) ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow, @@ -1290,8 +1291,9 @@ struct ImGuiTreeNodeStackData { ImGuiID ID; ImGuiTreeNodeFlags TreeFlags; - ImGuiItemFlags ItemFlags; // Used for nav landing - ImRect NavRect; // Used for nav landing + ImGuiItemFlags ItemFlags; // Used for nav landing + ImRect NavRect; // Used for nav landing + float DrawTreeLinesY2; }; // sizeof() = 20 diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 883a2648d0..2be18a5ac1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6559,6 +6559,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags) tree_node_data->TreeFlags = flags; tree_node_data->ItemFlags = g.LastItemData.ItemFlags; tree_node_data->NavRect = g.LastItemData.NavRect; + tree_node_data->DrawTreeLinesY2 = g.LastItemData.NavRect.Max.y; window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth); } @@ -6639,11 +6640,19 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && is_open && !g.NavIdIsAlive) if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) store_tree_node_stack_data = true; + flags |= ImGuiTreeNodeFlags_DrawTreeLines; // Always on by default + if (flags & ImGuiTreeNodeFlags_DrawTreeLines) + store_tree_node_stack_data = true; } const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; if (!is_visible) { + if ((flags & ImGuiTreeNodeFlags_DrawTreeLines) && (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1)))) + { + ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.back(); + parent_data->DrawTreeLinesY2 = ImMax(parent_data->DrawTreeLinesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway. + } if (store_tree_node_stack_data && is_open) TreeNodeStoreStackData(flags); // Call before TreePushOverrideID() if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) @@ -6805,6 +6814,17 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l LogSetNextTextDecoration(">", NULL); } + if ((flags & ImGuiTreeNodeFlags_DrawTreeLines) && (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1)))) + { + ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.back(); + float x1 = parent_data->NavRect.Min.x + ImTrunc(g.FontSize * 0.5f + g.Style.FramePadding.x); // GetTreeNodeToLabelSpacing() * 0.5f + float x2 = text_pos.x - text_offset_x; + float y = text_pos.y + ImTrunc(g.FontSize * 0.5f); + parent_data->DrawTreeLinesY2 = ImMax(parent_data->DrawTreeLinesY2, y); + if (x1 < x2) + window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_Border), 1.0f); + } + if (span_all_columns && !span_all_columns_label) TablePopBackgroundChannel(); @@ -6871,6 +6891,14 @@ void ImGui::TreePop() if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, data); } + if (data->TreeFlags & ImGuiTreeNodeFlags_DrawTreeLines) + { + float x = data->NavRect.Min.x + ImTrunc(g.FontSize * 0.5f + g.Style.FramePadding.x); // GetTreeNodeToLabelSpacing() * 0.5f + float y1 = ImMax(data->NavRect.Max.y, window->ClipRect.Min.y); + float y2 = ImMin(data->DrawTreeLinesY2, window->ClipRect.Max.y); + if (y1 < y2) + window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_Border), 1.0f); + } g.TreeNodeStack.pop_back(); window->DC.TreeHasStackDataDepthMask &= ~tree_depth_mask; } -- 2.45.2.windows.1