Skip to content

Commit

Permalink
feat(snappoints): Added support for Snap Points in ScrollViewer
Browse files Browse the repository at this point in the history
  • Loading branch information
carldebilly committed Feb 25, 2021
1 parent 054a91c commit a7158b4
Show file tree
Hide file tree
Showing 17 changed files with 809 additions and 106 deletions.
7 changes: 7 additions & 0 deletions src/SamplesApp/UITests.Shared/UITests.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_SnapPoints.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\Slider\Slider_Header.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -4880,6 +4884,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_ScrollBars.xaml.cs">
<DependentUpon>ScrollViewer_ScrollBars.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_SnapPoints.xaml.cs">
<DependentUpon>ScrollViewer_SnapPoints.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\Slider\Slider_Header.xaml.cs">
<DependentUpon>Slider_Header.xaml</DependentUpon>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<Page
x:Class="UITests.Windows_UI_Xaml_Controls.ScrollViewerTests.ScrollViewer_SnapPoints"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.Windows_UI_Xaml_Controls.ScrollViewerTests"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<StackPanel>
<TextBlock>Snap Points</TextBlock>
<ComboBox x:Name="snapPointsType" SelectedIndex="3">
<ComboBoxItem>None</ComboBoxItem>
<ComboBoxItem>Optional</ComboBoxItem>
<ComboBoxItem>OptionalSingle</ComboBoxItem>
<ComboBoxItem>Mandatory</ComboBoxItem>
<ComboBoxItem>MandatorySingle</ComboBoxItem>
</ComboBox>
<ComboBox x:Name="snapPointsAlignment" SelectedIndex="0">
<ComboBoxItem>Near</ComboBoxItem>
<ComboBoxItem>Center</ComboBoxItem>
<ComboBoxItem>Far</ComboBoxItem>
</ComboBox>
<Slider x:Name="spacing" Minimum="0" Maximum="30" Value="20" />
<Slider x:Name="height" Minimum="100" Maximum="400" Value="200" />
<Border BorderBrush="Black" BorderThickness="3" Width="200" Height="{Binding Value,ElementName=height}" HorizontalAlignment="Left">
<ScrollViewer
VerticalSnapPointsType="{Binding SelectedItem.Content, ElementName=snapPointsType}"
VerticalSnapPointsAlignment="{Binding SelectedItem.Content, ElementName=snapPointsAlignment}">
<StackPanel Spacing="{Binding Value, ElementName=spacing}" x:Name="panel">
<Rectangle Fill="#9400D3" Height="75" />
<Rectangle Fill="#4B0082" Height="75" />
<Rectangle Fill="#0000FF" Height="75" />
<Rectangle Fill="#00FF00" Height="75" />
<Rectangle Fill="#FFFF00" Height="75" />
<Rectangle Fill="#FF7F00" Height="75" />
<Rectangle Fill="#FF0000" Height="75" />
<Rectangle Fill="#9400D3" Height="75" />
<Rectangle Fill="#4B0082" Height="75" />
<Rectangle Fill="#0000FF" Height="75" />
<Rectangle Fill="#00FF00" Height="75" />
<Rectangle Fill="#FFFF00" Height="75" />
<Rectangle Fill="#FF7F00" Height="75" />
<Rectangle Fill="#FF0000" Height="75" />
<Rectangle Fill="#9400D3" Height="75" />
<Rectangle Fill="#4B0082" Height="75" />
<Rectangle Fill="#0000FF" Height="75" />
<Rectangle Fill="#00FF00" Height="75" />
<Rectangle Fill="#FFFF00" Height="75" />
<Rectangle Fill="#FF7F00" Height="75" />
<Rectangle Fill="#FF0000" Height="75" />
</StackPanel>
</ScrollViewer>
</Border>
<TextBlock x:Name="points" />
</StackPanel>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Uno.UI.Samples.Controls;

