diff --git a/src/Editor/Ghost.Editor.Core/Controls/Internal/Docking/DockMath.cs b/src/Editor/Ghost.Editor.Core/Controls/Internal/Docking/DockMath.cs
index 6d87c55..ad49763 100644
--- a/src/Editor/Ghost.Editor.Core/Controls/Internal/Docking/DockMath.cs
+++ b/src/Editor/Ghost.Editor.Core/Controls/Internal/Docking/DockMath.cs
@@ -3,7 +3,7 @@ namespace Ghost.Editor.Core.Controls.Internal.Docking;
///
/// Defines the possible dock positions for a drop operation.
///
-public enum DockPosition
+internal enum DockPosition
{
Center,
Top,
@@ -16,7 +16,7 @@ public enum DockPosition
///
/// Helper class for docking-related calculations.
///
-public static class DockMath
+internal static class DockMath
{
///
/// Calculates the dock position based on the relative position within a target element.
@@ -24,6 +24,12 @@ public static class DockMath
///
public static DockPosition CalculateDockPosition(double width, double height, double x, double y, double threshold)
{
+ // Guard against invalid inputs
+ if (width <= 0 || height <= 0) return DockPosition.None;
+
+ // Clamp threshold to valid range [0, 0.5]
+ threshold = Math.Max(0, Math.Min(0.5, threshold));
+
if (x < width * threshold) return DockPosition.Left;
if (x > width * (1 - threshold)) return DockPosition.Right;
if (y < height * threshold) return DockPosition.Top;
diff --git a/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs b/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs
index 94572db..99934da 100644
--- a/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs
+++ b/src/Editor/Ghost.Editor/View/Controls/DockLayout.cs
@@ -324,16 +324,21 @@ public sealed partial class DockLayout : Control
private void TabView_DragLeave(object sender, DragEventArgs e)
{
- ClearDragState();
+ ClearOverlayState();
}
- private void ClearDragState()
+ private void ClearOverlayState()
{
if (_dropTargetOverlay != null)
{
_dropTargetOverlay.Visibility = Visibility.Collapsed;
}
_currentDropPosition = DockPosition.None;
+ }
+
+ private void ClearDragOperationState()
+ {
+ ClearOverlayState();
_draggedItem = null;
_sourceNode = null;
}
@@ -374,10 +379,9 @@ public sealed partial class DockLayout : Control
}
}
- // Add a dummy TabView_Drop method so it compiles, we will implement it in Task 6
private void TabView_Drop(object sender, DragEventArgs e)
{
- ClearDragState();
+ ClearDragOperationState();
}
protected override void OnApplyTemplate()
diff --git a/src/Test/Ghost.UnitTest/DockLayoutTest.cs b/src/Test/Ghost.UnitTest/DockLayoutTest.cs
index ab39bc3..f8f249c 100644
--- a/src/Test/Ghost.UnitTest/DockLayoutTest.cs
+++ b/src/Test/Ghost.UnitTest/DockLayoutTest.cs
@@ -59,4 +59,48 @@ public class DockLayoutTest
var pos = DockMath.CalculateDockPosition(100, 100, 90, 90, THRESHOLD);
Assert.AreEqual(DockPosition.Right, pos);
}
+
+ [TestMethod]
+ public void TestCalculateDockPosition_Boundary_Left()
+ {
+ // x = 25 is exactly on the threshold. Current logic: x < 25 is Left, so 25 is Center.
+ var pos = DockMath.CalculateDockPosition(100, 100, 25, 50, THRESHOLD);
+ Assert.AreEqual(DockPosition.Center, pos);
+
+ pos = DockMath.CalculateDockPosition(100, 100, 24.9, 50, THRESHOLD);
+ Assert.AreEqual(DockPosition.Left, pos);
+ }
+
+ [TestMethod]
+ public void TestCalculateDockPosition_Boundary_Right()
+ {
+ // x = 75 is exactly on the threshold (100 * (1 - 0.25)). Current logic: x > 75 is Right, so 75 is Center.
+ var pos = DockMath.CalculateDockPosition(100, 100, 75, 50, THRESHOLD);
+ Assert.AreEqual(DockPosition.Center, pos);
+
+ pos = DockMath.CalculateDockPosition(100, 100, 75.1, 50, THRESHOLD);
+ Assert.AreEqual(DockPosition.Right, pos);
+ }
+
+ [TestMethod]
+ public void TestCalculateDockPosition_InvalidSize()
+ {
+ var pos = DockMath.CalculateDockPosition(0, 100, 50, 50, THRESHOLD);
+ Assert.AreEqual(DockPosition.None, pos);
+
+ pos = DockMath.CalculateDockPosition(100, -10, 50, 50, THRESHOLD);
+ Assert.AreEqual(DockPosition.None, pos);
+ }
+
+ [TestMethod]
+ public void TestCalculateDockPosition_ThresholdClamping()
+ {
+ // Threshold > 0.5 should be clamped to 0.5
+ var pos = DockMath.CalculateDockPosition(100, 100, 40, 50, 0.8);
+ Assert.AreEqual(DockPosition.Left, pos);
+
+ // Threshold < 0 should be clamped to 0
+ pos = DockMath.CalculateDockPosition(100, 100, 0.1, 50, -0.1);
+ Assert.AreEqual(DockPosition.Center, pos);
+ }
}