Open wolfpld opened 5 years ago
Hello @wolfpld,
Thanks for your detailed post. I'm going to have to think about what the best move here, but I agree this should be faisible and certainly would not want you to have to rely on the suggested workaround.
(That said, the workaround of "Draw the working area on background?", even though I wouldn't recommend it, might be easy to accomplish using ImGuiDockNodeFlags_PassthruDockspace
and then using DockBuilderGetCentralNode()
coordinates to create your "background" window.)
If docking in central node is disabled, then the user cannot attach anything to the center node, but the center node is also not rendered, so the working area is not displayed. It doesn't show as a separate window, so I assume it is attached correctly.
The code in ImGui::BeginDocked()
intentionally undocks anything docked to the central node when the flag is set:
// Undock if the ImGuiDockNodeFlags_NoDockingInCentralNode got set
if (node->IsCentralNode && (node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode))
{
DockContextProcessUndockWindow(ctx, window);
return;
}
It seemed like the right thing to do but your case is challenging this assertion. Would you be able to confirm that commenting this block fixes this one half of your issue? I'm not sure yet but it may be the right solution to just remove this block.
As for hiding the tab bar. My intuition is that the solution we are looking for may involve setting flags explicitely on a given node rater than stacking more behavior specifically referring to the central node.
I would eventually like to get rid of the "central node" concept at a lower-level and split it into a few precise properties (e.g. ~ AllowEmpty
UseRemainingSize
flags, haven't nailed how they would be designed yet, the tricky part is to decide what to do with them when merging/splitting). If you are curious, in imgui_internal.h
there is a DockBuilderXXX
api which is work-in-progress but aim to allow more precise control of the docking state.
We could add an explicit per-node flag that could you set on the central node manually.
I have done some reorganization toward this (with also in mind the changes I'd like to do regarding the concept of a central node).
If you imagine a ImGuiDockNodeFlags_NoTabBar
that could be set on individual node, the difficulty is to decide how options/flags spread with successive docking/spliting/merging operation. The interface expose both "outermost" docking (~dock on the side at the root level) and "inner" docking (~split existing node). You would expect the earlier to not be inheriting flags whereas the later would. However in your case if you already have something docked under you central node, you still want to offer the user the possibility to dock left/right within the vertical space of the center node, which currently is considered as a split of the center node and therefore would spread the NoTabBar
flag to the newly created node.
Perhaps the right solution is to let the user be more explicit about the minutia of flag transfer and inheritance.
Tl;DR; In the short term I may expose a NoTabBarOnCentralNode
(exactly what I was trying to avoid!) simply because we currently have a robust way of tracking the central node which is also carried in the persistent data (e.g. .ini file) and so it becomes a much simpler problem to solve.
Would you be able to confirm that commenting this block fixes this one half of your issue?
Removing this code block makes the flag behave as I'd expect.
As for hiding the tab bar. My intuition is that the solution we are looking for may involve setting flags explicitely on a given node rater than stacking more behavior specifically referring to the central node.
Yes, I think this is the required approach. Somehow I assumed (and didn't notice it is global for the whole dockspace) that the flag will only affect the central node.
Meanwhile, I have found some interesting related bugs. The first one can be reproduced using the example application straight away:
Instead of still being docked in the left part of the screen, the "Example: Log" window/tab is now docked in the center node, along the "ImGui Demo" window/tab. This enables docking additional windows to the center node by the user in my use case.
If instead of performing step 3 you would enable the Docking -> Flag: NoDockingInCentralNode option, then, at the end of repro steps the "Example: Log" window will appear to be docked, but it will be a floating window (because it is automatically undocked by the condition you have mentioned).
The second bug needs a modification of the example, adding the ImGuiDockNodeFlags_AutoHideTabBar
flag to the DockSpace()
call. To make it manifest, repeat repro steps 1, 2, 4, 5, 6 from the previous bug. ImGui will crash in imgui.cpp:11917:
if (node->TabBar->SelectedTabId)
node->SelectedTabID = node->TabBar->SelectedTabId;
With node->TabBar
being nullptr.
And just for fun, this is how the layout might look:
Thank you Bartosz.
Would you be able to confirm that commenting this block fixes this one half of your issue? Removing this code block makes the flag behave as I'd expect.
I pushed two commits including one to change this behavior, i think it is appropriate.
I am at GDC this week so may not be able to tackle the rest immediately, thank you for your patience.
The second bug needs a modification of the example, adding the ImGuiDockNodeFlags_AutoHideTabBar flag to the DockSpace() call. To make it manifest, repeat repro steps 1, 2, 4, 5, 6 from the previous bug. ImGui will crash in imgui.cpp:11917:
Pushed a fix for this issue.
(A) Two fixes in the two post aboves.
(B)
Meanwhile, I have found some interesting related bugs. The first one can be reproduced using the example application straight away: Instead of still being docked in the left part of the screen, the "Example: Log" window/tab is now docked in the center node, along the "ImGui Demo" window/tab. This enables docking additional windows to the center node by the user in my use case.
I could repro this, thank you.
Note that it happens if in step 7 "Undock "Hello, world!" into floating window."
you drag the window from its tab. It won't happen if you drag from the collapsing/docking button that is located on the left side of the tab-bar. There's a subtle difference where the later imply dragging the whole dock node (which in this case will preserve the reference), whereas dragging from a single window tab which in this situation will trigger an (incorrect) merge of two docking nodes.
At the moment there is a flaw where we don't fully track references to dock nodes from inactive or uncreated window during runtime (there is however some dedicated processing and a GC running at init time). Will transition toward doing this full tracking at the current model is erroneous. It's not a big change but it may take some time until I do it properly.
(C)
I made some change to allow for a ImGuiDockNodeFlags_NoTabBar
flag (and other flags) on a per-node basis but haven't exposed it in the public API yet namely because the logic for spreading (when splitting/merging) and persisting per-node flags is tricky and I am currently not sure of the exact design that would work for other features. However in your situation where you want to use _NoTabBar since you'll also be using the _NoDockingInCentral node flag you shouldn't have any problem and you can use the internal API:
#include <imgui_internal.h>
[...]
if (ImGuiDockNode* node = ImGui::DockBuilderGetCentralNode(dockspace_id))
node->LocalFlags |= ImGuiDockNodeFlags_NoTabBar;
It might occasionally break (if I rename the field or enum) in which case I will post the correction here and if that ever happen it should be a trivial fix. If you use this it is more likely the feature will get promoted into a public API down the line.
Two fixes in the two post aboves.
Thanks.
It won't happen if you drag from the collapsing/docking button that is located on the left side of the tab-bar.
I think there is a discoverability problem with this feature. I would expect this behavior to be also available when dragging the empty space on the tab bar.
If you use this it is more likely the feature will get promoted into a public API down the line.
I have already applied it to tracy's docking branch and it's working as advertised.
I think there is a discoverability problem with this feature. I would expect this behavior to be also available when dragging the empty space on the tab bar.
Correct. This is eventually planned. Thanks for the other issue report! (deleted our respective messages as it's been moved to #2453).
I think there is a discoverability problem with this feature. I would expect this behavior to be also available when dragging the empty space on the tab bar. Correct. This is eventually planned.
Forgot to mention this was added by #2645 in mid-July as part of v1.72 (which you are already using in Tracy afaik).
I'm currently having another pass looking at some of the feature discussed above (which are technically in the internal api), will post here if some of the design changes.
Another random notes for later references (may not apply to you anymore, I assume you found suitable workarounds)
// Undock if the ImGuiDockNodeFlags_NoDockingInCentralNode got set Removing this code block makes the flag behave as I'd expect.
A while ago I added more precise flags such as ImGuiDockNodeFlags_NoDockingOverMe
which you can set on the central node. In fact ImGuiDockNodeFlags_NoDockingInCentralNode
is ultimately going to be phased out. Assuming flags can be tracked meaningfully and persistently, it would be equivalent to just set _NoDockingXXX in that one specific node.
I'm still using ImGuiDockNodeFlags_NoDockingInCentralNode
, so this is a nice heads-up.
Right now I would suggest still using it and not bothering switching, as the persistence/tracking of individual flags with splitting/merging is still a bit of a mess (whereas ImGuiDockNodeFlags_NoDockingInCentralNode
is simpler as it always behave on whichever is the central node at a given point). I'll post again when I get around to rework this more widely.
Hello. Has there been any update to this issue? I'm quite interested in the use case presented in this issue as well, and I think it is quite common for people wishing to make "editors" using imgui.
The reason I'm asking is because this issue is still open, which makes me assume there has not been any final decision on the best way to handle this use case?
Version/Branch of Dear ImGui:
Version: b1af4d36ce1506b34b8f89dc1a038ec4c5fdbbdd Branch: docking
Background
Tracy Profiler consists of the following UI elements:
I would like to use the docking system in a following way:
What can be done with the current code
DockSpace()
,SetNextWindowDockID()
function (using the id passed toDockSpace()
),What is missing
I want the working area to be the only window which can be attached to the center node. By this I mean that:
This can almost be achieved by using a combination of
ImGuiDockNodeFlags_NoDockingInCentralNode
andImGuiDockNodeFlags_AutoHideTabBar
flags, but not quite.If docking in central node is disabled, then the user cannot attach anything to the center node, but the center node is also not rendered, so the working area is not displayed. It doesn't show as a separate window, so I assume it is attached correctly.
The tab-bar hiding feature is designed to work with multiple windows attached to the dock node, but I really want to just disable it, like using
ImGuiWindowFlags_NoTitleBar
would disable the title bar of the window. A new dock node flag would be needed, or, alternatively, the tab-bar should honor window flags, like the no title bar request.Additionally, the top docking node cannot be disabled (so that the floating windows can be only attached on the left, right or bottom), but this is a very low prio issue.
Possible workarounds?
Draw the working area on background? Or in a window which tracks center node size? Seems tricky due to the following issues:
Possible problems?
What should happen if two windows are attached to the center node, but docking is diabled and no tab-bar is displayed?
I would say this is a program logic error. Add an assert.
What if docking to center node is not disabled, in the situation above?
Display tab-bar, but disable it when only one window remains.
Why should the center node be the only one that implements the requested features?
It shouldn't be, but it's not needed in my use case.