Skip to content

Commit 9167982

Browse files
committed
Merge branch 'clippedShadows' of https://github.com/Keboo/MaterialDesignInXamlToolkit into Keboo-clippedShadows
2 parents 41a56c5 + 0f1c9b7 commit 9167982

9 files changed

+177
-40
lines changed

MaterialDesignThemes.Wpf/Converters/ShadowConverter.cs

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,19 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Globalization;
4-
using System.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
7-
using System.Windows;
83
using System.Windows.Data;
94
using System.Windows.Media.Effects;
105

116
namespace MaterialDesignThemes.Wpf.Converters
127
{
138
public class ShadowConverter : IValueConverter
149
{
15-
private static readonly IDictionary<ShadowDepth, DropShadowEffect> ShadowsDictionary;
1610
public static readonly ShadowConverter Instance = new ShadowConverter();
1711

18-
static ShadowConverter()
19-
{
20-
var resourceDictionary = new ResourceDictionary { Source = new Uri("pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Shadows.xaml", UriKind.Absolute) };
21-
22-
ShadowsDictionary = new Dictionary<ShadowDepth, DropShadowEffect>
23-
{
24-
{ ShadowDepth.Depth0, null },
25-
{ ShadowDepth.Depth1, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth1"] },
26-
{ ShadowDepth.Depth2, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth2"] },
27-
{ ShadowDepth.Depth3, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth3"] },
28-
{ ShadowDepth.Depth4, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth4"] },
29-
{ ShadowDepth.Depth5, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth5"] },
30-
};
31-
}
32-
3312
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
3413
{
3514
if (!(value is ShadowDepth)) return null;
3615

37-
return Clone(ShadowsDictionary[(ShadowDepth) value]);
16+
return Clone(ShadowInfo.GetDropShadow((ShadowDepth) value));
3817
}
3918

4019
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows;
4+
using System.Windows.Data;
5+
using System.Windows.Media;
6+
using System.Windows.Media.Effects;
7+
8+
namespace MaterialDesignThemes.Wpf.Converters
9+
{
10+
public class ShadowEdgeConverter : IMultiValueConverter
11+
{
12+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
13+
{
14+
if (values?.Length != 4)
15+
{
16+
return Binding.DoNothing;
17+
}
18+
19+
if (!(values[0] is double) || !(values[1] is double) || !(values[2] is ShadowDepth) ||
20+
!(values[3] is ShadowEdges))
21+
{
22+
return Binding.DoNothing;
23+
}
24+
25+
double width = (double)values[0];
26+
double height = (double)values[1];
27+
if (double.IsNaN(width) || double.IsInfinity(width) || double.IsNaN(height) || double.IsInfinity(height))
28+
{
29+
return Binding.DoNothing;
30+
}
31+
DropShadowEffect dropShadow = ShadowInfo.GetDropShadow((ShadowDepth)values[2]);
32+
if (dropShadow == null)
33+
{
34+
return Binding.DoNothing;
35+
}
36+
37+
ShadowEdges edges = (ShadowEdges)values[3];
38+
double blurRadius = dropShadow.BlurRadius;
39+
40+
var rect = new Rect(0, 0, width, height);
41+
42+
if (edges.HasFlag(ShadowEdges.Left))
43+
{
44+
rect = new Rect(rect.X - blurRadius, rect.Y, rect.Width + blurRadius, rect.Height);
45+
}
46+
if (edges.HasFlag(ShadowEdges.Top))
47+
{
48+
rect = new Rect(rect.X, rect.Y - blurRadius, rect.Width, rect.Height + blurRadius);
49+
}
50+
if (edges.HasFlag(ShadowEdges.Right))
51+
{
52+
rect = new Rect(rect.X, rect.Y, rect.Width + blurRadius, rect.Height);
53+
}
54+
if (edges.HasFlag(ShadowEdges.Bottom))
55+
{
56+
rect = new Rect(rect.X, rect.Y, rect.Width, rect.Height + blurRadius);
57+
}
58+
59+
var size = new GeometryDrawing(new SolidColorBrush(Colors.White), new Pen(), new RectangleGeometry(rect));
60+
return new DrawingBrush(size)
61+
{
62+
Stretch = Stretch.None,
63+
TileMode = TileMode.None,
64+
Viewport = rect,
65+
ViewportUnits = BrushMappingMode.Absolute,
66+
Viewbox = rect,
67+
ViewboxUnits = BrushMappingMode.Absolute
68+
};
69+
}
70+
71+
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
72+
{
73+
throw new NotImplementedException();
74+
}
75+
}
76+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Windows;
4+
using System.Windows.Media.Effects;
5+
6+
namespace MaterialDesignThemes.Wpf.Converters
7+
{
8+
internal static class ShadowInfo
9+
{
10+
private static readonly IDictionary<ShadowDepth, DropShadowEffect> ShadowsDictionary;
11+
12+
static ShadowInfo()
13+
{
14+
var resourceDictionary = new ResourceDictionary { Source = new Uri("pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Shadows.xaml", UriKind.Absolute) };
15+
16+
ShadowsDictionary = new Dictionary<ShadowDepth, DropShadowEffect>
17+
{
18+
{ ShadowDepth.Depth0, null },
19+
{ ShadowDepth.Depth1, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth1"] },
20+
{ ShadowDepth.Depth2, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth2"] },
21+
{ ShadowDepth.Depth3, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth3"] },
22+
{ ShadowDepth.Depth4, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth4"] },
23+
{ ShadowDepth.Depth5, (DropShadowEffect)resourceDictionary["MaterialDesignShadowDepth5"] },
24+
};
25+
}
26+
27+
public static DropShadowEffect GetDropShadow(ShadowDepth depth)
28+
{
29+
return ShadowsDictionary[depth];
30+
}
31+
}
32+
}

MaterialDesignThemes.Wpf/MaterialDesignThemes.Wpf.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@
294294
<Compile Include="Converters\NotZeroToVisibilityConverter.cs" />
295295
<Compile Include="Converters\PointValueConverter.cs" />
296296
<Compile Include="Converters\ShadowConverter.cs" />
297+
<Compile Include="Converters\ShadowEdgeConverter.cs" />
298+
<Compile Include="Converters\ShadowInfo.cs" />
297299
<Compile Include="Converters\SizeToRectConverter.cs" />
298300
<Compile Include="Converters\SnackbarMessageTypeConverter.cs" />
299301
<Compile Include="Converters\TimeToVisibilityConverter.cs" />

MaterialDesignThemes.Wpf/ShadowAssist.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Windows.Media;
44
using System.Windows.Media.Animation;
55
using System.Windows.Media.Effects;
6-
using System.Windows.Navigation;
76

87
namespace MaterialDesignThemes.Wpf
98
{
@@ -17,6 +16,17 @@ public enum ShadowDepth
1716
Depth5
1817
}
1918

19+
[Flags]
20+
public enum ShadowEdges
21+
{
22+
None = 0,
23+
Left = 1,
24+
Top = 2,
25+
Right = 4,
26+
Bottom = 8,
27+
All = Left | Top | Right | Bottom
28+
}
29+
2030
internal class ShadowLocalInfo
2131
{
2232
public ShadowLocalInfo(double standardOpacity)
@@ -111,5 +121,17 @@ public static CacheMode GetCacheMode(DependencyObject element)
111121
return (CacheMode)element.GetValue(CacheModeProperty);
112122
}
113123

124+
public static readonly DependencyProperty ShadowEdgesProperty = DependencyProperty.RegisterAttached(
125+
"ShadowEdges", typeof(ShadowEdges), typeof(ShadowAssist), new PropertyMetadata(ShadowEdges.All));
126+
127+
public static void SetShadowEdges(DependencyObject element, ShadowEdges value)
128+
{
129+
element.SetValue(ShadowEdgesProperty, value);
130+
}
131+
132+
public static ShadowEdges GetShadowEdges(DependencyObject element)
133+
{
134+
return (ShadowEdges) element.GetValue(ShadowEdgesProperty);
135+
}
114136
}
115137
}

MaterialDesignThemes.Wpf/Themes/Generic.xaml

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.SmartHint.xaml" />
3030
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Snackbar.xaml" />
3131
</ResourceDictionary.MergedDictionaries>
32-
32+
3333
<!-- set up default styles for our custom Material Design in XAML Toolkit controls -->
3434
<Style TargetType="{x:Type local:Clock}" BasedOn="{StaticResource MaterialDesignClock}" />
3535
<Style TargetType="{x:Type local:PopupBox}" BasedOn="{StaticResource MaterialDesignPopupBox}" />
3636
<Style TargetType="{x:Type local:TimePicker}" BasedOn="{StaticResource MaterialDesignTimePicker}" />
37-
37+
3838
<converters:BrushToRadialGradientBrushConverter x:Key="BrushToRadialGradientBrushConverter" />
3939
<converters:DrawerOffsetConverter x:Key="DrawerOffsetConverter" />
4040

@@ -46,7 +46,7 @@
4646
<Setter Property="VerticalAlignment" Value="Stretch" />
4747
<Setter Property="Background" Value="Transparent" />
4848
<Setter Property="IsTabStop" Value="False" />
49-
<Setter Property="ClipToBounds" Value="{Binding RelativeSource={RelativeSource Self}, Path=(local:RippleAssist.ClipToBounds)}" />
49+
<Setter Property="ClipToBounds" Value="{Binding RelativeSource={RelativeSource Self}, Path=(local:RippleAssist.ClipToBounds)}" />
5050
<Setter Property="Feedback" Value="{Binding RelativeSource={RelativeSource Self}, Path=(local:RippleAssist.Feedback)}" />
5151
<Setter Property="Template">
5252
<Setter.Value>
@@ -120,10 +120,10 @@
120120
<SineEase EasingMode="EaseOut" />
121121
</EasingDoubleKeyFrame.EasingFunction>
122122
</EasingDoubleKeyFrame>
123-
</DoubleAnimationUsingKeyFrames>
123+
</DoubleAnimationUsingKeyFrames>
124124
</Storyboard>
125-
</VisualTransition>
126-
</VisualStateGroup.Transitions>
125+
</VisualTransition>
126+
</VisualStateGroup.Transitions>
127127
<VisualState x:Name="Normal">
128128
<Storyboard>
129129
<DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="ScaleTransform" To="0"/>
@@ -179,7 +179,7 @@
179179
</Setter.Value>
180180
</Setter>
181181
</Style>
182-
182+
183183
<Style TargetType="{x:Type local:Underline}">
184184
<Setter Property="Background" Value="{DynamicResource PrimaryHueMidBrush}"/>
185185
<Setter Property="SnapsToDevicePixels" Value="True"/>
@@ -405,27 +405,38 @@
405405
</Style>
406406

407407
<Style TargetType="{x:Type local:ColorZone}">
408+
<Style.Resources>
409+
<converters:ShadowEdgeConverter x:Key="ShadowEdgeConverter" />
410+
</Style.Resources>
408411
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}" />
409412
<Setter Property="Foreground" Value="{DynamicResource MaterialDesignBody}" />
410413
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
411414
<Setter Property="VerticalContentAlignment" Value="Stretch" />
412415
<Setter Property="VerticalAlignment" Value="Top" />
413-
<Setter Property="IsTabStop" Value="False" />
416+
<Setter Property="IsTabStop" Value="False" />
414417
<Setter Property="Template">
415418
<Setter.Value>
416419
<ControlTemplate TargetType="{x:Type local:ColorZone}">
417420
<Grid Background="Transparent">
421+
<Grid.OpacityMask>
422+
<MultiBinding Converter="{StaticResource ShadowEdgeConverter}">
423+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ActualWidth"/>
424+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ActualHeight"/>
425+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="(local:ShadowAssist.ShadowDepth)" />
426+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="(local:ShadowAssist.ShadowEdges)" />
427+
</MultiBinding>
428+
</Grid.OpacityMask>
418429
<AdornerDecorator CacheMode="{Binding RelativeSource={RelativeSource Self}, Path=(local:ShadowAssist.CacheMode)}">
419430
<Border Background="{TemplateBinding Background}"
420-
CornerRadius="{TemplateBinding CornerRadius}"
431+
CornerRadius="{TemplateBinding CornerRadius}"
421432
Effect="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:ShadowAssist.ShadowDepth), Converter={x:Static converters:ShadowConverter.Instance}}">
422433
</Border>
423434
</AdornerDecorator>
424435
<Border Background="{TemplateBinding Background}"
425436
BorderBrush="{TemplateBinding BorderBrush}"
426437
BorderThickness="{TemplateBinding BorderThickness}"
427438
CornerRadius="{TemplateBinding CornerRadius}"
428-
ClipToBounds="True" >
439+
ClipToBounds="True">
429440
<ContentPresenter Content="{TemplateBinding Content}"
430441
ContentTemplate="{TemplateBinding ContentTemplate}"
431442
TextElement.Foreground="{TemplateBinding Foreground}"
@@ -983,7 +994,7 @@
983994
</ControlTemplate>
984995
</Setter.Value>
985996
</Setter>
986-
</Style>
997+
</Style>
987998

988999
<Style TargetType="{x:Type local:PackIcon}">
9891000
<Setter Property="Height" Value="16" />
@@ -1010,7 +1021,7 @@
10101021
</Setter>
10111022
</Style>
10121023

1013-
<Style TargetType="{x:Type transitions:Transitioner}">
1024+
<Style TargetType="{x:Type transitions:Transitioner}">
10141025
<Setter Property="ClipToBounds" Value="True" />
10151026
<Setter Property="ItemsPanel">
10161027
<Setter.Value>

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Card.xaml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,34 @@
1010
<converters:CardClipConverter x:Key="CardClipConverter" />
1111

1212
<ControlTemplate TargetType="{x:Type wpf:Card}" x:Key="CardTemplate">
13+
<ControlTemplate.Resources>
14+
<converters:ShadowEdgeConverter x:Key="ShadowEdgeConverter" />
15+
</ControlTemplate.Resources>
1316
<Grid Margin="{TemplateBinding Margin}" Background="Transparent">
17+
<Grid.OpacityMask>
18+
<MultiBinding Converter="{StaticResource ShadowEdgeConverter}">
19+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ActualWidth"/>
20+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ActualHeight"/>
21+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="(wpf:ShadowAssist.ShadowDepth)" />
22+
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="(wpf:ShadowAssist.ShadowEdges)" />
23+
</MultiBinding>
24+
</Grid.OpacityMask>
1425
<AdornerDecorator CacheMode="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:ShadowAssist.CacheMode)}">
1526
<Border Effect="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ShadowAssist.ShadowDepth), Converter={x:Static converters:ShadowConverter.Instance}}"
1627
CornerRadius="{TemplateBinding UniformCornerRadius}">
1728
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"
1829
x:Name="PART_ClipBorder"
19-
Clip="{TemplateBinding ContentClip}" />
30+
Clip="{TemplateBinding ContentClip}" />
2031
</Border>
2132
</AdornerDecorator>
2233
<ContentPresenter
23-
x:Name="ContentPresenter"
34+
x:Name="ContentPresenter"
2435
Margin="{TemplateBinding Padding}"
2536
Clip="{TemplateBinding ContentClip}"
2637
Content="{TemplateBinding ContentControl.Content}"
2738
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
2839
ContentTemplateSelector="{TemplateBinding ContentControl.ContentTemplateSelector}"
29-
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}">
40+
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}">
3041
</ContentPresenter>
3142
</Grid>
3243
</ControlTemplate>

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.GroupBox.xaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
<Grid>
3535
<Border Background="{TemplateBinding Background}" BorderBrush="{Binding Path=Background, ElementName=PART_ColorZone}" BorderThickness="{TemplateBinding BorderThickness}" />
3636
<DockPanel Background="{TemplateBinding Background}">
37-
<wpf:ColorZone UseLayoutRounding="True" x:Name="PART_ColorZone" DockPanel.Dock="Top" Padding="{TemplateBinding Padding}" Effect="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ShadowAssist.ShadowDepth), Converter={x:Static converters:ShadowConverter.Instance}}" Mode="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ColorZoneAssist.Mode)}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
37+
<wpf:ColorZone UseLayoutRounding="True" x:Name="PART_ColorZone" DockPanel.Dock="Top" Padding="{TemplateBinding Padding}"
38+
Effect="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ShadowAssist.ShadowDepth), Converter={x:Static converters:ShadowConverter.Instance}}"
39+
wpf:ShadowAssist.ShadowEdges="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ShadowAssist.ShadowEdges)}"
40+
Mode="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ColorZoneAssist.Mode)}"
41+
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
3842
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
3943
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
4044
ContentTemplate="{TemplateBinding HeaderTemplate}"

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.Shadows.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options">
44

5-
<!-- thanks: http://marcangers.com/material-design-shadows-in-wpf/ -->
5+
<!-- thanks: http://marcangers.com/material-design-shadows-in-wpf/ -->
66

77
<Color x:Key="MaterialDesignShadow">#AA000000</Color>
88
<SolidColorBrush x:Key="MaterialDesignShadowBrush" Color="{StaticResource MaterialDesignShadow}"/>

0 commit comments

Comments
 (0)