1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-24 02:14:22 +00:00

Demo: rework DockSpace(), DockSpaceOverViewport() demo.

This commit is contained in:
ocornut 2026-01-22 15:58:17 +01:00
parent f89ef40cb2
commit fb06d32844
3 changed files with 104 additions and 69 deletions

View file

@ -210,7 +210,10 @@ Other Changes:
Docking+Viewports Branch:
- Fixed implicit/fallback "Debug" window from staying visible if once docked. (#9151)
- Docking:
- Fixed implicit/fallback "Debug" window from staying visible if once docked. (#9151)
- Demo: rework 'Dockspace' demo to increase clarity and put more emphasis on the
basic path of simply calling `DockSpaceOverViewport()`.
- Viewports:
- Fixed a regression in 1.92.4 which could cause combos/popups window from
appearing under their parent viewport if their geometry overlapped the main

14
imgui.h
View file

@ -965,19 +965,21 @@ namespace ImGui
// Docking
// - Read https://github.com/ocornut/imgui/wiki/Docking for details.
// - Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.
// - You can use most Docking facilities without calling any API. You don't necessarily need to call a DockSpaceXXX function to use Docking!
// - You can use many Docking facilities without calling any API.
// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.
// - Drag from window menu button (upper-left button) to undock an entire node (all windows).
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
// - DockSpaceOverViewport:
// - This is a helper to create an invisible window covering a viewport, then submit a DockSpace() into it.
// - Most applications can simply call DockSpaceOverViewport() once to allow docking windows into e.g. the edge of your screen.
// e.g. ImGui::NewFrame(); ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport.
// or: ImGui::NewFrame(); ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, central node is transparent.
// - Dockspaces:
// - If you want to dock windows into the edge of your screen, most application can simply call DockSpaceOverViewport():
// e.g. ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport.
// or: ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent.
// - A dockspace is an explicit dock node within an existing window.
// - DockSpaceOverViewport() basically creates an invisible window covering a viewport, and submit a DockSpace() into it.
// - IMPORTANT: Dockspaces need to be submitted _before_ any window they can host. Submit them early in your frame!
// - IMPORTANT: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
// If you have e.g. multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
// - See 'Demo->Examples->Dockspace' or 'Demo->Examples->Documents' for more detailed demos.
// - Programmatic docking:
// - There is no public API yet other than the very limited SetNextWindowDockID() function. Sorry for that!
// - Read https://github.com/ocornut/imgui/wiki/Docking for examples of how to use current internal API.
@ -985,7 +987,7 @@ namespace ImGui
IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id
IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (control docking compatibility + provide hints to platform backend via custom viewport flags and platform parent/child relationship)
IMGUI_API ImGuiID GetWindowDockID();
IMGUI_API ImGuiID GetWindowDockID(); // get dock id of current window, or 0 if not associated to any docking node.
IMGUI_API bool IsWindowDocked(); // is current window docked into another window?
// Logging/Capture

View file

@ -10298,37 +10298,36 @@ static void ShowExampleAppCustomRendering(bool* p_open)
// [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
//-----------------------------------------------------------------------------
// Demonstrate using DockSpace() to create an explicit docking node within an existing window, with various options.
struct ImGuiDemoDockspaceArgs
{
bool IsFullscreen = true;
bool KeepWindowPadding = false; // Keep WindowPadding to help understand that DockSpace() is a widget inside the window.
ImGuiDockNodeFlags DockSpaceFlags = ImGuiDockNodeFlags_None;
};
// THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace().
// MOST REGULAR APPLICATIONS WHO WANT TO ALLOW DOCKING WINDOWS ON THE EDGE OF YOUR SCREEN CAN SIMPLY USE:
// ImGui::NewFrame();
// ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport
// MOST REGULAR APPLICATIONS WANTING TO ALLOW DOCKING WINDOWS ON THE EDGE OF YOUR SCREEN CAN SIMPLY USE:
// ImGui::NewFrame(); + ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport
// OR:
// ImGui::NewFrame();
// ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent.
// ImGui::NewFrame(); + ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent.
// Demonstrate using DockSpace() to create an explicit docking node within an existing window, with various options.
// Read https://github.com/ocornut/imgui/wiki/Docking for details.
// The reasons we do not use DockSpaceOverViewport() in this demo is because:
// - (1) we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false)
// - (1) we allow the host window to be floating/moveable instead of filling the viewport (when args->IsFullscreen == false)
// which is mostly to showcase the idea that DockSpace() may be submitted anywhere.
// - (2) we allow the host window to have padding (when opt_padding == true)
// - (3) we expose many flags and need a way to have them visible.
// - (4) we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport()
// in your code, but we don't here because we allow the window to be floating)
void ShowExampleAppDockSpace(bool* p_open)
// Also see 'Demo->Examples->Documents' for a less abstract version of this.
// - (2) we allow the host window to have padding (when args->UsePadding == true)
// - (3) we expose variety of other flags.
static void ShowExampleAppDockSpaceAdvanced(ImGuiDemoDockspaceArgs* args, bool* p_open)
{
// TL;DR; this demo is more complicated than what most users you would normally use.
// If we remove all options we are showcasing, this demo would become a simple call to ImGui::DockSpaceOverViewport() !!
// In this specific demo, we are not using DockSpaceOverViewport() because:
static bool opt_fullscreen = true;
static bool opt_padding = false;
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
ImGuiDockNodeFlags dockspace_flags = args->DockSpaceFlags;
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
if (opt_fullscreen)
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking;
if (args->IsFullscreen)
{
// Fullscreen dockspace: practically the same as calling DockSpaceOverViewport();
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
@ -10337,74 +10336,105 @@ void ShowExampleAppDockSpace(bool* p_open)
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
window_flags |= ImGuiWindowFlags_NoBackground;
}
else
{
// Floating dockspace
dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
}
// When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
// and handle the pass-thru hole, so we ask Begin() to not render a background.
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
window_flags |= ImGuiWindowFlags_NoBackground;
// Important: note that we proceed even if Begin() returns false (aka window is collapsed).
// This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
// all active windows docked into it will lose their parent and become undocked.
// We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
// any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
if (!opt_padding)
if (!args->KeepWindowPadding)
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", p_open, window_flags);
if (!opt_padding)
ImGui::Begin("Window with a DockSpace", p_open, window_flags);
if (!args->KeepWindowPadding)
ImGui::PopStyleVar();
if (opt_fullscreen)
if (args->IsFullscreen)
ImGui::PopStyleVar(2);
// Submit the DockSpace
// REMINDER: THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace()!
// MOST REGULAR APPLICATIONS WILL SIMPLY WANT TO CALL DockSpaceOverViewport(). READ COMMENTS ABOVE.
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
{
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
}
// Submit the DockSpace widget inside our window
// - Note that the id here is different from the one used by DockSpaceOverViewport(), so docking state won't get transfered between "Basic" and "Advanced" demos.
// - If we made the ShowExampleAppDockSpaceBasic() calculate its own ID and pass it to DockSpaceOverViewport() the ID could easily match.
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
ImGui::End();
}
static void ShowExampleAppDockSpaceBasic(ImGuiDockNodeFlags flags)
{
// Basic version which you can use in many apps:
// e.g:
// ImGui::DockSpaceOverViewport();
// or:
// ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Central node will be transparent
// or:
// ImGuiViewport* viewport = ImGui::GetMainViewport();
// ImGui::DockSpaceOverViewport(0, viewport, ImGuiDockNodeFlags_None);
ImGui::DockSpaceOverViewport(0, nullptr, flags);
}
void ShowExampleAppDockSpace(bool* p_open)
{
static int opt_demo_mode = 0;
static bool opt_demo_mode_changed = false;
static ImGuiDemoDockspaceArgs args;
if (opt_demo_mode == 0)
ShowExampleAppDockSpaceBasic(args.DockSpaceFlags);
else
ShowExampleAppDockSpaceAdvanced(&args, p_open);
// Refocus our window to minimize perceived loss of focus when changing mode (caused by the fact that each use a different window, which would not happen in a real app)
if (opt_demo_mode_changed)
ImGui::SetNextWindowFocus();
ImGui::Begin("Examples: Dockspace", p_open, ImGuiWindowFlags_MenuBar);
opt_demo_mode_changed = false;
opt_demo_mode_changed |= ImGui::RadioButton("Basic demo mode", &opt_demo_mode, 0);
opt_demo_mode_changed |= ImGui::RadioButton("Advanced demo mode", &opt_demo_mode, 1);
ImGui::SeparatorText("Options");
if ((ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable) == 0)
{
ShowDockingDisabledMessage();
}
else if (opt_demo_mode == 0)
{
args.DockSpaceFlags &= ImGuiDockNodeFlags_PassthruCentralNode; // Allowed flags
ImGui::CheckboxFlags("Flag: PassthruCentralNode", &args.DockSpaceFlags, ImGuiDockNodeFlags_PassthruCentralNode);
}
else if (opt_demo_mode == 1)
{
ImGui::Checkbox("Fullscreen", &args.IsFullscreen);
ImGui::Checkbox("Keep Window Padding", &args.KeepWindowPadding);
ImGui::SameLine();
HelpMarker("This is mostly exposed to facilitate understanding that a DockSpace() is _inside_ a window.");
ImGui::BeginDisabled(args.IsFullscreen == false);
ImGui::CheckboxFlags("Flag: PassthruCentralNode", &args.DockSpaceFlags, ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::EndDisabled();
ImGui::CheckboxFlags("Flag: NoDockingOverCentralNode", &args.DockSpaceFlags, ImGuiDockNodeFlags_NoDockingOverCentralNode);
ImGui::CheckboxFlags("Flag: NoDockingSplit", &args.DockSpaceFlags, ImGuiDockNodeFlags_NoDockingSplit);
ImGui::CheckboxFlags("Flag: NoUndocking", &args.DockSpaceFlags, ImGuiDockNodeFlags_NoUndocking);
ImGui::CheckboxFlags("Flag: NoResize", &args.DockSpaceFlags, ImGuiDockNodeFlags_NoResize);
ImGui::CheckboxFlags("Flag: AutoHideTabBar", &args.DockSpaceFlags, ImGuiDockNodeFlags_AutoHideTabBar);
}
// Show demo options and help
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Options"))
{
// Disabling fullscreen would allow the window to be moved to the front of other windows,
// which we can't undo at the moment without finer window depth/z control.
ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
ImGui::MenuItem("Padding", NULL, &opt_padding);
ImGui::Separator();
if (ImGui::MenuItem("Flag: NoDockingOverCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingOverCentralNode; }
if (ImGui::MenuItem("Flag: NoDockingSplit", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingSplit) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingSplit; }
if (ImGui::MenuItem("Flag: NoUndocking", "", (dockspace_flags & ImGuiDockNodeFlags_NoUndocking) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoUndocking; }
if (ImGui::MenuItem("Flag: NoResize", "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoResize; }
if (ImGui::MenuItem("Flag: AutoHideTabBar", "", (dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar; }
if (ImGui::MenuItem("Flag: PassthruCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0, opt_fullscreen)) { dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode; }
ImGui::Separator();
if (ImGui::MenuItem("Close", NULL, false, p_open != NULL))
*p_open = false;
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Help"))
{
ImGui::TextUnformatted(
"This demo has nothing to do with enabling docking!" "\n"
"This demo only demonstrate the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window." "\n"
"Most application can simply call ImGui::DockSpaceOverViewport() and be done with it.");
"This demonstrates the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window." "\n"
"The \"Basic\" version uses the ImGui::DockSpaceOverViewport() helper. Most applications can probably use this.");
ImGui::Separator();
ImGui::TextUnformatted("When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
"- Drag from window title bar or their tab to dock/undock." "\n"