using Blacklight.Core.Cameras; using Azimuth; namespace Blacklight.Core.UnitTests.Cameras { public class MicroscopeControllerTests : UnitTestSharp.TestFixture { public class RecordingWindowHandle : NullWindowHandle { public int SubmitCount = 0; public int TranslateCount = 0; public Vector LastTranslatePS = Vector.Zero; public int ZoomCount = 0; public Scalar LastZoomFactor = 1; public Vector LastZoomCenterPS = Vector.Zero; public RecordingWindowHandle() { TranslatedPS += delegate(Vector deltaPS) { LastTranslatePS = deltaPS; TranslateCount++; }; Zoomed += delegate(Scalar factor, Vector centerPS) { LastZoomFactor = factor; LastZoomCenterPS = centerPS; ZoomCount++; }; } public override void SubmitDrawCalls() { SubmitCount++; } } public static (MicroscopeController, RecordingWindowHandle) MakeBound() { var handle = new RecordingWindowHandle(); handle.Resize(800, 600); var controller = new MicroscopeController(); controller.Handle = handle; return (controller, handle); } public class CtorTests : UnitTestSharp.TestFixture { public void DefaultsToEnabled() { Check(new MicroscopeController().Enabled); } public void CreatesOptions() { CheckNotNull(new MicroscopeController().Options); } } public class BeginDragTests : UnitTestSharp.TestFixture { public void ReAnchorsDragOrigin() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.Drag(new Vector(10, 10)); controller.BeginDrag(new Vector(100, 100)); controller.Drag(new Vector(110, 110)); CheckEqual(new Vector(10, -10), handle.LastTranslatePS); } } public class DragTests : UnitTestSharp.TestFixture { public void TranslatesByPixelDeltaFlippingY() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(10, 10)); controller.Drag(new Vector(30, 25)); CheckEqual(new Vector(20, -15), handle.LastTranslatePS); } public void AccumulatesAcrossMoves() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.Drag(new Vector(10, 0)); controller.Drag(new Vector(25, 0)); CheckEqual(new Vector(15, 0), handle.LastTranslatePS); CheckEqual(2, handle.TranslateCount); } public void DoesNothingBeforeBeginDrag() { var (controller, handle) = MakeBound(); controller.Drag(new Vector(10, 10)); CheckEqual(0, handle.TranslateCount); } public void SubmitsDrawCalls() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.Drag(new Vector(5, 5)); CheckGreater(handle.SubmitCount, 0); } public void NoOpsWhenHandleNull() { var controller = new MicroscopeController(); controller.BeginDrag(new Vector(0, 0)); controller.Drag(new Vector(10, 10)); } } public class EndDragTests : UnitTestSharp.TestFixture { public void StopsTranslating() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.EndDrag(); controller.Drag(new Vector(10, 10)); CheckEqual(0, handle.TranslateCount); } } public class ZoomTests : UnitTestSharp.TestFixture { public void DefaultsToOne() { CheckEqual(1.0, (double)new MicroscopeController().Zoom); } public void SetterAppliesToHandleAtCenter() { var (controller, handle) = MakeBound(); controller.Zoom = 2.0; CheckEqual(1, handle.ZoomCount); CheckEqual(Vector.Zero, handle.LastZoomCenterPS); } } public class ZoomInOnceTests : UnitTestSharp.TestFixture { public void RaisesMagnification() { var (controller, handle) = MakeBound(); controller.ZoomInOnce(); CheckGreater((double)handle.LastZoomFactor, 1.0); } public void ZoomsAroundCenter() { var (controller, handle) = MakeBound(); controller.ZoomInOnce(); CheckEqual(Vector.Zero, handle.LastZoomCenterPS); } public void SubmitsDrawCalls() { var (controller, handle) = MakeBound(); controller.ZoomInOnce(); CheckGreater(handle.SubmitCount, 0); } public void AppliesEvenWhenDisabled() { var (controller, handle) = MakeBound(); controller.Enabled = false; controller.ZoomInOnce(); CheckEqual(1, handle.ZoomCount); } } public class ZoomOutOnceTests : UnitTestSharp.TestFixture { public void LowersMagnification() { var (controller, handle) = MakeBound(); controller.ZoomOutOnce(); CheckLess((double)handle.LastZoomFactor, 1.0); } } public class ZoomByTicksTests : UnitTestSharp.TestFixture { public void ConvertsPixelToCenteredProjectionSpace() { var (controller, handle) = MakeBound(); controller.ZoomByTicks(120, new Vector(600, 150)); CheckEqual(new Vector(200, 150), handle.LastZoomCenterPS); } public void ZoomsAroundOriginWhenZoomAroundMouseDisabled() { var (controller, handle) = MakeBound(); controller.Options.ZoomAroundMousePS = false; controller.ZoomByTicks(120, new Vector(600, 150)); CheckEqual(Vector.Zero, handle.LastZoomCenterPS); } public void PositiveTicksRaiseMagnification() { var (controller, handle) = MakeBound(); controller.ZoomByTicks(120, new Vector(400, 300)); CheckGreater((double)handle.LastZoomFactor, 1.0); } public void SpinDirectionFlipsSign() { var (controller, handle) = MakeBound(); controller.Options.SpinMouseWheelForwardToZoom = false; controller.ZoomByTicks(120, new Vector(400, 300)); CheckLess((double)handle.LastZoomFactor, 1.0); } public void NoOpsWhenHandleNull() { var controller = new MicroscopeController(); controller.ZoomByTicks(120, new Vector(10, 10)); } } public class PointerDownTests : UnitTestSharp.TestFixture { public void EnabledAndMatchingButtonBeginsDrag() { var (controller, handle) = MakeBound(); controller.PointerDown(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(new Vector(20, -15), handle.LastTranslatePS); } public void NonMatchingButtonDoesNotBeginDrag() { var (controller, handle) = MakeBound(); controller.PointerDown(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Right }); controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Right }); CheckEqual(0, handle.TranslateCount); } public void DisabledDoesNotBeginDrag() { var (controller, handle) = MakeBound(); controller.Enabled = false; controller.PointerDown(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); controller.Enabled = true; controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void InterceptorReturningTrueSkipsBeginDrag() { var (controller, handle) = MakeBound(); controller.PointerPressed = input => true; controller.PointerDown(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void InterceptorReturningFalseStillBeginsDrag() { var (controller, handle) = MakeBound(); controller.PointerPressed = input => false; controller.PointerDown(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(new Vector(20, -15), handle.LastTranslatePS); } public void PassesInputToInterceptor() { var (controller, _) = MakeBound(); PointerInput? captured = null; controller.PointerPressed = input => { captured = input; return true; }; controller.PointerDown(new PointerInput { PixelPos = new Vector(12, 34), Buttons = PointerButtons.Right }); CheckEqual(new Vector(12, 34), captured.Value.PixelPos); CheckEqual(PointerButtons.Right, captured.Value.Buttons); } } public class PointerMoveTests : UnitTestSharp.TestFixture { public void EnabledAndDraggingTranslates() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(10, 10)); controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(new Vector(20, -15), handle.LastTranslatePS); } public void NotDraggingDoesNotTranslate() { var (controller, handle) = MakeBound(); controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void DisabledDoesNotTranslate() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(10, 10)); controller.Enabled = false; controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void InterceptorReturningTrueSkipsTranslate() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(10, 10)); controller.PointerMoved = input => true; controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void InterceptorReturningFalseStillTranslates() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(10, 10)); controller.PointerMoved = input => false; controller.PointerMove(new PointerInput { PixelPos = new Vector(30, 25), Buttons = PointerButtons.Left }); CheckEqual(new Vector(20, -15), handle.LastTranslatePS); } public void PassesInputToInterceptor() { var (controller, _) = MakeBound(); PointerInput? captured = null; controller.PointerMoved = input => { captured = input; return true; }; controller.PointerMove( new PointerInput { PixelPos = new Vector(1, 2), Buttons = PointerButtons.Left | PointerButtons.Right }); CheckEqual(new Vector(1, 2), captured.Value.PixelPos); CheckEqual(PointerButtons.Left | PointerButtons.Right, captured.Value.Buttons); } } public class PointerUpTests : UnitTestSharp.TestFixture { public void MatchingButtonEndsDrag() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.PointerUp(new PointerInput { PixelPos = new Vector(0, 0), Buttons = PointerButtons.Left }); controller.PointerMove(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void NonMatchingButtonDoesNotEndDrag() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.PointerUp(new PointerInput { PixelPos = new Vector(0, 0), Buttons = PointerButtons.Right }); controller.PointerMove(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); CheckEqual(1, handle.TranslateCount); } public void EndsDragEvenWhenControllerDisabled() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.Enabled = false; controller.PointerUp(new PointerInput { PixelPos = new Vector(0, 0), Buttons = PointerButtons.Left }); controller.Enabled = true; controller.PointerMove(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void InterceptorReturningTrueSkipsEndDrag() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.PointerReleased = input => true; controller.PointerUp(new PointerInput { PixelPos = new Vector(0, 0), Buttons = PointerButtons.Left }); controller.PointerMove(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); CheckEqual(1, handle.TranslateCount); } public void InterceptorReturningFalseStillEndsDrag() { var (controller, handle) = MakeBound(); controller.BeginDrag(new Vector(0, 0)); controller.PointerReleased = input => false; controller.PointerUp(new PointerInput { PixelPos = new Vector(0, 0), Buttons = PointerButtons.Left }); controller.PointerMove(new PointerInput { PixelPos = new Vector(10, 10), Buttons = PointerButtons.Left }); CheckEqual(0, handle.TranslateCount); } public void PassesInputToInterceptor() { var (controller, _) = MakeBound(); PointerInput? captured = null; controller.PointerReleased = input => { captured = input; return true; }; controller.PointerUp(new PointerInput { PixelPos = new Vector(12, 34), Buttons = PointerButtons.Right }); CheckEqual(new Vector(12, 34), captured.Value.PixelPos); CheckEqual(PointerButtons.Right, captured.Value.Buttons); } } public class WheelTests : UnitTestSharp.TestFixture { public void EnabledZoomsAroundPointerPosition() { var (controller, handle) = MakeBound(); controller.Wheel(120, new Vector(600, 150)); CheckEqual(1, handle.ZoomCount); CheckEqual(new Vector(200, 150), handle.LastZoomCenterPS); } public void DisabledDoesNotZoom() { var (controller, handle) = MakeBound(); controller.Enabled = false; controller.Wheel(120, new Vector(600, 150)); CheckEqual(0, handle.ZoomCount); } } public class KeyDownTests : UnitTestSharp.TestFixture { public void ZoomInKeyRaisesMagnification() { var (controller, handle) = MakeBound(); controller.KeyDown(Key.PageUp); CheckGreater((double)handle.LastZoomFactor, 1.0); } public void ZoomOutKeyLowersMagnification() { var (controller, handle) = MakeBound(); controller.KeyDown(Key.PageDown); CheckLess((double)handle.LastZoomFactor, 1.0); } public void DisabledDoesNotZoom() { var (controller, handle) = MakeBound(); controller.Enabled = false; controller.KeyDown(Key.PageUp); CheckEqual(0, handle.ZoomCount); } public void ReadsBindingsFromOptionsRatherThanHardcodedKeys() { var (controller, handle) = MakeBound(); controller.Options.ZoomInKey = Key.PageDown; controller.KeyDown(Key.PageDown); CheckGreater((double)handle.LastZoomFactor, 1.0); } public void NeitherBoundKeyDoesNothing() { var (controller, handle) = MakeBound(); controller.Options.ZoomInKey = Key.PageDown; controller.Options.ZoomOutKey = Key.PageDown; controller.KeyDown(Key.PageUp); CheckEqual(0, handle.ZoomCount); } } public class KeyUpTests : UnitTestSharp.TestFixture { public void IsANoOp() { var (controller, handle) = MakeBound(); controller.KeyUp(Key.PageUp); CheckEqual(0, handle.ZoomCount); } } } }