@ -11272,7 +11272,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
ImGuiContext & g = * ctx ;
ImGuiWindow * payload_window = req - > DockPayload ; // Optional
ImGuiWindow * target_window = req - > DockTargetWindow ;
ImGuiDockNode * target_ node = req - > DockTargetNode ;
ImGuiDockNode * node = req - > DockTargetNode ;
// Decide which Tab will be selected at the end of the operation
ImGuiID next_selected_id = 0 ;
@ -11289,21 +11289,21 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
// FIXME-DOCK: When we are trying to dock an existing single-window node into a loose window, transfer Node ID as well
// When processing an interactive split, usually LastFrameAlive will be < g.FrameCount. But DockBuilder operations can make it ==.
if ( target_ node)
IM_ASSERT ( target_ node- > LastFrameAlive < = g . FrameCount ) ;
if ( target_ node & & target_window & & target_ node = = target_window - > DockNodeAsHost )
IM_ASSERT ( target_ node- > Windows . Size > 0 | | target_ node- > IsSplitNode ( ) | | target_ node- > IsCentralNode ( ) ) ;
if ( node)
IM_ASSERT ( node- > LastFrameAlive < = g . FrameCount ) ;
if ( node & & target_window & & node = = target_window - > DockNodeAsHost )
IM_ASSERT ( node- > Windows . Size > 0 | | node- > IsSplitNode ( ) | | node- > IsCentralNode ( ) ) ;
// Create new node and add existing window to it
if ( target_ node = = NULL )
if ( node = = NULL )
{
target_ node = DockContextAddNode ( ctx , 0 ) ;
target_ node- > Pos = target_window - > Pos ;
target_ node- > Size = target_window - > Size ;
node = DockContextAddNode ( ctx , 0 ) ;
node- > Pos = target_window - > Pos ;
node- > Size = target_window - > Size ;
if ( target_window - > DockNodeAsHost = = NULL )
{
DockNodeAddWindow ( target_ node, target_window , true ) ;
target_ node- > TabBar - > Tabs [ 0 ] . Flags & = ~ ImGuiTabItemFlags_Unsorted ;
DockNodeAddWindow ( node, target_window , true ) ;
node- > TabBar - > Tabs [ 0 ] . Flags & = ~ ImGuiTabItemFlags_Unsorted ;
target_window - > DockIsActive = true ;
}
}
@ -11315,21 +11315,21 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
const ImGuiAxis split_axis = ( split_dir = = ImGuiDir_Left | | split_dir = = ImGuiDir_Right ) ? ImGuiAxis_X : ImGuiAxis_Y ;
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
const float split_ratio = req - > DockSplitRatio ;
DockNodeTreeSplit ( ctx , target_ node, split_axis , split_inheritor_child_idx , split_ratio , payload_node ) ; // payload_node may be NULL here!
ImGuiDockNode * new_node = target_ node- > ChildNodes [ split_inheritor_child_idx ^ 1 ] ;
new_node - > HostWindow = target_ node- > HostWindow ;
target_ node = new_node ;
DockNodeTreeSplit ( ctx , node, split_axis , split_inheritor_child_idx , split_ratio , payload_node ) ; // payload_node may be NULL here!
ImGuiDockNode * new_node = node- > ChildNodes [ split_inheritor_child_idx ^ 1 ] ;
new_node - > HostWindow = node- > HostWindow ;
node = new_node ;
}
target_ node- > LocalFlags & = ~ ImGuiDockNodeFlags_HiddenTabBar ;
node- > LocalFlags & = ~ ImGuiDockNodeFlags_HiddenTabBar ;
if ( target_ node ! = payload_node )
if ( node ! = payload_node )
{
// Create tab bar before we call DockNodeMoveWindows (which would attempt to move the old tab-bar, which would lead us to payload tabs wrongly appearing before target tabs!)
if ( target_ node- > Windows . Size > 0 & & target_ node- > TabBar = = NULL )
if ( node- > Windows . Size > 0 & & node- > TabBar = = NULL )
{
DockNodeAddTabBar ( target_ node) ;
for ( int n = 0 ; n < target_ node- > Windows . Size ; n + + )
TabBarAddTab ( target_ node- > TabBar , ImGuiTabItemFlags_None , target_ node- > Windows [ n ] ) ;
DockNodeAddTabBar ( node) ;
for ( int n = 0 ; n < node- > Windows . Size ; n + + )
TabBarAddTab ( node- > TabBar , ImGuiTabItemFlags_None , node- > Windows [ n ] ) ;
}
if ( payload_node ! = NULL )
@ -11337,7 +11337,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
// Transfer full payload node (with 1+ child windows or child nodes)
if ( payload_node - > IsSplitNode ( ) )
{
if ( target_ node- > Windows . Size > 0 )
if ( node- > Windows . Size > 0 )
{
// We can dock a split payload into a node that already has windows _only_ if our payload is a node tree with a single visible node.
// In this situation, we move the windows of the target node into the currently visible node of the payload.
@ -11346,28 +11346,28 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
ImGuiDockNode * visible_node = payload_node - > OnlyNodeWithWindows ;
if ( visible_node - > TabBar )
IM_ASSERT ( visible_node - > TabBar - > Tabs . Size > 0 ) ;
DockNodeMoveWindows ( target_ node, visible_node ) ;
DockNodeMoveWindows ( visible_node , target_ node) ;
DockSettingsRenameNodeReferences ( target_ node- > ID , visible_node - > ID ) ;
DockNodeMoveWindows ( node, visible_node ) ;
DockNodeMoveWindows ( visible_node , node) ;
DockSettingsRenameNodeReferences ( node- > ID , visible_node - > ID ) ;
}
if ( target_ node- > IsCentralNode ( ) )
if ( node- > IsCentralNode ( ) )
{
// Central node property needs to be moved to a leaf node, pick the last focused one.
// FIXME-DOCKING: If we had to transfer other flags here, what would the policy be?
ImGuiDockNode * last_focused_node = DockContextFindNodeByID ( ctx , payload_node - > LastFocusedNodeID ) ;
IM_ASSERT ( last_focused_node ! = NULL & & DockNodeGetRootNode ( last_focused_node ) = = DockNodeGetRootNode ( payload_node ) ) ;
last_focused_node - > LocalFlags | = ImGuiDockNodeFlags_CentralNode ;
target_ node- > LocalFlags & = ~ ImGuiDockNodeFlags_CentralNode ;
node- > LocalFlags & = ~ ImGuiDockNodeFlags_CentralNode ;
}
IM_ASSERT ( target_ node- > Windows . Size = = 0 ) ;
DockNodeMoveChildNodes ( target_ node, payload_node ) ;
IM_ASSERT ( node- > Windows . Size = = 0 ) ;
DockNodeMoveChildNodes ( node, payload_node ) ;
}
else
{
const ImGuiID payload_dock_id = payload_node - > ID ;
DockNodeMoveWindows ( target_ node, payload_node ) ;
DockSettingsRenameNodeReferences ( payload_dock_id , target_ node- > ID ) ;
DockNodeMoveWindows ( node, payload_node ) ;
DockSettingsRenameNodeReferences ( payload_dock_id , node- > ID ) ;
}
DockContextRemoveNode ( ctx , payload_node , true ) ;
}
@ -11375,15 +11375,15 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req)
{
// Transfer single window
const ImGuiID payload_dock_id = payload_window - > DockId ;
target_ node- > VisibleWindow = payload_window ;
DockNodeAddWindow ( target_ node, payload_window , true ) ;
node- > VisibleWindow = payload_window ;
DockNodeAddWindow ( node, payload_window , true ) ;
if ( payload_dock_id ! = 0 )
DockSettingsRenameNodeReferences ( payload_dock_id , target_ node- > ID ) ;
DockSettingsRenameNodeReferences ( payload_dock_id , node- > ID ) ;
}
}
// Update selection immediately
if ( ImGuiTabBar * tab_bar = target_ node- > TabBar )
if ( ImGuiTabBar * tab_bar = node- > TabBar )
tab_bar - > NextSelectedTabId = next_selected_id ;
MarkIniSettingsDirty ( ) ;
}
@ -13653,36 +13653,37 @@ void ImGui::BeginAsDockableDragDropTarget(ImGuiWindow* window)
ImGuiWindow * payload_window = * ( ImGuiWindow * * ) payload - > Data ;
if ( AcceptDragDropPayload ( IMGUI_PAYLOAD_TYPE_WINDOW , ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect ) )
{
// Select target node
ImGuiDockNode * node = NULL ;
bool allow_null_target_node = false ;
ImGuiDockNode * target_node = NULL ;
if ( window - > DockNodeAsHost )
target_ node = DockNodeTreeFindNodeByPos ( window - > DockNodeAsHost , g . IO . MousePos ) ;
node = DockNodeTreeFindNodeByPos ( window - > DockNodeAsHost , g . IO . MousePos ) ;
else if ( window - > DockNode ) // && window->DockIsActive)
target_ node = window - > DockNode ;
node = window - > DockNode ;
else
allow_null_target_node = true ; // Dock into a regular window
const ImRect explicit_target_rect = ( target_ node & & target_ node- > TabBar & & ! target_ node- > IsHiddenTabBar ( ) & & ! target_ node- > IsNoTabBar ( ) ) ? target_ node- > TabBar - > BarRect : ImRect ( window - > Pos , window - > Pos + ImVec2 ( window - > Size . x , GetFrameHeight ( ) ) ) ;
const ImRect explicit_target_rect = ( node & & node- > TabBar & & ! node- > IsHiddenTabBar ( ) & & ! node- > IsNoTabBar ( ) ) ? node- > TabBar - > BarRect : ImRect ( window - > Pos , window - > Pos + ImVec2 ( window - > Size . x , GetFrameHeight ( ) ) ) ;
const bool is_explicit_target = g . IO . ConfigDockingWithShift | | IsMouseHoveringRect ( explicit_target_rect . Min , explicit_target_rect . Max ) ;
// Preview docking request and find out split direction/ratio
//const bool do_preview = true; // Ignore testing for payload->IsPreview() which removes one frame of delay, but breaks overlapping drop targets within the same window.
const bool do_preview = payload - > IsPreview ( ) | | payload - > IsDelivery ( ) ;
if ( do_preview & & ( target_ node ! = NULL | | allow_null_target_node ) )
if ( do_preview & & ( node ! = NULL | | allow_null_target_node ) )
{
ImGuiDockPreviewData split_inner , split_outer ;
ImGuiDockPreviewData * split_data = & split_inner ;
if ( target_ node & & ( target_ node- > ParentNode | | target_ node- > IsCentralNode ( ) ) )
if ( ImGuiDockNode * root_node = DockNodeGetRootNode ( target_ node) )
if ( node & & ( node- > ParentNode | | node- > IsCentralNode ( ) ) )
if ( ImGuiDockNode * root_node = DockNodeGetRootNode ( node) )
if ( DockNodePreviewDockCalc ( window , root_node , payload_window , & split_outer , is_explicit_target , true ) )
split_data = & split_outer ;
DockNodePreviewDockCalc ( window , target_ node, payload_window , & split_inner , is_explicit_target , false ) ;
DockNodePreviewDockCalc ( window , node, payload_window , & split_inner , is_explicit_target , false ) ;
if ( split_data = = & split_outer )
split_inner . IsDropAllowed = false ;
// Draw inner then outer, so that previewed tab (in inner data) will be behind the outer drop boxes
DockNodePreviewDockRender ( window , target_ node, payload_window , & split_inner ) ;
DockNodePreviewDockRender ( window , target_ node, payload_window , & split_outer ) ;
DockNodePreviewDockRender ( window , node, payload_window , & split_inner ) ;
DockNodePreviewDockRender ( window , node, payload_window , & split_outer ) ;
// Queue docking request
if ( split_data - > IsDropAllowed & & payload - > IsDelivery ( ) )