namespace UITests.Windows_UI_Xaml_Controls.ScrollViewerTests
{
[Sample("ScrollViewer")]
public sealed partial class ScrollViewer_SnapPoints : Page
{
public ScrollViewer_SnapPoints()
{
this.InitializeComponent();

panel.VerticalSnapPointsChanged += SnapPointsChanged;
}

private void SnapPointsChanged(object sender, object e)
{
if (panel.AreVerticalSnapPointsRegular)
{
points.Text = "Regular";
}
else
{
var near = string.Join(", ", panel.GetIrregularSnapPoints(Orientation.Vertical, SnapPointsAlignment.Near));
var center = string.Join(", ", panel.GetIrregularSnapPoints(Orientation.Vertical, SnapPointsAlignment.Center));
var far = string.Join(", ", panel.GetIrregularSnapPoints(Orientation.Vertical, SnapPointsAlignment.Far));
points.Text = $"near: {near}\ncenter: {center}\nfar: {far}";
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,6 @@ public bool AreScrollSnapPointsRegular
}
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public bool AreHorizontalSnapPointsRegular
{
get
{
throw new global::System.NotImplementedException("The member bool StackPanel.AreHorizontalSnapPointsRegular is not implemented in Uno.");
}
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public bool AreVerticalSnapPointsRegular
{
get
{
throw new global::System.NotImplementedException("The member bool StackPanel.AreVerticalSnapPointsRegular is not implemented in Uno.");
}
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public static global::Windows.UI.Xaml.DependencyProperty AreScrollSnapPointsRegularProperty { get; } =
Windows.UI.Xaml.DependencyProperty.Register(
nameof(AreScrollSnapPointsRegular), typeof(bool),
typeof(global::Windows.UI.Xaml.Controls.StackPanel),
new FrameworkPropertyMetadata(default(bool)));
#endif
// Skipping already declared property OrientationProperty
// Skipping already declared property BorderBrushProperty
// Skipping already declared property BorderThicknessProperty
Expand Down Expand Up @@ -109,20 +81,6 @@ public bool AreVerticalSnapPointsRegular
// Forced skipping of method Windows.UI.Xaml.Controls.StackPanel.VerticalSnapPointsChanged.remove
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::System.Collections.Generic.IReadOnlyList<float> GetIrregularSnapPoints( global::Windows.UI.Xaml.Controls.Orientation orientation, global::Windows.UI.Xaml.Controls.Primitives.SnapPointsAlignment alignment)
{
throw new global::System.NotImplementedException("The member IReadOnlyList<float> StackPanel.GetIrregularSnapPoints(Orientation orientation, SnapPointsAlignment alignment) is not implemented in Uno.");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public float GetRegularSnapPoints( global::Windows.UI.Xaml.Controls.Orientation orientation, global::Windows.UI.Xaml.Controls.Primitives.SnapPointsAlignment alignment, out float offset)
{
throw new global::System.NotImplementedException("The member float StackPanel.GetRegularSnapPoints(Orientation orientation, SnapPointsAlignment alignment, out float offset) is not implemented in Uno.");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public void GetInsertionIndexes( global::Windows.Foundation.Point position, out int first, out int second)
{
throw new global::System.NotImplementedException("The member void StackPanel.GetInsertionIndexes(Point position, out int first, out int second) is not implemented in Uno.");
Expand All @@ -136,38 +94,6 @@ public void GetInsertionIndexes( global::Windows.Foundation.Point position, out
// Forced skipping of method Windows.UI.Xaml.Controls.StackPanel.PaddingProperty.get
// Forced skipping of method Windows.UI.Xaml.Controls.StackPanel.AreScrollSnapPointsRegularProperty.get
// Forced skipping of method Windows.UI.Xaml.Controls.StackPanel.OrientationProperty.get
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public event global::System.EventHandler<object> HorizontalSnapPointsChanged
{
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
add
{
global::Windows.Foundation.Metadata.ApiInformation.TryRaiseNotImplemented("Windows.UI.Xaml.Controls.StackPanel", "event EventHandler<object> StackPanel.HorizontalSnapPointsChanged");
}
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
remove
{
global::Windows.Foundation.Metadata.ApiInformation.TryRaiseNotImplemented("Windows.UI.Xaml.Controls.StackPanel", "event EventHandler<object> StackPanel.HorizontalSnapPointsChanged");
}
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public event global::System.EventHandler<object> VerticalSnapPointsChanged
{
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
add
{
global::Windows.Foundation.Metadata.ApiInformation.TryRaiseNotImplemented("Windows.UI.Xaml.Controls.StackPanel", "event EventHandler<object> StackPanel.VerticalSnapPointsChanged");
}
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
remove
{
global::Windows.Foundation.Metadata.ApiInformation.TryRaiseNotImplemented("Windows.UI.Xaml.Controls.StackPanel", "event EventHandler<object> StackPanel.VerticalSnapPointsChanged");
}
}
#endif
// Processing: Windows.UI.Xaml.Controls.Primitives.IScrollSnapPointsInfo
// Processing: Windows.UI.Xaml.Controls.IInsertionPanel
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.IO;
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml.Controls.Primitives;

namespace Windows.UI.Xaml.Controls
{
Expand Down Expand Up @@ -101,7 +102,9 @@ public ScrollContentPresenter()
RegisterAsScrollPort(this);
}

public void SetVerticalOffset(double offset)
public void SetVerticalOffset(double offset) => SetVerticalOffsetInternal(offset);

internal bool SetVerticalOffsetInternal(double offset)
{
var extentHeight = ExtentHeight;
var viewportHeight = ViewportHeight;
Expand All @@ -114,9 +117,13 @@ public void SetVerticalOffset(double offset)
}

UpdateTransform();

return scrollY == offset;
}

public void SetHorizontalOffset(double offset)
public void SetHorizontalOffset(double offset) => SetHorizontalOffsetInternal(offset);

internal bool SetHorizontalOffsetInternal(double offset)
{
var extentWidth = ExtentWidth;
var viewportWidth = ViewportWidth;
Expand All @@ -129,6 +136,8 @@ public void SetHorizontalOffset(double offset)
}

UpdateTransform();

return scrollX == offset;
}

// Ensure the offset we're scrolling to is valid.
Expand Down Expand Up @@ -186,7 +195,11 @@ private void ScrollContentPresenter_PointerWheelChanged(object sender, Input.Poi
var canScrollHorizontally = HorizontalScrollBarVisibility != ScrollBarVisibility.Disabled;
var canScrollVertically = VerticalScrollBarVisibility != ScrollBarVisibility.Disabled;

if (!canScrollVertically || properties.IsHorizontalMouseWheel || e.KeyModifiers.HasFlag(global::Windows.System.VirtualKeyModifiers.Shift))
if (e.KeyModifiers == global::Windows.System.VirtualKeyModifiers.Control)
{
// TODO: Handle zoom
}
else if (!canScrollVertically || properties.IsHorizontalMouseWheel || e.KeyModifiers == global::Windows.System.VirtualKeyModifiers.Shift)
{
if (canScrollHorizontally)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal static int GetMeasureValue(int value, ScrollBarVisibility scrollBarVisi
}
}

private bool ChangeViewScroll(double? horizontalOffset, double? verticalOffset, bool disableAnimation)
private bool ChangeViewScrollNative(double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation)
{
var physicalHorizontalOffset = ViewHelper.LogicalToPhysicalPixels(horizontalOffset ?? HorizontalOffset);
var physicalVerticalOffset = ViewHelper.LogicalToPhysicalPixels(verticalOffset ?? VerticalOffset);
Expand All @@ -56,12 +56,17 @@ private bool ChangeViewScroll(double? horizontalOffset, double? verticalOffset,
_presenter?.SmoothScrollTo(adjustedPhysicalHorizontalOffset, adjustedPhysicalVerticalOffset);
}

if (zoomFactor is { } zoom)
{
ChangeViewZoom(zoom, disableAnimation);
}

// Return true if successfully scrolled to asked offsets
return (horizontalOffset == null || physicalHorizontalOffset == adjustedPhysicalHorizontalOffset) &&
(verticalOffset == null || physicalVerticalOffset == adjustedPhysicalVerticalOffset);
}

partial void ChangeViewZoom(float zoomFactor, bool disableAnimation)
private void ChangeViewZoom(float zoomFactor, bool disableAnimation)
{
if (!disableAnimation && this.Log().IsEnabled(LogLevel.Warning))
{
Expand Down
24 changes: 18 additions & 6 deletions src/Uno.UI/UI/Xaml/Controls/ScrollViewer/ScrollViewer.Skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,33 @@ public Color BackgroundColor
private void UpdateZoomedContentAlignment() { }


private bool ChangeViewScroll(double? horizontalOffset, double? verticalOffset, bool disableAnimation)
private bool ChangeViewScrollNative(double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation)
{
if (_presenter is ScrollContentPresenter presenter)
{
if (horizontalOffset.HasValue)
bool hSuccess, vSuccess;

if (horizontalOffset is {} hOffset)
{
hSuccess = presenter.SetHorizontalOffsetInternal(hOffset);
}
else
{
presenter.SetHorizontalOffset(horizontalOffset.Value);
hSuccess = true;
}

if (verticalOffset.HasValue)
if (verticalOffset is {} vOffset)
{
presenter.SetVerticalOffset(verticalOffset.Value);
vSuccess = presenter.SetVerticalOffsetInternal(vOffset);
}
else
{
vSuccess = true;
}

// TODO: zoom factor

return true;
return hSuccess && vSuccess;
}

return false;
Expand Down
Loading

0 comments on commit a7158b4

Please sign in to comment.