Browse Source

Merge pull request #2779 from AvaloniaUI/fixes/2730-gestures-handled

Fix Tapped and DoubleTapped gestures
pull/2794/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
8011125af8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      src/Avalonia.Input/Gestures.cs
  2. 2
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
  3. 2
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs
  4. 208
      tests/Avalonia.Input.UnitTests/GesturesTests.cs
  5. 2
      tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj
  6. 112
      tests/Avalonia.Interactivity.UnitTests/GestureTests.cs
  7. 1
      tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
  8. 3
      tests/Avalonia.UnitTests/MouseTestHelper.cs

13
src/Avalonia.Input/Gestures.cs

@ -18,6 +18,11 @@ namespace Avalonia.Input
RoutingStrategies.Bubble,
typeof(Gestures));
public static readonly RoutedEvent<RoutedEventArgs> RightTappedEvent = RoutedEvent.Register<RoutedEventArgs>(
"RightTapped",
RoutingStrategies.Bubble,
typeof(Gestures));
public static readonly RoutedEvent<ScrollGestureEventArgs> ScrollGestureEvent =
RoutedEvent.Register<ScrollGestureEventArgs>(
"ScrollGesture", RoutingStrategies.Bubble, typeof(Gestures));
@ -46,7 +51,7 @@ namespace Avalonia.Input
}
else if (s_lastPress?.IsAlive == true && e.ClickCount == 2 && s_lastPress.Target == e.Source)
{
if (!ev.Handled)
if (e.MouseButton != MouseButton.Right)
{
e.Source.RaiseEvent(new RoutedEventArgs(DoubleTappedEvent));
}
@ -62,10 +67,8 @@ namespace Avalonia.Input
if (s_lastPress?.IsAlive == true && s_lastPress.Target == e.Source)
{
if (!ev.Handled)
{
((IInteractive)s_lastPress.Target).RaiseEvent(new RoutedEventArgs(TappedEvent));
}
var et = e.MouseButton != MouseButton.Right ? TappedEvent : RightTappedEvent;
((IInteractive)s_lastPress.Target).RaiseEvent(new RoutedEventArgs(et));
}
}
}

2
tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs

@ -9,8 +9,8 @@ using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.LogicalTree;
using Avalonia.Markup.Data;
using Avalonia.Styling;
using Avalonia.UnitTests;
using Avalonia.VisualTree;
using Xunit;

2
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs

@ -13,7 +13,7 @@ using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Data;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests.Primitives

208
tests/Avalonia.Input.UnitTests/GesturesTests.cs

@ -0,0 +1,208 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Interactivity.UnitTests
{
public class GesturesTests
{
private MouseTestHelper _mouse = new MouseTestHelper();
[Fact]
public void Tapped_Should_Follow_Pointer_Pressed_Released()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
AddHandlers(decorator, border, result, false);
_mouse.Click(border);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt" }, result);
}
[Fact]
public void Tapped_Should_Be_Raised_Even_When_Pressed_Released_Handled()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
AddHandlers(decorator, border, result, true);
_mouse.Click(border);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt" }, result);
}
[Fact]
public void Tapped_Should_Be_Raised_For_Middle_Button()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var raised = false;
decorator.AddHandler(Gestures.TappedEvent, (s, e) => raised = true);
_mouse.Click(border, MouseButton.Middle);
Assert.True(raised);
}
[Fact]
public void Tapped_Should_Not_Be_Raised_For_Right_Button()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var raised = false;
decorator.AddHandler(Gestures.TappedEvent, (s, e) => raised = true);
_mouse.Click(border, MouseButton.Right);
Assert.False(raised);
}
[Fact]
public void RightTapped_Should_Be_Raised_For_Right_Button()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var raised = false;
decorator.AddHandler(Gestures.RightTappedEvent, (s, e) => raised = true);
_mouse.Click(border, MouseButton.Right);
Assert.True(raised);
}
[Fact]
public void DoubleTapped_Should_Follow_Pointer_Pressed_Released_Pressed()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
AddHandlers(decorator, border, result, false);
_mouse.Click(border);
_mouse.Down(border, clickCount: 2);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp", "bdt", "ddt" }, result);
}
[Fact]
public void DoubleTapped_Should_Be_Raised_Even_When_Pressed_Released_Handled()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
AddHandlers(decorator, border, result, true);
_mouse.Click(border);
_mouse.Down(border, clickCount: 2);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp", "bdt", "ddt" }, result);
}
[Fact]
public void DoubleTapped_Should_Be_Raised_For_Middle_Button()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var raised = false;
decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => raised = true);
_mouse.Click(border, MouseButton.Middle);
_mouse.Down(border, MouseButton.Middle, clickCount: 2);
Assert.True(raised);
}
[Fact]
public void DoubleTapped_Should_Not_Be_Raised_For_Right_Button()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var raised = false;
decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => raised = true);
_mouse.Click(border, MouseButton.Right);
_mouse.Down(border, MouseButton.Right, clickCount: 2);
Assert.False(raised);
}
private void AddHandlers(
Decorator decorator,
Border border,
IList<string> result,
bool markHandled)
{
decorator.AddHandler(Border.PointerPressedEvent, (s, e) =>
{
result.Add("dp");
if (markHandled)
{
e.Handled = true;
}
});
decorator.AddHandler(Border.PointerReleasedEvent, (s, e) =>
{
result.Add("dr");
if (markHandled)
{
e.Handled = true;
}
});
border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp"));
border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br"));
decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt"));
decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("ddt"));
border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt"));
border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt"));
}
}
}

