fix(dock): use structured drag payload and namespaced property key

This commit is contained in:
2026-03-28 16:58:20 +09:00
parent a409a93a10
commit c1f7f3e14e

View File

@@ -19,7 +19,7 @@ public sealed partial class DockLayout : Control
{ {
private const string PART_ROOT_GRID = "PART_RootGrid"; private const string PART_ROOT_GRID = "PART_RootGrid";
private const string PART_DROP_TARGET_OVERLAY = "PART_DropTargetOverlay"; private const string PART_DROP_TARGET_OVERLAY = "PART_DropTargetOverlay";
private const string DRAG_PROPERTY_DOCK_TAB = "DockTab"; private const string DRAG_PROPERTY_DOCK_TAB = "Ghost.Editor.DockLayout.TabDragPayload";
private const double MIN_PANE_SIZE = 100; private const double MIN_PANE_SIZE = 100;
private const double SPLITTER_THICKNESS = 4; private const double SPLITTER_THICKNESS = 4;
private const double DROP_EDGE_THRESHOLD = 0.25; private const double DROP_EDGE_THRESHOLD = 0.25;
@@ -301,16 +301,26 @@ public sealed partial class DockLayout : Control
private DockPanelNode? _sourceNode; private DockPanelNode? _sourceNode;
private DockPosition _currentDropPosition = DockPosition.None; private DockPosition _currentDropPosition = DockPosition.None;
private record DockDragPayload(object Item, DockPanelNode SourceNode);
private void TabView_TabDragStarting(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDragStartingEventArgs args) private void TabView_TabDragStarting(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDragStartingEventArgs args)
{ {
_draggedItem = args.Item; _draggedItem = args.Item;
_sourceNode = sender.Tag as DockPanelNode; _sourceNode = sender.Tag as DockPanelNode;
args.Data.Properties.Add(DRAG_PROPERTY_DOCK_TAB, _draggedItem); // Identify our drag
if (_draggedItem != null && _sourceNode != null)
{
var payload = new DockDragPayload(_draggedItem, _sourceNode);
args.Data.Properties.Add(DRAG_PROPERTY_DOCK_TAB, payload); // Identify our drag
}
} }
private void TabView_DragOver(object sender, DragEventArgs e) private void TabView_DragOver(object sender, DragEventArgs e)
{ {
if (e.DataView.Properties.ContainsKey(DRAG_PROPERTY_DOCK_TAB) && sender is FrameworkElement targetElement) if (e.DataView.Properties.TryGetValue(DRAG_PROPERTY_DOCK_TAB, out var payloadObj) &&
payloadObj is DockDragPayload payload &&
payload.Item == _draggedItem &&
sender is FrameworkElement targetElement)
{ {
e.AcceptedOperation = global::Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move; e.AcceptedOperation = global::Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move;
@@ -386,9 +396,11 @@ public sealed partial class DockLayout : Control
{ {
if (_dropTargetOverlay != null) _dropTargetOverlay.Visibility = Visibility.Collapsed; if (_dropTargetOverlay != null) _dropTargetOverlay.Visibility = Visibility.Collapsed;
if (!e.DataView.Properties.TryGetValue(DRAG_PROPERTY_DOCK_TAB, out var payload) || if (!e.DataView.Properties.TryGetValue(DRAG_PROPERTY_DOCK_TAB, out var payloadObj) ||
payload != _draggedItem || payloadObj is not DockDragPayload payload ||
_draggedItem == null || _sourceNode == null || !(sender is FrameworkElement targetElement) || !(targetElement.Tag is DockPanelNode targetNode)) payload.Item != _draggedItem ||
!(sender is FrameworkElement targetElement) ||
!(targetElement.Tag is DockPanelNode targetNode))
{ {
ClearDragOperationState(); ClearDragOperationState();
return; return;
@@ -400,7 +412,7 @@ public sealed partial class DockLayout : Control
return; return;
} }
if (_sourceNode == targetNode && _currentDropPosition == DockPosition.Center) if (payload.SourceNode == targetNode && _currentDropPosition == DockPosition.Center)
{ {
ClearDragOperationState(); ClearDragOperationState();
return; // Reordering within same tab is handled natively by TabView return; // Reordering within same tab is handled natively by TabView
@@ -413,9 +425,9 @@ public sealed partial class DockLayout : Control
} }
// 1. Execute mutation // 1. Execute mutation
if (DockMutationEngine.TryApplyDropMutation(Root, targetNode, _sourceNode, _draggedItem, _currentDropPosition)) if (DockMutationEngine.TryApplyDropMutation(Root, targetNode, payload.SourceNode, payload.Item, _currentDropPosition))
{ {
DockMutationEngine.CleanupEmptyNodes(_sourceNode); DockMutationEngine.CleanupEmptyNodes(payload.SourceNode);
} }
ClearDragOperationState(); ClearDragOperationState();
@@ -441,6 +453,10 @@ public sealed partial class DockLayout : Control
Logger.LogWarning($"Tab tear-off failed: {result.Message}"); Logger.LogWarning($"Tab tear-off failed: {result.Message}");
} }
} }
else
{
Logger.LogWarning($"TabDroppedOutside: Item {args.Item} not found in source node {sourceNode}.");
}
} }
} }
finally finally