Adjust Docking window size depending on the contents of the other docked window
Version/Branch of Dear ImGui:
v1.91.1 WIP Docking
Back-ends:
imgui_impl_sdl2.h, imgui_impl_opengl3.h
Compiler, OS:
Windows 64 mingw, windows 32 mingw, Linux 64 gcc, Linux 32 gcc, Emscripten llvm
Full config/build information:
Dear ImGui 1.91.1 WIP (19101)
--------------------------------
sizeof(size_t): 4, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201103
define: __linux__
define: __GNUC__=13
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_sdl2
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000081
NavEnableKeyboard
DockingEnable
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
HasMouseCursors
HasSetMousePos
PlatformHasViewports
HasMouseHoveredViewport
RendererHasVtxOffset
RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,721.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 4.00
style.FrameBorderSize: 1.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00
Details:
I have an issue with an imgui docking window. I am trying to create a right hand side docking window which is split in two horizontally. The split is set initially at 50/50, but it shouldn't matter, because I am changing the size of the node split depending on the content of the top docking window (or at least that's what I'm attempting to do)
This does sort of work, but not as I would expect it, and I don't know what to attribute the strange behaviour. The dock window is in fact changing the height of the split window, but it's not exactly taking my values into account, it's using some other parameters to determine what size the node should be. Also, I've observed some strange exponential height changes toward the extreme (ver small and very large dock size)
Is this logic supported, to scale the dock dynamically based on content? I want the card to always be fully visible in the Preview window, at the cost of the other docked window in that vertical split group
Screenshots/Video:
https://github.com/user-attachments/assets/e4624ab5-98f5-4276-a09d-ee6c4492072a
Minimal, Complete and Verifiable Example code:
ImGuiViewport* viewport;
ImGuiID dockspace_id, dockspace_right_id, dockspace_left_id, dockspace_bottom_right_id, dockspace_top_right_id;
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode;
void Interface::setupDocking() {
static bool first_time = true;
viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace", nullptr, window_flags);
ImGui::PopStyleVar(3);
dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
if (first_time) {
ImGui::DockBuilderRemoveNode(dockspace_id); // clear any previous layout
ImGui::DockBuilderAddNode(dockspace_id, dockspace_flags | ImGuiDockNodeFlags_DockSpace);
ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size);
dockspace_right_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 0.2f, nullptr, &dockspace_id);
ImGui::DockBuilderSetNodeSize(dockspace_right_id, ImVec2(viewport->Size.x * 0.2f, viewport->Size.y));
dockspace_top_right_id = ImGui::DockBuilderSplitNode(dockspace_right_id, ImGuiDir_Up, 0.5f, nullptr, &dockspace_right_id);
dockspace_bottom_right_id = ImGui::DockBuilderSplitNode(dockspace_right_id, ImGuiDir_Down, 0.5f, nullptr, &dockspace_right_id);
ImGui::DockBuilderDockWindow("Search", dockspace_bottom_right_id);
ImGui::DockBuilderDockWindow("Preview", dockspace_top_right_id);
ImGui::DockBuilderFinish(dockspace_id);
first_time = false;
}
void Interface::drawCardWindow(const Card* card, const std::string& cardName) {
ImGui::Begin("Preview");
// Get the size of the preview window. We use it to set the texture size and update the dock node size.
ImVec2 windowSize = ImGui::GetWindowSize();
float width = windowSize.x;
float height = width * 1.395973154362416f;
if (ImGui::IsWindowDocked()) {
ImGuiID dockID = ImGui::GetWindowDockID();
ImGuiDockNode* dockNode = ImGui::DockBuilderGetNode(dockID);
if (dockNode) {
ImGui::DockBuilderSetNodeSize(dockID, ImVec2(width, height*1.5));
}
}
// Set the texture size based on the window size
ImGui::Image((void*)(intptr_t)card->getFrontTexture()->getID(), ImVec2(width - ImGui::GetStyle().WindowPadding.x * 2, height));
ImGui::End();
}
basically I get the window width, multiply the width by the aspect ratio of the image to get the height, and modify the dock window node size to match the height.
You may notice height*1.5 in the DockBuilderSetNodeSize, that's just because I was playing around with the values. Changing that value affects the initial placement of the split after loading the preview window, but doesn't affect anything once we start scaling the docking window horizontally
Any ideas? Am I missing something? Is this normally supported behaviour, and I simply am using the library wrong? If so, even such a hint will help me
I don't think you're missing anything, this isn't something that's currently straightforward to accomplish in the current iteration of the docking API. Improving this sort of situation is mentioned in section 6.5 of Omar's 10 year update.
(Also I can't speak for everyone who helps out around here, but I almost never reply to dock builder questions because they're just too situation-specific to answer quickly and they turn into support rabbit holes.)
My suggestion would be to make the card art fit to the window bounds rather than always filling the width.
Thank you, that's good to know, I'll start working on a different solution in that case. Your idea sounds like a good workaround