@@ -9648,7 +9648,7 @@ namespace ImGui
9648
9648
static void DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id); // Use root_id==0 to add all
9649
9649
9650
9650
// ImGuiDockNode
9651
- static void DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window);
9651
+ static void DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, bool add_to_tab_bar );
9652
9652
static void DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
9653
9653
static void DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
9654
9654
static void DockNodeApplyPosSizeToWindows(ImGuiDockNode* node);
@@ -10012,7 +10012,7 @@ void ImGui::DockContextBuildAddWindowsToNodes(ImGuiContext* ctx, ImGuiID root_id
10012
10012
ImGuiDockNode* dock_node = DockContextFindNodeByID(ctx, window->DockId);
10013
10013
IM_ASSERT(dock_node != NULL); // This should have been called after DockContextBuildNodesFromSettings()
10014
10014
if (root_id == 0 || DockNodeGetRootNode(dock_node)->ID == root_id)
10015
- DockNodeAddWindow(dock_node, window);
10015
+ DockNodeAddWindow(dock_node, window, true );
10016
10016
}
10017
10017
}
10018
10018
@@ -10095,7 +10095,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
10095
10095
target_node->Size = target_window->Size;
10096
10096
if (target_window->DockNodeAsHost == NULL)
10097
10097
{
10098
- DockNodeAddWindow(target_node, target_window);
10098
+ DockNodeAddWindow(target_node, target_window, true );
10099
10099
target_window->DockIsActive = true;
10100
10100
}
10101
10101
}
@@ -10167,7 +10167,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
10167
10167
{
10168
10168
// Transfer single window
10169
10169
target_node->VisibleWindow = payload_window;
10170
- DockNodeAddWindow(target_node, payload_window);
10170
+ DockNodeAddWindow(target_node, payload_window, true );
10171
10171
}
10172
10172
}
10173
10173
@@ -10196,20 +10196,26 @@ void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
10196
10196
IM_ASSERT(!node->IsSplitNode());
10197
10197
IM_ASSERT(node->Windows.Size >= 1);
10198
10198
10199
- ImGuiDockNode* new_node = DockContextAddNode(ctx, (ImGuiID)-1);
10200
- DockNodeMoveWindows(new_node, node);
10201
- for (int n = 0; n < new_node->Windows.Size; n++)
10202
- UpdateWindowParentAndRootLinks(new_node->Windows[n], new_node->Windows[n]->Flags, NULL);
10203
- new_node->WantMouseMove = true;
10204
-
10205
10199
// In the case of a root node, a node will have to stay in place. Create a new node for this purpose.
10206
10200
// Otherwise delete the previous node by merging the other sibling back into the parent node.
10207
- // FIXME-DOCK: Transition persistent DockId for all non-active windows
10208
- if (!node->IsRootNode())
10201
+ if (node->IsRootNode())
10202
+ {
10203
+ // FIXME-DOCK: Transition persistent DockId for all non-active windows
10204
+ ImGuiDockNode* new_node = DockContextAddNode(ctx, (ImGuiID)-1);
10205
+ DockNodeMoveWindows(new_node, node);
10206
+ for (int n = 0; n < new_node->Windows.Size; n++)
10207
+ UpdateWindowParentAndRootLinks(new_node->Windows[n], new_node->Windows[n]->Flags, NULL);
10208
+ new_node->WantMouseMove = true;
10209
+ }
10210
+ else
10209
10211
{
10210
10212
IM_ASSERT(node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
10211
- ImGuiDockNode* lead_sibling = node->ParentNode->ChildNodes[(node->ParentNode->ChildNodes[0] == node) ? 1 : 0];
10212
- DockNodeTreeMerge(ctx, node->ParentNode, lead_sibling);
10213
+ int index_in_parent = (node->ParentNode->ChildNodes[0] == node) ? 0 : 1;
10214
+ node->ParentNode->ChildNodes[index_in_parent] = NULL;
10215
+ DockNodeTreeMerge(ctx, node->ParentNode, node->ParentNode->ChildNodes[index_in_parent ^ 1]);
10216
+ node->ParentNode = NULL;
10217
+ node->InitFromFirstWindow = true;
10218
+ node->WantMouseMove = true;
10213
10219
}
10214
10220
MarkIniSettingsDirty();
10215
10221
}
@@ -10252,7 +10258,7 @@ int ImGui::DockNodeGetTabOrder(ImGuiWindow* window)
10252
10258
return tab ? tab_bar->GetTabOrder(tab) : -1;
10253
10259
}
10254
10260
10255
- static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window)
10261
+ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, bool add_to_tab_bar )
10256
10262
{
10257
10263
ImGuiContext& g = *GImGui; (void)g;
10258
10264
if (window->DockNode)
@@ -10281,12 +10287,16 @@ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window)
10281
10287
if (node->Windows.Size == 2 && !node->IsDockSpace)
10282
10288
node->InitFromFirstWindow = true;
10283
10289
10284
- if (node->TabBar == NULL)
10290
+ // Add to tab bar if requested
10291
+ if (add_to_tab_bar)
10285
10292
{
10286
- node->TabBar = IM_NEW(ImGuiTabBar)();
10287
- node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabID;
10293
+ if (node->TabBar == NULL)
10294
+ {
10295
+ node->TabBar = IM_NEW(ImGuiTabBar)();
10296
+ node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabID;
10297
+ }
10298
+ TabBarAddTab(node->TabBar, window);
10288
10299
}
10289
- TabBarAddTab(node->TabBar, window);
10290
10300
10291
10301
DockNodeUpdateVisibleFlag(node);
10292
10302
@@ -10376,19 +10386,31 @@ static void ImGui::DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* s
10376
10386
ImGuiTabBar* src_tab_bar = src_node->TabBar;
10377
10387
if (src_tab_bar != NULL)
10378
10388
IM_ASSERT(src_node->Windows.Size == src_node->TabBar->Tabs.Size);
10389
+
10390
+ // If the dst_node is empty we can just move the entire tab bar (to preserve selection, scrolling, etc.)
10391
+ bool move_tab_bar = (src_tab_bar != NULL) && (dst_node->TabBar == NULL);
10392
+ if (move_tab_bar)
10393
+ {
10394
+ dst_node->TabBar = src_node->TabBar;
10395
+ src_node->TabBar = NULL;
10396
+ }
10397
+
10379
10398
for (int n = 0; n < src_node->Windows.Size; n++)
10380
10399
{
10381
10400
ImGuiWindow* window = src_tab_bar ? src_tab_bar->Tabs[n].Window : src_node->Windows[n];
10382
10401
window->DockNode = NULL;
10383
10402
window->DockIsActive = false;
10384
- DockNodeAddWindow(dst_node, window);
10403
+ DockNodeAddWindow(dst_node, window, move_tab_bar ? false : true );
10385
10404
}
10386
- if (dst_node->TabBar == NULL)
10387
- dst_node->TabBar = src_node->TabBar;
10388
- else
10389
- IM_DELETE(src_node->TabBar);
10390
- src_node->TabBar = NULL;
10391
10405
src_node->Windows.clear();
10406
+
10407
+ if (!move_tab_bar && src_node->TabBar)
10408
+ {
10409
+ if (dst_node->TabBar)
10410
+ dst_node->TabBar->SelectedTabId = src_node->TabBar->SelectedTabId;
10411
+ IM_DELETE(src_node->TabBar);
10412
+ src_node->TabBar = NULL;
10413
+ }
10392
10414
}
10393
10415
10394
10416
static void ImGui::DockNodeApplyPosSizeToWindows(ImGuiDockNode* node)
@@ -11192,30 +11214,39 @@ void ImGui::DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImG
11192
11214
11193
11215
void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImGuiDockNode* merge_lead_child)
11194
11216
{
11217
+ // When called from DockContextProcessUndockNode() it is possible that one of the child is NULL.
11195
11218
ImGuiDockNode* child_0 = parent_node->ChildNodes[0];
11196
11219
ImGuiDockNode* child_1 = parent_node->ChildNodes[1];
11197
- IM_ASSERT(child_0 && child_1);
11220
+ IM_ASSERT(child_0 || child_1);
11198
11221
IM_ASSERT(merge_lead_child == child_0 || merge_lead_child == child_1);
11199
- if (child_0->Windows.Size > 0 || child_1->Windows.Size > 0)
11222
+ if (( child_0 && child_0 ->Windows.Size > 0) || ( child_1 && child_1 ->Windows.Size > 0) )
11200
11223
{
11201
11224
IM_ASSERT(parent_node->TabBar == NULL);
11202
11225
IM_ASSERT(parent_node->Windows.Size == 0);
11203
11226
}
11204
11227
11205
11228
ImVec2 backup_last_explicit_size = parent_node->SizeRef;
11206
11229
DockNodeMoveChildNodes(parent_node, merge_lead_child);
11207
- DockNodeMoveWindows(parent_node, child_0); // Generally only 1 of the 2 child node will have windows
11208
- DockNodeMoveWindows(parent_node, child_1);
11230
+ if (child_0)
11231
+ DockNodeMoveWindows(parent_node, child_0); // Generally only 1 of the 2 child node will have windows
11232
+ if (child_1)
11233
+ DockNodeMoveWindows(parent_node, child_1);
11209
11234
DockNodeApplyPosSizeToWindows(parent_node);
11210
11235
parent_node->InitFromFirstWindow = false;
11211
11236
parent_node->VisibleWindow = merge_lead_child->VisibleWindow;
11212
- parent_node->IsDocumentRoot = child_0->IsDocumentRoot || child_1->IsDocumentRoot;
11237
+ parent_node->IsDocumentRoot = ( child_0 && child_0 ->IsDocumentRoot) || ( child_1 && child_1 ->IsDocumentRoot) ;
11213
11238
parent_node->SizeRef = backup_last_explicit_size;
11214
11239
11215
- ctx->DockContext->Nodes.SetVoidPtr(child_0->ID, NULL);
11216
- ctx->DockContext->Nodes.SetVoidPtr(child_1->ID, NULL);
11217
- IM_DELETE(child_0);
11218
- IM_DELETE(child_1);
11240
+ if (child_0)
11241
+ {
11242
+ ctx->DockContext->Nodes.SetVoidPtr(child_0->ID, NULL);
11243
+ IM_DELETE(child_0);
11244
+ }
11245
+ if (child_1)
11246
+ {
11247
+ ctx->DockContext->Nodes.SetVoidPtr(child_1->ID, NULL);
11248
+ IM_DELETE(child_1);
11249
+ }
11219
11250
}
11220
11251
11221
11252
// Update Pos/Size for a node hierarchy (don't affect child Windows yet)
@@ -11613,7 +11644,7 @@ void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open)
11613
11644
return;
11614
11645
}
11615
11646
11616
- DockNodeAddWindow(dock_node, window);
11647
+ DockNodeAddWindow(dock_node, window, true );
11617
11648
IM_ASSERT(dock_node == window->DockNode);
11618
11649
11619
11650
// Fix an edge case with auto-resizing windows: if they are created on the same frame they are creating their dock node,
0 commit comments