Skip to content

Commit e8bb8fb

Browse files
committed
Add IsRounded Property for CompositionShadow
1 parent 4ba2218 commit e8bb8fb

4 files changed

Lines changed: 87 additions & 11 deletions

File tree

dev/DevWinUI.Controls/Controls/Win2DAndComposition/CompositionShadow/CompositionShadow.Properties.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,22 @@ private static async void OnImageSourceForEdgeColorChanged(DependencyObject d, D
128128
await ctl.UpdateColorFromImageAsync();
129129
}
130130
}
131+
132+
public bool IsRounded
133+
{
134+
get { return (bool)GetValue(IsRoundedProperty); }
135+
set { SetValue(IsRoundedProperty, value); }
136+
}
137+
138+
public static readonly DependencyProperty IsRoundedProperty =
139+
DependencyProperty.Register(nameof(IsRounded), typeof(bool), typeof(CompositionShadow), new PropertyMetadata(false, OnIsRoundedChanged));
140+
141+
private static void OnIsRoundedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
142+
{
143+
var ctl = (CompositionShadow)d;
144+
if (ctl != null)
145+
{
146+
ctl.UpdateIsRounded();
147+
}
148+
}
131149
}

dev/DevWinUI.Controls/Controls/Win2DAndComposition/CompositionShadow/CompositionShadow.cs

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ public partial class CompositionShadow : Control
1515
public DropShadow DropShadow => _dropShadow;
1616

1717
public SpriteVisual Visual => _shadowVisual;
18+
public Compositor compositor;
1819

20+
private bool _isCustomMask;
1921
public CompositionBrush Mask
2022
{
2123
get => _dropShadow?.Mask;
@@ -24,6 +26,7 @@ public CompositionBrush Mask
2426
if (_dropShadow != null)
2527
{
2628
_dropShadow.Mask = value;
29+
_isCustomMask = value != null; // mark that user provided a mask
2730
}
2831
}
2932
}
@@ -32,7 +35,7 @@ public CompositionShadow()
3235
this.DefaultStyleKey = typeof(CompositionShadow);
3336
this.SizeChanged += CompositionShadow_SizeChanged;
3437
this.Loaded += CompositionShadow_Loaded;
35-
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
38+
compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
3639

3740
_shadowVisual = compositor.CreateSpriteVisual();
3841
_dropShadow = compositor.CreateDropShadow();
@@ -70,7 +73,15 @@ private void CompositionShadow_SizeChanged(object sender, SizeChangedEventArgs e
7073

7174
private void ConfigureShadowVisualForContent()
7275
{
73-
UpdateShadowMask();
76+
if (IsRounded)
77+
{
78+
UpdateIsRounded();
79+
}
80+
else
81+
{
82+
UpdateShadowMask();
83+
}
84+
7485
UpdateShadowSize();
7586

7687
if (_dropShadow != null)
@@ -87,25 +98,26 @@ private void UpdateShadowMask()
8798
if (_dropShadow == null)
8899
return;
89100

90-
if (Content != null)
101+
// If IsRounded is true, always use rounded mask
102+
if (IsRounded)
103+
return; // Mask is already set in UpdateIsRounded
104+
105+
// Only auto-generate mask if user hasn't set a custom mask
106+
if (!_isCustomMask && Content != null)
91107
{
92108
CompositionBrush mask = null;
93109
if (Content is Image image)
94-
{
95110
mask = image.GetAlphaMask();
96-
}
97111
else if (Content is Shape shape)
98-
{
99112
mask = shape.GetAlphaMask();
100-
}
101113
else if (Content is TextBlock textBlock)
102-
{
103114
mask = textBlock.GetAlphaMask();
104-
}
115+
105116
_dropShadow.Mask = mask;
106117
}
107-
else
118+
else if (!_isCustomMask)
108119
{
120+
// fallback if Content is null or unsupported
109121
_dropShadow.Mask = null;
110122
}
111123
}
@@ -156,4 +168,37 @@ private async Task UpdateColorFromImageAsync()
156168
Color = Colors.Black;
157169
}
158170
}
171+
172+
private void UpdateIsRounded()
173+
{
174+
if (IsRounded)
175+
{
176+
float width = (float)this.ActualWidth;
177+
float height = (float)this.ActualHeight;
178+
float radius = MathF.Min(width, height) / 2f;
179+
180+
var ellipse = compositor.CreateEllipseGeometry();
181+
ellipse.Center = new Vector2(width / 2f, height / 2f);
182+
ellipse.Radius = new Vector2(radius, radius);
183+
184+
var shape = compositor.CreateSpriteShape(ellipse);
185+
shape.FillBrush = compositor.CreateColorBrush(Colors.White);
186+
187+
var shapeVisual = compositor.CreateShapeVisual();
188+
shapeVisual.Size = new Vector2(width, height);
189+
shapeVisual.Shapes.Add(shape);
190+
191+
var visualSurface = compositor.CreateVisualSurface();
192+
visualSurface.SourceVisual = shapeVisual;
193+
visualSurface.SourceSize = new Vector2(width, height);
194+
195+
var maskBrush = compositor.CreateSurfaceBrush(visualSurface);
196+
197+
_dropShadow.Mask = maskBrush;
198+
}
199+
else
200+
{
201+
UpdateShadowMask();
202+
}
203+
}
159204
}

