feat(ui): ghost-window drag infrastructure for task rows
Add the borderless, transparent, topmost, click-through DragGhostWindow that hosts a tilted (~-6deg) translucent snapshot of the dragged row, a TaskDragController that owns its lifecycle (snapshot -> show -> follow -> close), and a pure DPI-aware DragHitTest helper (unit-tested) for the cross-window screen hit test. Adds the TaskRowViewModel.IsDragging flag and the 'grabbed' Border.task-row.dragging style (lift + scale + lower opacity + shadow). Not yet wired into the drag source.
This commit is contained in:
44
tests/ClaudeDo.Ui.Tests/DragHitTestTests.cs
Normal file
44
tests/ClaudeDo.Ui.Tests/DragHitTestTests.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Avalonia;
|
||||
using ClaudeDo.Ui.Views.Controls;
|
||||
using Xunit;
|
||||
|
||||
namespace ClaudeDo.Ui.Tests;
|
||||
|
||||
public class DragHitTestTests
|
||||
{
|
||||
[Fact]
|
||||
public void Cursor_inside_window_rect_is_contained()
|
||||
{
|
||||
var pos = new PixelPoint(100, 100);
|
||||
var client = new Size(800, 600);
|
||||
Assert.True(DragHitTest.WindowContains(pos, client, 1.0, new PixelPoint(500, 400)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Cursor_outside_window_rect_is_not_contained()
|
||||
{
|
||||
var pos = new PixelPoint(100, 100);
|
||||
var client = new Size(800, 600);
|
||||
Assert.False(DragHitTest.WindowContains(pos, client, 1.0, new PixelPoint(50, 50))); // above-left
|
||||
Assert.False(DragHitTest.WindowContains(pos, client, 1.0, new PixelPoint(950, 400))); // past right edge
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Top_left_is_inclusive_bottom_right_is_exclusive()
|
||||
{
|
||||
var pos = new PixelPoint(100, 100);
|
||||
var client = new Size(800, 600);
|
||||
Assert.True(DragHitTest.WindowContains(pos, client, 1.0, new PixelPoint(100, 100))); // top-left corner
|
||||
Assert.False(DragHitTest.WindowContains(pos, client, 1.0, new PixelPoint(900, 700))); // bottom-right corner
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Scaling_expands_the_physical_rect()
|
||||
{
|
||||
var pos = new PixelPoint(100, 100);
|
||||
var client = new Size(800, 600); // logical
|
||||
// At 2x the right edge is 100 + 1600 = 1700, so a point at x=1600 now falls inside.
|
||||
Assert.False(DragHitTest.WindowContains(pos, client, 1.0, new PixelPoint(1600, 400)));
|
||||
Assert.True(DragHitTest.WindowContains(pos, client, 2.0, new PixelPoint(1600, 400)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user