Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to CornerRadiusToThicknessConverter for more filters #90

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added active/CornerRadius/CornerRadius.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
149 changes: 149 additions & 0 deletions active/CornerRadius/CornerRadiusToThickness2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@

# Background

_This spec updates the existing [CornerRadiusToThicknessConverter](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Controls.Primitives.CornerRadiusToThicknessConverter) class with new filters._
MikeHillberg marked this conversation as resolved.
Show resolved Hide resolved

WinUI has a [CornerRadius](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.CornerRadius) struct that's used to define the rounding the 4 corners of a box, and the [Thickness](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Thickness) struct that's used for defining the padding or margin around the 4 sides of a box.

CornerRadius defines the radius length of the circle segment that's used to draw a rounded corner. For example the following uses 4 different radii for the 4 corners (the corners are listed in clockwise order starting from the top left corner):

```xml
<Border CornerRadius="0,20,40,60" BorderBrush="Red" BorderThickness="2" Height="100" Width="100" />
```

![Corner radius example](./CornerRadius.png)

Thickness defines 4 sides. For example the following uses 4 different values for the margins around a blue rectangle in a red box (the sides are listed in clockwise order starting from the left):

```xml
<Border BorderBrush="Red" BorderThickness="2" Height="100" Width="100" >
<Rectangle Fill="Blue" Margin="0,20,40,60" />
</Border>
```

![Thickness example](./Thickness.png)

For consistency it's useful to be able to build a Thickness out of components of a CornerRadius. For this reason the [CornerRadiusFilterConverter](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Controls.Primitives.CornerRadiusFilterConverter) exists, which can be used in Xaml markup. That converter has a [CornerRadiusFilterKind](https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Controls.Primitives.CornerRadiusFilterKind) that lets you define which parts to pull out, what's being added in this spec is update to that enum to allow more parts to be pulled out.

**Existing values:**
* FilterTopAndBottomFromLeft,
* FilterTopAndBottomFromRight,
* FilterLeftAndRightFromTop,
* FilterLeftAndRightFromBottom

**New values:**
* FilterTopFromTopLeft,
* FilterTopFromTopRight,
* FilterRightFromTopRight,
* FilterRightFromBottomRight,
* FilterBottomFromBottomRight,
* FilterBottomFromBottomLeft,
* FilterLeftFromBottomLeft,
* FilterLeftFromTopLeft,
MikeHillberg marked this conversation as resolved.
Show resolved Hide resolved

The CornerRadiusFilterConverter is also updated with a new property -- Multiplier -- which is applied during the conversion. For example, setting this to -1 negates the value.
MikeHillberg marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having trouble understanding the scenario for a negative multiplier. I tried

                    <StackPanel Orientation="Horizontal" Padding="50,0,0,0">
                        <Rectangle Height="50" Width="50" Fill="White"/>
                        <Border BorderBrush="White" BorderThickness="2" CornerRadius="30" Margin="-30">
                            <Rectangle Height="200" Width="200" Fill="Red" Opacity="0.5"/>
                        </Border>
                        <Rectangle Height="50" Width="50" Fill="White"/>
                    </StackPanel>

in a test app and the result didn't make sense.

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For once, a (hacky) use case, where this spec is also coming from is the inset corner radii of the WinUI TabView control: microsoft/microsoft-ui-xaml#2201

What negative margin does (from my understanding) is the following: If you have content, the width and height is calculated based on the available size, and the margin. If a control has 200px * 200px, and 50px margin, then it will render with an actual size of 100px * 100px. So with negative margin, the space used for rendering is 200px - (-50px + -50px) = 300px, making it render with a width and height of 300px. Since the control has a fixed position and "available size", it starts to render out of those bounds, extending into other content.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend: add some high level explanation about how the paths are using negative margins to extend out to the left and right


# Examples

This example creates a converter that creates a Thickness from a CornerRadius, where the Thickness is set to zeros except for its left, which uses the the left component of the corner's bottom/left, and then negates it. For example, this converts

