| 18278 | } |
| 18279 | |
| 18280 | void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req) |
| 18281 | { |
| 18282 | IM_ASSERT((req->Type == ImGuiDockRequestType_Dock && req->DockPayload != NULL) || (req->Type == ImGuiDockRequestType_Split && req->DockPayload == NULL)); |
| 18283 | IM_ASSERT(req->DockTargetWindow != NULL || req->DockTargetNode != NULL); |
| 18284 | |
| 18285 | ImGuiContext& g = *ctx; |
| 18286 | IM_UNUSED(g); |
| 18287 | |
| 18288 | ImGuiWindow* payload_window = req->DockPayload; // Optional |
| 18289 | ImGuiWindow* target_window = req->DockTargetWindow; |
| 18290 | ImGuiDockNode* node = req->DockTargetNode; |
| 18291 | if (payload_window) |
| 18292 | IMGUI_DEBUG_LOG_DOCKING("[docking] DockContextProcessDock node 0x%08X target '%s' dock window '%s', split_dir %d\n", node ? node->ID : 0, target_window ? target_window->Name : "NULL", payload_window->Name, req->DockSplitDir); |
| 18293 | else |
| 18294 | IMGUI_DEBUG_LOG_DOCKING("[docking] DockContextProcessDock node 0x%08X, split_dir %d\n", node ? node->ID : 0, req->DockSplitDir); |
| 18295 | |
| 18296 | // Decide which Tab will be selected at the end of the operation |
| 18297 | ImGuiID next_selected_id = 0; |
| 18298 | ImGuiDockNode* payload_node = NULL; |
| 18299 | if (payload_window) |
| 18300 | { |
| 18301 | payload_node = payload_window->DockNodeAsHost; |
| 18302 | payload_window->DockNodeAsHost = NULL; // Important to clear this as the node will have its life as a child which might be merged/deleted later. |
| 18303 | if (payload_node && payload_node->IsLeafNode()) |
| 18304 | next_selected_id = payload_node->TabBar->NextSelectedTabId ? payload_node->TabBar->NextSelectedTabId : payload_node->TabBar->SelectedTabId; |
| 18305 | if (payload_node == NULL) |
| 18306 | next_selected_id = payload_window->TabId; |
| 18307 | } |
| 18308 | |
| 18309 | // FIXME-DOCK: When we are trying to dock an existing single-window node into a loose window, transfer Node ID as well |
| 18310 | // When processing an interactive split, usually LastFrameAlive will be < g.FrameCount. But DockBuilder operations can make it ==. |
| 18311 | if (node) |
| 18312 | IM_ASSERT(node->LastFrameAlive <= g.FrameCount); |
| 18313 | if (node && target_window && node == target_window->DockNodeAsHost) |
| 18314 | IM_ASSERT(node->Windows.Size > 0 || node->IsSplitNode() || node->IsCentralNode()); |
| 18315 | |
| 18316 | // Create new node and add existing window to it |
| 18317 | if (node == NULL) |
| 18318 | { |
| 18319 | node = DockContextAddNode(ctx, 0); |
| 18320 | node->Pos = target_window->Pos; |
| 18321 | node->Size = target_window->Size; |
| 18322 | if (target_window->DockNodeAsHost == NULL) |
| 18323 | { |
| 18324 | DockNodeAddWindow(node, target_window, true); |
| 18325 | node->TabBar->Tabs[0].Flags &= ~ImGuiTabItemFlags_Unsorted; |
| 18326 | target_window->DockIsActive = true; |
| 18327 | } |
| 18328 | } |
| 18329 | |
| 18330 | ImGuiDir split_dir = req->DockSplitDir; |
| 18331 | if (split_dir != ImGuiDir_None) |
| 18332 | { |
| 18333 | // Split into two, one side will be our payload node unless we are dropping a loose window |
| 18334 | const ImGuiAxis split_axis = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y; |
| 18335 | const int split_inheritor_child_idx = (split_dir == ImGuiDir_Left || split_dir == ImGuiDir_Up) ? 1 : 0; // Current contents will be moved to the opposite side |
| 18336 | const float split_ratio = req->DockSplitRatio; |
| 18337 | DockNodeTreeSplit(ctx, node, split_axis, split_inheritor_child_idx, split_ratio, payload_node); // payload_node may be NULL here! |
nothing calls this directly
no test coverage detected