Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust Docking window size depending on the contents of the other docked window #8383

Open
jrynkiew opened this issue Feb 9, 2025 · 3 comments
Labels

Comments

@jrynkiew
Copy link

jrynkiew commented Feb 9, 2025

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:

vlc-record-2025-02-09-21h41m31s-2025-02-09.21-40-21.mkv-.mp4

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

@ocornut ocornut added the docking label Feb 9, 2025
@jrynkiew
Copy link
Author

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

@PathogenDavid
Copy link
Contributor

PathogenDavid commented Feb 15, 2025

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.

@jrynkiew
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants