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

Docking a window permanently #2583

Closed
gitbetter opened this issue May 25, 2019 · 17 comments
Closed

Docking a window permanently #2583

gitbetter opened this issue May 25, 2019 · 17 comments
Labels

Comments

@gitbetter
Copy link

gitbetter commented May 25, 2019

Version/Branch of Dear ImGui:

Version: 1.71
Branch: docking

Back-end/Renderer/OS:

Back-ends: imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
Operating System: Windows 10

My Issue/Question:

I have been looking through some of the code, comments and issues but haven't found anything relevant to this particular feature, or maybe I missed it. Is there anyway to dock a node permanently? I am looking for a way to create a toolbar the will rest below the menu bar, so it would be nice to dock it on top of everything else and disallow un-docking for that particular window, while allowing all other windows to be moved around as usual.

@gitbetter
Copy link
Author

gitbetter commented May 26, 2019

So while I was not able to find anything directly related to permanent docking I did manage to find a workaround.

What I did was to add ImGuiDockNodeFlags_NoTabBar to the LocalFlags of the ImGuiDockNode* that I was interested in, which has the side effect that you subsequently cannot un-dock the window, although it necessarily disables the tab bar if that's something you wanted to keep, which is why this is just a workaround.

My dockspace code looks like this now:

ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_None;
ImGuiID dockspaceID = ImGui::GetID(ID().c_str());
if (!ImGui::DockBuilderGetNode(dockspaceID)) {
	ImGui::DockBuilderRemoveNode(dockspaceID);
	ImGui::DockBuilderAddNode(dockspaceID, ImGuiDockNodeFlags_None);

	ImGuiID dock_main_id = dockspaceID;
	ImGuiID dock_up_id = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Up, 0.05f, nullptr, &dock_main_id);
	ImGuiID dock_right_id = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, 0.2f, nullptr, &dock_main_id);
	ImGuiID dock_left_id = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.2f, nullptr, &dock_main_id);
	ImGuiID dock_down_id = ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Down, 0.2f, nullptr, &dock_main_id);
	ImGuiID dock_down_right_id = ImGui::DockBuilderSplitNode(dock_down_id, ImGuiDir_Right, 0.6f, nullptr, &dock_down_id);

	ImGui::DockBuilderDockWindow("Actions", dock_up_id);
	ImGui::DockBuilderDockWindow("Hierarchy", dock_right_id);
	ImGui::DockBuilderDockWindow("Inspector", dock_left_id);
	ImGui::DockBuilderDockWindow("Console", dock_down_id);
	ImGui::DockBuilderDockWindow("Project", dock_down_right_id);
	ImGui::DockBuilderDockWindow("Scene", dock_main_id);

        // Disable tab bar for custom toolbar
	ImGuiDockNode* node = ImGui::DockBuilderGetNode(dock_up_id);
	node->LocalFlags |= ImGuiDockNodeFlags_NoTabBar;

	ImGui::DockBuilderFinish(dock_main_id);
}
ImGui::DockSpace(dockspaceID, ImVec2(0.0f, 0.0f), dockspaceFlags);

Although now I am also wondering if there is any way to remove the tab bar menu arrow next to the tab for a window, as well as maybe the x exit button on the right of each tab window, in case we want to style the window a bit differently.

@ocornut
Copy link
Owner

ocornut commented May 27, 2019

Hello,

The workaround looks appropriate.

If you wanted to show tab-bar this would widen the question: do you want to disable undocking on a per-docking-node basis (anything docked on this tab-bar), or disable undocking of a particular window (maybe through a window flag).

I'm happy with you using the workaround, considering that DockBuilderXXX is current draft for what ideally would become a public API.

Although now I am also wondering if there is any way to remove the tab bar menu arrow next to the tab for a window, as well as maybe the x exit button on the right of each tab window, in case we want to style the window a bit differently.

I am not sure I understand, you would want to show the tab-bar with multiple docked windows but disable the docking/tab menu? At this point if undocking is not permitted you may as well disable the docking tab bar (as you did) and create a tab bar yourself without those elements. But I appreciate this would necessate using a different API (BeginTabBar()) explicitely.

I could add flags to disable the Docking/Menu button and Close button on a per DockNode basis.

PS: I think to clarify that currently you are supposed to call DockBuilderSetNodeSize() on your initial node, at the moment if you don't, then DockBuilderSplitNode() will split a little differently than what you may be expecting (not getting into details here but I'll work on fixing this).

