diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs new file mode 100644 index 0000000000..fd6748dee7 --- /dev/null +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Avalonia.Input.GestureRecognizers +{ + public abstract class GestureRecognizer : StyledElement + { + public abstract IInputElement? Target { get; } + public abstract void Initialize(IInputElement target); + public abstract void PointerPressed(PointerPressedEventArgs e); + public abstract void PointerReleased(PointerReleasedEventArgs e); + public abstract void PointerMoved(PointerEventArgs e); + public abstract void PointerCaptureLost(IPointer pointer); + + protected void Capture(IPointer pointer) + { + (pointer as Pointer)?.CaptureGestureRecognizer(this); + } + } +} diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs index 8ec9cb7301..e7c6513c43 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs @@ -6,26 +6,26 @@ using Avalonia.Reactive; namespace Avalonia.Input.GestureRecognizers { - public class GestureRecognizerCollection : IReadOnlyCollection, IGestureRecognizerActionsDispatcher + public class GestureRecognizerCollection : IReadOnlyCollection { private readonly IInputElement _inputElement; - private List? _recognizers; + private List? _recognizers; public GestureRecognizerCollection(IInputElement inputElement) { _inputElement = inputElement; } - public void Add(IGestureRecognizer recognizer) + public void Add(GestureRecognizer recognizer) { if (_recognizers == null) { // We initialize the collection when the first recognizer is added - _recognizers = new List(); + _recognizers = new List(); } _recognizers.Add(recognizer); - recognizer.Initialize(_inputElement, this); + recognizer.Initialize(_inputElement); // Hacks to make bindings work @@ -38,16 +38,15 @@ namespace Avalonia.Input.GestureRecognizers } } - static readonly List s_Empty = new List(); + static readonly List s_Empty = new List(); - public IEnumerator GetEnumerator() + public IEnumerator GetEnumerator() => _recognizers?.GetEnumerator() ?? s_Empty.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public int Count => _recognizers?.Count ?? 0; - internal bool HandlePointerPressed(PointerPressedEventArgs e) { if (_recognizers == null) @@ -91,19 +90,5 @@ namespace Avalonia.Input.GestureRecognizers } return e.Handled; } - - void IGestureRecognizerActionsDispatcher.Capture(IPointer pointer, IGestureRecognizer recognizer) - { - var p = pointer as Pointer; - - p?.CaptureGestureRecognizer(recognizer); - - foreach (var r in _recognizers!) - { - if (r != recognizer) - r.PointerCaptureLost(pointer); - } - } - } } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs deleted file mode 100644 index 51c36a93de..0000000000 --- a/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Avalonia.Input.GestureRecognizers -{ - public interface IGestureRecognizer - { - IInputElement? Target { get; } - void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions); - void PointerPressed(PointerPressedEventArgs e); - void PointerReleased(PointerReleasedEventArgs e); - void PointerMoved(PointerEventArgs e); - void PointerCaptureLost(IPointer pointer); - } - - public interface IGestureRecognizerActionsDispatcher - { - void Capture(IPointer pointer, IGestureRecognizer recognizer); - } - - public enum GestureRecognizerResult - { - None, - Capture, - ReleaseCapture - } -} diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs index 4390167e98..133fd76947 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs @@ -2,10 +2,9 @@ namespace Avalonia.Input { - public class PinchGestureRecognizer : AvaloniaObject, IGestureRecognizer + public class PinchGestureRecognizer : GestureRecognizer { private IInputElement? _target; - private IGestureRecognizerActionsDispatcher? _actions; private float _initialDistance; private IPointer? _firstContact; private Point _firstPoint; @@ -13,12 +12,11 @@ namespace Avalonia.Input private Point _secondPoint; private Point _origin; - public IInputElement? Target => _target; + public override IInputElement? Target => _target; - public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) + public override void Initialize(IInputElement target) { _target = target; - _actions = actions; } private void OnPointerPressed(object? sender, PointerPressedEventArgs e) @@ -31,12 +29,12 @@ namespace Avalonia.Input PointerReleased(e); } - public void PointerCaptureLost(IPointer pointer) + public override void PointerCaptureLost(IPointer pointer) { RemoveContact(pointer); } - public void PointerMoved(PointerEventArgs e) + public override void PointerMoved(PointerEventArgs e) { if (_target != null && _target is Visual visual) { @@ -67,7 +65,7 @@ namespace Avalonia.Input } } - public void PointerPressed(PointerPressedEventArgs e) + public override void PointerPressed(PointerPressedEventArgs e) { if (_target != null && _target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -94,13 +92,13 @@ namespace Avalonia.Input _origin = new Point((_firstPoint.X + _secondPoint.X) / 2.0f, (_firstPoint.Y + _secondPoint.Y) / 2.0f); - _actions!.Capture(_firstContact, this); - _actions!.Capture(_secondContact, this); + Capture(_firstContact); + Capture(_secondContact); } } } - public void PointerReleased(PointerReleasedEventArgs e) + public override void PointerReleased(PointerReleasedEventArgs e) { RemoveContact(e.Pointer); } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs index 7391cdbaca..f6ab1c4508 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs @@ -3,12 +3,11 @@ using Avalonia.Input.GestureRecognizers; namespace Avalonia.Input { - public class PullGestureRecognizer : AvaloniaObject, IGestureRecognizer + public class PullGestureRecognizer : GestureRecognizer { internal static int MinPullDetectionSize = 50; private IInputElement? _target; - private IGestureRecognizerActionsDispatcher? _actions; private Point _initialPosition; private int _gestureId; private IPointer? _tracking; @@ -26,7 +25,7 @@ namespace Avalonia.Input set => SetValue(PullDirectionProperty, value); } - public IInputElement? Target => _target; + public override IInputElement? Target => _target; public PullGestureRecognizer(PullDirection pullDirection) { @@ -35,13 +34,12 @@ namespace Avalonia.Input public PullGestureRecognizer() { } - public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) + public override void Initialize(IInputElement target) { _target = target; - _actions = actions; } - public void PointerCaptureLost(IPointer pointer) + public override void PointerCaptureLost(IPointer pointer) { if (_tracking == pointer) { @@ -49,12 +47,12 @@ namespace Avalonia.Input } } - public void PointerMoved(PointerEventArgs e) + public override void PointerMoved(PointerEventArgs e) { if (_tracking == e.Pointer && _target is Visual visual) { var currentPosition = e.GetPosition(visual); - _actions!.Capture(e.Pointer, this); + Capture(e.Pointer); e.PreventGestureRecognition(); Vector delta = default; @@ -94,7 +92,7 @@ namespace Avalonia.Input } } - public void PointerPressed(PointerPressedEventArgs e) + public override void PointerPressed(PointerPressedEventArgs e) { if (_target != null && _target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -129,7 +127,7 @@ namespace Avalonia.Input } } - public void PointerReleased(PointerReleasedEventArgs e) + public override void PointerReleased(PointerReleasedEventArgs e) { if (_tracking == e.Pointer && _pullInProgress) { diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index 3206c3903a..ecc72c8f60 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -4,7 +4,7 @@ using Avalonia.Threading; namespace Avalonia.Input.GestureRecognizers { - public class ScrollGestureRecognizer : AvaloniaObject, IGestureRecognizer + public class ScrollGestureRecognizer : GestureRecognizer { // Pixels per second speed that is considered to be the stop of inertial scroll internal const double InertialScrollSpeedEnd = 5; @@ -19,7 +19,6 @@ namespace Avalonia.Input.GestureRecognizers private Point _trackedRootPoint; private IPointer? _tracking; private IInputElement? _target; - private IGestureRecognizerActionsDispatcher? _actions; private int _gestureId; private Point _pointerPressedPoint; private VelocityTracker? _velocityTracker; @@ -93,15 +92,14 @@ namespace Avalonia.Input.GestureRecognizers set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value); } - public IInputElement? Target => _target; + public override IInputElement? Target => _target; - public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) + public override void Initialize(IInputElement target) { _target = target; - _actions = actions; } - public void PointerPressed(PointerPressedEventArgs e) + public override void PointerPressed(PointerPressedEventArgs e) { if (e.Pointer.IsPrimary && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) @@ -112,8 +110,8 @@ namespace Avalonia.Input.GestureRecognizers _trackedRootPoint = _pointerPressedPoint = e.GetPosition((Visual?)_target); } } - - public void PointerMoved(PointerEventArgs e) + + public override void PointerMoved(PointerEventArgs e) { if (e.Pointer == _tracking) { @@ -133,7 +131,7 @@ namespace Avalonia.Input.GestureRecognizers _trackedRootPoint.X - (_trackedRootPoint.X >= rootPoint.X ? ScrollStartDistance : -ScrollStartDistance), _trackedRootPoint.Y - (_trackedRootPoint.Y >= rootPoint.Y ? ScrollStartDistance : -ScrollStartDistance)); - _actions!.Capture(e.Pointer, this); + Capture(e.Pointer); e.PreventGestureRecognition(); } @@ -153,7 +151,7 @@ namespace Avalonia.Input.GestureRecognizers } } - public void PointerCaptureLost(IPointer pointer) + public override void PointerCaptureLost(IPointer pointer) { if (pointer == _tracking) EndGesture(); } @@ -173,7 +171,7 @@ namespace Avalonia.Input.GestureRecognizers } - public void PointerReleased(PointerReleasedEventArgs e) + public override void PointerReleased(PointerReleasedEventArgs e) { if (e.Pointer == _tracking && _scrolling) { diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs index 328d5e945f..4da8062897 100644 --- a/src/Avalonia.Base/Input/MouseDevice.cs +++ b/src/Avalonia.Base/Input/MouseDevice.cs @@ -163,14 +163,11 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - IInputElement? source; - if (_pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if(source != null) + if(gestureRecognizer.Target != null) { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)root, + var e = new PointerEventArgs(InputElement.PointerMovedEvent, gestureRecognizer.Target, _pointer, (Visual)root, p, timestamp, properties, inputModifiers, intermediatePoints); gestureRecognizer.PointerMoved(e); @@ -178,7 +175,7 @@ namespace Avalonia.Input } } - source = _pointer.Captured ?? hitTest; + var source = _pointer.Captured ?? hitTest; if (source is object) { @@ -198,15 +195,12 @@ namespace Avalonia.Input { device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - - IInputElement? source; - if (_pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + + if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if (source != null) + if (gestureRecognizer.Target != null) { - var e = new PointerReleasedEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers, + var e = new PointerReleasedEventArgs(gestureRecognizer.Target, _pointer, (Visual)root, p, timestamp, props, inputModifiers, _lastMouseDownButton); gestureRecognizer.PointerReleased(e); @@ -214,7 +208,7 @@ namespace Avalonia.Input } } - source = _pointer.Captured ?? hitTest; + var source = _pointer.Captured ?? hitTest; if (source is not null) { diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs index a183dbbaf8..fab0f1320c 100644 --- a/src/Avalonia.Base/Input/PenDevice.cs +++ b/src/Avalonia.Base/Input/PenDevice.cs @@ -115,14 +115,11 @@ namespace Avalonia.Input KeyModifiers inputModifiers, IInputElement? hitTest, Lazy?>? intermediatePoints) { - IInputElement? source; - if (pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if (source != null) + if (gestureRecognizer.Target != null) { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, (Visual)root, + var e = new PointerEventArgs(InputElement.PointerMovedEvent, gestureRecognizer.Target, pointer, (Visual)root, p, timestamp, properties, inputModifiers, intermediatePoints); gestureRecognizer.PointerMoved(e); @@ -130,7 +127,7 @@ namespace Avalonia.Input } } - source = pointer.Captured ?? hitTest; + var source = pointer.Captured ?? hitTest; if (source is not null) { @@ -148,14 +145,11 @@ namespace Avalonia.Input IInputElement root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers, IInputElement? hitTest) { - IInputElement? source; - if (pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if (source != null) + if (gestureRecognizer.Target != null) { - var e = new PointerReleasedEventArgs(source, pointer, (Visual)root, p, timestamp, properties, inputModifiers, + var e = new PointerReleasedEventArgs(gestureRecognizer.Target, pointer, (Visual)root, p, timestamp, properties, inputModifiers, _lastMouseDownButton); gestureRecognizer.PointerReleased(e); @@ -163,7 +157,7 @@ namespace Avalonia.Input } } - source = pointer.Captured ?? hitTest; + var source = pointer.Captured ?? hitTest; if (source is not null) { diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs index 3abda3637e..65c0d7f538 100644 --- a/src/Avalonia.Base/Input/Pointer.cs +++ b/src/Avalonia.Base/Input/Pointer.cs @@ -77,7 +77,7 @@ namespace Avalonia.Input /// /// Gets the gesture recognizer that is currently capturing by the pointer, if any. /// - internal IGestureRecognizer? CapturedGestureRecognizer { get; private set; } + internal GestureRecognizer? CapturedGestureRecognizer { get; private set; } public void Dispose() { @@ -89,7 +89,7 @@ namespace Avalonia.Input /// /// The gesture recognizer. /// - internal void CaptureGestureRecognizer(IGestureRecognizer? gestureRecognizer) + internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer) { if (CapturedGestureRecognizer != gestureRecognizer) CapturedGestureRecognizer?.PointerCaptureLost(this);