Skip to content

Commit

Permalink
[WinUI] Implement PointerPressed and PointerReleased (#16213)
Browse files Browse the repository at this point in the history
* Implement on Windows and add unit tests

* Update src/Controls/src/Core/PointerGestureRecognizer.cs

Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com>

---------

Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com>
  • Loading branch information
rachelkang and samhouts authored Aug 8, 2023
1 parent 7667bb8 commit 9fcccd5
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@
x:Class="Maui.Controls.Sample.Pages.PointerGestureGalleryPage"
xmlns:views="clr-namespace:Maui.Controls.Sample.Pages.Base">
<StackLayout>

<Label
x:Name="pgrLabel"
FontSize="24"
Text="Hover, press, and release me!">
<Label.GestureRecognizers>
<PointerGestureRecognizer PointerEntered="PointerHoverStarted" PointerExited="PointerHoverEnded" PointerMoved="PointerMoved" PointerPressed="PointerPressStarted" PointerReleased="PointerPressEnded" />
</Label.GestureRecognizers>
</Label>
<Label x:Name="pgrPositionLabel" Text="Hover above label to reveal pointer position"/>
<Label x:Name="pgrPositionToWindow" />
<Label x:Name="pgrPositionToThisLabel" />

<Label
x:Name="hoverLabel"
FontSize="24"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,54 @@ namespace Maui.Controls.Sample.Pages
{
public partial class PointerGestureGalleryPage
{
Command _hoverEnterCommand;
Command _hoverCommand;

public PointerGestureGalleryPage()
{
InitializeComponent();

_hoverEnterCommand = new Command<Color>(HandleHoverEnterCommand);
_hoverCommand = new Command<Color>(HandleHoverCommand);

var colorfulHoverEnterGesture = new PointerGestureRecognizer
var colorfulHoverGesture = new PointerGestureRecognizer
{
PointerEnteredCommand = _hoverEnterCommand,
PointerEnteredCommandParameter = Colors.Green
PointerEnteredCommand = _hoverCommand,
PointerEnteredCommandParameter = Colors.Green,
PointerExitedCommand = _hoverCommand,
PointerExitedCommandParameter = Colors.Black
};
colorfulHoverLabel.GestureRecognizers.Add(colorfulHoverEnterGesture);
colorfulHoverLabel.GestureRecognizers.Add(colorfulHoverGesture);
}

void PointerHoverStarted(object sender, PointerEventArgs e)
{
pgrLabel.Text = "Thanks for hovering me! Now press me!";
pgrLabel.BackgroundColor = Colors.PaleGreen;
}

void PointerHoverEnded(object sender, PointerEventArgs e)
{
pgrLabel.Text = "Hover me again!";
pgrPositionLabel.Text = "Hover above label to reveal pointer position again";
pgrLabel.BackgroundColor = Colors.Transparent;
}

void PointerMoved(object sender, PointerEventArgs e)
{
pgrPositionLabel.Text = $"Pointer position is at: {e.GetPosition((View)sender)}";
pgrPositionToWindow.Text = $"Pointer position inside window: {e.GetPosition(null)}";
pgrPositionToThisLabel.Text = $"Pointer position relative to this label: {e.GetPosition(pgrPositionToThisLabel)}";
}

void PointerPressStarted(object sender, PointerEventArgs e)
{
pgrLabel.Text = "Thanks for pressing me! Now release me!";
pgrLabel.BackgroundColor = Colors.SkyBlue;
}

void PointerPressEnded(object sender, PointerEventArgs e)
{
pgrLabel.Text = "Thanks for releasing me! Press me again or leave me!";
pgrLabel.BackgroundColor = Colors.Yellow;
}

void HoverBegan(object sender, PointerEventArgs e)
Expand All @@ -39,7 +73,7 @@ void HoverMoved(object sender, PointerEventArgs e)
positionToThisLabel.Text = $"Pointer position relative to this label: {e.GetPosition(positionToThisLabel)}";
}

void HandleHoverEnterCommand(Color hoverColor)
void HandleHoverCommand(Color hoverColor)
{
colorfulHoverLabel.TextColor = hoverColor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ void ClearContainerEventHandlers()
_container.PointerEntered -= OnPgrPointerEntered;
_container.PointerExited -= OnPgrPointerExited;
_container.PointerMoved -= OnPgrPointerMoved;
_container.PointerPressed -= OnPgrPointerPressed;
_container.PointerReleased -= OnPgrPointerReleased;
}
}

Expand Down Expand Up @@ -474,7 +476,7 @@ void OnPointerReleased(object sender, PointerRoutedEventArgs e)
{
uint id = e.Pointer.PointerId;
if (_fingers.Contains(id))
_fingers.Remove(id);
_fingers.Remove(id);
SwipeComplete(true);
PinchComplete(true);
PanComplete(true);
Expand All @@ -492,6 +494,14 @@ void OnPgrPointerMoved(object sender, PointerRoutedEventArgs e)
=> HandlePgrPointerEvent(e, (view, recognizer)
=> recognizer.SendPointerMoved(view, (relativeTo) => GetPosition(relativeTo, e)));

void OnPgrPointerPressed(object sender, PointerRoutedEventArgs e)
=> HandlePgrPointerEvent(e, (view, recognizer)
=> recognizer.SendPointerPressed(view, (relativeTo) => GetPosition(relativeTo, e)));

void OnPgrPointerReleased(object sender, PointerRoutedEventArgs e)
=> HandlePgrPointerEvent(e, (view, recognizer)
=> recognizer.SendPointerReleased(view, (relativeTo) => GetPosition(relativeTo, e)));

private void HandlePgrPointerEvent(PointerRoutedEventArgs e, Action<View, PointerGestureRecognizer> SendPointerEvent)
{
var view = Element as View;
Expand Down Expand Up @@ -711,6 +721,8 @@ void UpdatingGestureRecognizers()
_container.PointerEntered += OnPgrPointerEntered;
_container.PointerExited += OnPgrPointerExited;
_container.PointerMoved += OnPgrPointerMoved;
_container.PointerPressed += OnPgrPointerPressed;
_container.PointerReleased += OnPgrPointerReleased;

bool hasSwipeGesture = gestures.GetGesturesFor<SwipeGestureRecognizer>().GetEnumerator().MoveNext();
bool hasPinchGesture = gestures.GetGesturesFor<PinchGestureRecognizer>().GetEnumerator().MoveNext();
Expand Down
93 changes: 93 additions & 0 deletions src/Controls/src/Core/PointerGestureRecognizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,27 @@ public sealed class PointerGestureRecognizer : GestureRecognizer
/// </summary>
public static readonly BindableProperty PointerMovedCommandParameterProperty = BindableProperty.Create(nameof(PointerMovedCommandParameter), typeof(object), typeof(PointerGestureRecognizer), null);

/// <summary>
/// The command to invoke when the pointer initiates a press within the view. This is a bindable property.
/// </summary>
public static readonly BindableProperty PointerPressedCommandProperty = BindableProperty.Create(nameof(PointerPressedCommand), typeof(ICommand), typeof(PointerGestureRecognizer), null);

/// <summary>
/// An object to be passed to the PointerPressedCommand. This is a bindable property.
/// </summary>
public static readonly BindableProperty PointerPressedCommandParameterProperty = BindableProperty.Create(nameof(PointerPressedCommandParameter), typeof(object), typeof(PointerGestureRecognizer), null);

/// <summary>
/// A command to invoke when the pointer that has previous initiated a press is released within the view. This is a bindable property.
/// </summary>
public static readonly BindableProperty PointerReleasedCommandProperty = BindableProperty.Create(nameof(PointerReleasedCommand), typeof(ICommand), typeof(PointerGestureRecognizer), null);

/// <summary>
/// An object to be passed to the PointerReleasedCommand. This is a bindable property.
/// </summary>
public static readonly BindableProperty PointerReleasedCommandParameterProperty = BindableProperty.Create(nameof(PointerReleasedCommandParameter), typeof(object), typeof(PointerGestureRecognizer), null);


/// <summary>
/// Initializes a new instance of PointerGestureRecognizer.
/// </summary>
Expand All @@ -62,6 +83,16 @@ public PointerGestureRecognizer()
/// </summary>
public event EventHandler<PointerEventArgs>? PointerMoved;

/// <summary>
/// Raised when the pointer initiates a press within the view.
/// </summary>
public event EventHandler<PointerEventArgs>? PointerPressed;

/// <summary>
/// Raised when the pointer that has previous initiated a press is released within the view.
/// </summary>
public event EventHandler<PointerEventArgs>? PointerReleased;

/// <summary>
/// Identifies the PointerEnteredCommand bindable property.
/// </summary>
Expand Down Expand Up @@ -116,6 +147,42 @@ public object PointerMovedCommandParameter
set { SetValue(PointerMovedCommandParameterProperty, value); }
}

/// <summary>
/// Identifies the PointerPressedCommand bindable property.
/// </summary>
public ICommand PointerPressedCommand
{
get { return (ICommand)GetValue(PointerPressedCommandProperty); }
set { SetValue(PointerPressedCommandProperty, value); }
}

/// <summary>
/// Identifies the PointerPressedCommandParameter bindable property.
/// </summary>
public object PointerPressedCommandParameter
{
get { return GetValue(PointerPressedCommandParameterProperty); }
set { SetValue(PointerPressedCommandParameterProperty, value); }
}

/// <summary>
/// Identifies the PointerReleasedCommand bindable property.
/// </summary>
public ICommand PointerReleasedCommand
{
get { return (ICommand)GetValue(PointerReleasedCommandProperty); }
set { SetValue(PointerReleasedCommandProperty, value); }
}

/// <summary>
/// Identifies the PointerReleasedCommandParameter bindable property.
/// </summary>
public object PointerReleasedCommandParameter
{
get { return GetValue(PointerReleasedCommandParameterProperty); }
set { SetValue(PointerReleasedCommandParameterProperty, value); }
}

/// <summary>
/// For internal use by the .NET MAUI platform.
/// </summary>
Expand Down Expand Up @@ -155,6 +222,32 @@ internal void SendPointerMoved(View sender, Func<IElement?, Point?>? getPosition
handler?.Invoke(sender, new PointerEventArgs(getPosition));
}

/// <summary>
/// For internal use by the .NET MAUI platform.
/// </summary>
internal void SendPointerPressed(View sender, Func<IElement?, Point?>? getPosition)
{
ICommand cmd = PointerPressedCommand;
if (cmd?.CanExecute(PointerPressedCommandParameter) == true)
cmd.Execute(PointerPressedCommandParameter);

EventHandler<PointerEventArgs>? handler = PointerPressed;
handler?.Invoke(sender, new PointerEventArgs(getPosition));
}

/// <summary>
/// For internal use by the .NET MAUI platform.
/// </summary>
internal void SendPointerReleased(View sender, Func<IElement?, Point?>? getPosition)
{
ICommand cmd = PointerReleasedCommand;
if (cmd?.CanExecute(PointerReleasedCommandParameter) == true)
cmd.Execute(PointerReleasedCommandParameter);

EventHandler<PointerEventArgs>? handler = PointerReleased;
handler?.Invoke(sender, new PointerEventArgs(getPosition));
}

internal static void SetupForPointerOverVSM(
VisualElement element,
Action<bool> updatePointerState,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressed -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleased -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.set -> void
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Expand Down
14 changes: 14 additions & 0 deletions src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressed -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleased -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.set -> void
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressed -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleased -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.set -> void
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Expand Down
14 changes: 14 additions & 0 deletions src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressed -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameter.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleased -> System.EventHandler<Microsoft.Maui.Controls.PointerEventArgs!>?
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.get -> System.Windows.Input.ICommand!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.set -> void
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerPressedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandProperty -> Microsoft.Maui.Controls.BindableProperty!
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
Loading

0 comments on commit 9fcccd5

Please sign in to comment.