public void Dragging_Cancels_OnTimeoutOrInvalidTouch()
        {
            var target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            var child1 = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1)
            };

            target.AddChild(child1);

            var t = new GameTime();

            target.ReportTouch(new TouchLocation(4, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            t.TotalGameTime = TimeSpan.FromSeconds(target.FlickThreshholdSeconds);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Moved, new Vector2(6f, 4f)), t);
            target.ResolveGestures(t);
            child1.AssertLast(3, "OnDrag({X:5 Y:3} , {X:2 Y:0})");

            t.TotalGameTime = TimeSpan.FromSeconds(100);
            target.ResolveGestures(t);
            child1.AssertLast(4, "OnDragCancel");
        }
        public void QuickLongDrag_CausesFlick()
        {
            var target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            var child1 = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1)
            };

            target.AddChild(child1);

            var t = new GameTime();

            target.ReportTouch(new TouchLocation(4, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Released, new Vector2(6f, 4f)), t);
            target.ResolveGestures(t);
            child1.AssertLast(3, "OnFlick({X:3 Y:3} , {X:2 Y:0})");

            // Again with a move
            target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            child1 = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1)
            };
            target.AddChild(child1);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Moved, new Vector2(6f, 4f)), t);
            target.ResolveGestures(t);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Released, new Vector2(6f, 4.5f)), t);
            target.ResolveGestures(t);
            Assert.AreEqual("OnDrag({X:5 Y:3} , {X:2 Y:0})", child1.Calls[2]); // Should also have a drag
            child1.AssertLast(4, "OnFlick({X:3 Y:3} , {X:2 Y:0.5})");
        }
        public void TouchSingleDownUp_GeneratesTap_AfterDoubleTapTimeout()
        {
            var target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            var child = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1)
            };

            target.AddChild(child);

            var t = new GameTime();

            target.ReportTouch(new TouchLocation(5, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Released, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            child.AssertLast(2, "OnTouchUp(5:{X:3 Y:3})");

            t.TotalGameTime = TimeSpan.FromSeconds(target.DoubleTapIntervalSeconds);
            target.ResolveGestures(t);
            child.AssertLast(3, "OnTap({X:3 Y:3})");

            // an immediate second tap should not generate more onTap calls
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            child.AssertLast(4, "OnTouchDown(5:{X:3 Y:3})");
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Released, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            child.AssertLast(5, "OnTouchUp(5:{X:3 Y:3})");

            // Another immediate tap should generate a doubleTap
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            child.AssertLast(6, "OnTouchDown(5:{X:3 Y:3})");
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Released, new Vector2(4, 4)), t);
            child.AssertLast(8, "OnDoubleTap({X:3 Y:3})");
        }
        public void Dragging_KicksOff_WhenFarEnough()
        {
            var target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            var child1 = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1), PassThrough = true
            };
            var child2 = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(2, 2)
            };
            var child3 = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(3, 3)
            };

            target.AddChild(child3);
            target.AddChild(child2);
            target.AddChild(child1);

            var t = new GameTime();

            target.ReportTouch(new TouchLocation(4, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ResolveGestures(t);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Moved, new Vector2(4.01f, 4f)), t);
            target.ResolveGestures(t);
            t.TotalGameTime = TimeSpan.FromSeconds(target.FlickThreshholdSeconds);
            child1.AssertLast(2, "OnTouchMove(Move , 4 , {X:3.01 Y:3} , {X:3 Y:3})");
            child2.AssertLast(2, "OnTouchMove(Move , 4 , {X:2.01 Y:2} , {X:2 Y:2})");
            Assert.AreEqual(0, child3.Calls.Count);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Moved, new Vector2(5, 4)), t);
            target.ResolveGestures(t);
            child1.AssertLast(4, "OnDrag({X:4 Y:3} , {X:1 Y:0})");
            child2.AssertLast(4, "OnDrag({X:3 Y:2} , {X:1 Y:0})");
            Assert.AreEqual(0, child3.Calls.Count);

            // Don't re-report moves
            target.ResolveGestures(t);
            child1.AssertLast(4, "OnDrag({X:4 Y:3} , {X:1 Y:0})");

            // Drag down
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Moved, new Vector2(5, 5)), t);
            target.ResolveGestures(t);
            child1.AssertLast(6, "OnDrag({X:4 Y:4} , {X:0 Y:1})");
            child2.AssertLast(6, "OnDrag({X:3 Y:3} , {X:0 Y:1})");

            // Release the drag
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Released, new Vector2(5, 5)), t);
            target.ResolveGestures(t);
            child1.AssertLast(8, "OnDragComplete");
            child2.AssertLast(8, "OnDragComplete");
            Assert.AreEqual(0, child3.Calls.Count);
        }
        public void LongSlowStationaryTouch_GeneratesTap()
        {
            var target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            var child = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1)
            };

            target.AddChild(child);

            var t = new GameTime();

            target.ReportTouch(new TouchLocation(4, TouchLocationState.Pressed, new Vector2(2, 2)), t);
            t.TotalGameTime = TimeSpan.FromSeconds(1);
            target.ReportTouch(new TouchLocation(4, TouchLocationState.Released, new Vector2(2.01f, 2.01f)), t);
            target.ResolveGestures(t);
            child.AssertLast(3, "OnTap({X:1.01 Y:1.01})");
        }
        public void Touch_GeneratesTwoTapsInsteadOfDouble_WhenFarApart()
        {
            var target = new TouchTester()
            {
                Size = new Vector2(10, 10)
            };
            var child = new TouchTester()
            {
                Size = new Vector2(5, 5), Offset = new Vector2(1, 1)
            };

            target.AddChild(child);

            var t = new GameTime();

            target.ReportTouch(new TouchLocation(5, TouchLocationState.Pressed, new Vector2(2, 2)), t);
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Released, new Vector2(2, 2)), t);
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Pressed, new Vector2(4, 4)), t);
            target.ReportTouch(new TouchLocation(5, TouchLocationState.Released, new Vector2(4, 4)), t);
            t.TotalGameTime = TimeSpan.FromSeconds(1);
            target.ResolveGestures(t);
            child.AssertLast(6, "OnTap({X:3 Y:3})");
            Assert.AreEqual("OnTap({X:1 Y:1})", child.Calls[4]);
        }