using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnitTestSharp; using Azimuth; using System.ComponentModel; namespace Glass.UnitTests { public class MouseManagerTests : TestFixture { public class MouseDownTests : TestFixture { public void Empty() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var lockedControl = manager.MouseDown(state, MouseButtonFlags.Left); CheckNull(lockedControl); } public void ClickOnChildLocksChild() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var control = new Button(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); var lockedControl = manager.MouseDown(state, MouseButtonFlags.Left); CheckEqual(control, lockedControl); } public void NotClickingOnChildDoesNotLockChild() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(10, 10), }; var control = new Button(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); var lockedControl = manager.MouseDown(state, MouseButtonFlags.Left); CheckNull(lockedControl); } public void CallsCallbackOnClickedChild() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var control = new Button(); bool called = false; control.OnMouseDown = (in MouseState _state, MouseButtonFlags _button) => { CheckEqual(state, _state); CheckEqual(MouseButtonFlags.Left, _button); called = true; }; control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); manager.MouseDown(state, MouseButtonFlags.Left); Check(called); } public void LeafControlsHavePriority() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var parent = new Button(); parent.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(parent); var child = new Button(); child.Bounds = Rect.FromTwoPoints(Vector.Zero, new Vector(4, 5)); parent.ChildControls.Add(child); var lockedControl = manager.MouseDown(state, MouseButtonFlags.Left); CheckEqual(child, lockedControl); } public void DetectsCycles() { var manager = new MouseManager(); var parent = new Button(); manager.Controls.Add(parent); var child = new Button(); parent.ChildControls.Add(child); child.ChildControls.Add(parent); CheckThrow(typeof(InvalidOperationException)); manager.MouseDown(new MouseState(), MouseButtonFlags.Left); } public void DetectsDuplicateControls() { var manager = new MouseManager(); var parent = new Button { DebugName = "parent" }; manager.Controls.Add(parent); var child = new Button { DebugName = "child" }; parent.ChildControls.Add(child); parent.ChildControls.Add(child); CheckThrow(typeof(InvalidOperationException)); manager.MouseDown(new MouseState(), MouseButtonFlags.Left); } public void DetectsRecursiveCalls() { var manager = new MouseManager(); var parent = new Button { DebugName = "parent" }; parent.OnMouseDown = (in MouseState _state, MouseButtonFlags _button) => { manager.MouseDown(_state, _button); }; manager.Controls.Add(parent); CheckThrow(typeof(InvalidOperationException)); manager.MouseDown(new MouseState(), MouseButtonFlags.Left); } } public class MouseUpTests : TestFixture { public void Empty() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var lockedControl = manager.MouseUp(state, MouseButtonFlags.Left); CheckNull(lockedControl); } public void ClickOnChildControl() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var control = new Control(); control.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { }; control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); var lockedControl = manager.MouseUp(state, MouseButtonFlags.Left); CheckEqual(control, lockedControl); } public void ClickOutsideChildControl() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(6, 6), }; var control = new Control(); control.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { }; control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); var lockedControl = manager.MouseUp(state, MouseButtonFlags.Left); CheckNull(lockedControl); } public void CallsCallbackOnClickedChild() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var control = new Control(); bool called = false; control.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { CheckEqual(state, _state); CheckEqual(MouseButtonFlags.Left, _button); called = true; }; control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); manager.MouseUp(state, MouseButtonFlags.Left); Check(called); } public void LeafControlsHavePriority() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var parent = new Control(); parent.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { }; parent.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(parent); var child = new Control(); child.Bounds = Rect.FromTwoPoints(Vector.Zero, new Vector(4, 5)); child.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { }; parent.ChildControls.Add(child); var lockedControl = manager.MouseUp(state, MouseButtonFlags.Left); CheckEqual(child, lockedControl); } public void CallsLockedControlEvenIfNotOver() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(0, 0), }; var control = new Control(); control.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { }; control.OnMouseDown = (in MouseState _state, MouseButtonFlags _button) => { }; control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); var lockedControl = manager.MouseDown(state, MouseButtonFlags.Left); CheckEqual(control, lockedControl); var newState = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(6, 6), }; lockedControl = manager.MouseUp(newState, MouseButtonFlags.Left); CheckEqual(control, lockedControl); } public class TestControl : Control { public int callCount = 0; public override bool MouseUp(in MouseState state, MouseButtonFlags button) { ++callCount; return false; } } public void WillNotCallLockedChildTwice() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(0, 0), }; var control = new Control("parent"); control.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { }; control.OnMouseDown = (in MouseState _state, MouseButtonFlags _button) => { }; control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); manager.Controls.Add(control); var child = new TestControl { DebugName = "child", }; child.OnMouseDown = (in MouseState _state, MouseButtonFlags _button) => { }; child.Bounds = Rect.FromTwoPoints(new Vector(-2, -2), new Vector(2, 2)); control.ChildControls.Add(child); manager.MouseDown(state, MouseButtonFlags.Left); var respondingControl = manager.MouseUp(state, MouseButtonFlags.Left); CheckEqual(1, child.callCount); CheckEqual(control, respondingControl); } public void DetectsCycles() { var manager = new MouseManager(); var parent = new Button(); manager.Controls.Add(parent); var child = new Button(); parent.ChildControls.Add(child); child.ChildControls.Add(parent); CheckThrow(typeof(InvalidOperationException)); manager.MouseUp(new MouseState(), MouseButtonFlags.Left); } public void DetectsDuplicateControls() { var manager = new MouseManager(); var parent = new Button { DebugName = "parent" }; manager.Controls.Add(parent); var child = new Button { DebugName = "child" }; parent.ChildControls.Add(child); parent.ChildControls.Add(child); CheckThrow(typeof(InvalidOperationException)); manager.MouseUp(new MouseState(), MouseButtonFlags.Left); } public void DetectsRecursiveCalls() { var manager = new MouseManager(); var parent = new Button { DebugName = "parent" }; parent.OnMouseUp = (in MouseState _state, MouseButtonFlags _button) => { manager.MouseUp(_state, _button); }; manager.Controls.Add(parent); CheckThrow(typeof(InvalidOperationException)); manager.MouseUp(new MouseState(), MouseButtonFlags.Left); } } public class MouseMoveTests : TestFixture { public void Empty() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var lockedControl = manager.MouseMove(state); CheckNull(lockedControl); } public void MoveOnChildLocksChild() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(3, 4), }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); control.OnMouseMove = (in MouseState _state) => { }; manager.Controls.Add(control); var lockedControl = manager.MouseMove(state); CheckEqual(control, lockedControl); } public void MoveNotOnChildDoesNotLockOrCallChild() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(6, 6), }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); bool called = false; control.OnMouseMove = (in MouseState _state) => called = true; manager.Controls.Add(control); var lockedControl = manager.MouseMove(state); CheckNull(lockedControl); CheckFalse(called); } public void CallsCallbackOnLockedControl() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); bool called = false; control.OnMouseMove = (in MouseState _state) => { called = true; CheckEqual(state, _state); }; manager.Controls.Add(control); var lockedControl = manager.MouseMove(state); CheckEqual(control, lockedControl); Check(called); } public void LeafControlsHavePriority() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); bool calledParent = false; control.OnMouseMove = (in MouseState _state) => { calledParent = true; CheckEqual(state, _state); }; manager.Controls.Add(control); var child = new Control(); child.Bounds = Rect.FromTwoPoints(new Vector(-1, -1), new Vector(1, 1)); bool calledChild = false; child.OnMouseMove = (in MouseState _state) => { calledChild = true; CheckEqual(state, _state); }; control.ChildControls.Add(child); var lockedControl = manager.MouseMove(state); Check(calledChild); CheckFalse(calledParent); CheckEqual(child, lockedControl); } public void CallsMouseMoveStartOnLockingControlAndNotMouseMove() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); bool calledMove = false; control.OnMouseMove = (in MouseState _state) => { calledMove = true; }; bool calledStart = false; control.OnMouseMoveStart = (in MouseState _state) => { calledStart = true; CheckEqual(state, _state); }; manager.Controls.Add(control); var lockedControl = manager.MouseMove(state); CheckEqual(control, lockedControl); CheckFalse(calledMove); Check(calledStart); } public void CallsMouseMoveEndOnMoveOutsideControl() { var manager = new MouseManager(); var stateIn = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var stateOut = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(10, 10), }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); control.OnMouseMove = (in MouseState _state) => { }; bool calledEnd = false; control.OnMouseMoveEnd = (in MouseState _state) => { calledEnd = true; CheckEqual(stateOut, _state); }; manager.Controls.Add(control); var lockedControl = manager.MouseMove(stateIn); lockedControl = manager.MouseMove(stateOut); CheckNull(lockedControl); Check(calledEnd); } public void CallsMouseMoveWhenNoMouseMoveEndAndMovesOutsideControl() { var manager = new MouseManager(); var stateIn = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var stateOut = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(10, 10), }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); control.OnMouseMove = (in MouseState _state) => { }; bool calledEnd = false; bool testing = false; control.OnMouseMove = (in MouseState _state) => { calledEnd = true; if (testing) { CheckEqual(stateOut, _state); } }; manager.Controls.Add(control); var lockedControl = manager.MouseMove(stateIn); calledEnd = false; testing = true; lockedControl = manager.MouseMove(stateOut); CheckNull(lockedControl); Check(calledEnd); } public void UnlocksControlWhenMouseMoveReturnsFalse() { var manager = new MouseManager(); var stateIn = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var control = new Control(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); control.OnMouseMove = (in MouseState _state) => { }; bool calledEnd = false; control.OnMouseMoveEnd = (in MouseState _state) => { calledEnd = true; }; control.OnMouseMove = (in MouseState _state) => { }; manager.Controls.Add(control); manager.MouseMove(stateIn); control.OnMouseMove = null; calledEnd = false; var lockedControl = manager.MouseMove(stateIn); CheckNull(lockedControl); Check(calledEnd); } public void CallsMouseMoveOnClickLockedControlsWhenInside() { var manager = new MouseManager(); var state = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var control = new Button(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); bool moved = false; control.OnMouseMove = (in MouseState _state) => { CheckEqual(state, _state); moved = true; }; manager.Controls.Add(control); var clickLocked = manager.MouseDown(state, MouseButtonFlags.Left); var moveLocked = manager.MouseMove(state); CheckEqual(control, clickLocked); CheckEqual(control, moveLocked); Check(moved); } public void CallsMouseMoveOnClickLockedControlsWhenOutside() { var manager = new MouseManager(); var stateIn = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var stateOut = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(10, 10), }; var control = new Button(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); int count = 0; control.OnMouseMove = (in MouseState _state) => { CheckEqual(stateOut, _state); ++count; }; manager.Controls.Add(control); var clickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Left); var moveLocked = manager.MouseMove(stateOut); CheckEqual(control, clickLocked); CheckNull(moveLocked); CheckEqual(1, count); } public void CallsMouseMoveOnClickLockedControlsOnlyOnce_Inside() { var manager = new MouseManager(); var stateIn = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var control = new Button(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); int count = 0; control.OnMouseMove = (in MouseState _state) => ++count; manager.Controls.Add(control); var leftClickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Left); var middleClickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Middle); var rightClickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Right); var moveLocked = manager.MouseMove(stateIn); CheckEqual(control, leftClickLocked); CheckEqual(control, middleClickLocked); CheckEqual(control, rightClickLocked); CheckEqual(control, moveLocked); CheckEqual(1, count); } public void CallsMouseMoveOnClickLockedControlsOnlyOnce_Outside() { var manager = new MouseManager(); var stateIn = new MouseState { Buttons = MouseButtonFlags.Left, Position = Vector.Zero, }; var stateOut = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(10, 10), }; var control = new Button(); control.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(5, 5)); int count = 0; control.OnMouseMove = (in MouseState _state) => ++count; manager.Controls.Add(control); var leftClickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Left); var middleClickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Middle); var rightClickLocked = manager.MouseDown(stateIn, MouseButtonFlags.Right); var moveLocked = manager.MouseMove(stateOut); CheckEqual(control, leftClickLocked); CheckEqual(control, middleClickLocked); CheckEqual(control, rightClickLocked); CheckNull(moveLocked); CheckEqual(1, count); } public void ReplacedMouseLockControlHasMouseEndCalledOnIt() { var manager = new MouseManager(); var state1 = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(2, 2), }; var state2 = new MouseState { Buttons = MouseButtonFlags.Left, Position = new Vector(-2, -2), }; var control1 = new Control(); control1.Bounds = Rect.FromTwoPoints(new Vector(0, 0), new Vector(5, 5)); bool calledEnd1 = false; control1.OnMouseMoveEnd = (in MouseState _state) => calledEnd1 = true; control1.OnMouseMove = (in MouseState _state) => { }; manager.Controls.Add(control1); var control2 = new Control(); control2.Bounds = Rect.FromTwoPoints(new Vector(-5, -5), new Vector(0, 0)); bool calledEnd2 = false; control2.OnMouseMoveEnd = (in MouseState _state) => calledEnd2 = true; control2.OnMouseMove = (in MouseState _state) => { }; manager.Controls.Add(control2); var lockedControl1 = manager.MouseMove(state1); var lockedControl2 = manager.MouseMove(state2); CheckEqual(control1, lockedControl1); CheckEqual(control2, lockedControl2); Check(calledEnd1); CheckFalse(calledEnd2); } public void DetectsCycles() { var manager = new MouseManager(); var parent = new Button(); manager.Controls.Add(parent); var child = new Button(); parent.ChildControls.Add(child); child.ChildControls.Add(parent); CheckThrow(typeof(InvalidOperationException)); manager.MouseMove(new MouseState()); } public void DetectsDuplicateControls() { var manager = new MouseManager(); var parent = new Button { DebugName = "parent" }; manager.Controls.Add(parent); var child = new Button { DebugName = "child" }; parent.ChildControls.Add(child); parent.ChildControls.Add(child); CheckThrow(typeof(InvalidOperationException)); manager.MouseMove(new MouseState()); } public void DetectsRecursiveCalls() { var manager = new MouseManager(); var parent = new Button { DebugName = "parent" }; parent.OnMouseMove = (in MouseState _state) => { manager.MouseMove(_state); }; manager.Controls.Add(parent); CheckThrow(typeof(InvalidOperationException)); manager.MouseMove(new MouseState()); } } } }