fix(dock): restore core docking behavior and fix build breaks
This commit is contained in:
@@ -297,6 +297,128 @@ public sealed partial class DockLayout : Control
|
|||||||
return tabView;
|
return tabView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object? _draggedItem;
|
||||||
|
private DockPanelNode? _sourceNode;
|
||||||
|
private DockPosition _currentDropPosition = DockPosition.None;
|
||||||
|
|
||||||
|
private void TabView_TabDragStarting(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDragStartingEventArgs args)
|
||||||
|
{
|
||||||
|
_draggedItem = args.Item;
|
||||||
|
_sourceNode = sender.Tag as DockPanelNode;
|
||||||
|
args.Data.Properties.Add(DRAG_PROPERTY_DOCK_TAB, _draggedItem); // Identify our drag
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TabView_DragOver(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.DataView.Properties.ContainsKey(DRAG_PROPERTY_DOCK_TAB) && sender is FrameworkElement targetElement)
|
||||||
|
{
|
||||||
|
e.AcceptedOperation = global::Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move;
|
||||||
|
|
||||||
|
var position = e.GetPosition(targetElement);
|
||||||
|
var newPosition = DockMath.CalculateDockPosition(targetElement.ActualWidth, targetElement.ActualHeight, position.X, position.Y, DROP_EDGE_THRESHOLD);
|
||||||
|
|
||||||
|
if (newPosition != _currentDropPosition)
|
||||||
|
{
|
||||||
|
_currentDropPosition = newPosition;
|
||||||
|
UpdateDropOverlay(targetElement, _currentDropPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TabView_DragLeave(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
ClearOverlayState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearOverlayState()
|
||||||
|
{
|
||||||
|
if (_dropTargetOverlay != null)
|
||||||
|
{
|
||||||
|
_dropTargetOverlay.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
_currentDropPosition = DockPosition.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearDragOperationState()
|
||||||
|
{
|
||||||
|
ClearOverlayState();
|
||||||
|
_draggedItem = null;
|
||||||
|
_sourceNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateDropOverlay(FrameworkElement targetElement, DockPosition position)
|
||||||
|
{
|
||||||
|
if (_dropTargetOverlay == null) return;
|
||||||
|
if (position == DockPosition.None)
|
||||||
|
{
|
||||||
|
_dropTargetOverlay.Visibility = Visibility.Collapsed;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var transform = targetElement.TransformToVisual(this);
|
||||||
|
var bounds = transform.TransformBounds(new global::Windows.Foundation.Rect(0, 0, targetElement.ActualWidth, targetElement.ActualHeight));
|
||||||
|
|
||||||
|
_dropTargetOverlay.Visibility = Visibility.Visible;
|
||||||
|
_dropTargetOverlay.Width = double.NaN;
|
||||||
|
_dropTargetOverlay.Height = double.NaN;
|
||||||
|
|
||||||
|
switch (position)
|
||||||
|
{
|
||||||
|
case DockPosition.Center:
|
||||||
|
_dropTargetOverlay.Margin = new Thickness(bounds.Left, bounds.Top, ActualWidth - bounds.Right, ActualHeight - bounds.Bottom);
|
||||||
|
break;
|
||||||
|
case DockPosition.Left:
|
||||||
|
_dropTargetOverlay.Margin = new Thickness(bounds.Left, bounds.Top, ActualWidth - (bounds.Left + bounds.Width / 2), ActualHeight - bounds.Bottom);
|
||||||
|
break;
|
||||||
|
case DockPosition.Right:
|
||||||
|
_dropTargetOverlay.Margin = new Thickness(bounds.Left + bounds.Width / 2, bounds.Top, ActualWidth - bounds.Right, ActualHeight - bounds.Bottom);
|
||||||
|
break;
|
||||||
|
case DockPosition.Top:
|
||||||
|
_dropTargetOverlay.Margin = new Thickness(bounds.Left, bounds.Top, ActualWidth - bounds.Right, ActualHeight - (bounds.Top + bounds.Height / 2));
|
||||||
|
break;
|
||||||
|
case DockPosition.Bottom:
|
||||||
|
_dropTargetOverlay.Margin = new Thickness(bounds.Left, bounds.Top + bounds.Height / 2, ActualWidth - bounds.Right, ActualHeight - bounds.Bottom);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TabView_Drop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (_dropTargetOverlay != null) _dropTargetOverlay.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
|
if (_draggedItem == null || _sourceNode == null || !(sender is FrameworkElement targetElement) || !(targetElement.Tag is DockPanelNode targetNode))
|
||||||
|
{
|
||||||
|
ClearDragOperationState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentDropPosition == DockPosition.None)
|
||||||
|
{
|
||||||
|
ClearDragOperationState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sourceNode == targetNode && _currentDropPosition == DockPosition.Center)
|
||||||
|
{
|
||||||
|
ClearDragOperationState();
|
||||||
|
return; // Reordering within same tab is handled natively by TabView
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Root == null)
|
||||||
|
{
|
||||||
|
ClearDragOperationState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Execute mutation
|
||||||
|
if (DockMutationEngine.TryApplyDropMutation(Root, targetNode, _sourceNode, _draggedItem, _currentDropPosition))
|
||||||
|
{
|
||||||
|
DockMutationEngine.CleanupEmptyNodes(_sourceNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearDragOperationState();
|
||||||
|
}
|
||||||
|
|
||||||
private void TabView_TabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args)
|
private void TabView_TabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args)
|
||||||
{
|
{
|
||||||
if (_sourceNode != null && _draggedItem != null)
|
if (_sourceNode != null && _draggedItem != null)
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ internal sealed partial class EngineEditorWindow : WindowEx
|
|||||||
private void OnTabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args)
|
private void OnTabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args)
|
||||||
{
|
{
|
||||||
// For static tabs in EngineEditorWindow, we remove the item from TabItems
|
// For static tabs in EngineEditorWindow, we remove the item from TabItems
|
||||||
if (sender.TabItems.Contains(args.Item))
|
if (sender.TabItems is System.Collections.IList list && list.Contains(args.Item))
|
||||||
{
|
{
|
||||||
var result = TabTearOffService.TryTearOffTab((System.Collections.IList)sender.TabItems, args.Item, sender);
|
var result = TabTearOffService.TryTearOffTab(list, args.Item, sender);
|
||||||
|
|
||||||
if (!result.IsSuccess)
|
if (!result.IsSuccess)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user