CornerRadius: `10, 20, 30, 40`

Thickness: `-40, 0, 0, 0`

```xml
<CornerRadiusToThicknessConverter ConversionKind="FilterLeftFromBottomLeft" Multiplier="-1" x:Name='CornerRadiusToThickness1'/>
```

This converter can then be used elsewhere in Xaml:

```xml
<Path
Margin="{Binding Source={ThemeResource OverlayCornerRadius},
Converter={StaticResource CornerRadiusToThickness1}}"
Height="100"
Margin="100"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TYPO: Margin being set twice.

Fill="Red"
Data="M4 0 L4 4 L0 4 A4,4 90 0 0 4 0 Z" />
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like to see the results of this example. I tried pasting this into a test app and saw nothing because there is no stroke thickness or brush, and because I'm not sure what "M4 0 ..." produces. A labeled illustration would help.

Copy link
Contributor

@marcelwgn marcelwgn Jul 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, the example should show something when simply copy pasted. Fun fact, the path renders this kind of shape (the black part):

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend: everything should be copy/paste-able.



# API Notes

## CornerRadiusToThicknessConverter.Multiplier property

Type: [Thickness](https://docs.microsoft.com/uwp/api/Windows.UI.Xaml.Thickness)

Multiplied to the value in the target Thickness. Defaults to (1,1,1,1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TYPO: "Multiplied by"


This multiplier is a Thickness with left/top/right/bottom values, which are applied to the matching fields in the target. Note that in Xaml markup you can specify a single number and it's set to all 4 fields. For example the following sets the Multipler to (-1, -1, -1, -1):

```xml
Multipler = '-1'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TYPO: Multiplier.

Also, I believe XML style is to remove spaces around the = sign.

```

## CornerRadiusToThicknessConverterKind enum

**New values:**

| | |
| - | - |
| FilterTopFromTopLeft | Sets top from the top left corner |
| FilterTopFromTopRight | Sets the top from the top right corner |
| FilterRightFromTopRight | Sets the right from the top right corner |
| FilterRightFromBottomRight | Sets the right from the bottom right corner |
| FilterBottomFromBottomRight | Sets the bottom from the bottom right corner |
| FilterBottomFromBottomLeft | Sets the bottom from the bottom left corner |
| FilterLeftFromBottomLeft | Sets the left from the bottom left corner |
| FilterLeftFromTopLeft | Sets the left from the top left corner |

**Existing values:**

| | |
| - | - |
| FilterLeftAndRightFromBottom | |
| FilterLeftAndRightFromTop | |
| FilterTopAndBottomFromLeft | |
| FilterTopAndBottomFromRight | |

https://docs.microsoft.com/uwp/api/Microsoft.UI.Xaml.Controls.Primitives.CornerRadiusToThicknessConverterKind


# API Details

```cs

[webhosthidden]
[default_interface]
runtimeclass CornerRadiusToThicknessConverter : Windows.UI.Xaml.DependencyObject, Windows.UI.Xaml.Data.IValueConverter
{
CornerRadiusToThicknessConverter();

CornerRadiusToThicknessConverterKind ConversionKind{ get; set; };
static Windows.UI.Xaml.DependencyProperty ConversionKindProperty{ get; };

// ** New **
Thickness Multiplier{ get; set; };
static Windows.UI.Xaml.DependencyProperty MultiplierProperty{ get; };
};

[webhosthidden]
enum CornerRadiusToThicknessConverterKind
{
FilterTopAndBottomFromLeft,
FilterTopAndBottomFromRight,
FilterLeftAndRightFromTop,
FilterLeftAndRightFromBottom,

// New
FilterTopFromTopLeft,
FilterTopFromTopRight,
FilterRightFromTopRight,
FilterRightFromBottomRight,
FilterBottomFromBottomRight,
FilterBottomFromBottomLeft,
FilterLeftFromBottomLeft,
FilterLeftFromTopLeft,
};
```

Binary file added active/CornerRadius/Thickness.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.