diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index c60191023..8f695b87c 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -27,6 +27,7 @@ // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2025-04-09: [Docking] Revert update monitors and work areas information every frame. Only do it on Windows. (#8415, #8558) +// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561) // 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. // 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) // 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) @@ -161,6 +162,7 @@ struct ImGui_ImplSDL2_Data SDL_Cursor* MouseLastCursor; int MouseLastLeaveFrame; bool MouseCanUseGlobalState; + bool MouseCanUseCapture; bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state. // Gamepad handling @@ -521,25 +523,13 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); - // Check and store if we are on a SDL backend that supports global mouse position - // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) - bool mouse_can_use_global_state = false; -#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - const char* sdl_backend = SDL_GetCurrentVideoDriver(); - const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; - for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++) - if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0) - mouse_can_use_global_state = true; -#endif - // Setup backend capabilities flags ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)(); io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = "imgui_impl_sdl2"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) - if (mouse_can_use_global_state) - io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) + // (ImGuiBackendFlags_PlatformHasViewports may be set just below) bd->Window = window; bd->WindowID = SDL_GetWindowID(window); @@ -547,13 +537,27 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void // SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960) // We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame. - bd->MouseCanUseGlobalState = mouse_can_use_global_state; #ifndef __APPLE__ bd->MouseCanReportHoveredViewport = bd->MouseCanUseGlobalState; #else bd->MouseCanReportHoveredViewport = false; #endif + // Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse() + // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) + bd->MouseCanUseGlobalState = false; + bd->MouseCanUseCapture = false; +#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE + const char* sdl_backend = SDL_GetCurrentVideoDriver(); + const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; + for (const char* item : capture_and_global_state_whitelist) + if (strncmp(sdl_backend, item, strlen(item)) == 0) + bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true; +#endif + if (bd->MouseCanUseGlobalState) + io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) + + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; @@ -701,12 +705,15 @@ static void ImGui_ImplSDL2_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE // - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside. - // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to migitate the issue we wait until mouse has moved to begin capture. - bool want_capture = false; - for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) - if (ImGui::IsMouseDragging(button_n, 1.0f)) - want_capture = true; - SDL_CaptureMouse(want_capture ? SDL_TRUE : SDL_FALSE); + // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture. + if (bd->MouseCanUseCapture) + { + bool want_capture = false; + for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) + if (ImGui::IsMouseDragging(button_n, 1.0f)) + want_capture = true; + SDL_CaptureMouse(want_capture ? SDL_TRUE : SDL_FALSE); + } SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (focused_window && (bd->Window == focused_window || ImGui_ImplSDL2_GetViewportForWindowID(SDL_GetWindowID(focused_window)) != NULL)); diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 4c330d8f3..6eb7856b8 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -25,6 +25,7 @@ // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2025-04-09: [Docking] Revert update monitors and work areas information every frame. Only do it on Windows. (#8415, #8558) +// 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561) // 2025-03-30: Update for SDL3 api changes: Revert SDL_GetClipboardText() memory ownership change. (#8530, #7801) // 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. // 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) @@ -120,6 +121,7 @@ struct ImGui_ImplSDL3_Data SDL_Cursor* MouseLastCursor; int MousePendingLeaveFrame; bool MouseCanUseGlobalState; + bool MouseCanUseCapture; bool MouseCanReportHoveredViewport; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state. // Gamepad handling @@ -505,25 +507,13 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); IM_UNUSED(sdl_gl_context); // Unused in this branch - // Check and store if we are on a SDL backend that supports global mouse position - // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) - bool mouse_can_use_global_state = false; -#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - const char* sdl_backend = SDL_GetCurrentVideoDriver(); - const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; - for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++) - if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0) - mouse_can_use_global_state = true; -#endif - // Setup backend capabilities flags ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)(); io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = "imgui_impl_sdl3"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) - if (mouse_can_use_global_state) - io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) + // (ImGuiBackendFlags_PlatformHasViewports may be set just below) bd->Window = window; bd->WindowID = SDL_GetWindowID(window); @@ -531,13 +521,26 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void // SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960) // We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame. - bd->MouseCanUseGlobalState = mouse_can_use_global_state; #ifndef __APPLE__ bd->MouseCanReportHoveredViewport = bd->MouseCanUseGlobalState; #else bd->MouseCanReportHoveredViewport = false; #endif + // Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse() + // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list) + bd->MouseCanUseGlobalState = false; + bd->MouseCanUseCapture = false; +#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE + const char* sdl_backend = SDL_GetCurrentVideoDriver(); + const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" }; + for (const char* item : capture_and_global_state_whitelist) + if (strncmp(sdl_backend, item, strlen(item)) == 0) + bd->MouseCanUseGlobalState = bd->MouseCanUseCapture = true; +#endif + if (bd->MouseCanUseGlobalState) + io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional) + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; @@ -664,12 +667,15 @@ static void ImGui_ImplSDL3_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE // - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside. - // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to migitate the issue we wait until mouse has moved to begin capture. - bool want_capture = false; - for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) - if (ImGui::IsMouseDragging(button_n, 1.0f)) - want_capture = true; - SDL_CaptureMouse(want_capture); + // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to mitigate the issue we wait until mouse has moved to begin capture. + if (bd->MouseCanUseCapture) + { + bool want_capture = false; + for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) + if (ImGui::IsMouseDragging(button_n, 1.0f)) + want_capture = true; + SDL_CaptureMouse(want_capture); + } SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (focused_window && (bd->Window == focused_window || ImGui_ImplSDL3_GetViewportForWindowID(SDL_GetWindowID(focused_window)) != NULL)); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4cc57c408..641fdd382 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,14 +57,18 @@ Other changes: one in docking (they accidentally diverged). (#8554) - TreeNode: added flags to draw tree hierarchy outlines linking parent and tree nodes: (#2920) - - ImGuiTreeNodeFlags_DrawLinesNone: No lines drawn. + - ImGuiTreeNodeFlags_DrawLinesNone: No lines drawn (default value in style.TreeLinesFlags). - ImGuiTreeNodeFlags_DrawLinesFull: Horizontal lines to child nodes. Vertical line drawn down to TreePop() position: cover full contents. - ImGuiTreeNodeFlags_DrawLinesToNodes: Horizontal lines to child nodes. Vertical line drawn down to bottom-most child node. - Added style.TreeLinesFlags which stores the default setting, which may be overriden in individual TreeNode() calls. - Added style.TreeLinesSize (default to 1.0f). - Added ImGuiCol_TreeLines (in default style this is the same as ImGuiCol_Border). - - The feature adds a little cost as extra data needs to be stored. + - Caveats: + - Tree nodes may be used in many creative ways (manually positioning openable + nodes in unusual ways, using indent to create tree-looking structures, etc.) + and the feature may not accurately represent them in every cases. + - The feature adds a little cost as extra data needs to be stored. - Nav: fixed assertion when holding gamepad FaceLeft/West button to open CTRL+Tab windowing + pressing a keyboard key. (#8525) - Error Handling: added better error report and recovery for extraneous @@ -77,6 +81,9 @@ Other changes: - Misc: added extra operators to ImVec4 in IMGUI_DEFINE_MATH_OPERATORS block. (#8510) [@gan74] - Backends: SDL2, SDL3, OSX: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. (#8508) +- Backends: SDL2, SDL3: don't attempt to call SDL_CaptureMouse() on drivers where we don't + call SDL_GetGlobalMouseState(). This is specifically for Wayland but we currently use + the same white-list as SDL_GetGlobalMouseState(). (#8561) [@vs49688] - Backends: SDL3: Update for SDL3 api changes: revert SDL_GetClipboardText() memory ownership change. (#8530, #7801) [@Green-Sky] - Backends: SDLGPU3: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which diff --git a/imgui.cpp b/imgui.cpp index ff2a08936..3d3248194 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -22444,9 +22444,9 @@ void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int wi ImFormatString(buf, IM_ARRAYSIZE(buf), "[%04d] Window", window->BeginOrderWithinContext); //BulletText("[%04d] Window '%s'", window->BeginOrderWithinContext, window->Name); DebugNodeWindow(window, buf); - Indent(); + TreePush(buf); DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window); - Unindent(); + TreePop(); } } diff --git a/imgui.h b/imgui.h index 0bc4c5052..6e8cd75c8 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.0 WIP" -#define IMGUI_VERSION_NUM 19192 +#define IMGUI_VERSION_NUM 19193 #define IMGUI_HAS_TABLE #define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 14c00252b..e3a4c37b9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8382,7 +8382,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) style.TreeLinesFlags = option; ImGui::EndCombo(); } - ImGui::SliderFloat("TreeLinesSize", &style.TreeLinesSize, 0.0f, 1.0f, "%.0f"); + ImGui::SliderFloat("TreeLinesSize", &style.TreeLinesSize, 0.0f, 2.0f, "%.0f"); ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); diff --git a/imgui_internal.h b/imgui_internal.h index 9b90dcd43..ddaac7e8d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3768,6 +3768,7 @@ namespace ImGui // Widgets: Tree Nodes IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); + IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos); IMGUI_API void TreePushOverrideID(ImGuiID id); IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 11938aec2..1a4737dc6 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6569,7 +6569,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1) tree_node_data->NavRect = g.LastItemData.NavRect; // Initially I tried to latch value for GetColorU32(ImGuiCol_TreeLines) but it's not a good trade-off for very large trees. - tree_node_data->DrawLinesX1 = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) ? x1 : +FLT_MAX; + tree_node_data->DrawLinesX1 = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) ? (x1 + g.FontSize * 0.5f + g.Style.FramePadding.x) : +FLT_MAX; tree_node_data->DrawLinesY2 = -FLT_MAX; window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth); } @@ -6648,7 +6648,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bool store_tree_node_stack_data = false; if ((flags & ImGuiTreeNodeFlags_DrawLinesMask_) == 0) flags |= g.Style.TreeLinesFlags; - const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y);// && (g.Style.TreeLinesSize > 0.0f); + const bool draw_tree_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) && (frame_bb.Min.y < window->ClipRect.Max.y) && (g.Style.TreeLinesSize > 0.0f); if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) { if ((flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !g.NavIdIsAlive) @@ -6829,17 +6829,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l LogSetNextTextDecoration(">", NULL); } - if (draw_tree_lines && (window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1)))) - { - // Draw horizontal line from our parent node - ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1]; - float x1 = parent_data->DrawLinesX1 + 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->DrawLinesY2 = ImMax(parent_data->DrawLinesY2, y); - if (x1 < x2) - window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize); - } + if (draw_tree_lines) + TreeNodeDrawLineToChildNode(ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.5f)); if (span_all_columns && !span_all_columns_label) TablePopBackgroundChannel(); @@ -6863,6 +6854,24 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l return is_open; } +// Draw horizontal line from our parent node +// This is only called for visible child nodes so we are not too fussy anymore about performances +void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if ((window->DC.TreeHasStackDataDepthMask & (1 << (window->DC.TreeDepth - 1))) == 0) + return; + + ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1]; + float x1 = ImTrunc(parent_data->DrawLinesX1); + float x2 = ImTrunc(target_pos.x - g.Style.ItemInnerSpacing.x); + float y = ImTrunc(target_pos.y); + parent_data->DrawLinesY2 = ImMax(parent_data->DrawLinesY2, y); + if (x1 < x2) + window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize); +} + void ImGui::TreePush(const char* str_id) { ImGuiWindow* window = GetCurrentWindow(); @@ -6915,7 +6924,7 @@ void ImGui::TreePop() y2 = ImMin(y2, window->ClipRect.Max.y); if (y1 < y2) { - float x = data->DrawLinesX1 + ImTrunc(g.FontSize * 0.5f + g.Style.FramePadding.x); // GetTreeNodeToLabelSpacing() * 0.5f + float x = ImTrunc(data->DrawLinesX1); window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize); } }