Skip to content
This repository was archived by the owner on Nov 28, 2024. It is now read-only.

Commit c82af79

Browse files
authored
Merge pull request #493 from telerik/development
Merge development into master
2 parents 6e5cae5 + eebad81 commit c82af79

File tree

12 files changed

+2502
-1717
lines changed

12 files changed

+2502
-1717
lines changed

BuildTools/BuildNuGet.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
SET MSBUILD=%WINDIR%\microsoft.net\framework\v4.0.30319\MSBuild.exe
2-
%MSBUILD% BuildNuget.UWP.proj /property:Version=1.0.2.3
2+
%MSBUILD% BuildNuget.UWP.proj /property:Version=1.0.2.4

BuildTools/BuildNuget.UWP.proj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<Target Name="PrepareNugetProperties">
1616

1717
<PropertyGroup>
18-
<Version Condition= " '$(Version)' == '' ">1.0.2.3</Version>
18+
<Version Condition= " '$(Version)' == '' ">1.0.2.4</Version>
1919
<FullPathDeployDirectory>$([System.IO.Path]::GetFullPath('$(DeployDirectory)'))</FullPathDeployDirectory>
2020
<BinariesSubDir>$(BinariesTargetDirectory)</BinariesSubDir>
2121

BuildTools/Nuspecs.UWP/Package.UniversalWindowsPlatform.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<iconUrl>http://www.telerik.com/docs/default-source/nuget-feed-product-files/nugeticon_uwp.png?sfvrsn=2</iconUrl>
1212
<requireLicenseAcceptance>true</requireLicenseAcceptance>
1313
<description>UI for Universal Windows Platform is a toolset for building Universal Windows Platform apps for the Windows Store and the enterprise. The library is designed to offer the same user experience, functionality and behavior on Windows devices of all form factors.</description>
14-
<releaseNotes>For full release notes see https://github.com/telerik/UI-For-UWP/releases/tag/1.0.2.3</releaseNotes>
14+
<releaseNotes>For full release notes see https://github.com/telerik/UI-For-UWP/releases/tag/1.0.2.4</releaseNotes>
1515
<tags>UWP Windows Telerik Controls XAML C#</tags>
1616
<language>en-US</language>
1717
</metadata>

BuildTools/Nuspecs.UWP/VisualStudioToolsManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.RadCustomHubTile"/>
1111
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.RadPaginationControl"/>
1212
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.RadRadialMenu"/>
13+
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.RadShadow"/>
1314
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.RadSideDrawer"/>
1415
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.LoopingList.RadLoopingList"/>
1516
<Item Type = "Telerik.UI.Xaml.Controls.Primitives.RadHexHubTile"/>

Controls/Primitives/Primitives.UWP/Primitives.UWP.csproj

