Skip to content

Commit f28d919

Browse files
committed
Add SquircleClipAttach
1 parent f8d2c9d commit f28d919

File tree

7 files changed

+16153
-12008
lines changed

7 files changed

+16153
-12008
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//https://github.com/cnbluefire/Squircle.Windows
2+
3+
namespace DevWinUI;
4+
5+
internal partial class CompositionPathBuilder : SquirclePathBuilder
6+
{
7+
public CompositionPath? CreateGeometry()
8+
{
9+
var win2dPathBuilder = new Win2DPathBuilder();
10+
this.CopyTo(win2dPathBuilder);
11+
12+
using var geometry = win2dPathBuilder.CreateGeometry(null);
13+
if (geometry != null)
14+
{
15+
return new CompositionPath(geometry);
16+
}
17+
return null;
18+
}
19+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//https://github.com/cnbluefire/Squircle.Windows
2+
3+
namespace DevWinUI;
4+
5+
public static partial class SquircleClipAttach
6+
{
7+
private readonly static object BoxedCornerRadius = new Microsoft.UI.Xaml.CornerRadius(0);
8+
private readonly static object BoxedDouble = 0d;
9+
10+
public static Microsoft.UI.Xaml.CornerRadius GetCornerRadius(FrameworkElement obj)
11+
{
12+
return (Microsoft.UI.Xaml.CornerRadius)obj.GetValue(CornerRadiusProperty);
13+
}
14+
15+
public static void SetCornerRadius(FrameworkElement obj, Microsoft.UI.Xaml.CornerRadius value)
16+
{
17+
obj.SetValue(CornerRadiusProperty, value);
18+
}
19+
20+
public static readonly DependencyProperty CornerRadiusProperty =
21+
DependencyProperty.RegisterAttached("CornerRadius", typeof(Microsoft.UI.Xaml.CornerRadius), typeof(SquircleClipAttach), new PropertyMetadata(BoxedCornerRadius, OnPropertyChanged));
22+
23+
public static double GetCornerSmoothing(FrameworkElement obj)
24+
{
25+
return (double)obj.GetValue(CornerSmoothingProperty);
26+
}
27+
28+
public static void SetCornerSmoothing(FrameworkElement obj, double value)
29+
{
30+
obj.SetValue(CornerSmoothingProperty, value);
31+
}
32+
33+
public static readonly DependencyProperty CornerSmoothingProperty =
34+
DependencyProperty.RegisterAttached("CornerSmoothing", typeof(double), typeof(SquircleClipAttach), new PropertyMetadata(BoxedDouble, OnPropertyChanged));
35+
36+
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
37+
{
38+
if (d is FrameworkElement sender && !Equals(e.NewValue, e.OldValue))
39+
{
40+
var cornerRadius = GetCornerRadius(sender);
41+
var cornerSmoothing = GetCornerSmoothing(sender);
42+
43+
var props = new SquircleProperties(
44+
sender.ActualWidth,
45+
sender.ActualHeight,
46+
cornerRadius.ToCornerRadius(),
47+
cornerSmoothing,
48+
true);
49+
50+
sender.SizeChanged -= OnSizeChanged;
51+
52+
if (SquircleFactory.IsValidProperties(in props, false))
53+
{
54+
sender.SizeChanged += OnSizeChanged;
55+
}
56+
57+
UpdateElementCorner(sender, in props);
58+
}
59+
60+
static void OnSizeChanged(object _sender, SizeChangedEventArgs _e)
61+
{
62+
if (_sender is FrameworkElement _element)
63+
{
64+
var _cornerRadius = GetCornerRadius(_element);
65+
var _cornerSmoothing = GetCornerSmoothing(_element);
66+
67+
UpdateElementCorner(
68+
_element,
69+
new SquircleProperties(
70+
_e.NewSize.Width,
71+
_e.NewSize.Height,
72+
_cornerRadius.ToCornerRadius(),
73+
_cornerSmoothing,
74+
true));
75+
}
76+
}
77+
78+
static void UpdateElementCorner(FrameworkElement? _element, in SquircleProperties _props)
79+
{
80+
const string SquircleClipCommit = "_SQUIRCLE_CLIP";
81+
82+
if (_element == null) return;
83+
84+
var _visual = ElementCompositionPreview.GetElementVisual(_element);
85+
var _compositor = _visual.Compositor;
86+
87+
var _pathBuilder = SquircleFactory.CreateGeometry(in _props, () => new CompositionPathBuilder());
88+
var _path = _pathBuilder?.CreateGeometry();
89+
if (_path == null)
90+
{
91+
if (_visual.Clip is CompositionGeometricClip _clip
92+
&& _visual.Clip.Comment == SquircleClipCommit
93+
&& _clip.Geometry is CompositionPathGeometry _pathGeometry)
94+
{
95+
_pathGeometry.Path = null;
96+
}
97+
}
98+
else
99+
{
100+
if (_visual.Clip is CompositionGeometricClip _clip
101+
&& _visual.Clip.Comment == SquircleClipCommit
102+
&& _clip.Geometry is CompositionPathGeometry _pathGeometry)
103+
{
104+
_pathGeometry.Path = _path;
105+
}
106+
else
107+
{
108+
_pathGeometry = _compositor.CreatePathGeometry(_path);
109+
_clip = _compositor.CreateGeometricClip(_pathGeometry);
110+
_clip.Comment = SquircleClipCommit;
111+
_visual.Clip = _clip;
112+
}
113+
}
114+
}
115+
}
116+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//https://github.com/cnbluefire/Squircle.Windows
2+
3+
namespace DevWinUI;
4+
5+
public static partial class SquircleCornerRadiusExtensions
6+
{
7+
public static SquircleCornerRadius ToCornerRadius(this Microsoft.UI.Xaml.CornerRadius cornerRadius)
8+
{
9+
return new SquircleCornerRadius(cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft);
10+
}
11+
12+
public static Microsoft.UI.Xaml.CornerRadius ToCornerRadius(this SquircleCornerRadius cornerRadius)
13+
{
14+
return new Microsoft.UI.Xaml.CornerRadius(cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft);
15+
}
16+
}

0 commit comments

Comments
 (0)