Skip to content

Commit

Permalink
[Windows] Fixes border content clipping (#17310)
Browse files Browse the repository at this point in the history
* [Windows] Fixes border content clipping

Fixes clip path size to consider the border stroke thickness, so it only uses the inner space. For the space the border takes we consider both sides (top and bottom, or left and right) and not just the thickness.

On top of that, the clip should not be sentered with the content, so we need to offset it based on the contents position.

* [Windows] Fixes border content clipping

Fixes clip path size to consider the border stroke thickness, so it only uses the inner space. For the space the border takes we consider both sides (top and bottom, or left and right) and not just the thickness.

On top of that, the clip should not be sentered with the content, so we need to offset it based on the contents position.

* Fix BorderResizeContent sample

Add stroke thickness to polygon border

* Add border gallery for UI tests

* Minor fixups to the Border1 Controls.Sample.UITest

* Add border gallery ui tests

* Update border test

* Removed unnecessary .csproj changes

* Add WaitForStubControl, waiting for UI to appear

* Fix up border appium tests

* Make WaitForStubControl have label text - didn't seem to show up otherwise

* Disable test for now; will enable in a separate PR

---------

Co-authored-by: Bret Johnson <[email protected]>
Co-authored-by: Jeffrey Stedfast <[email protected]>
  • Loading branch information
3 people authored Sep 25, 2023
1 parent f09e3d5 commit ca12263
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#FFFFFF" BaseSize="168,208" />
</ItemGroup>

<ItemGroup>
<Compile Update="Elements\BordersWithVariousShapes.xaml.cs">
<DependentUpon>BordersWithVariousShapes.xaml</DependentUpon>
</Compile>
</ItemGroup>

<Import Project="$(MauiSrcDirectory)Maui.InTree.props" Condition=" '$(UseMaui)' != 'true' " />

<ItemGroup>
<MauiXaml Update="Elements\BordersWithVariousShapes.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public override string ToString()
}

