Browse Source

addressed review

pull/20848/head
Emmanuel Hansen 3 days ago
parent
commit
2c8133874a
  1. 1
      src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
  2. 8
      src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs
  3. 2
      src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
  4. 61
      src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs
  5. 12
      src/Avalonia.Controls/Primitives/TextSelectionHandle.cs
  6. 13
      src/Avalonia.Controls/TextBox.cs
  7. 10
      src/Avalonia.Themes.Fluent/Controls/TextSelectionHandle.xaml
  8. 10
      src/Avalonia.Themes.Simple/Controls/TextSelectionHandle.xaml

1
src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -178,7 +178,6 @@ namespace Avalonia.Input.GestureRecognizers
_inertia = default; _inertia = default;
_delta = default; _delta = default;
_scrolling = false; _scrolling = false;
_velocityTracker?.Dispose();
_velocityTracker = null; _velocityTracker = null;
Target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId)); Target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId));
_gestureId = 0; _gestureId = 0;

8
src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs

@ -3,7 +3,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using Avalonia.Utilities;
namespace Avalonia.Input.GestureRecognizers namespace Avalonia.Input.GestureRecognizers
{ {
@ -59,7 +58,7 @@ namespace Avalonia.Input.GestureRecognizers
/// ///
/// The quality of the velocity estimation will be better if more data points /// The quality of the velocity estimation will be better if more data points
/// have been received. /// have been received.
internal class VelocityTracker : IDisposable internal class VelocityTracker
{ {
private const int AssumePointerMoveStoppedMilliseconds = 40; private const int AssumePointerMoveStoppedMilliseconds = 40;
private const int HistorySize = 20; private const int HistorySize = 20;
@ -202,11 +201,6 @@ namespace Avalonia.Input.GestureRecognizers
{ {
return GetVelocity().ClampMagnitude(MinFlingVelocity, MaxFlingVelocity); return GetVelocity().ClampMagnitude(MinFlingVelocity, MaxFlingVelocity);
} }
public void Dispose()
{
_sinceLastSample.Stop();
}
} }
/// An nth degree polynomial fit to a dataset. /// An nth degree polynomial fit to a dataset.

2
src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs

@ -621,7 +621,7 @@ namespace Avalonia.Controls.Presenters
e.Handled = !IsScrollChainingEnabled || offsetChanged; e.Handled = !IsScrollChainingEnabled || offsetChanged;
if(!e.Handled) if(!e.Handled && !IsScrollChainingEnabled)
{ {
// Gesture may cause an overscroll so we mark the event as handled if it did. // Gesture may cause an overscroll so we mark the event as handled if it did.
e.Handled = canXScroll || canYScroll; e.Handled = canXScroll || canYScroll;

61
src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs

@ -5,7 +5,6 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives.PopupPositioning; using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media.TextFormatting; using Avalonia.Media.TextFormatting;
using Avalonia.Threading; using Avalonia.Threading;
using Avalonia.VisualTree; using Avalonia.VisualTree;
@ -386,7 +385,7 @@ namespace Avalonia.Controls.Primitives
if (!_handle1.IsDragging) if (!_handle1.IsDragging)
{ {
var pos = _handle1.SelectionHandleType == SelectionHandleType.Start ? startPoint : endPoint; var pos = _handle1.SelectionHandleType == SelectionHandleType.Start ? startPoint : endPoint;
if(pos.isRtl != _handle1.IsRtl) if (pos.isRtl != _handle1.IsRtl)
_handle1.NeedsIndicatorUpdate = true; _handle1.NeedsIndicatorUpdate = true;
_handle1.IsRtl = pos.isRtl; _handle1.IsRtl = pos.isRtl;
_handle1.SetTopLeft(ToLayer(pos.position)); _handle1.SetTopLeft(ToLayer(pos.position));
@ -580,7 +579,7 @@ namespace Avalonia.Controls.Primitives
ShowHandles = false; ShowHandles = false;
CloseFlyout(); CloseFlyout();
} }
else if(e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty else if (e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty
|| e.Property == TextBox.CaretIndexProperty) || e.Property == TextBox.CaretIndexProperty)
{ {
MoveHandlesToSelection(); MoveHandlesToSelection();
@ -596,42 +595,18 @@ namespace Avalonia.Controls.Primitives
// Listener to layout changes for presenter. // Listener to layout changes for presenter.
private class PresenterVisualListener private class PresenterVisualListener
{ {
private List<Visual> _attachedVisuals = new List<Visual>();
private TextPresenter? _presenter; private TextPresenter? _presenter;
private object _lock = new object();
public event EventHandler? Invalidated; public event EventHandler? Invalidated;
public void Attach(TextPresenter presenter) public void Attach(TextPresenter presenter)
{ {
lock (_lock) if (_presenter != null)
{ throw new InvalidOperationException("Listener is already attached to a TextPresenter");
if (_presenter != null)
throw new InvalidOperationException("Listener is already attached to a TextPresenter");
_presenter = presenter;
presenter.SizeChanged += Presenter_SizeChanged;
presenter.EffectiveViewportChanged += Visual_EffectiveViewportChanged;
void AttachViewportHandler(Visual visual)
{
if (visual is Layoutable layoutable)
{
layoutable.EffectiveViewportChanged += Visual_EffectiveViewportChanged;
}
_attachedVisuals.Add(visual);
}
var visualParent = presenter.VisualParent; _presenter = presenter;
while (visualParent != null) presenter.SizeChanged += Presenter_SizeChanged;
{ presenter.EffectiveViewportChanged += Visual_EffectiveViewportChanged;
AttachViewportHandler(visualParent);
visualParent = visualParent.VisualParent;
}
}
} }
private void Visual_EffectiveViewportChanged(object? sender, Layout.EffectiveViewportChangedEventArgs e) private void Visual_EffectiveViewportChanged(object? sender, Layout.EffectiveViewportChangedEventArgs e)
@ -646,25 +621,13 @@ namespace Avalonia.Controls.Primitives
public void Detach() public void Detach()
{ {
lock (_lock) if (_presenter is { } presenter)
{ {
if (_presenter is { } presenter) presenter.SizeChanged -= Presenter_SizeChanged;
{ presenter.EffectiveViewportChanged -= Visual_EffectiveViewportChanged;
presenter.SizeChanged -= Presenter_SizeChanged;
presenter.EffectiveViewportChanged -= Visual_EffectiveViewportChanged;
}
foreach (var visual in _attachedVisuals)
{
if (visual is Layoutable layoutable)
{
layoutable.EffectiveViewportChanged -= Visual_EffectiveViewportChanged;
}
}
_presenter = null;
_attachedVisuals.Clear();
} }
_presenter = null;
} }
private void OnInvalidated() private void OnInvalidated()

12
src/Avalonia.Controls/Primitives/TextSelectionHandle.cs

@ -1,9 +1,7 @@
using System; using System;
using System.Drawing;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media;
namespace Avalonia.Controls.Primitives namespace Avalonia.Controls.Primitives
{ {
@ -252,17 +250,17 @@ namespace Avalonia.Controls.Primitives
private void UpdateHandleClasses() private void UpdateHandleClasses()
{ {
Classes.Remove("caret"); PseudoClasses.Remove(":caret");
Classes.Remove("start"); PseudoClasses.Remove(":start");
Classes.Remove("end"); PseudoClasses.Remove(":end");
Classes.Add(SelectionHandleType switch PseudoClasses.Add(":" + (SelectionHandleType switch
{ {
SelectionHandleType.Caret => "caret", SelectionHandleType.Caret => "caret",
SelectionHandleType.Start => IsRtl ? "end" : "start", SelectionHandleType.Start => IsRtl ? "end" : "start",
SelectionHandleType.End => IsRtl ? "start" : "end", SelectionHandleType.End => IsRtl ? "start" : "end",
_ => throw new NotImplementedException(), _ => throw new NotImplementedException(),
}); }));
InvalidateVisual(); InvalidateVisual();
} }
} }

13
src/Avalonia.Controls/TextBox.cs

@ -35,7 +35,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// The radius for touch input. Used to determine if selection should change from moving a touch pointer. /// The radius for touch input. Used to determine if selection should change from moving a touch pointer.
/// </summary> /// </summary>
private readonly static int s_touchRadius = (int)((AvaloniaLocator.Current?.GetService<IPlatformSettings>()?.GetTapSize(PointerType.Touch).Height ?? 10) / 2) + 5; private readonly Lazy<int> _touchRadius = new(() => (int)((AvaloniaLocator.Current?.GetService<IPlatformSettings>()?.GetTapSize(PointerType.Touch).Height ?? 10) / 2) + 5);
/// <summary> /// <summary>
/// Gets a platform-specific <see cref="KeyGesture"/> for the Cut action /// Gets a platform-specific <see cref="KeyGesture"/> for the Cut action
@ -1735,7 +1735,7 @@ namespace Avalonia.Controls
{ {
base.OnTapped(e); base.OnTapped(e);
if(e.Pointer.Type != PointerType.Mouse) if (e.Pointer.Type != PointerType.Mouse)
{ {
_presenter?.EnsureTextSelectionLayer(); _presenter?.EnsureTextSelectionLayer();
_presenter?.TextSelectionHandleCanvas?.Show(); _presenter?.TextSelectionHandleCanvas?.Show();
@ -1815,18 +1815,13 @@ namespace Avalonia.Controls
if (_isDoubleTapped) if (_isDoubleTapped)
{ {
var oldCaret = _presenter.CaretIndex;
_presenter.MoveCaretToPoint(_lastPoint); _presenter.MoveCaretToPoint(_lastPoint);
var caretIndex = _presenter.CaretIndex; var caretIndex = _presenter.CaretIndex;
if(Math.Abs(oldCaret - caretIndex) > 3)
{
return;
}
var selectionStart = SelectionStart; var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd; var selectionEnd = SelectionEnd;
SelectWord(text, caretIndex, caretIndex, caretIndex); SelectWord(text, caretIndex, selectionStart, selectionEnd);
_presenter?.EnsureTextSelectionLayer(); _presenter?.EnsureTextSelectionLayer();
_presenter?.TextSelectionHandleCanvas?.Show(); _presenter?.TextSelectionHandleCanvas?.Show();
} }
@ -1957,7 +1952,7 @@ namespace Avalonia.Controls
if (!_isInTouchCaretMode) if (!_isInTouchCaretMode)
{ {
var touchRect = new Rect(_lastPoint.X, _lastPoint.Y, 0, 0).Inflate(s_touchRadius); var touchRect = new Rect(_lastPoint.X, _lastPoint.Y, 0, 0).Inflate(_touchRadius.Value);
var isInRect = touchRect.X < point.X && var isInRect = touchRect.X < point.X &&
touchRect.Y < point.Y && touchRect.Y < point.Y &&
touchRect.Right > point.X && touchRect.Right > point.X &&

10
src/Avalonia.Themes.Fluent/Controls/TextSelectionHandle.xaml

@ -97,21 +97,21 @@
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Style Selector="^.caret /template/ Image#PART_HandlePathIcon"> <Style Selector="^:caret /template/ Image#PART_HandlePathIcon">
<Setter Property="Source" Value="{DynamicResource TextCaretHandleDrawing}" /> <Setter Property="Source" Value="{DynamicResource TextCaretHandleDrawing}" />
</Style> </Style>
<Style Selector="^.start /template/ Image#PART_HandlePathIcon"> <Style Selector="^:start /template/ Image#PART_HandlePathIcon">
<Setter Property="RenderTransform"> <Setter Property="RenderTransform">
<ScaleTransform ScaleX="-1" ScaleY="1"/> <ScaleTransform ScaleX="-1" ScaleY="1"/>
</Setter> </Setter>
</Style> </Style>
<Style Selector="^.caret /template/ Border#PART_Indicator"> <Style Selector="^:caret /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />
</Style> </Style>
<Style Selector="^.end /template/ Border#PART_Indicator"> <Style Selector="^:end /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="HorizontalAlignment" Value="Left" />
</Style> </Style>
<Style Selector="^.start /template/ Border#PART_Indicator"> <Style Selector="^:start /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="HorizontalAlignment" Value="Right" />
</Style> </Style>
</ControlTheme> </ControlTheme>

10
src/Avalonia.Themes.Simple/Controls/TextSelectionHandle.xaml

@ -85,21 +85,21 @@
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
<Style Selector="^.caret /template/ Image#PART_HandlePathIcon"> <Style Selector="^:caret /template/ Image#PART_HandlePathIcon">
<Setter Property="Source" Value="{DynamicResource TextCaretHandleDrawing}" /> <Setter Property="Source" Value="{DynamicResource TextCaretHandleDrawing}" />
</Style> </Style>
<Style Selector="^.start /template/ Image#PART_HandlePathIcon"> <Style Selector="^:start /template/ Image#PART_HandlePathIcon">
<Setter Property="RenderTransform"> <Setter Property="RenderTransform">
<ScaleTransform ScaleX="-1" ScaleY="1"/> <ScaleTransform ScaleX="-1" ScaleY="1"/>
</Setter> </Setter>
</Style> </Style>
<Style Selector="^.caret /template/ Border#PART_Indicator"> <Style Selector="^:caret /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />
</Style> </Style>
<Style Selector="^.end /template/ Border#PART_Indicator"> <Style Selector="^:end /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="HorizontalAlignment" Value="Left" />
</Style> </Style>
<Style Selector="^.start /template/ Border#PART_Indicator"> <Style Selector="^:start /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="HorizontalAlignment" Value="Right" />
</Style> </Style>
</ControlTheme> </ControlTheme>

Loading…
Cancel
Save