Skip to content

Commit

Permalink
Docking: Add source dock node parameter DockContextCalcDropPosForDock…
Browse files Browse the repository at this point in the history
…ing() to facilitate test engine (un)docking nodes before they are split out to their own window.

Metrics: Display dock_node->Windows in node metrics.
  • Loading branch information
rokups authored and ocornut committed Aug 8, 2022
1 parent ff1567e commit 8cbd391
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 12 deletions.
25 changes: 14 additions & 11 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13841,7 +13841,7 @@ namespace ImGui
static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
static void DockNodeStartMouseMovingWindow(ImGuiDockNode* node, ImGuiWindow* window);
static bool DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow* payload_window);
static void DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockPreviewData* preview_data, bool is_explicit_target, bool is_outer_docking);
static void DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDockPreviewData* preview_data, bool is_explicit_target, bool is_outer_docking);
static void DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, const ImGuiDockPreviewData* preview_data);
static void DockNodeCalcTabBarLayout(const ImGuiDockNode* node, ImRect* out_title_rect, ImRect* out_tab_bar_rect, ImVec2* out_window_menu_button_pos, ImVec2* out_close_button_pos);
static void DockNodeCalcSplitRects(ImVec2& pos_old, ImVec2& size_old, ImVec2& pos_new, ImVec2& size_new, ImGuiDir dir, ImVec2 size_new_desired);
Expand Down Expand Up @@ -14500,14 +14500,14 @@ void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
}

