From 5a665e423c5a6dd4d7a327f1a85eaca299d343ef Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Mar 2019 20:44:49 +0100 Subject: [PATCH] Docking: Added ImGuiDockNodeFlags_NoTabBar (not exposed publicly). (#2423, #2109) --- imgui.cpp | 28 ++++++++++++++++------------ imgui_internal.h | 6 ++++-- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e18d69fd..5a86f8f1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5814,8 +5814,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } - // Docking: Unhide tab bar - if (window->DockNode && window->DockNode->IsHiddenTabBar()) + // Docking: Unhide tab bar (small triangle in the corner) + if (window->DockNode && window->DockNode->IsHiddenTabBar() && !window->DockNode->IsNoTabBar()) { float unhide_sz_draw = ImFloor(g.FontSize * 0.70f); float unhide_sz_hit = ImFloor(g.FontSize * 0.55f); @@ -11247,7 +11247,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req) { if (target_node->Windows.Size > 0) { - // We can dock into a node that already has windows _only_ if our payload is a node tree with a single visible node. + // We can dock a split payload into a node that already has windows _only_ if our payload is a node tree with a single visible node. // In this situation, we move the windows of the target node into the currently visible node of the payload. // This allows us to preserve some of the underlying dock tree settings nicely. IM_ASSERT(payload_node->OnlyNodeWithWindows != NULL); // The docking should have been blocked by DockNodePreviewDockCalc() early on and never submitted. @@ -11725,6 +11725,10 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) } } + // Remove tab bar if not needed + if (node->TabBar && node->IsNoTabBar()) + DockNodeRemoveTabBar(node); + // Early out for hidden root dock nodes (when all DockId references are in inactive windows, or there is only 1 floating window holding on the DockId) if (node->Windows.Size <= 1 && node->IsRootNode() && node->IsLeafNode() && !node->IsDockSpace() && !g.IO.ConfigDockingTabBarOnSingleWindows) { @@ -12011,7 +12015,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w is_focused = true; // Hidden tab bar will show a triangle on the upper-left (in Begin) - if (node->IsHiddenTabBar()) + if (node->IsHiddenTabBar() || node->IsNoTabBar()) { node->VisibleWindow = (node->Windows.Size > 0) ? node->Windows[0] : NULL; node->IsFocused = is_focused; @@ -12473,7 +12477,7 @@ static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDock ImVec2 tab_pos = tab_bar_rect.Min; if (host_node && host_node->TabBar) { - if (!host_node->IsHiddenTabBar()) + if (!host_node->IsHiddenTabBar() && !host_node->IsNoTabBar()) tab_pos.x += host_node->TabBar->OffsetMax + g.Style.ItemInnerSpacing.x; // We don't use OffsetNewTab because when using non-persistent-order tab bar it is incremented with each Tab submission. else tab_pos.x += g.Style.ItemInnerSpacing.x + TabItemCalcSize(host_node->Windows[0]->Name, host_node->Windows[0]->HasCloseButton).x; @@ -13195,6 +13199,7 @@ void ImGui::DockBuilderRemoveNodeDockedWindows(ImGuiID root_id, bool clear_persi } } +// FIXME-DOCK: We are not exposing nor using split_outer. ImGuiID ImGui::DockBuilderSplitNode(ImGuiID id, ImGuiDir split_dir, float size_ratio_for_node_at_dir, ImGuiID* out_id_at_dir, ImGuiID* out_id_other) { ImGuiContext* ctx = GImGui; @@ -13511,7 +13516,7 @@ void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open) // Update window flag IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) == 0); window->Flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoResize; - if (node->IsHiddenTabBar()) + if (node->IsHiddenTabBar() || node->IsNoTabBar()) window->Flags |= ImGuiWindowFlags_NoTitleBar; else window->Flags &= ~ImGuiWindowFlags_NoTitleBar; // Clear the NoTitleBar flag in case the user set it: confusingly enough we need a title bar height so we are correctly offset, but it won't be displayed! @@ -13577,7 +13582,7 @@ void ImGui::BeginAsDockableDragDropTarget(ImGuiWindow* window) else allow_null_target_node = true; // Dock into a regular window - const ImRect explicit_target_rect = (target_node && target_node->TabBar && !target_node->IsHiddenTabBar()) ? target_node->TabBar->BarRect : ImRect(window->Pos, window->Pos + ImVec2(window->Size.x, GetFrameHeight())); + const ImRect explicit_target_rect = (target_node && target_node->TabBar && !target_node->IsHiddenTabBar() && !target_node->IsNoTabBar()) ? target_node->TabBar->BarRect : ImRect(window->Pos, window->Pos + ImVec2(window->Size.x, GetFrameHeight())); const bool is_explicit_target = g.IO.ConfigDockingWithShift || IsMouseHoveringRect(explicit_target_rect.Min, explicit_target_rect.Max); // Preview docking request and find out split direction/ratio @@ -14209,14 +14214,13 @@ void ImGui::ShowDockingDebug() ImGui::BulletText("Pos (%.0f,%.0f), Size (%.0f, %.0f) Ref (%.0f, %.0f)", node->Pos.x, node->Pos.y, node->Size.x, node->Size.y, node->SizeRef.x, node->SizeRef.y); ImGui::BulletText("VisibleWindow: 0x%08X %s", node->VisibleWindow ? node->VisibleWindow->ID : 0, node->VisibleWindow ? node->VisibleWindow->Name : "NULL"); - ImGui::BulletText("SelectedTabID: 0x%08X", node->SelectedTabID); - ImGui::BulletText("LastFocusedNodeID: 0x%08X", node->LastFocusedNodeID); - if (ImGui::TreeNode("flags", "SharedFlags 0x%03X NodeFlags 0x%03X%s%s%s%s", - node->SharedFlags, node->LocalFlags, node->IsDockSpace() ? ", IsDockSpace" : "", node->IsCentralNode() ? ", IsCentralNode" : "", - (g.FrameCount - node->LastFrameAlive < 2) ? ", IsAlive" : "", (g.FrameCount - node->LastFrameActive < 2) ? ", IsActive" : "")) + ImGui::BulletText("SelectedTabID: 0x%08X, LastFocusedNodeID: 0x%08X", node->SelectedTabID, node->LastFocusedNodeID); + ImGui::BulletText("Misc:%s%s%s%s", node->IsDockSpace() ? " IsDockSpace" : "", node->IsCentralNode() ? " IsCentralNode" : "", (g.FrameCount - node->LastFrameAlive < 2) ? " IsAlive" : "", (g.FrameCount - node->LastFrameActive < 2) ? " IsActive" : ""); + if (ImGui::TreeNode("flags", "LocalFlags: 0x%04X SharedFlags: 0x%04X", node->LocalFlags, node->SharedFlags)) { ImGui::CheckboxFlags("LocalFlags: NoSplit", (unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_NoSplit); ImGui::CheckboxFlags("LocalFlags: NoResize", (unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_NoResize); + ImGui::CheckboxFlags("LocalFlags: NoTabBar", (unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_NoTabBar); ImGui::CheckboxFlags("LocalFlags: HiddenTabBar",(unsigned int*)&node->LocalFlags, ImGuiDockNodeFlags_HiddenTabBar); ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 1ed273cc..1c52d078 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -854,9 +854,10 @@ enum ImGuiDockNodeFlagsPrivate_ // [Internal] ImGuiDockNodeFlags_DockSpace = 1 << 10, // Local // A dockspace is a node that occupy space within an existing user window. Otherwise the node is floating and create its own window. ImGuiDockNodeFlags_CentralNode = 1 << 11, // Local + ImGuiDockNodeFlags_NoTabBar = 1 << 12, // Local // Tab bar is completely unavailable. No triangle in the corner to enable it back. ImGuiDockNodeFlags_HiddenTabBar = 1 << 13, // Local // Tab bar is hidden, with a triangle in the corner to show it again (NB: actual tab-bar instance may be destroyed as this is only used for single-window tab bar) ImGuiDockNodeFlags_SharedFlagsInheritMask_ = ~0, - ImGuiDockNodeFlags_LocalFlagsMask_ = ImGuiDockNodeFlags_NoSplit | ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_DockSpace | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_HiddenTabBar, + ImGuiDockNodeFlags_LocalFlagsMask_ = ImGuiDockNodeFlags_NoSplit | ImGuiDockNodeFlags_NoResize | ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_DockSpace | ImGuiDockNodeFlags_CentralNode | ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_HiddenTabBar, ImGuiDockNodeFlags_LocalFlagsTransferMask_ = ImGuiDockNodeFlags_LocalFlagsMask_ & ~ImGuiDockNodeFlags_DockSpace // When splitting those flags are moved to the inheriting child, never duplicated }; @@ -911,7 +912,8 @@ struct ImGuiDockNode bool IsRootNode() const { return ParentNode == NULL; } bool IsDockSpace() const { return (LocalFlags & ImGuiDockNodeFlags_DockSpace) != 0; } bool IsCentralNode() const { return (LocalFlags & ImGuiDockNodeFlags_CentralNode) != 0; } - bool IsHiddenTabBar() const { return (LocalFlags & ImGuiDockNodeFlags_HiddenTabBar) != 0; } + bool IsHiddenTabBar() const { return (LocalFlags & ImGuiDockNodeFlags_HiddenTabBar) != 0; } // Hidden tab bar can be shown back by clicking the small triangle + bool IsNoTabBar() const { return (LocalFlags & ImGuiDockNodeFlags_NoTabBar) != 0; } // Never show a tab bar bool IsSplitNode() const { return ChildNodes[0] != NULL; } bool IsLeafNode() const { return ChildNodes[0] == NULL; } bool IsEmpty() const { return ChildNodes[0] == NULL && Windows.Size == 0; }