Added corner radius for RadShadow

This commit is contained in:
atanas.popatanasov 2021-03-22 19:51:57 +02:00
Родитель b62e833534
Коммит 88d9166ac4
2 изменённых файлов: 1362 добавлений и 1284 удалений

Просмотреть файл

@ -1,9 +1,11 @@
using System.Numerics;
using System;
using System.Numerics;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Hosting;
using Windows.UI.Xaml.Markup;
using Windows.UI.Xaml.Shapes;
@ -51,7 +53,13 @@ namespace Telerik.UI.Xaml.Controls.Primitives
/// Identifies the <see cref="Content"/> dependency property.
/// </summary>
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register(nameof(Content), typeof(object), typeof(RadShadow), new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnContentPropertyChanged())));
DependencyProperty.Register(nameof(Content), typeof(object), typeof(RadShadow), new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((RadShadow)d).Invalidate())));
/// <summary>
/// Identifies the <see cref="CornerRadius"/> dependency property.
/// </summary>
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register(nameof(CornerRadius), typeof(int), typeof(RadShadow), new PropertyMetadata(0, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnCornerRadiusPropertyChanged())));
private const string PartShadowName = "PART_Shadow";
@ -59,6 +67,7 @@ namespace Telerik.UI.Xaml.Controls.Primitives
private SpriteVisual shadowVisual;
private DropShadow dropShadow;
private Canvas shadowView;
private Rectangle radiusMask;
/// <summary>
/// Initializes a new instance of the <see cref="RadShadow"/> class.
@ -122,6 +131,15 @@ namespace Telerik.UI.Xaml.Controls.Primitives
set { this.SetValue(ContentProperty, value); }
}
/// <summary>
/// Gets or sets the corner radius of the shadow.
/// </summary>
public int CornerRadius
{
get { return (int)this.GetValue(CornerRadiusProperty); }
set { this.SetValue(CornerRadiusProperty, value); }
}
/// <summary>
/// Use to get the shadow mask if the Content has such mask. Views like Shapes, TextBlock and Image provide masks - you can get them through the GetAlphaMask methods.
/// </summary>
@ -147,7 +165,7 @@ namespace Telerik.UI.Xaml.Controls.Primitives
return image.GetAlphaMask();
}
return null;
return this.radiusMask?.GetAlphaMask();
}
/// <inheritdoc />
@ -158,13 +176,27 @@ namespace Telerik.UI.Xaml.Controls.Primitives
var content = this.GetVisualContent();
if (content != null)
{
this.ApplyShadowMaskIfNeeded(content);
var contentPosition = content.TransformToVisual(this);
var offset = contentPosition.TransformPoint(new Point(0, 0));
this.shadowVisual.Offset = new Vector3((float)offset.X - (float)this.BorderThickness.Left, (float)offset.Y - (float)this.BorderThickness.Top, 0);
this.shadowVisual.Size = new Vector2((float)content.ActualWidth, (float)content.ActualHeight);
var x = (float)offset.X - (float)this.BorderThickness.Left;
var y = (float)offset.Y - (float)this.BorderThickness.Top;
this.shadowVisual.Offset = new Vector3(x, y, 0);
var width = content.ActualWidth;
var height = content.ActualHeight;
this.shadowVisual.Size = new Vector2((float)width, (float)height);
if (this.radiusMask != null)
{
this.radiusMask.Width = width;
this.radiusMask.Height = height;
Canvas.SetTop(this.radiusMask, y);
Canvas.SetLeft(this.radiusMask, x);
}
this.ApplyShadowMaskIfNeeded(content);
}
return size;
@ -196,6 +228,7 @@ namespace Telerik.UI.Xaml.Controls.Primitives
this.OnOffsetPropertyChanged();
this.OnBlurRadiusPropertyChanged(this.BlurRadius);
this.OnShadowOpacityPropertyChanged(this.ShadowOpacity);
this.OnCornerRadiusPropertyChanged();
this.shadowVisual.Shadow = this.dropShadow;
@ -263,7 +296,51 @@ namespace Telerik.UI.Xaml.Controls.Primitives
}
}
private void OnContentPropertyChanged()
private void OnCornerRadiusPropertyChanged()
{
if (this.shadowView == null)
{
return;
}
var cornerRadius = this.CornerRadius;
if (cornerRadius < 0)
{
throw new ArgumentException($"{cornerRadius} is an invalid value for {nameof(this.CornerRadius)}");
}
if (cornerRadius > 0)
{
if (this.radiusMask == null)
{
this.radiusMask = new Rectangle();
this.radiusMask.SetBinding(Rectangle.FillProperty, new Binding()
{
Path = new PropertyPath(nameof(this.Background)),
Source = this, Mode = BindingMode.TwoWay
});
this.shadowView.Children.Add(this.radiusMask);
}
this.radiusMask.RadiusY = cornerRadius;
this.radiusMask.RadiusX = cornerRadius;
}
else
{
if (this.shadowView.Children.Contains(this.radiusMask))
{
this.shadowView.Children.Remove(this.radiusMask);
}
this.radiusMask.ClearValue(Rectangle.FillProperty);
this.radiusMask = null;
}
this.Invalidate();
}
private void Invalidate()
{
this.invalidateShadowMask = true;
this.InvalidateArrange();

Просмотреть файл

@ -14,6 +14,7 @@
</ResourceDictionary.MergedDictionaries>
<Style TargetType="local:RadShadow">
<Setter Property="Background" Value="{ThemeResource SystemAltHighColor}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RadShadow">