2
tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj

@ -20,7 +20,7 @@
<ProjectReference Include="..\..\src\Avalonia.Layout\Avalonia.Layout.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Visuals\Avalonia.Visuals.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Styling\Avalonia.Styling.csproj" />
<Compile Include="..\Avalonia.Controls.UnitTests\MouseTestHelper.cs" />
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />

112
tests/Avalonia.Interactivity.UnitTests/GestureTests.cs

@ -1,112 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Controls.UnitTests;
using Avalonia.Input;
using Xunit;
namespace Avalonia.Interactivity.UnitTests
{
public class GestureTests
{
private MouseTestHelper _mouse = new MouseTestHelper();
[Fact]
public void Tapped_Should_Follow_Pointer_Pressed_Released()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
decorator.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("dp"));
decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("dr"));
decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt"));
border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp"));
border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br"));
border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt"));
_mouse.Click(border);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt" }, result);
}
[Fact]
public void Tapped_Should_Be_Raised_Even_When_PointerPressed_Handled()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
border.AddHandler(Border.PointerPressedEvent, (s, e) => e.Handled = true);
decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt"));
border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt"));
_mouse.Click(border);
Assert.Equal(new[] { "bt", "dt" }, result);
}
[Fact]
public void DoubleTapped_Should_Follow_Pointer_Pressed_Released_Pressed()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
decorator.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("dp"));
decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("dr"));
decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt"));
decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("ddt"));
border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp"));
border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br"));
border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt"));
border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt"));
_mouse.Click(border);
_mouse.Down(border, clickCount: 2);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp", "bdt", "ddt" }, result);
}
[Fact]
public void DoubleTapped_Should_Not_Be_Rasied_if_Pressed_is_Handled()
{
Border border = new Border();
var decorator = new Decorator
{
Child = border
};
var result = new List<string>();
decorator.AddHandler(Border.PointerPressedEvent, (s, e) =>
{
result.Add("dp");
e.Handled = true;
});
decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("dr"));
decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt"));
decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("ddt"));
border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp"));
border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br"));
border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt"));
border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt"));
_mouse.Click(border);
_mouse.Down(border, clickCount: 2);
Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp" }, result);
}
}
}

1
tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Library</OutputType>
<IsPackable>false</IsPackable>

3
tests/Avalonia.Controls.UnitTests/MouseTestHelper.cs → tests/Avalonia.UnitTests/MouseTestHelper.cs

@ -1,9 +1,8 @@
using System.Reactive;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
namespace Avalonia.Controls.UnitTests
namespace Avalonia.UnitTests
{
public class MouseTestHelper
{
Loading…
Cancel
Save