ocornut added a commit that referenced this issue May 27, 2019
…o Window Menu button matching master. Added private ImGuiDockNodeFlags_NoWindowMenuButton, ImGuiDockNodeFlags_NoCloseButton flags. (#2583, #2109)
@ocornut
Copy link
Owner

ocornut commented May 27, 2019

I have pushed two flags in imgui_internal.h to do what is discussed above.

ImGuiDockNodeFlags_NoWindowMenuButton
ImGuiDockNodeFlags_NoCloseButton

(There was quite a few inconsistency in wording "collapse button" vs "docking button" vs "tab list button" which I have been rewording as "window menu button", a term that is compatible with the Master branch and will allow us to add features in both. Basically in a docking node the window menu button replace the collapse button).

@gitbetter
Copy link
Author

gitbetter commented May 27, 2019

Thanks for looking into this Omar.

I guess for this specific situation I would only need to disable undocking for an entire window, since this window is not meant to be docked into (it should only have a single tab) so disabling undocking on a per docking-node basis would not make much sense here.

I think hiding the tab bar for this particular window is the way to go, but I also noticed that it only works as expected when first launching the application. After first launch and after the imgui.ini file has been created, even after setting the ImGuiDockNodeFlags_NoTabBar flag in the application the tab bar mysteriously appears again. I'm thinking the .ini settings are overriding any of the set docking node flags. Tried setting the ImGuiWindowFlags_NoSavedSettings flag on the window but it didn't seem to do the trick.

Either way thanks for adding the discussed window menu button and close button flags, they can definitely be useful in some cases.

PS: I think to clarify that currently you are supposed to call DockBuilderSetNodeSize() on your initial node, at the moment if you don't, then DockBuilderSplitNode() will split a little differently than what you may be expecting (not getting into details here but I'll work on fixing this).

From what I understood here DockBuilderSplitNode() allows you to split a node with a given resizing ratio, which is what I am currently trying out, although DockBuilderSetNodeSize() might give a bit more granularity in the resizing, but currently the ratio parameter seems to do a good enough job.

@ocornut
Copy link
Owner

ocornut commented May 27, 2019

I guess for this specific situation I would only need to disable undocking for an entire window, since this window is not meant to be docked into (it should only have a single tab) so disabling undocking on a per docking-node basis would not make much sense here.

It's easier to do it on a per-node basis (mostly because window flags are too scarce to be nilly-willy allocated) and your setup requires you to setup a docking node tho?

I think hiding the tab bar for this particular window is the way to go, but I also noticed that it only works as expected when first launching the application. After first launch and after the imgui.ini file has been created, even after setting the ImGuiDockNodeFlags_NoTabBar flag in the application the tab bar mysteriously appears again. I'm thinking the .ini settings are overriding any of the set docking node flags. Tried setting the ImGuiWindowFlags_NoSavedSettings flag on the window but it didn't seem to do the trick.

Sorry, we indeed don't save any of those flag in the .ini file presently. I completely ommitted that fact. I can start adding some of those flags for saving.

Either way thanks for adding the discussed window menu button and close button flags, they can definitely be useful in some cases.

Hmm, you asked for them above? If they are not useful to you I'll tempted to remove them.

From what I understood here DockBuilderSplitNode() allows you to split a node with a given resizing ratio, which is what I am currently trying out, although DockBuilderSetNodeSize() might give a bit more granularity in the resizing, but currently the ratio parameter seems to do a good enough job.

There's an issue bug somewhere related to how we handle central node and minimum size and I'm pretty sure in some situation it would give you results that are very off the ratio you gave. If you ever stumble on that issue it'll probably be the reason.