List<GalleryPageFactory> _pages = new List<GalleryPageFactory> {
new GalleryPageFactory(() => new BorderGallery(), "Border Gallery"),
new GalleryPageFactory(() => new ButtonCoreGalleryPage(), "Button Gallery"),
new GalleryPageFactory(() => new CarouselViewCoreGalleryPage(), "CarouselView Gallery"),
new GalleryPageFactory(() => new CheckBoxCoreGalleryPage(), "CheckBox Gallery"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.Maui.Controls.Internals;

namespace Maui.Controls.Sample
{
[Preserve(AllMembers = true)]
public class BorderGallery : ContentViewGalleryPage
{
public BorderGallery()
{
Add(new BordersWithVariousShapes());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
x:Class="Maui.Controls.Sample.BordersWithVariousShapes"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
AutomationId="BordersWithVariousShapes">
<ContentView.Resources>
<Style x:Key="BorderStyle" TargetType="Border">
<Style.Setters>
<Setter Property="StrokeShape">
<Setter.Value>
<Ellipse />
</Setter.Value>
</Setter>
<Setter Property="WidthRequest" Value="101" />
<Setter Property="HeightRequest" Value="101" />
<Setter Property="BackgroundColor" Value="LightBlue" />
<Setter Property="StrokeThickness" Value="8" />
<Setter Property="Stroke" Value="LightGreen" />
</Style.Setters>
</Style>

<Style x:Key="BorderStyle2" TargetType="Border">
<Style.Setters>
<Setter Property="StrokeShape">
<Setter.Value>
<RoundRectangle />
</Setter.Value>
</Setter>
<Setter Property="WidthRequest" Value="101" />
<Setter Property="HeightRequest" Value="101" />
<Setter Property="BackgroundColor" Value="LightBlue" />
<Setter Property="StrokeThickness" Value="8" />
<Setter Property="Stroke" Value="LightGreen" />
</Style.Setters>
</Style>

<Style x:Key="BorderStyle3" TargetType="Border">
<Style.Setters>
<Setter Property="StrokeShape">
<Setter.Value>
<Polygon Points="40,10 70,80 10,50" StrokeThickness="3" />
</Setter.Value>
</Setter>
<Setter Property="WidthRequest" Value="101" />
<Setter Property="HeightRequest" Value="101" />
<Setter Property="BackgroundColor" Value="LightBlue" />

<Setter Property="Stroke" Value="LightGreen" />
</Style.Setters>
</Style>

<Style x:Key="ButtonIconStyle" TargetType="Label">
<Style.Setters>
<Setter Property="BackgroundColor" Value="#99FF0000" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
</Style.Setters>
</Style>
</ContentView.Resources>

<HorizontalStackLayout Margin="10,10,10,10" Spacing="10">
<VerticalStackLayout Spacing="10" VerticalOptions="Center">
<Border Style="{StaticResource BorderStyle}">
<Label
FontSize="18"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Border Style="{StaticResource BorderStyle2}">
<Label
FontSize="18"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Border Style="{StaticResource BorderStyle3}">
<Label
FontSize="18"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Label AutomationId="WaitForStubControl" Text="" />
</VerticalStackLayout>

<VerticalStackLayout Spacing="10" VerticalOptions="Center">
<Border Style="{StaticResource BorderStyle}">
<Label
FontSize="96"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Border Style="{StaticResource BorderStyle2}">
<Label
FontSize="96"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Border Style="{StaticResource BorderStyle3}">
<Label
FontSize="96"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>
</VerticalStackLayout>

<VerticalStackLayout Spacing="10" VerticalOptions="Center">
<Border Style="{StaticResource BorderStyle}">
<Label
FontSize="120"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Border Style="{StaticResource BorderStyle2}">
<Label
FontSize="120"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>

<Border Style="{StaticResource BorderStyle3}">
<Label
FontSize="120"
Style="{StaticResource ButtonIconStyle}"
Text="+"
TextColor="#0088ee" />
</Border>
</VerticalStackLayout>
</HorizontalStackLayout>

</ContentView>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;

namespace Maui.Controls.Sample
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BordersWithVariousShapes : ContentView
{
public BordersWithVariousShapes()
{
InitializeComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Graphics;

namespace Maui.Controls.Sample
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
Value="101" />
<Setter Property="BackgroundColor"
Value="LightBlue" />

<Setter Property="StrokeThickness" Value="8" />
<Setter Property="Stroke"
Value="LightGreen" />
</Style.Setters>
Expand Down
40 changes: 40 additions & 0 deletions src/Controls/tests/UITests/Tests/BorderUITests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Microsoft.Maui.Appium;
using NUnit.Framework;

namespace Microsoft.Maui.AppiumTests
{
public class BorderUITests : UITestBase
{
const string BorderGallery = "* marked:'Border Gallery'";

public BorderUITests(TestDevice device)
: base(device)
{
}

protected override void FixtureSetup()
{
base.FixtureSetup();
App.NavigateToGallery(BorderGallery);
}

protected override void FixtureTeardown()
{
base.FixtureTeardown();
App.NavigateBack();
}

// TODO: Enable this as a test once fully working
//[Test]
public void BordersWithVariousShapes()
{
App.WaitForElement("TargetView");
App.EnterText("TargetView", "BordersWithVariousShapes");
App.Tap("GoButton");

App.WaitForElement("WaitForStubControl");

VerifyScreenshot();
}
}
}
18 changes: 13 additions & 5 deletions src/Core/src/Platform/Windows/ContentPanel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable enable
using System;
using System.Numerics;
using Microsoft.Graphics.Canvas;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Platform;
Expand Down Expand Up @@ -38,7 +39,12 @@ internal FrameworkElement? Content

_borderPath?.Arrange(new global::Windows.Foundation.Rect(0, 0, finalSize.Width, finalSize.Height));

return new global::Windows.Foundation.Size(Math.Max(0, actual.Width), Math.Max(0, actual.Height));
var size = new global::Windows.Foundation.Size(Math.Max(0, actual.Width), Math.Max(0, actual.Height));

// We need to update the clip since the content's position might have changed
UpdateClip(_borderStroke?.Shape, size.Width, size.Height);

return size;
}

public ContentPanel()
Expand Down Expand Up @@ -140,13 +146,13 @@ void UpdateClip(IShape? borderShape, double width, double height)
var visual = ElementCompositionPreview.GetElementVisual(Content);
var compositor = visual.Compositor;


var pathSize = new Graphics.Rect(0, 0, width, height);
PathF? clipPath;
float strokeThickness = (float)(_borderPath?.StrokeThickness ?? 0);
// The path size should consider the space taken by the border (top and bottom, left and right)
var pathSize = new Graphics.Rect(0, 0, width - strokeThickness * 2, height - strokeThickness * 2);

if (clipGeometry is IRoundRectangle roundedRectangle)
{
float strokeThickness = (float)(_borderPath?.StrokeThickness ?? 0);
clipPath = roundedRectangle.InnerPathForBounds(pathSize, strokeThickness / 2);
IsInnerPath = true;
}
Expand All @@ -158,11 +164,13 @@ void UpdateClip(IShape? borderShape, double width, double height)

var device = CanvasDevice.GetSharedDevice();
var geometry = clipPath.AsPath(device);

var path = new CompositionPath(geometry);
var pathGeometry = compositor.CreatePathGeometry(path);
var geometricClip = compositor.CreateGeometricClip(pathGeometry);

// The clip needs to consider the content's offset in case it is in a different position because of a different alignment.
geometricClip.Offset = new Vector2(strokeThickness - Content.ActualOffset.X, strokeThickness - Content.ActualOffset.Y);

visual.Clip = geometricClip;
}
}
Expand Down

0 comments on commit ca12263

Please sign in to comment.