Skip to content

Commit

Permalink
fix(ScrollViewer): Content margin was not taken into consideration fo…
Browse files Browse the repository at this point in the history
…r Skia and WASM.

(Note for WASM; bottom or right margin in ScrollViewer cannot be scrolled to the end still need to be fixed with issue #7000)
  • Loading branch information
Agnès Zitte committed Mar 24, 2022
1 parent 6c721b1 commit 0d201d4
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,44 @@ public void ScrollViewer_Clipping()
);
}

[Test]
[AutoRetry]
// Issue needs to be fixed first for WASM for Right and Bottom Margin missing
// Details here: https://github.com/unoplatform/uno/issues/7000
[ActivePlatforms(Platform.iOS, Platform.Android)]
public void ScrollViewer_Content_Margin()
{
Run("UITests.Windows_UI_Xaml_Controls.ScrollViewerTests.ScrollViewer_Content_Margin");
_app.WaitForElement("ChildStatusTextBlock");
var rect = _app.GetPhysicalRect("OuterBorder");
var outsideColor = Color.LightBlue;
var insideColor = Color.Pink;

AssertCurrentColors("Before-Scrolled", insideColor, outsideColor, outsideColor, outsideColor, insideColor);

_app.FastTap("ScrollToRightBottomButton");
_app.Wait(TimeSpan.FromSeconds(5));
_app.WaitForText("ChildStatusTextBlock", "Scrolled");

AssertCurrentColors("After-Scrolled", insideColor, insideColor, outsideColor, outsideColor, outsideColor);

void AssertCurrentColors(string description, Color centerColor, Color topLeftColor, Color topRightColor, Color bottomLeftColor, Color bottomRightColor)
{
var screenshot = TakeScreenshot(description);

// Top / Left
ImageAssert.HasColorAt(screenshot, rect.X, rect.Y, topLeftColor);
// Top / Right
ImageAssert.HasColorAt(screenshot, rect.Right - LogicalToPhysical(1), rect.Y, topRightColor);
// Center
ImageAssert.HasColorAt(screenshot, rect.CenterX, rect.CenterY, centerColor);
// Bottom / Left
ImageAssert.HasColorAt(screenshot, rect.X, rect.Bottom - LogicalToPhysical(1), bottomLeftColor);
// Bottom / Right
ImageAssert.HasColorAt(screenshot, rect.Right - LogicalToPhysical(1), rect.Bottom - LogicalToPhysical(1), bottomRightColor);
}
}

[Test]
[AutoRetry]
public void ScrollViewer_Removed_And_Added()
Expand Down Expand Up @@ -150,27 +188,27 @@ public void ScrollViewer_Margin()
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(1), physicalRect.Y + LogicalToPhysical(1), Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.CenterX, physicalRect.Y + 21, Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(11), physicalRect.Y + LogicalToPhysical(11), Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(22), physicalRect.Y + LogicalToPhysical(22), Color.Red);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(23), physicalRect.Y + LogicalToPhysical(23), Color.Red);
// Right / Top
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(1), physicalRect.Y, Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(2), physicalRect.Y + LogicalToPhysical(1), Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(22), physicalRect.CenterY, Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(21), physicalRect.CenterY, Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(12), physicalRect.Y + LogicalToPhysical(11), Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(23), physicalRect.Y + LogicalToPhysical(22), Color.Red);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(24), physicalRect.Y + LogicalToPhysical(23), Color.Red);
// Middle
ImageAssert.HasColorAt(screenshot, physicalRect.CenterX, physicalRect.CenterY, Color.Red);
// Left / Bottom
ImageAssert.HasColorAt(screenshot, physicalRect.X, physicalRect.Bottom - LogicalToPhysical(1), Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(1), physicalRect.Bottom - LogicalToPhysical(2), Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(21), physicalRect.CenterY, Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(11), physicalRect.Bottom - LogicalToPhysical(12), Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(22), physicalRect.Bottom - LogicalToPhysical(23), Color.Red);
ImageAssert.HasColorAt(screenshot, physicalRect.X + LogicalToPhysical(23), physicalRect.Bottom - LogicalToPhysical(24), Color.Red);
// Right / Bottom
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(1), physicalRect.Bottom - LogicalToPhysical(1), Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(2), physicalRect.Bottom - LogicalToPhysical(2), Color.Blue);
ImageAssert.HasColorAt(screenshot, physicalRect.CenterX, physicalRect.Bottom - LogicalToPhysical(22), Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.CenterX, physicalRect.Bottom - LogicalToPhysical(21), Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(12), physicalRect.Bottom - LogicalToPhysical(12), Color.Orange);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(23), physicalRect.Bottom - LogicalToPhysical(23), Color.Red);
ImageAssert.HasColorAt(screenshot, physicalRect.Right - LogicalToPhysical(24), physicalRect.Bottom - LogicalToPhysical(24), Color.Red);

}
}
Expand Down
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 @@ -1789,6 +1789,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_Content_Margin.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_Fluent.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -5776,6 +5780,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_Clipping.xaml.cs">
<DependentUpon>ScrollViewer_Clipping.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_Content_Margin.xaml.cs">
<DependentUpon>ScrollViewer_Content_Margin.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\ScrollViewerTests\ScrollViewer_Fluent.xaml.cs">
<DependentUpon>ScrollViewer_Fluent.xaml</DependentUpon>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<UserControl x:Class="UITests.Windows_UI_Xaml_Controls.ScrollViewerTests.ScrollViewer_Content_Margin"
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"
d:DesignHeight="300"
d:DesignWidth="400">

