diff --git a/ModernWpf.Controls/Common/SharedHelpers.cs b/ModernWpf.Controls/Common/SharedHelpers.cs index 49266990..36b0b660 100644 --- a/ModernWpf.Controls/Common/SharedHelpers.cs +++ b/ModernWpf.Controls/Common/SharedHelpers.cs @@ -158,6 +158,75 @@ public static void RaiseAutomationPropertyChangedEvent(UIElement element, object } } + public static IconElement MakeIconElementFrom(IconSource iconSource) + { + if (iconSource is FontIconSource fontIconSource) + { + FontIcon fontIcon = new(); + + fontIcon.Glyph = fontIconSource.Glyph; + fontIcon.FontSize = fontIconSource.FontSize; + if (fontIconSource.Foreground is { } newForeground) + { + fontIcon.Foreground = newForeground; + } + + if (fontIconSource.FontFamily != null) + { + fontIcon.FontFamily = fontIconSource.FontFamily; + } + + fontIcon.FontWeight = fontIconSource.FontWeight; + fontIcon.FontStyle = fontIconSource.FontStyle; + //fontIcon.IsTextScaleFactorEnabled(fontIconSource.IsTextScaleFactorEnabled()); + //fontIcon.MirroredWhenRightToLeft(fontIconSource.MirroredWhenRightToLeft()); + + return fontIcon; + } + else if (iconSource is SymbolIconSource symbolIconSource) + { + SymbolIcon symbolIcon = new(); + symbolIcon.Symbol = symbolIconSource.Symbol; + if (symbolIconSource.Foreground is { } newForeground) + { + symbolIcon.Foreground = newForeground; + } + return symbolIcon; + } + else if (iconSource is BitmapIconSource bitmapIconSource) + { + BitmapIcon bitmapIcon = new(); + + if (bitmapIconSource.UriSource != null) + { + bitmapIcon.UriSource = bitmapIconSource.UriSource; + } + + bitmapIcon.ShowAsMonochrome = bitmapIconSource.ShowAsMonochrome; + if (bitmapIconSource.Foreground is { } newForeground) + { + bitmapIcon.Foreground = newForeground; + } + return bitmapIcon; + } + else if (iconSource is PathIconSource pathIconSource) + { + PathIcon pathIcon = new(); + + if (pathIconSource.Data != null) + { + pathIcon.Data = pathIconSource.Data; + } + if (pathIconSource.Foreground is { } newForeground) + { + pathIcon.Foreground = newForeground; + } + return pathIcon; + } + + return null; + } + public static BindingExpressionBase SetBinding( this FrameworkElement element, DependencyProperty dp, diff --git a/ModernWpf.Controls/DropDownButton/DropDownButton.xaml b/ModernWpf.Controls/DropDownButton/DropDownButton.xaml index 8bc7bdf8..014ee204 100644 --- a/ModernWpf.Controls/DropDownButton/DropDownButton.xaml +++ b/ModernWpf.Controls/DropDownButton/DropDownButton.xaml @@ -55,7 +55,6 @@ Grid.Column="1" FontFamily="{DynamicResource SymbolThemeFontFamily}" FontSize="8" - Foreground="{DynamicResource ButtonForegroundPressed}" Data="{StaticResource ChevronDownSmall}" VerticalAlignment="Center" Padding="2,4,2,0" diff --git a/ModernWpf/IconSource/BitmapIconSource.cs b/ModernWpf/IconSource/BitmapIconSource.cs index d93c9065..793faad4 100644 --- a/ModernWpf/IconSource/BitmapIconSource.cs +++ b/ModernWpf/IconSource/BitmapIconSource.cs @@ -75,5 +75,19 @@ protected override IconElement CreateIconElementCore() } return bitmapIcon; } + + protected override DependencyProperty GetIconElementPropertyCore(DependencyProperty sourceProperty) + { + if (sourceProperty == ShowAsMonochromeProperty) + { + return BitmapIcon.ShowAsMonochromeProperty; + } + else if (sourceProperty == UriSourceProperty) + { + return BitmapIcon.UriSourceProperty; + } + + return base.GetIconElementPropertyCore(sourceProperty); + } } } diff --git a/ModernWpf/IconSource/FontIconSource.cs b/ModernWpf/IconSource/FontIconSource.cs index 01367482..da2cbbe8 100644 --- a/ModernWpf/IconSource/FontIconSource.cs +++ b/ModernWpf/IconSource/FontIconSource.cs @@ -155,5 +155,39 @@ protected override IconElement CreateIconElementCore() return fontIcon; } + + protected override DependencyProperty GetIconElementPropertyCore(DependencyProperty sourceProperty) + { + if (sourceProperty == FontFamilyProperty) + { + return FontIcon.FontFamilyProperty; + } + else if (sourceProperty == FontSizeProperty) + { + return FontIcon.FontSizeProperty; + } + else if (sourceProperty == FontStyleProperty) + { + return FontIcon.FontStyleProperty; + } + else if (sourceProperty == FontWeightProperty) + { + return FontIcon.FontWeightProperty; + } + else if (sourceProperty == GlyphProperty) + { + return FontIcon.GlyphProperty; + } + //else if (sourceProperty == IsTextScaleFactorEnabledProperty) + //{ + // return FontIcon.IsTextScaleFactorEnabledProperty; + //} + //else if (sourceProperty == MirroredWhenRightToLeftProperty) + //{ + // return FontIcon.MirroredWhenRightToLeftProperty; + //} + + return base.GetIconElementPropertyCore(sourceProperty); + } } } diff --git a/ModernWpf/IconSource/IconSource.cs b/ModernWpf/IconSource/IconSource.cs index a802dd72..984c1387 100644 --- a/ModernWpf/IconSource/IconSource.cs +++ b/ModernWpf/IconSource/IconSource.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. +using System; +using System.Collections.Generic; using System.Windows; using System.Windows.Media; @@ -35,9 +37,42 @@ public Brush Foreground public IconElement CreateIconElement() { - return CreateIconElementCore(); + var element = CreateIconElementCore(); + m_createdIconElements.Add(new WeakReference(element)); + return element; } protected abstract IconElement CreateIconElementCore(); + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs args) + { + base.OnPropertyChanged(args); + + var iconProp = GetIconElementPropertyCore(args.Property); + if (iconProp != null) + { + m_createdIconElements.RemoveAll(weakElement => + { + if (weakElement.TryGetTarget(out var element)) + { + element.SetValue(iconProp, args.NewValue); + return false; + } + return true; + }); + } + } + + protected virtual DependencyProperty GetIconElementPropertyCore(DependencyProperty sourceProperty) + { + if (sourceProperty == ForegroundProperty) + { + return IconElement.ForegroundProperty; + } + + return null; + } + + private readonly List> m_createdIconElements = new(); } } diff --git a/ModernWpf/IconSource/PathIconSource.cs b/ModernWpf/IconSource/PathIconSource.cs index 2bf18e1c..48a63f00 100644 --- a/ModernWpf/IconSource/PathIconSource.cs +++ b/ModernWpf/IconSource/PathIconSource.cs @@ -53,5 +53,15 @@ protected override IconElement CreateIconElementCore() } return pathIcon; } + + protected override DependencyProperty GetIconElementPropertyCore(DependencyProperty sourceProperty) + { + if (sourceProperty == DataProperty) + { + return PathIcon.DataProperty; + } + + return base.GetIconElementPropertyCore(sourceProperty); + } } } diff --git a/ModernWpf/IconSource/SymbolIconSource.cs b/ModernWpf/IconSource/SymbolIconSource.cs index d0cf5d71..8a5efe66 100644 --- a/ModernWpf/IconSource/SymbolIconSource.cs +++ b/ModernWpf/IconSource/SymbolIconSource.cs @@ -49,5 +49,15 @@ protected override IconElement CreateIconElementCore() } return symbolIcon; } + + protected override DependencyProperty GetIconElementPropertyCore(DependencyProperty sourceProperty) + { + if (sourceProperty == SymbolProperty) + { + return SymbolIcon.SymbolProperty; + } + + return base.GetIconElementPropertyCore(sourceProperty); + } } } diff --git a/ModernWpf/Styles/CheckBox.xaml b/ModernWpf/Styles/CheckBox.xaml index 35c2e9e4..43a9f515 100644 --- a/ModernWpf/Styles/CheckBox.xaml +++ b/ModernWpf/Styles/CheckBox.xaml @@ -11,7 +11,7 @@ 1 20 - 16 + 12 32 120 8,5,0,0 @@ -76,6 +76,7 @@ Data="{StaticResource CheckMark}" FontSize="{StaticResource CheckBoxGlyphSize}" Foreground="{DynamicResource CheckBoxCheckGlyphForegroundUnchecked}" + Margin="4" Opacity="0" /> + { + iconSource = new SymbolIconSource(); + symbolIcon = iconSource.CreateIconElement() as SymbolIcon; + + // IconSource.Foreground should be null to allow foreground inheritance from + // the parent to work. + Verify.AreEqual(iconSource.Foreground, null); + //Verify.AreEqual(symbolIcon.Foreground, null); + + Log.Comment("Validate the defaults match SymbolIcon."); + + var icon = new SymbolIcon(); + Verify.AreEqual(icon.Symbol, iconSource.Symbol); + Verify.AreEqual(symbolIcon.Symbol, iconSource.Symbol); + + Log.Comment("Validate that you can change the properties."); + + iconSource.Foreground = new SolidColorBrush(Colors.Red); + iconSource.Symbol = Symbol.HangUp; + }); + IdleSynchronizer.Wait(); + + RunOnUIThread.Execute(() => + { + Verify.IsTrue(iconSource.Foreground is SolidColorBrush); + Verify.AreEqual(Colors.Red, (iconSource.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Colors.Red, (symbolIcon.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Symbol.HangUp, iconSource.Symbol); + Verify.AreEqual(Symbol.HangUp, symbolIcon.Symbol); + }); + } + + [TestMethod] + public void FontIconSourceTest() + { + FontIconSource iconSource = null; + FontIcon fontIcon = null; + + RunOnUIThread.Execute(() => + { + iconSource = new FontIconSource(); + fontIcon = iconSource.CreateIconElement() as FontIcon; + + // IconSource.Foreground should be null to allow foreground inheritance from + // the parent to work. + Verify.AreEqual(iconSource.Foreground, null); + //Verify.AreEqual(fontIcon.Foreground, null); + + Log.Comment("Validate the defaults match FontIcon."); + + var icon = new FontIcon(); + Verify.AreEqual(icon.Glyph, iconSource.Glyph); + Verify.AreEqual(fontIcon.Glyph, iconSource.Glyph); + Verify.AreEqual(icon.FontSize, iconSource.FontSize); + Verify.AreEqual(fontIcon.FontSize, iconSource.FontSize); + Verify.AreEqual(icon.FontStyle, iconSource.FontStyle); + Verify.AreEqual(fontIcon.FontStyle, iconSource.FontStyle); + Verify.AreEqual(icon.FontWeight, iconSource.FontWeight); + Verify.AreEqual(fontIcon.FontWeight, iconSource.FontWeight); + Verify.AreEqual(icon.FontFamily.Source, iconSource.FontFamily.Source); + Verify.AreEqual(fontIcon.FontFamily.Source, iconSource.FontFamily.Source); + //Verify.AreEqual(icon.IsTextScaleFactorEnabled, iconSource.IsTextScaleFactorEnabled); + //Verify.AreEqual(fontIcon.IsTextScaleFactorEnabled, iconSource.IsTextScaleFactorEnabled); + //Verify.AreEqual(icon.MirroredWhenRightToLeft, iconSource.MirroredWhenRightToLeft); + //Verify.AreEqual(fontIcon.MirroredWhenRightToLeft, iconSource.MirroredWhenRightToLeft); + + Log.Comment("Validate that you can change the properties."); + + iconSource.Foreground = new SolidColorBrush(Colors.Red); + iconSource.Glyph = ""; + iconSource.FontSize = 25; + iconSource.FontStyle = FontStyles.Oblique; + iconSource.FontWeight = FontWeight.FromOpenTypeWeight(250); + iconSource.FontFamily = new FontFamily("Segoe UI Symbol"); + //iconSource.IsTextScaleFactorEnabled = true; + //iconSource.MirroredWhenRightToLeft = true; + }); + IdleSynchronizer.Wait(); + + RunOnUIThread.Execute(() => + { + Verify.IsTrue(iconSource.Foreground is SolidColorBrush); + Verify.IsTrue(fontIcon.Foreground is SolidColorBrush); + Verify.AreEqual(Colors.Red, (iconSource.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Colors.Red, (fontIcon.Foreground as SolidColorBrush).Color); + Verify.AreEqual("", iconSource.Glyph); + Verify.AreEqual("", fontIcon.Glyph); + Verify.AreEqual(25, iconSource.FontSize); + Verify.AreEqual(25, fontIcon.FontSize); + Verify.AreEqual(FontStyles.Oblique, iconSource.FontStyle); + Verify.AreEqual(FontStyles.Oblique, fontIcon.FontStyle); + Verify.AreEqual(250, iconSource.FontWeight.ToOpenTypeWeight()); + Verify.AreEqual(250, fontIcon.FontWeight.ToOpenTypeWeight()); + Verify.AreEqual("Segoe UI Symbol", iconSource.FontFamily.Source); + Verify.AreEqual("Segoe UI Symbol", fontIcon.FontFamily.Source); + //Verify.AreEqual(true, iconSource.IsTextScaleFactorEnabled); + //Verify.AreEqual(true, fontIcon.IsTextScaleFactorEnabled); + //Verify.AreEqual(true, iconSource.MirroredWhenRightToLeft); + //Verify.AreEqual(true, fontIcon.MirroredWhenRightToLeft); + }); + } + + [TestMethod] + public void BitmapIconSourceTest() + { + BitmapIconSource iconSource = null; + BitmapIcon bitmapIcon = null; + var uri = new Uri("ms-appx:///Assets/ingredient1.png"); + + RunOnUIThread.Execute(() => + { + iconSource = new BitmapIconSource(); + bitmapIcon = iconSource.CreateIconElement() as BitmapIcon; + + // IconSource.Foreground should be null to allow foreground inheritance from + // the parent to work. + Verify.AreEqual(iconSource.Foreground, null); + //Verify.AreEqual(bitmapIcon.Foreground, null); + + Log.Comment("Validate the defaults match BitmapIcon."); + + var icon = new BitmapIcon(); + Verify.AreEqual(icon.UriSource, iconSource.UriSource); + Verify.AreEqual(bitmapIcon.UriSource, iconSource.UriSource); + + Verify.AreEqual(icon.ShowAsMonochrome, iconSource.ShowAsMonochrome); + Verify.AreEqual(bitmapIcon.ShowAsMonochrome, iconSource.ShowAsMonochrome); + + Log.Comment("Validate that you can change the properties."); + + iconSource.Foreground = new SolidColorBrush(Colors.Red); + iconSource.UriSource = uri; + iconSource.ShowAsMonochrome = false; + }); + IdleSynchronizer.Wait(); + + RunOnUIThread.Execute(() => + { + Verify.IsTrue(iconSource.Foreground is SolidColorBrush); + Verify.IsTrue(bitmapIcon.Foreground is SolidColorBrush); + Verify.AreEqual(Colors.Red, (iconSource.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Colors.Red, (bitmapIcon.Foreground as SolidColorBrush).Color); + Verify.AreEqual(uri, iconSource.UriSource); + Verify.AreEqual(uri, bitmapIcon.UriSource); + Verify.AreEqual(false, iconSource.ShowAsMonochrome); + Verify.AreEqual(false, bitmapIcon.ShowAsMonochrome); + }); + } + + /* + [TestMethod] + public void ImageIconSourceTest() + { + ImageIconSource iconSource = null; + ImageIcon imageIcon = null; + var uri = new Uri("ms-appx:///Assets/Nuclear_symbol.svg"); + + RunOnUIThread.Execute(() => + { + iconSource = new ImageIconSource(); + imageIcon = iconSource.CreateIconElement() as ImageIcon; + + // IconSource.Foreground should be null to allow foreground inheritance from + // the parent to work. + Verify.AreEqual(iconSource.Foreground, null); + //Verify.AreEqual(imageIcon.Foreground, null); + + Log.Comment("Validate the defaults match BitmapIcon."); + + var icon = new ImageIcon(); + Verify.AreEqual(icon.Source, iconSource.ImageSource); + Verify.AreEqual(imageIcon.Source, iconSource.ImageSource); + + Log.Comment("Validate that you can change the properties."); + + iconSource.Foreground = new SolidColorBrush(Colors.Red); + iconSource.ImageSource = new SvgImageSource(uri); + }); + IdleSynchronizer.Wait(); + + RunOnUIThread.Execute(() => + { + Verify.IsTrue(iconSource.Foreground is SolidColorBrush); + Verify.IsTrue(imageIcon.Foreground is SolidColorBrush); + Verify.AreEqual(Colors.Red, (iconSource.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Colors.Red, (imageIcon.Foreground as SolidColorBrush).Color); + Verify.AreEqual(uri, ((SvgImageSource)iconSource.ImageSource).UriSource); + Verify.AreEqual(uri, ((SvgImageSource)imageIcon.Source).UriSource); + }); + } + */ + + /* + [TestMethod] + public void AnimatedIconSourceTest() + { + AnimatedIconSource iconSource = null; + IAnimatedVisualSource2 source = null; + AnimatedIcon animatedIcon = null; + + RunOnUIThread.Execute(() => + { + iconSource = new AnimatedIconSource(); + source = new AnimatedChevronDownSmallVisualSource(); + animatedIcon = iconSource.CreateIconElement() as AnimatedIcon; + + // IconSource.Foreground should be null to allow foreground inheritance from + // the parent to work. + Verify.AreEqual(iconSource.Foreground, null); + //Verify.AreEqual(animatedIcon.Foreground, null); + + Log.Comment("Validate the defaults match BitmapIcon."); + + var icon = new AnimatedIcon(); + Verify.AreEqual(icon.Source, iconSource.Source); + Verify.AreEqual(animatedIcon.Source, iconSource.Source); + + Log.Comment("Validate that you can change the properties."); + + iconSource.Foreground = new SolidColorBrush(Colors.Red); + iconSource.Source = source; + }); + IdleSynchronizer.Wait(); + + RunOnUIThread.Execute(() => + { + Verify.IsTrue(iconSource.Foreground is SolidColorBrush); + Verify.IsTrue(animatedIcon.Foreground is SolidColorBrush); + Verify.AreEqual(Colors.Red, (iconSource.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Colors.Red, (animatedIcon.Foreground as SolidColorBrush).Color); + Verify.AreEqual(source, iconSource.Source); + Verify.AreEqual(source, animatedIcon.Source); + }); + } + */ + + [TestMethod] + public void PathIconSourceTest() + { + PathIconSource iconSource = null; + RectangleGeometry rectGeometry = null; + PathIcon pathIcon = null; + + RunOnUIThread.Execute(() => + { + iconSource = new PathIconSource(); + pathIcon = iconSource.CreateIconElement() as PathIcon; + + // IconSource.Foreground should be null to allow foreground inheritance from + // the parent to work. + Verify.AreEqual(iconSource.Foreground, null); + //Verify.AreEqual(pathIcon.Foreground, null); + + Log.Comment("Validate the defaults match PathIcon."); + + var icon = new PathIcon(); + Verify.AreEqual(icon.Data, iconSource.Data); + Verify.AreEqual(pathIcon.Data, iconSource.Data); + + Log.Comment("Validate that you can change the properties."); + + iconSource.Foreground = new SolidColorBrush(Colors.Red); + iconSource.Data = rectGeometry = new RectangleGeometry(); + }); + IdleSynchronizer.Wait(); + + RunOnUIThread.Execute(() => + { + Verify.IsTrue(iconSource.Foreground is SolidColorBrush); + Verify.IsTrue(pathIcon.Foreground is SolidColorBrush); + Verify.AreEqual(Colors.Red, (iconSource.Foreground as SolidColorBrush).Color); + Verify.AreEqual(Colors.Red, (pathIcon.Foreground as SolidColorBrush).Color); + Verify.AreEqual(rectGeometry, iconSource.Data); + Verify.AreEqual(rectGeometry, pathIcon.Data); + }); + } + } +}