dev/DevWinUI.Controls/Themes/Generic.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17372,11 +17372,13 @@ Themes\Styles\Controls\WaveProgressBar.xaml
1737217372
<Setter Property="IsTabStop" Value="False" />
1737317373
<Setter Property="CompactPaneLength" Value="{ThemeResource RailNavigationViewCompactPaneLength}" />
1737417374
<Setter Property="CornerRadius" Value="{ThemeResource OverlayCornerRadius}" />
17375-
<Setter Property="MenuItemContainerStyle" Value="{StaticResource NavigationViewItemStoreStyle}" />
1737617375
<Setter Property="Template">
1737717376
<Setter.Value>
1737817377
<ControlTemplate TargetType="NavigationView">
1737917378
<Grid x:Name="RootGrid">
17379+
<Grid.Resources>
17380+
<Style TargetType="NavigationViewItem" BasedOn="{StaticResource NavigationViewItemStoreStyle}" />
17381+
</Grid.Resources>
1738017382
<VisualStateManager.VisualStateGroups>
1738117383
<VisualStateGroup x:Name="DisplayModeGroup">
1738217384
<VisualState x:Name="Compact" />

dev/DevWinUI.Gallery/Views/Pages/Composition/CompositionShadowPage.xaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
IsHexInputVisible="False"
4646
IsMoreButtonVisible="False"
4747
Color="Yellow" />
48+
<ToggleSwitch x:Name="TGIsRounded"
49+
Header="Is Rounded"
50+
IsOn="True" />
4851
</StackPanel>
4952
</local:ControlExample.Pane>
5053
<StackPanel Spacing="10">
@@ -78,6 +81,14 @@
7881
<Polygon Fill="Blue"
7982
Points="50,0 0,50 50,50" />
8083
</dev:CompositionShadow>
84+
<dev:CompositionShadow Width="100"
85+
Height="100"
86+
BlurRadius="{x:Bind BlurSlider.Value, Mode=OneWay}"
87+
IsRounded="{x:Bind TGIsRounded.IsOn, Mode=OneWay}"
88+
OffsetX="{x:Bind OffsetXSlider.Value, Mode=OneWay}"
89+
OffsetY="{x:Bind OffsetYSlider.Value, Mode=OneWay}"
90+
ShadowOpacity="{x:Bind ShadowSlider.Value, Mode=OneWay}"
91+
Color="{x:Bind ColorPickerSample.Color, Mode=OneWay}" />
8192
</StackPanel>
8293

8394
</local:ControlExample>

0 commit comments

Comments
 (0)