<StackPanel Spacing="10"
HorizontalAlignment="Center">

<Button x:Name="ScrollToRightBottomButton"
Content="Scroll to Right | Bottom"
Click="ScrollToRightBottomButton_Click" />

<Border x:Name="OuterBorder"
Background="LightBlue">

<ScrollViewer x:Name="BothDirectionsScrollViewer"
Width="300"
Height="300"
VerticalScrollMode="Enabled"
VerticalScrollBarVisibility="Auto"
HorizontalScrollMode="Enabled"
HorizontalScrollBarVisibility="Auto">
<Border Width="500"
Height="500"
Margin="100"
Background="Pink"
BorderBrush="Red"
BorderThickness="10" />
</ScrollViewer>

</Border>

<TextBlock x:Name="ChildStatusTextBlock"
Text="Unscrolled" />
</StackPanel>
</UserControl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Uno.UI.Samples.Controls;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

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

private void ScrollToRightBottomButton_Click(object sender, object args)
{
BothDirectionsScrollViewer.ChangeView(500, 500, null, disableAnimation: true);
ChildStatusTextBlock.Text = "Scrolled";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public async Task When_ScrollViewer_Centered_With_Margin_Inside_Tall_Rectangle()

const double ScrollViewerHeight = ContentHeight + 2 * ContentMargin;
await WindowHelper.WaitForEqual(ScrollViewerHeight, () => SUT.ActualHeight);
Assert.AreEqual(ContentHeight, SUT.ExtentHeight);
Assert.AreEqual(ScrollViewerHeight, SUT.ExtentHeight);
}

[TestMethod]
Expand Down Expand Up @@ -277,7 +277,7 @@ public async Task When_ScrollViewer_Centered_With_Margin_Inside_Wide_Rectangle()

const double ScrollViewerWidth = ContentWidth + 2 * ContentMargin;
await WindowHelper.WaitForEqual(ScrollViewerWidth, () => SUT.ActualWidth);
Assert.AreEqual(ContentWidth, SUT.ExtentWidth);
Assert.AreEqual(ScrollViewerWidth, SUT.ExtentWidth);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace Windows.UI.Xaml.Controls
/// An Uno-only class which allows the <see cref="ScrollViewer"/> within a <see cref="ListViewBase"/> template
/// to host a native collection view.
/// </summary>
public sealed partial class ListViewBaseScrollContentPresenter : ScrollContentPresenter, IScrollContentPresenter, INativeScrollContentPresenter
public sealed partial class ListViewBaseScrollContentPresenter : ScrollContentPresenter, INativeScrollContentPresenter
{
public ListViewBaseScrollContentPresenter()
{
Expand Down Expand Up @@ -69,6 +69,20 @@ bool INativeScrollContentPresenter.CanVerticallyScroll
set { }
}

private double _extentWidth;
double INativeScrollContentPresenter.ExtentWidth
{
get => _extentWidth;
set => _extentWidth = value;
}

private double _extentHeight;
double INativeScrollContentPresenter.ExtentHeight
{
get => _extentHeight;
set => _extentHeight = value;
}

internal NativeListViewBase NativePanel => (Content as ItemsPresenter)?.Panel as NativeListViewBase;

public void OnMaxZoomFactorChanged(float newValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ internal interface INativeScrollContentPresenter
bool CanHorizontallyScroll { get; set; }
bool CanVerticallyScroll { get; set; }

double ExtentWidth { get; set; }
double ExtentHeight { get; set; }

object Content { get; set; }

bool Set(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,20 @@ public bool CanVerticallyScroll
set { }
}

private double _extentWidth;
double INativeScrollContentPresenter.ExtentWidth
{
get => _extentWidth;
set => _extentWidth = value;
}

private double _extentHeight;
double INativeScrollContentPresenter.ExtentHeight
{
get => _extentHeight;
set => _extentHeight = value;
}

public object Content
{
get => _content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ private static double GetHorizontalScrollWheelDelta(Size size, double delta)

public double VerticalOffset { get; private set; }

public double ExtentHeight { get; internal set; }

public double ExtentWidth { get; internal set; }

internal Size ScrollBarSize => new Size(0, 0);

internal Size? CustomContentExtent => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ public bool CanVerticallyScroll
}
}
}

