From 93f6d3196650c2f27c29b24530db7a038f8ef705 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Tue, 17 Jan 2023 13:48:30 +0000 Subject: [PATCH] support single scroll snap on pointer wheel --- .../Presenters/ScrollContentPresenter.cs | 80 ++++++++++++++++--- 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs index 0f8a8bd965..2326699c36 100644 --- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs @@ -607,6 +607,30 @@ namespace Avalonia.Controls.Presenters if (Extent.Height > Viewport.Height) { double height = isLogical ? scrollable!.ScrollSize.Height : 50; + if(VerticalSnapPointsType == SnapPointsType.MandatorySingle && Content is IScrollSnapPointsInfo) + { + if(_areVerticalSnapPointsRegular) + { + height = _verticalSnapPoint; + } + else + { + double yOffset = Offset.Y; + switch (VerticalSnapPointsAlignment) + { + case SnapPointsAlignment.Center: + yOffset += Viewport.Height / 2; + break; + case SnapPointsAlignment.Far: + yOffset += Viewport.Height; + break; + } + + var snapPoint = FindNearestSnapPoint(_verticalSnapPoints, yOffset, out var lowerSnapPoint); + + height = snapPoint - lowerSnapPoint; + } + } y += -delta.Y * height; y = Math.Max(y, 0); y = Math.Min(y, Extent.Height - Viewport.Height); @@ -615,6 +639,30 @@ namespace Avalonia.Controls.Presenters if (Extent.Width > Viewport.Width) { double width = isLogical ? scrollable!.ScrollSize.Width : 50; + if (HorizontalSnapPointsType == SnapPointsType.MandatorySingle && Content is IScrollSnapPointsInfo) + { + if (_areHorizontalSnapPointsRegular) + { + width = _horizontalSnapPoint; + } + else + { + double xOffset = Offset.X; + switch (VerticalSnapPointsAlignment) + { + case SnapPointsAlignment.Center: + xOffset += Viewport.Width / 2; + break; + case SnapPointsAlignment.Far: + xOffset += Viewport.Width; + break; + } + + var snapPoint = FindNearestSnapPoint(_horizontalSnapPoints, xOffset, out var lowerSnapPoint); + + width = snapPoint - lowerSnapPoint; + } + } x += -delta.X * width; x = Math.Max(x, 0); x = Math.Min(x, Extent.Width - Viewport.Width); @@ -903,19 +951,6 @@ namespace Avalonia.Controls.Presenters } - double FindNearestSnapPoint(IReadOnlyList snapPoints, double value, out double lowerSnapPoint) - { - var point = snapPoints.BinarySearch(value, Comparer.Default); - - if (point < 0) - { - point = ~point; - } - - lowerSnapPoint = snapPoints[Math.Max(0, point - 1)]; - return snapPoints[Math.Min(point, snapPoints.Count - 1)]; - } - Vector GetAlignedDiff() { var vector = offset; @@ -945,5 +980,24 @@ namespace Avalonia.Controls.Presenters return offset; } + + private static double FindNearestSnapPoint(IReadOnlyList snapPoints, double value, out double lowerSnapPoint) + { + var point = snapPoints.BinarySearch(value, Comparer.Default); + + if (point < 0) + { + point = ~point; + + lowerSnapPoint = snapPoints[Math.Max(0, point - 1)]; + } + else + { + lowerSnapPoint = snapPoints[point]; + + point += 1; + } + return snapPoints[Math.Min(point, snapPoints.Count - 1)]; + } } }