"Edit cell boxes" mode: the selected cell grows resize handles on the preview -- drag to move/resize with live outline tracking and a re-render on drop, or type exact X/Y/W/H in the new geometry fields. Plain clicks still select and cycle stacked cells (click-vs-drag resolved by a movement threshold on mouse-up). The move/resize math is pure and unit-tested (OverlayRegionEdit: corner/edge/move handle hit-testing with tolerance, min-size clamped resizing that pins the opposite edge). "Save template" persists the shared cell geometry back to the regions.json; "Reload template" re-reads it to discard unsaved box edits. Cursor feedback per handle; template save/reload disabled when no template path was supplied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
70 lines
2.3 KiB
C#
70 lines
2.3 KiB
C#
using RioJoy.Core.Overlay;
|
|
using Xunit;
|
|
|
|
namespace RioJoy.Core.Tests.Overlay;
|
|
|
|
public class OverlayRegionEditTests
|
|
{
|
|
private static OverlayRegion Box() => new() { Name = "r", X = 100, Y = 50, Width = 200, Height = 80 };
|
|
|
|
[Theory]
|
|
[InlineData(100, 50, OverlayBoxHandle.NorthWest)]
|
|
[InlineData(300, 50, OverlayBoxHandle.NorthEast)]
|
|
[InlineData(100, 130, OverlayBoxHandle.SouthWest)]
|
|
[InlineData(300, 130, OverlayBoxHandle.SouthEast)]
|
|
[InlineData(200, 50, OverlayBoxHandle.North)]
|
|
[InlineData(200, 130, OverlayBoxHandle.South)]
|
|
[InlineData(100, 90, OverlayBoxHandle.West)]
|
|
[InlineData(300, 90, OverlayBoxHandle.East)]
|
|
[InlineData(200, 90, OverlayBoxHandle.Move)]
|
|
[InlineData(0, 0, OverlayBoxHandle.None)]
|
|
public void HitHandle_ResolvesEachZone(double x, double y, OverlayBoxHandle expected)
|
|
{
|
|
Assert.Equal(expected, OverlayRegionEdit.HitHandle(Box(), x, y, tolerance: 4));
|
|
}
|
|
|
|
[Fact]
|
|
public void HitHandle_ToleranceExtendsOutsideTheBox()
|
|
{
|
|
Assert.Equal(OverlayBoxHandle.NorthWest, OverlayRegionEdit.HitHandle(Box(), 97, 47, 4));
|
|
Assert.Equal(OverlayBoxHandle.None, OverlayRegionEdit.HitHandle(Box(), 94, 44, 4));
|
|
}
|
|
|
|
[Fact]
|
|
public void Apply_MoveShiftsWithoutResizing()
|
|
{
|
|
var r = OverlayRegionEdit.Apply(100, 50, 200, 80, OverlayBoxHandle.Move, 15, -10);
|
|
|
|
Assert.Equal((115d, 40d, 200d, 80d), r);
|
|
}
|
|
|
|
[Fact]
|
|
public void Apply_EastGrowsWidthOnly()
|
|
{
|
|
var r = OverlayRegionEdit.Apply(100, 50, 200, 80, OverlayBoxHandle.East, 30, 99);
|
|
|
|
Assert.Equal((100d, 50d, 230d, 80d), r);
|
|
}
|
|
|
|
[Fact]
|
|
public void Apply_NorthWestMovesOriginAndResizes()
|
|
{
|
|
var r = OverlayRegionEdit.Apply(100, 50, 200, 80, OverlayBoxHandle.NorthWest, 10, 20);
|
|
|
|
Assert.Equal((110d, 70d, 190d, 60d), r);
|
|
}
|
|
|
|
[Fact]
|
|
public void Apply_ClampsToMinSize_OppositeEdgeStaysPut()
|
|
{
|
|
var r = OverlayRegionEdit.Apply(100, 50, 200, 80, OverlayBoxHandle.West, 500, 0, minSize: 4);
|
|
|
|
Assert.Equal(296, r.X, 6); // right edge (300) minus min width
|
|
Assert.Equal(4, r.Width, 6);
|
|
|
|
var s = OverlayRegionEdit.Apply(100, 50, 200, 80, OverlayBoxHandle.South, 0, -500, minSize: 4);
|
|
Assert.Equal(50, s.Y, 6);
|
|
Assert.Equal(4, s.Height, 6);
|
|
}
|
|
}
|