public double ExtentHeight
{
get => Native?.ExtentHeight ?? 0;
set
{
if (Native is { } native)
{
native.ExtentHeight = 0;
}
}
}

public double ExtentWidth
{
get => Native?.ExtentWidth ?? 0;
set
{
if (Native is { } native)
{
native.ExtentWidth = 0;
}
}
}
#endregion

#region Native SCP to SCP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Runtime.CompilerServices;
using System.Text;
using Windows.Foundation;
using Uno.UI;
#if XAMARIN_ANDROID
using View = Android.Views.View;
using Font = Android.Graphics.Typeface;
Expand Down Expand Up @@ -104,61 +105,20 @@ bool ILayoutConstraints.IsHeightConstrained(View requester)
return this.IsHeightConstrainedSimple() ?? (Parent as ILayoutConstraints)?.IsHeightConstrained(this) ?? false;
}

public double ExtentHeight
{
get
{
if (Content is FrameworkElement fe)
{
var explicitHeight = fe.Height;
if (!explicitHeight.IsNaN())
{
return explicitHeight;
}
var canUseActualHeightAsExtent =
ActualHeight > 0 &&
fe.VerticalAlignment == VerticalAlignment.Stretch;

return canUseActualHeightAsExtent ? fe.ActualHeight : fe.DesiredSize.Height;
}

return 0d;
}
}

public double ExtentWidth
{
get
{
if (Content is FrameworkElement fe)
{
var explicitWidth = fe.Width;
if (!explicitWidth.IsNaN())
{
return explicitWidth;
}

var canUseActualWidthAsExtent =
ActualWidth > 0 &&
fe.HorizontalAlignment == HorizontalAlignment.Stretch;

return canUseActualWidthAsExtent ? fe.ActualWidth : fe.DesiredSize.Width;
}

return 0d;
}
}

public double ViewportHeight => DesiredSize.Height;

public double ViewportWidth => DesiredSize.Width;

#if UNO_HAS_MANAGED_SCROLL_PRESENTER || __WASM__
protected override Size MeasureOverride(Size size)
protected override Size MeasureOverride(Size availableSize)
{
if (Content is UIElement child)
{
var slotSize = size;
var (minSize, maxSize) = Scroller.GetMinMax();

var slotSize = availableSize
.AtMost(maxSize)
.AtLeast(minSize);

if (CanVerticallyScroll)
{
Expand All @@ -177,8 +137,8 @@ protected override Size MeasureOverride(Size size)
(child as ICustomScrollInfo)?.ApplyViewport(ref desired);

return new Size(
Math.Min(size.Width, desired.Width),
Math.Min(size.Height, desired.Height)
Math.Min(slotSize.Width, desired.Width),
Math.Min(slotSize.Height, desired.Height)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public partial class ScrollContentPresenter : ContentPresenter

public bool CanVerticallyScroll { get; set; }

public double ExtentHeight { get; internal set; }

public double ExtentWidth { get; internal set; }

internal ScrollBarVisibility VerticalScrollBarVisibility { get; set; }

internal ScrollBarVisibility HorizontalScrollBarVisibility { get; set; }
Expand Down
Loading

0 comments on commit 0d201d4

Please sign in to comment.