Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="views:ActionSheetItem">
<Grid PointerPressed="InputElement_OnPointerPressed"
PointerReleased="InputElement_OnPointerReleased"
<Grid PointerPressed="Item_OnPointerPressed"
PointerMoved="Item_OnPointerMoved"
PointerReleased="Item_OnPointerReleased"
PointerCaptureLost="Item_OnPointerCaptureLost"
Background="Transparent"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using Avalonia.VisualTree;

namespace Svg.Editor.Avalon.Forms.Dialog.Views;

Expand All @@ -15,42 +16,92 @@ public ActionSheetDialogContent()

private ActionSheetDialogResultViewModel ResultViewModel => (ActionSheetDialogResultViewModel)DataContext!;

private void SelectingItemsControl_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (ResultViewModel is null)
throw new InvalidOperationException("DataContext was null");

ResultViewModel.AcceptPrimary();
}

#region HandleClickingItem

private object? _previouslyClickedOnItem = null;
/// <summary>Used when the control is not (yet) attached to a visual root.</summary>
private static readonly Size FallbackTapSize = new(10, 10);

private IPointer? _pressedPointer;
private Control? _pressedItemVisual;
private Point _pressRootPoint;
private bool _tapCancelled;

private void InputElement_OnPointerPressed(object? sender, PointerPressedEventArgs e)
private void Item_OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
_previouslyClickedOnItem = sender;
// Reset first: a press that we do not track must not leave state from a previous
// gesture behind, otherwise a later release could be matched against a stale press.
_pressedPointer = null;
_pressedItemVisual = null;
_tapCancelled = false;

if (!e.GetCurrentPoint(null).Properties.IsLeftButtonPressed)
return;

_pressedPointer = e.Pointer;
_pressedItemVisual = sender as Control;
// Root (TopLevel) coordinates on purpose: measuring relative to the item would be
// useless, because while the ListBox scrolls the item travels with the finger and
// the relative delta stays at ~zero.
_pressRootPoint = e.GetPosition(null);
}

private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
private void Item_OnPointerMoved(object? sender, PointerEventArgs e)
{
if (sender == _previouslyClickedOnItem)
{
ResultViewModel.AcceptPrimary();
_previouslyClickedOnItem = null;
}
if (_tapCancelled || _pressedPointer is null || !ReferenceEquals(e.Pointer, _pressedPointer))
return;

if (ExceedsTapSlop(e.GetPosition(null), e.Pointer.Type))
_tapCancelled = true;
}

#endregion
/// <summary>
/// Raised when a gesture recognizer (ScrollGestureRecognizer) steals the pointer,
/// i.e. the user started scrolling rather than tapping.
/// </summary>
private void Item_OnPointerCaptureLost(object? sender, PointerCaptureLostEventArgs e)
{
if (_pressedPointer is not null && ReferenceEquals(e.Pointer, _pressedPointer))
_tapCancelled = true;
}

#region HandlePressingEnterr on item
private void Item_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
var cancelled = _tapCancelled;
var pressedPointer = _pressedPointer;
var pressedItemVisual = _pressedItemVisual;

_tapCancelled = false;
_pressedPointer = null;
_pressedItemVisual = null;

if (cancelled
|| pressedPointer is null
|| !ReferenceEquals(e.Pointer, pressedPointer)
|| !ReferenceEquals(sender, pressedItemVisual)
|| e.InitialPressMouseButton != MouseButton.Left)
return;

if (ExceedsTapSlop(e.GetPosition(null), e.Pointer.Type))
return;

if (sender is not Control { DataContext: ActionSheetItem item })
return;

// Resolve the tapped item ourselves instead of relying on ListBox.SelectedItem:
// for touch and pen the ListBox only updates the selection *later* in the same
// bubbling route (it selects on PointerReleased, not PointerPressed), so reading
// SelectedItem here could yield the previously selected item.
ResultViewModel.SelectedItem = item;
ResultViewModel.AcceptPrimary();
}

private void InputElement_OnKeyUp(object? sender, KeyEventArgs e)
private bool ExceedsTapSlop(Point currentRootPoint, PointerType pointerType)
{
if (e.Key == Key.Enter)
{
ResultViewModel.AcceptPrimary();
}
// TopLevel.PlatformSettings is private in Avalonia 12; VisualExtensions is the public way in.
var slop = this.GetPlatformSettings()?.GetTapSize(pointerType) ?? FallbackTapSize;

return Math.Abs(currentRootPoint.X - _pressRootPoint.X) > slop.Width
|| Math.Abs(currentRootPoint.Y - _pressRootPoint.Y) > slop.Height;
}

#endregion
Expand Down
4 changes: 3 additions & 1 deletion Svg.Editor.Avalonia.Forms/Svg.Editor.Avalon.Forms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<Version>3.2.0-optiq11</Version>
<Version>3.2.0-optiq12</Version>
<PackageReleaseNotes>
#3.2.0-optiq12
Fixed action sheet returning the wrong item on touch and selecting while scrolling
#3.2.0-optiq11
Fixed huge paragraph spacing in multi-line text (LineHeight 12f -> 1.25f)
#3.2.0-optiq09
Expand Down
4 changes: 3 additions & 1 deletion Svg.Editor.Avalonia.Views/Svg.Editor.Avalon.Views.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<Version>3.2.0-optiq11</Version>
<Version>3.2.0-optiq12</Version>
<PackageReleaseNotes>
#3.2.0-optiq12
Fixed action sheet returning the wrong item on touch and selecting while scrolling
#3.2.0-optiq11
Fixed huge paragraph spacing in multi-line text (LineHeight 12f -> 1.25f)
#3.2.0-optiq09
Expand Down
4 changes: 3 additions & 1 deletion Svg.Editor.Core/Svg.Editor.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
<AssemblyName>Svg.Editor</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetFramework>net10.0</TargetFramework>
<Version>3.2.0-optiq11</Version>
<Version>3.2.0-optiq12</Version>
<LangVersion>latest</LangVersion>
<PackageReleaseNotes>
#3.2.0-optiq12
Fixed action sheet returning the wrong item on touch and selecting while scrolling
#3.2.0-optiq11
Fixed huge paragraph spacing in multi-line text (LineHeight 12f -> 1.25f)
#3.2.0-optiq09
Expand Down
4 changes: 3 additions & 1 deletion Svg/Svg.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net48;net10.0</TargetFrameworks>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<Version>3.2.0-optiq11</Version>
<Version>3.2.0-optiq12</Version>
<Authors>gentledpp,zepr</Authors>
<Company>Opti-Q GmbH</Company>
<PackageReleaseNotes>
#3.2.0-optiq12
Fixed action sheet returning the wrong item on touch and selecting while scrolling
#3.2.0-optiq11
Fixed huge paragraph spacing in multi-line text (LineHeight 12f -> 1.25f)
#3.2.0-optiq10
Expand Down
Loading