Lines changed: 454 additions & 452 deletions
Large diffs are not rendered by default.
Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
using System;
2+
using System.Numerics;
3+
using Windows.Foundation;
4+
using Windows.UI;
5+
using Windows.UI.Composition;
6+
using Windows.UI.Xaml;
7+
using Windows.UI.Xaml.Controls;
8+
using Windows.UI.Xaml.Data;
9+
using Windows.UI.Xaml.Hosting;
10+
using Windows.UI.Xaml.Markup;
11+
using Windows.UI.Xaml.Shapes;
12+
13+
namespace Telerik.UI.Xaml.Controls.Primitives
14+
{
15+
/// <summary>
16+
/// Represents a control that enables a user to show a shadow around another view.
17+
/// </summary>
18+
[TemplatePart(Name = "PART_Shadow", Type = typeof(Canvas))]
19+
[ContentProperty(Name = nameof(Content))]
20+
public class RadShadow : RadControl
21+
{
22+
/// <summary>
23+
/// Identifies the <see cref="Color"/> dependency property.
24+
/// </summary>
25+
public static readonly DependencyProperty ColorProperty =
26+
DependencyProperty.Register(nameof(Color), typeof(Color), typeof(RadShadow), new PropertyMetadata(Colors.Black, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnColorPropertyChanged())));
27+
28+
/// <summary>
29+
/// Identifies the <see cref="OffsetX"/> dependency property.
30+
/// </summary>
31+
public static readonly DependencyProperty OffsetXProperty =
32+
DependencyProperty.Register(nameof(OffsetX), typeof(double), typeof(RadShadow), new PropertyMetadata(0.0, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnOffsetPropertyChanged())));
33+
34+
/// <summary>
35+
/// Identifies the <see cref="OffsetY"/> dependency property.
36+
/// </summary>
37+
public static readonly DependencyProperty OffsetYProperty =
38+
DependencyProperty.Register(nameof(OffsetY), typeof(double), typeof(RadShadow), new PropertyMetadata(0.0, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnOffsetPropertyChanged())));
39+
40+
/// <summary>
41+
/// Identifies the <see cref="BlurRadius"/> dependency property.
42+
/// </summary>
43+
public static readonly DependencyProperty BlurRadiusProperty =
44+
DependencyProperty.Register(nameof(BlurRadius), typeof(double), typeof(RadShadow), new PropertyMetadata(9.0, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnBlurRadiusPropertyChanged())));
45+
46+
/// <summary>
47+
/// Identifies the <see cref="ShadowOpacity"/> dependency property.
48+
/// </summary>
49+
public static readonly DependencyProperty ShadowOpacityProperty =
50+
DependencyProperty.Register(nameof(ShadowOpacity), typeof(double), typeof(RadShadow), new PropertyMetadata(0.26, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnShadowOpacityPropertyChanged())));
51+
52+
/// <summary>
53+
/// Identifies the <see cref="Content"/> dependency property.
54+
/// </summary>
55+
public static readonly DependencyProperty ContentProperty =
56+
DependencyProperty.Register(nameof(Content), typeof(object), typeof(RadShadow), new PropertyMetadata(null, new PropertyChangedCallback((d, e) => ((RadShadow)d).Invalidate())));
57+
58+
/// <summary>
59+
/// Identifies the <see cref="CornerRadius"/> dependency property.
60+
/// </summary>
61+
public static readonly DependencyProperty CornerRadiusProperty =
62+
DependencyProperty.Register(nameof(CornerRadius), typeof(double), typeof(RadShadow), new PropertyMetadata(0.0d, new PropertyChangedCallback((d, e) => ((RadShadow)d).OnCornerRadiusPropertyChanged())));
63+
64+
private const string PartShadowName = "PART_Shadow";
65+
66+
private bool invalidateShadowMask;
67+
private SpriteVisual shadowVisual;
68+
private DropShadow dropShadow;
69+
private Canvas shadowView;
70+
private Rectangle radiusMask;
71+
72+
/// <summary>
73+
/// Initializes a new instance of the <see cref="RadShadow"/> class.
74+
/// </summary>
75+
public RadShadow()
76+
{
77+
this.DefaultStyleKey = typeof(RadShadow);
78+
}
79+
80+
/// <summary>
81+
/// Gets or sets the color of the shadow.
82+
/// </summary>
83+
public Color Color
84+
{
85+
get { return (Color)this.GetValue(ColorProperty); }
86+
set { this.SetValue(ColorProperty, value); }
87+
}
88+
89+
/// <summary>
90+
/// Gets or sets the X offset of the shadow from its content.
91+
/// </summary>
92+
public double OffsetX
93+
{
94+
get { return (double)this.GetValue(OffsetXProperty); }
95+
set { this.SetValue(OffsetXProperty, value); }
96+
}
97+
98+
/// <summary>
99+
/// Gets or sets the Y offset of the shadow from its content.
100+
/// </summary>
101+
public double OffsetY
102+
{
103+
get { return (double)this.GetValue(OffsetYProperty); }
104+
set { this.SetValue(OffsetYProperty, value); }
105+
}
106+
107+
/// <summary>
108+
/// Gets or sets the blur radius of the shadow.
109+
/// </summary>
110+
public double BlurRadius
111+
{
112+
get { return (double)this.GetValue(BlurRadiusProperty); }
113+
set { this.SetValue(BlurRadiusProperty, value); }
114+
}
115+
116+
/// <summary>
117+
/// Gets or sets the opacity of the shadow.
118+
/// </summary>
119+
public double ShadowOpacity
120+
{
121+
get { return (double)this.GetValue(ShadowOpacityProperty); }
122+
set { this.SetValue(ShadowOpacityProperty, value); }
123+
}
124+
125+
/// <summary>
126+
/// Gets or sets the content of the RadShadow.
127+
/// </summary>
128+
public object Content
129+
{
130+
get { return (object)this.GetValue(ContentProperty); }
131+
set { this.SetValue(ContentProperty, value); }
132+
}
133+
134+
/// <summary>
135+
/// Gets or sets the corner radius of the shadow.
136+
/// </summary>
137+
public double CornerRadius
138+
{
139+
get { return (double)this.GetValue(CornerRadiusProperty); }
140+
set { this.SetValue(CornerRadiusProperty, value); }
141+
}
142+
143+
/// <summary>
144+
/// 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.
145+
/// </summary>
146+
/// <param name="content">The content of the shadow control.</param>
147+
/// <returns>The alpha mask applied to the shadow.</returns>
148+
public virtual CompositionBrush GetShadowMask(FrameworkElement content)
149+
{
150+
var shape = content as Shape;
151+
if (shape != null)
152+
{
153+
return shape.GetAlphaMask();
154+
}
155+
156+
var textBlock = content as TextBlock;
157+
if (textBlock != null)
158+
{
159+
return textBlock.GetAlphaMask();
160+
}
161+
162+
var image = content as Image;
163+
if (image != null)
164+
{
165+
return image.GetAlphaMask();
166+
}
167+
168+
return this.radiusMask?.GetAlphaMask();
169+
}
170+
171+
/// <inheritdoc />
172+
protected override Size ArrangeOverride(Size finalSize)
173+
{
174+
var size = base.ArrangeOverride(finalSize);
175+
176+
var content = this.GetVisualContent();
177+
if (content != null)
178+
{
179+
var contentPosition = content.TransformToVisual(this);
180+
var offset = contentPosition.TransformPoint(new Point(0, 0));
181+
182+
var x = (float)offset.X - (float)this.BorderThickness.Left;
183+
var y = (float)offset.Y - (float)this.BorderThickness.Top;
184+
this.shadowVisual.Offset = new Vector3(x, y, 0);
185+
186+
var width = content.ActualWidth;
187+
var height = content.ActualHeight;
188+
this.shadowVisual.Size = new Vector2((float)width, (float)height);
189+
190+
if (this.radiusMask != null)
191+
{
192+
this.radiusMask.Width = width;
193+
this.radiusMask.Height = height;
194+
195+
Canvas.SetTop(this.radiusMask, y);
196+
Canvas.SetLeft(this.radiusMask, x);
197+
}
198+
199+
this.ApplyShadowMaskIfNeeded(content);
200+
}
201+
202+
return size;
203+
}
204+
205+
/// <inheritdoc />
206+
protected override bool ApplyTemplateCore()
207+
{
208+
bool applied = base.ApplyTemplateCore();
209+
210+
this.shadowView = this.GetTemplatePartField<Canvas>(PartShadowName);
211+
applied = applied && this.shadowView != null;
212+
213+
if (applied)
214+
{
215+
this.InitializeDropShadow();
216+
}
217+
218+
return applied;
219+
}
220+
221+
private void InitializeDropShadow()
222+
{
223+
var compositor = ElementCompositionPreview.GetElementVisual(this.shadowView).Compositor;
224+
this.shadowVisual = compositor.CreateSpriteVisual();
225+
this.dropShadow = compositor.CreateDropShadow();
226+
227+
this.OnColorPropertyChanged();
228+
this.OnOffsetPropertyChanged();
229+
this.OnBlurRadiusPropertyChanged();
230+
this.OnShadowOpacityPropertyChanged();
231+
this.OnCornerRadiusPropertyChanged();
232+
233+
this.shadowVisual.Shadow = this.dropShadow;
234+
235+
ElementCompositionPreview.SetElementChildVisual(this.shadowView, this.shadowVisual);
236+
}
237+
238+
private void ApplyShadowMaskIfNeeded(FrameworkElement content)
239+
{
240+
if (!this.invalidateShadowMask)
241+
{
242+
return;
243+
}
244+
245+
this.invalidateShadowMask = false;
246+
247+
this.dropShadow.Mask = this.GetShadowMask(content);
248+
}
249+
250+
private FrameworkElement GetVisualContent()
251+
{
252+
var content = this.Content;
253+
if (content == null)
254+
{
255+
return null;
256+
}
257+
258+
FrameworkElement visualContent = this.Content as FrameworkElement;
259+
if (visualContent == null)
260+
{
261+
visualContent = ElementTreeHelper.FindVisualDescendant<TextBlock>(this);
262+
}
263+
264+
return visualContent;
265+
}
266+
267+
private void OnColorPropertyChanged()
268+
{
269+
if (this.dropShadow != null)
270+
{
271+
this.dropShadow.Color = this.Color;
272+
}
273+
}
274+
275+
private void OnOffsetPropertyChanged()
276+
{
277+
if (this.dropShadow != null)
278+
{
279+
this.dropShadow.Offset = new Vector3((float)this.OffsetX, (float)this.OffsetY, 0f);
280+
}
281+
}
282+
283+
private void OnBlurRadiusPropertyChanged()
284+
{
285+
if (this.dropShadow != null)
286+
{
287+
this.dropShadow.BlurRadius = (float)this.BlurRadius;
288+
}
289+
}
290+
291+
private void OnShadowOpacityPropertyChanged()
292+
{
293+
if (this.dropShadow != null)
294+
{
295+
this.dropShadow.Opacity = (float)this.ShadowOpacity;
296+
}
297+
}
298+
299+
private void OnCornerRadiusPropertyChanged()
300+
{
301+
if (this.shadowView == null)
302+
{
303+
return;
304+
}
305+
306+
var cornerRadius = this.CornerRadius;
307+
if (cornerRadius < 0)
308+
{
309+
throw new ArgumentException($"{cornerRadius} is an invalid value for {nameof(this.CornerRadius)}");
310+
}
311+
312+
if (cornerRadius > 0)
313+
{
314+
if (this.radiusMask == null)
315+
{
316+
this.radiusMask = new Rectangle();
317+
this.radiusMask.SetBinding(Rectangle.FillProperty, new Binding() { Path = new PropertyPath(nameof(this.Background)), Source = this, Mode = BindingMode.TwoWay });
318+
this.shadowView.Children.Add(this.radiusMask);
319+
}
320+
321+
this.radiusMask.RadiusY = cornerRadius;
322+
this.radiusMask.RadiusX = cornerRadius;
323+
}
324+
else
325+
{
326+
if (this.shadowView.Children.Contains(this.radiusMask))
327+
{
328+
this.shadowView.Children.Remove(this.radiusMask);
329+
}
330+
331+
this.radiusMask?.ClearValue(Rectangle.FillProperty);
332+
this.radiusMask = null;
333+
}
334+
335+
this.Invalidate();
336+
}
337+
338+
private void Invalidate()
339+
{
340+
this.invalidateShadowMask = true;
341+
this.InvalidateArrange();
342+
}
343+
}
344+
}

0 commit comments

Comments
 (0)