// This is mostly used for automation.
bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos)
bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos)
{
// In DockNodePreviewDockSetup() for a root central node instead of showing both "inner" and "outer" drop rects
// (which would be functionally identical) we only show the outer one. Reflect this here.
if (target_node && target_node->ParentNode == NULL && target_node->IsCentralNode() && split_dir != ImGuiDir_None)
split_outer = true;
ImGuiDockPreviewData split_data;
DockNodePreviewDockSetup(target, target_node, payload, &split_data, false, split_outer);
DockNodePreviewDockSetup(target, target_node, payload_window, payload_node, &split_data, false, split_outer);
if (split_data.DropRectsDraw[split_dir+1].IsInverted())
return false;
*out_pos = split_data.DropRectsDraw[split_dir+1].GetCenter();
Expand Down Expand Up @@ -15829,20 +15829,21 @@ bool ImGui::DockNodeCalcDropRectsAndTestMousePos(const ImRect& parent, ImGuiDir

// host_node may be NULL if the window doesn't have a DockNode already.
// FIXME-DOCK: This is misnamed since it's also doing the filtering.
static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* root_payload, ImGuiDockPreviewData* data, bool is_explicit_target, bool is_outer_docking)
static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockNode* host_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDockPreviewData* data, bool is_explicit_target, bool is_outer_docking)
{
ImGuiContext& g = *GImGui;

// There is an edge case when docking into a dockspace which only has inactive nodes.
// In this case DockNodeTreeFindNodeByPos() will have selected a leaf node which is inactive.
// Because the inactive leaf node doesn't have proper pos/size yet, we'll use the root node as reference.
ImGuiDockNode* root_payload_as_host = root_payload->DockNodeAsHost;
if (payload_node == NULL)
payload_node = payload_window->DockNodeAsHost;
ImGuiDockNode* ref_node_for_rect = (host_node && !host_node->IsVisible) ? DockNodeGetRootNode(host_node) : host_node;
if (ref_node_for_rect)
IM_ASSERT(ref_node_for_rect->IsVisible == true);

// Filter, figure out where we are allowed to dock
ImGuiDockNodeFlags src_node_flags = root_payload_as_host ? root_payload_as_host->MergedFlags : root_payload->WindowClass.DockNodeFlagsOverrideSet;
ImGuiDockNodeFlags src_node_flags = payload_node ? payload_node->MergedFlags : payload_window->WindowClass.DockNodeFlagsOverrideSet;
ImGuiDockNodeFlags dst_node_flags = host_node ? host_node->MergedFlags : host_window->WindowClass.DockNodeFlagsOverrideSet;
data->IsCenterAvailable = true;
if (is_outer_docking)
Expand All @@ -15851,7 +15852,7 @@ static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockN
data->IsCenterAvailable = false;
else if (host_node && (dst_node_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) && host_node->IsCentralNode())
data->IsCenterAvailable = false;
else if ((!host_node || !host_node->IsEmpty()) && root_payload_as_host && root_payload_as_host->IsSplitNode() && (root_payload_as_host->OnlyNodeWithWindows == NULL)) // Is _visibly_ split?
else if ((!host_node || !host_node->IsEmpty()) && payload_node && payload_node->IsSplitNode() && (payload_node->OnlyNodeWithWindows == NULL)) // Is _visibly_ split?
data->IsCenterAvailable = false;
else if (dst_node_flags & ImGuiDockNodeFlags_NoDockingOverMe)
data->IsCenterAvailable = false;
Expand All @@ -15869,7 +15870,7 @@ static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockN
data->IsSidesAvailable = false;

// Build a tentative future node (reuse same structure because it is practical. Shape will be readjusted when previewing a split)
data->FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (root_payload->HasCloseButton);
data->FutureNode.HasCloseButton = (host_node ? host_node->HasCloseButton : host_window->HasCloseButton) || (payload_window->HasCloseButton);
data->FutureNode.HasWindowMenuButton = host_node ? true : ((host_window->Flags & ImGuiWindowFlags_NoCollapse) == 0);
data->FutureNode.Pos = ref_node_for_rect ? ref_node_for_rect->Pos : host_window->Pos;
data->FutureNode.Size = ref_node_for_rect ? ref_node_for_rect->Size : host_window->Size;
Expand Down Expand Up @@ -15906,7 +15907,7 @@ static void ImGui::DockNodePreviewDockSetup(ImGuiWindow* host_window, ImGuiDockN
ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
ImVec2 pos_new, pos_old = data->FutureNode.Pos;
ImVec2 size_new, size_old = data->FutureNode.Size;
DockNodeCalcSplitRects(pos_old, size_old, pos_new, size_new, split_dir, root_payload->Size);
DockNodeCalcSplitRects(pos_old, size_old, pos_new, size_new, split_dir, payload_window->Size);

// Calculate split ratio so we can pass it down the docking request
float split_ratio = ImSaturate(size_new[split_axis] / data->FutureNode.Size[split_axis]);
Expand Down Expand Up @@ -17274,11 +17275,11 @@ void ImGui::BeginDockableDragDropTarget(ImGuiWindow* window)
if (node && (node->ParentNode || node->IsCentralNode()))
if (ImGuiDockNode* root_node = DockNodeGetRootNode(node))
{
DockNodePreviewDockSetup(window, root_node, payload_window, &split_outer, is_explicit_target, true);
DockNodePreviewDockSetup(window, root_node, payload_window, NULL, &split_outer, is_explicit_target, true);
if (split_outer.IsSplitDirExplicit)
split_data = &split_outer;
}
DockNodePreviewDockSetup(window, node, payload_window, &split_inner, is_explicit_target, false);
DockNodePreviewDockSetup(window, node, payload_window, NULL, &split_inner, is_explicit_target, false);
if (split_data == &split_outer)
split_inner.IsDropAllowed = false;

Expand Down Expand Up @@ -18449,6 +18450,8 @@ void ImGui::DebugNodeDockNode(ImGuiDockNode* node, const char* label)
DebugNodeDockNode(node->ChildNodes[1], "Child[1]");
if (node->TabBar)
DebugNodeTabBar(node->TabBar, "TabBar");
DebugNodeWindowsList(&node->Windows, "Windows");

TreePop();
}
}
Expand Down
2 changes: 1 addition & 1 deletion imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2971,7 +2971,7 @@ namespace ImGui
IMGUI_API void DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, float split_ratio, bool split_outer);
IMGUI_API void DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window);
IMGUI_API void DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node);
IMGUI_API bool DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos);
IMGUI_API bool DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload_window, ImGuiDockNode* payload_node, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos);
IMGUI_API ImGuiDockNode*DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id);
IMGUI_API bool DockNodeBeginAmendTabBar(ImGuiDockNode* node);
IMGUI_API void DockNodeEndAmendTabBar();
Expand Down

0 comments on commit 8cbd391

Please sign in to comment.