ocornut added a commit that referenced this issue May 27, 2019
…s of dock node into the .ini file. Added them to the Metrics window. (#2583, #2423, #2109).
@ocornut
Copy link
Owner

ocornut commented May 27, 2019

Sorry, we indeed don't save any of those flag in the .ini file presently. I completely ommitted that fact. I can start adding some of those flags for saving.

I have now pushed code to save the NoTabBar, NoWindowMenuButton, NoCloseButton flags in the .ini file. They were simply overlooked as all those flags have been recently added.

Note that in the Metrics window under Docking you can manipulate the local flags of dock node to test around the behavior of each:

image

@gitbetter
Copy link
Author

Yes I think I'll definitely find use for the newly added NoWindowMenuButton/NoCloseButton flags. Thanks again for that.

There's an issue bug somewhere related to how we handle central node and minimum size and I'm pretty sure in some situation it would give you results that are very off the ratio you gave. If you ever stumble on that issue it'll probably be the reason.

Good to know I didn't know this might happen. In that case I'll probably start using the DockBuilderSetNodeSize() calls, it seems like a more flexible solution to boot.

I have now pushed code to save the NoTabBar, NoWindowMenuButton, NoCloseButton flags in the .ini file. They were simply overlooked as all those flags have been recently added.

And thanks for looking into this. I shall pull the latest version and test this out.

@gitbetter
Copy link
Author

I have now pushed code to save the NoTabBar, NoWindowMenuButton, NoCloseButton flags in the .ini file. They were simply overlooked as all those flags have been recently added.

By the way, as an addendum, I noticed that the ImGuiDockNodeFlags_NoResize flag is also not saved. Can you also add this one to the .ini file?

Thanks again for everything!

@ocornut
Copy link
Owner

ocornut commented May 27, 2019

The ImGuiDockNodeFlags_NoResize when passed to DockSpace() propagates from the root node so normally you would set it at runtime and it would apply to all nodes.

You can indeed set it manually for a single node by writing in LocalFlags but I have a suspicion it isn't easy to use in this manner as the node tree isn't always obvious to the end-user. I added code to save _NoResize in LocalFlags, I would appreciate if you have feedback of whether it works in your context.

@gitbetter
Copy link
Author

gitbetter commented May 27, 2019

Just pulled and tested out the new commit but it seems the _NoResize flag isn't getting saved to the .ini file. After setting it for a node in the application and looking in the .ini file this is what I see, for that specific node
DockNode ID=0x00000001 Parent=0xB863DB2D SizeRef=0,47 NoTabBar=1 HiddenTabBar=1

In my case (at least for now) I have a very specific setup where the custom top toolbar should not be un-docked or resized. Works perfectly on first run but the only thing missing now is the resizing on subsequent runs.

Looking at the previous commit for the NoTabBar/NoWindowMenuButton/NoCloseButton flag additions, and comparing to the current commit, I believe you are missing these lines

somewhere after line 14094:

    if (sscanf(line, " NoResize=%d%n", &x, &r) == 1)                { line += r; if (x != 0) node.Flags |= ImGuiDockNodeFlags_NoResize; }

and somewhere after line 14166:

if (node_settings->Flags & ImGuiDockNodeFlags_NoResize)
            buf->appendf(" NoResize=1");

@ocornut
Copy link
Owner

ocornut commented May 27, 2019

That's exactly what the latest commit in docking adds so I'm not sure you've pulled latest?

@gitbetter
Copy link
Author

gitbetter commented May 27, 2019

Ah my mistake must have been looking at another commit. Yes I pulled the latest and I do see it has those changes, but it seems the _NoResize flag is still not ending up in the .ini file, even after doing
node->LocalFlags |= ImGuiDockNodeFlags_NoTabBar | ImGuiDockNodeFlags_NoResize;

@ocornut
Copy link
Owner

ocornut commented May 27, 2019

It is for me and when testing with the Metrics>Docking section so there must be something different in your case. As a rule of thumb, anything related to docking is always much more complicated that in appears to be, so careful repro needs to be done.

Skimming at the code I just found a bug (I think unrelated to yours since you are not splitting your node, but DockBuilderRemoveNode() overwrite whole parent LocalFlags when removing a child node that's the central node, which is incorrect, should be move the CentralNode flag, not overwrite the whole sets of flag. Anyway this should not affect you).

@gitbetter
Copy link
Author

Yes my mistake again, I forgot to copy in imgui_internal.h into my project when I pulled, which had the ImGuiDockNodeFlags_NoResize added to the _SavedFlagsMask_. Thank you, everything's working as expected now (y)

@ocornut
Copy link
Owner

ocornut commented May 28, 2019

I forgot to copy in imgui_internal.h into my project when I pulled

(Ouch, you should probably avoid using such error-prone process in the first place. Pulling should be pulling and done, not some manual error-prone sync step!)

Closing this now!

@ocornut
Copy link
Owner

ocornut commented Nov 22, 2019

Hello @gitbetter,

I will probably need to redesign some of the things that were added for this thread, and I'll need
references of how they are used. Is your main project the one publicly hosted at https://github.com/gitbetter/Zenith ?
Namely: https://github.com/gitbetter/Zenith/blob/23533b7de21fc8a6fd4303659da12381a112b1a4/Editor/_Source/ZEditor.cpp#L310

Can you think of any other more advanced use you made of the system?

@gitbetter
Copy link
Author

Hey @ocornut,

Yes that's the project in question. At the moment, that is really the only place where I was in need of the docking behavior. Haven't come up with any more complex use cases as of yet. Feel free to use the project as is.

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

2 participants