From 0e6a096afdc89219e98aeed49d7875a1ead3ba16 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jul 2019 11:29:22 -0700 Subject: [PATCH] Docking: Renamed io.ConfigDockingTabBarOnSingleWindows to io.ConfigDockingAlwaysTabBar. (#2109) Added ImGuiWindowClass::DockingAlwaysTabBar to set on individual windows. --- docs/CHANGELOG.txt | 9 ++++--- examples/example_win32_directx11/main.cpp | 2 +- imgui.cpp | 32 +++++++++++++++++------ imgui.h | 5 ++-- imgui_demo.cpp | 4 +-- imgui_internal.h | 6 +++-- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fb921de3..7ea1aec5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -38,15 +38,16 @@ DOCKING FEATURES - Added Docking system: [BETA] (#2109, #351) - Added ImGuiConfigFlags_DockingEnable flag to enable Docking. Set with `io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;`. - - Added DockSpace() API. + - Added DockSpace(), DockSpaceOverViewport() API. - Added ImGuiDockNodeFlags flags for DockSpace(). - - Added SetNextWindowDock(), SetNextWindowClass() API. - - Added GetWindowDockId(), IsWindowDocked() API. + - Added SetNextWindowDockID(), SetNextWindowClass() API. + - Added GetWindowDockID(), IsWindowDocked() API. - Added ImGuiWindowFlags_NoDocking window flag to disable the possibility for a window to be docked. Popup, Menu and Child windows always have the ImGuiWindowFlags_NoDocking flag set. + - Added ImGuiWindowClass to specify advanced docking/viewport related flags via SetNextWindowClass(). - Added io.ConfigDockingNoSplit option. - Added io.ConfigDockingWithShift option. - - Added io.ConfigDockingTabBarOnSingleWindows option. + - Added io.ConfigDockingAlwaysTabBar option. - Added io.ConfigDockingTransparentPayload option. - Style: Added ImGuiCol_DockingPreview, ImGuiCol_DockingEmptyBg colors. - Demo: Added "DockSpace" example app showcasing use of explicit dockspace nodes. diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index e8c1057d..d765ba1b 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -55,7 +55,7 @@ int main(int, char**) //io.ConfigViewportsNoAutoMerge = true; //io.ConfigViewportsNoTaskBarIcon = true; //io.ConfigViewportsNoDefaultParent = true; - //io.ConfigDockingTabBarOnSingleWindows = true; + //io.ConfigDockingAlwaysTabBar = true; //io.ConfigDockingTransparentPayload = true; #if 1 io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; // FIXME-DPI: THIS CURRENTLY DOESN'T WORK AS EXPECTED. DON'T USE IN USER APP! diff --git a/imgui.cpp b/imgui.cpp index c1d5a351..97cb014c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1262,7 +1262,7 @@ ImGuiIO::ImGuiIO() // Docking options (when ImGuiConfigFlags_DockingEnable is set) ConfigDockingNoSplit = false; ConfigDockingWithShift = false; - ConfigDockingTabBarOnSingleWindows = false; + ConfigDockingAlwaysTabBar = false; ConfigDockingTransparentPayload = false; // Viewport options (when ImGuiConfigFlags_ViewportsEnable is set) @@ -2731,6 +2731,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) SkipItems = false; Appearing = false; Hidden = false; + FallbackWindow = false; HasCloseButton = false; ResizeBorderHeld = -1; BeginCount = 0; @@ -4034,7 +4035,8 @@ void ImGui::NewFrame() // This fallback is particularly important as it avoid ImGui:: calls from crashing. SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); Begin("Debug##Default"); - g.FrameScopePushedImplicitWindow = true; + IM_ASSERT(g.CurrentWindow->FallbackWindow == true); + g.FrameScopePushedFallbackWindow = true; #ifdef IMGUI_ENABLE_TEST_ENGINE ImGuiTestEngineHook_PostNewFrame(&g); @@ -4407,7 +4409,7 @@ void ImGui::EndFrame() } // Hide implicit/fallback "Debug" window if it hasn't been used - g.FrameScopePushedImplicitWindow = false; + g.FrameScopePushedFallbackWindow = false; if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) g.CurrentWindow->Active = false; End(); @@ -5760,7 +5762,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Find or create ImGuiWindow* window = FindWindowByName(name); const bool window_just_created = (window == NULL); - const bool window_is_fallback = (g.CurrentWindowStack.Size == 0); if (window_just_created) { ImVec2 size_on_first_use = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. @@ -5776,6 +5777,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const int current_frame = g.FrameCount; const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); + window->FallbackWindow = (g.CurrentWindowStack.Size == 0); // Update the Appearing flag bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on @@ -5812,7 +5814,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (first_begin_of_the_frame) { bool has_dock_node = (window->DockId != 0 || window->DockNode != NULL); - bool new_auto_dock_node = !has_dock_node && g.IO.ConfigDockingTabBarOnSingleWindows && !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)) && !window_is_fallback; + bool new_auto_dock_node = !has_dock_node && GetWindowAlwaysWantOwnTabBar(window); if (has_dock_node || new_auto_dock_node) { BeginDocked(window, p_open); @@ -6556,7 +6558,7 @@ void ImGui::End() { ImGuiContext& g = *GImGui; - if (g.CurrentWindowStack.Size <= 1 && g.FrameScopePushedImplicitWindow) + if (g.CurrentWindowStack.Size <= 1 && g.FrameScopePushedFallbackWindow) { IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!"); return; // FIXME-ERRORHANDLING @@ -12026,7 +12028,11 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) 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->IsFloatingNode() && node->IsLeafNode() && !g.IO.ConfigDockingTabBarOnSingleWindows) + bool want_to_hide_host_window = false; + if (node->Windows.Size <= 1 && node->IsFloatingNode() && node->IsLeafNode()) + if (!g.IO.ConfigDockingAlwaysTabBar && (node->Windows.Size == 0 || !node->Windows[0]->WindowClass.DockingAlwaysTabBar)) + want_to_hide_host_window = true; + if (want_to_hide_host_window) { if (node->Windows.Size == 1) { @@ -13749,12 +13755,22 @@ void ImGui::DockBuilderFinish(ImGuiID root_id) // Docking: Begin/End Functions (called from Begin/End) //----------------------------------------------------------------------------- +bool ImGui::GetWindowAlwaysWantOwnTabBar(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (g.IO.ConfigDockingAlwaysTabBar || window->WindowClass.DockingAlwaysTabBar) + if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)) == 0) + if (!window->FallbackWindow) // We don't support AlwaysTabBar on the fallback/implicit window to avoid unused dock-node overhead/noise + return true; + return false; +} + void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open) { ImGuiContext* ctx = GImGui; ImGuiContext& g = *ctx; - const bool auto_dock_node = (g.IO.ConfigDockingTabBarOnSingleWindows) && !(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDocking)); + const bool auto_dock_node = GetWindowAlwaysWantOwnTabBar(window); if (auto_dock_node) { if (window->DockId == 0) diff --git a/imgui.h b/imgui.h index 6d488ff3..ca623aeb 100644 --- a/imgui.h +++ b/imgui.h @@ -1425,7 +1425,7 @@ struct ImGuiIO // Docking options (when ImGuiConfigFlags_DockingEnable is set) bool ConfigDockingNoSplit; // = false // Simplified docking mode: disable window splitting, so docking is limited to merging multiple windows together into tab-bars. bool ConfigDockingWithShift; // = false // Enable docking with holding Shift key (reduce visual noise, allows dropping in wider space) - bool ConfigDockingTabBarOnSingleWindows; // = false // [BETA] Make every single floating window display within a docking node. + bool ConfigDockingAlwaysTabBar; // = false // [BETA] [FIXME: This currently creates regression with auto-sizing and general overhead] Make every single floating window display within a docking node. bool ConfigDockingTransparentPayload;// = false // [BETA] Make window or viewport transparent when docking and only display docking boxes on the target viewport. Useful if rendering of multiple viewport cannot be synced. Best used with ConfigViewportsNoAutoMerge. // Viewport options (when ImGuiConfigFlags_ViewportsEnable is set) @@ -1612,9 +1612,10 @@ struct ImGuiWindowClass ImGuiID ParentViewportId; // Hint for the platform back-end. If non-zero, the platform back-end can create a parent<>child relationship between the platform windows. Not conforming back-ends are free to e.g. parent every viewport to the main viewport or not. ImGuiViewportFlags ViewportFlagsOverrideMask; // Viewport flags to override when a window of this class owns a viewport. This allows you to enforce OS decoration or task bar icon, override the defaults on a per-window basis. ImGuiViewportFlags ViewportFlagsOverrideValue; // Viewport flags values to override when a window of this class owns a viewport. + bool DockingAlwaysTabBar; // Set to true to enforce windows of this class always having their own tab (equivalent of setting the global io.ConfigDockingAlwaysTabBar) bool DockingAllowUnclassed; // Set to true to allow windows of this class to be docked/merged with an unclassed window. - ImGuiWindowClass() { ClassId = 0; ParentViewportId = 0; ViewportFlagsOverrideMask = ViewportFlagsOverrideValue = 0x00; DockingAllowUnclassed = true; } + ImGuiWindowClass() { ClassId = 0; ParentViewportId = 0; ViewportFlagsOverrideMask = ViewportFlagsOverrideValue = 0x00; DockingAlwaysTabBar = false; DockingAllowUnclassed = true; } }; //----------------------------------------------------------------------------- diff --git a/imgui_demo.cpp b/imgui_demo.cpp index dd25873b..bb09d02d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -368,7 +368,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::SameLine(); HelpMarker("Simplified docking mode: disable window splitting, so docking is limited to merging multiple windows together into tab-bars."); ImGui::Checkbox("io.ConfigDockingWithShift", &io.ConfigDockingWithShift); ImGui::SameLine(); HelpMarker("Enable docking when holding Shift only (allows to drop in wider space, reduce visual noise)"); - ImGui::Checkbox("io.ConfigDockingTabBarOnSingleWindows", &io.ConfigDockingTabBarOnSingleWindows); + ImGui::Checkbox("io.ConfigDockingAlwaysTabBar", &io.ConfigDockingAlwaysTabBar); ImGui::SameLine(); HelpMarker("Create a docking node and tab-bar on single floating windows."); ImGui::Checkbox("io.ConfigDockingTransparentPayload", &io.ConfigDockingTransparentPayload); ImGui::SameLine(); HelpMarker("Make window or viewport transparent when docking and only display docking boxes on the target viewport. Useful if rendering of multiple viewport cannot be synced. Best used with ConfigViewportsNoAutoMerge."); @@ -3079,7 +3079,7 @@ void ImGui::ShowAboutWindow(bool* p_open) if (io.ConfigViewportsNoDefaultParent) ImGui::Text("io.ConfigViewportsNoDefaultParent"); if (io.ConfigDockingNoSplit) ImGui::Text("io.ConfigDockingNoSplit"); if (io.ConfigDockingWithShift) ImGui::Text("io.ConfigDockingWithShift"); - if (io.ConfigDockingTabBarOnSingleWindows) ImGui::Text("io.ConfigDockingTabBarOnSingleWindows"); + if (io.ConfigDockingAlwaysTabBar) ImGui::Text("io.ConfigDockingAlwaysTabBar"); if (io.ConfigDockingTransparentPayload) ImGui::Text("io.ConfigDockingTransparentPayload"); if (io.ConfigMacOSXBehaviors) ImGui::Text("io.ConfigMacOSXBehaviors"); if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink"); diff --git a/imgui_internal.h b/imgui_internal.h index bd1f9aad..3b3d23de 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -982,7 +982,7 @@ struct ImGuiContext { bool Initialized; bool FrameScopeActive; // Set by NewFrame(), cleared by EndFrame() - bool FrameScopePushedImplicitWindow; // Set by NewFrame(), cleared by EndFrame() + bool FrameScopePushedFallbackWindow; // Set by NewFrame(), cleared by EndFrame() bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; ImGuiPlatformIO PlatformIO; @@ -1195,7 +1195,7 @@ struct ImGuiContext ImGuiContext(ImFontAtlas* shared_font_atlas) { Initialized = false; - FrameScopeActive = FrameScopePushedImplicitWindow = false; + FrameScopeActive = FrameScopePushedFallbackWindow = false; ConfigFlagsForFrame = ImGuiConfigFlags_None; Font = NULL; FontSize = FontBaseSize = 0.0f; @@ -1449,6 +1449,7 @@ struct IMGUI_API ImGuiWindow bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool Appearing; // Set during the frame where the window is appearing (or re-appearing) bool Hidden; // Do not display (== (HiddenFrames*** > 0)) + bool FallbackWindow; bool HasCloseButton; // Set when the window has a close button (p_open != NULL) signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3) short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) @@ -1758,6 +1759,7 @@ namespace ImGui IMGUI_API void DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node); IMGUI_API bool DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos); inline ImGuiDockNode* DockNodeGetRootNode(ImGuiDockNode* node) { while (node->ParentNode) node = node->ParentNode; return node; } + IMGUI_API bool GetWindowAlwaysWantOwnTabBar(ImGuiWindow* window); IMGUI_API void BeginDocked(ImGuiWindow* window, bool* p_open); IMGUI_API void BeginAsDockableDragDropSource(ImGuiWindow* window); IMGUI_API void BeginAsDockableDragDropTarget(ImGuiWindow* window);