diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/BitmapIconExtension.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/BitmapIconExtension.cs new file mode 100644 index 00000000000..68ded4e2cea --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/BitmapIconExtension.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; + +namespace Microsoft.Toolkit.Uwp.UI.Extensions +{ + /// + /// Custom which can provide values. + /// + [Bindable] + [MarkupExtensionReturnType(ReturnType = typeof(BitmapIcon))] + public sealed class BitmapIconExtension : MarkupExtension + { + /// + /// Gets or sets the representing the image to display. + /// + public Uri Source { get; set; } + + /// + /// Gets or sets a value indicating whether to display the icon as monochrome. + /// + public bool ShowAsMonochrome { get; set; } + + /// + protected override object ProvideValue() + { + return new BitmapIcon + { + ShowAsMonochrome = ShowAsMonochrome, + UriSource = Source + }; + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconExtension.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconExtension.cs new file mode 100644 index 00000000000..8394c244fea --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconExtension.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Windows.UI.Text; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; +using Windows.UI.Xaml.Media; + +namespace Microsoft.Toolkit.Uwp.UI.Extensions +{ + /// + /// Custom which can provide values. + /// + [Bindable] + [MarkupExtensionReturnType(ReturnType = typeof(FontIcon))] + public class FontIconExtension : MarkupExtension + { + /// + /// Gets or sets the representing the icon to display. + /// + public string Glyph { get; set; } + + /// + /// Gets or sets the size of the icon to display. + /// + public double FontSize { get; set; } + + /// + /// Gets or sets the font family to use to display the icon. If , "Segoe MDL2 Assets" will be used. + /// + public FontFamily FontFamily { get; set; } + + /// + /// Gets or sets the thickness of the icon glyph. + /// + public FontWeight FontWeight { get; set; } = FontWeights.Normal; + + /// + /// Gets or sets the font style for the icon glyph. + /// + public FontStyle FontStyle { get; set; } = FontStyle.Normal; + + /// + /// Gets or sets a value indicating whether automatic text enlargement, to reflect the system text size setting, is enabled. + /// + public bool IsTextScaleFactorEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether the icon is mirrored when the flow direction is right to left. + /// + public bool MirroredWhenRightToLeft { get; set; } + + /// + protected override object ProvideValue() + { + var fontIcon = new FontIcon + { + Glyph = Glyph, + FontFamily = FontFamily ?? new FontFamily("Segoe MDL2 Assets"), + FontWeight = FontWeight, + FontStyle = FontStyle, + IsTextScaleFactorEnabled = IsTextScaleFactorEnabled, + MirroredWhenRightToLeft = MirroredWhenRightToLeft + }; + + if (FontSize > 0) + { + fontIcon.FontSize = FontSize; + } + + return fontIcon; + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconSourceExtension.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconSourceExtension.cs new file mode 100644 index 00000000000..6e909bd1cb2 --- /dev/null +++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconSourceExtension.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Windows.UI.Text; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Markup; +using Windows.UI.Xaml.Media; + +namespace Microsoft.Toolkit.Uwp.UI.Extensions +{ + /// + /// Custom which can provide values. + /// + [Bindable] + [MarkupExtensionReturnType(ReturnType = typeof(FontIconSource))] + public class FontIconSourceExtension : MarkupExtension + { + /// + /// Gets or sets the representing the icon to display. + /// + public string Glyph { get; set; } + + /// + /// Gets or sets the size of the icon to display. + /// + public double FontSize { get; set; } + + /// + /// Gets or sets the font family to use to display the icon. If , "Segoe MDL2 Assets" will be used. + /// + public FontFamily FontFamily { get; set; } + + /// + /// Gets or sets the thickness of the icon glyph. + /// + public FontWeight FontWeight { get; set; } = FontWeights.Normal; + + /// + /// Gets or sets the font style for the icon glyph. + /// + public FontStyle FontStyle { get; set; } = FontStyle.Normal; + + /// + /// Gets or sets a value indicating whether automatic text enlargement, to reflect the system text size setting, is enabled. + /// + public bool IsTextScaleFactorEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether the icon is mirrored when the flow direction is right to left. + /// + public bool MirroredWhenRightToLeft { get; set; } + + /// + protected override object ProvideValue() + { + var fontIcon = new FontIconSource + { + Glyph = Glyph, + FontFamily = FontFamily ?? new FontFamily("Segoe MDL2 Assets"), + FontWeight = FontWeight, + FontStyle = FontStyle, + IsTextScaleFactorEnabled = IsTextScaleFactorEnabled, + MirroredWhenRightToLeft = MirroredWhenRightToLeft + }; + + if (FontSize > 0) + { + fontIcon.FontSize = FontSize; + } + + return fontIcon; + } + } +} diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/NullableBool.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/NullableBool.cs index cb1831ea4ab..e3a5224dfa8 100644 --- a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/NullableBool.cs +++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/NullableBool.cs @@ -2,11 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Markup; diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/OnDevice.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/OnDevice.cs index 21fdf480344..866a54383a1 100644 --- a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/OnDevice.cs +++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/OnDevice.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using Windows.ApplicationModel; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Markup; diff --git a/UnitTests/Extensions/Test_BitmapIconExtensionMarkupExtension.cs b/UnitTests/Extensions/Test_BitmapIconExtensionMarkupExtension.cs new file mode 100644 index 00000000000..7eba199289f --- /dev/null +++ b/UnitTests/Extensions/Test_BitmapIconExtensionMarkupExtension.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.Extensions +{ + [TestClass] + public class Test_BitmapIconExtensionMarkupExtension + { + [TestCategory("BitmapIconExtensionMarkupExtension")] + [UITestMethod] + public void Test_BitmapIconExtension_MarkupExtension_ProvideImage() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("RootButton") as Button; + + Assert.IsNotNull(button, $"Could not find the {nameof(Button)} control in tree."); + + var item = ((MenuFlyout)button.Flyout)?.Items?.FirstOrDefault() as MenuFlyoutItem; + + Assert.IsNotNull(button, $"Could not find the target {nameof(MenuFlyoutItem)} control."); + + var icon = item.Icon as BitmapIcon; + + Assert.IsNotNull(icon, $"Could not find the {nameof(BitmapIcon)} element in button."); + + Assert.AreEqual(icon.UriSource, new Uri("ms-resource:///Files/Assets/StoreLogo.png"), "Expected ms-resource:///Files/Assets/StoreLogo.png uri."); + Assert.AreEqual(icon.ShowAsMonochrome, false, "Expected icon not to be monochrome"); + } + + [TestCategory("BitmapIconExtensionMarkupExtension")] + [UITestMethod] + public void Test_BitmapIconExtension_MarkupExtension_ProvideImageAndMonochrome() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("RootButton") as Button; + + Assert.IsNotNull(button, $"Could not find the {nameof(Button)} control in tree."); + + var item = ((MenuFlyout)button.Flyout)?.Items?.FirstOrDefault() as MenuFlyoutItem; + + Assert.IsNotNull(button, $"Could not find the target {nameof(MenuFlyoutItem)} control."); + + var icon = item.Icon as BitmapIcon; + + Assert.IsNotNull(icon, $"Could not find the {nameof(BitmapIcon)} element in button."); + + Assert.AreEqual(icon.UriSource, new Uri("ms-resource:///Files/Assets/StoreLogo.png"), "Expected ms-resource:///Files/Assets/StoreLogo.png uri."); + Assert.AreEqual(icon.ShowAsMonochrome, true, "Expected icon to be monochrome"); + } + } +} \ No newline at end of file diff --git a/UnitTests/Extensions/Test_FontIconExtensionMarkupExtension.cs b/UnitTests/Extensions/Test_FontIconExtensionMarkupExtension.cs new file mode 100644 index 00000000000..57021acb75e --- /dev/null +++ b/UnitTests/Extensions/Test_FontIconExtensionMarkupExtension.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Windows.UI.Text; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.Extensions +{ + [TestClass] + public class Test_FontIconExtensionMarkupExtension + { + [TestCategory("FontIconExtensionMarkupExtension")] + [UITestMethod] + public void Test_FontIconExtension_MarkupExtension_ProvideSegoeMdl2Asset() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("Check") as AppBarButton; + + Assert.IsNotNull(button, $"Could not find the {nameof(AppBarButton)} control in tree."); + + var icon = button.Icon as FontIcon; + + Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button."); + + Assert.AreEqual(icon.Glyph, "\uE105", "Expected icon glyph to be E105."); + Assert.AreEqual(icon.FontFamily.Source, "Segoe MDL2 Assets", "Expected font family to be Segoe MDL2 Assets"); + } + + [TestCategory("FontIconExtensionMarkupExtension")] + [UITestMethod] + public void Test_FontIconExtension_MarkupExtension_ProvideSegoeUI() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("Check") as AppBarButton; + + Assert.IsNotNull(button, $"Could not find the {nameof(AppBarButton)} control in tree."); + + var icon = button.Icon as FontIcon; + + Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button."); + + Assert.AreEqual(icon.Glyph, "\uE14D", "Expected icon glyph to be E14D."); + Assert.AreEqual(icon.FontFamily.Source, "Segoe UI", "Expected font family to be Segoe UI"); + } + + [TestCategory("FontIconExtensionMarkupExtension")] + [UITestMethod] + public void Test_FontIconExtension_MarkupExtension_ProvideCustomFontIcon() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("Check") as AppBarButton; + + Assert.IsNotNull(button, $"Could not find the {nameof(AppBarButton)} control in tree."); + + var icon = button.Icon as FontIcon; + + Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button."); + + Assert.AreEqual(icon.Glyph, "\uE14D", "Expected icon glyph to be E14D."); + Assert.AreEqual(icon.FontSize, 7.0, "Expected font size of 7"); + Assert.AreEqual(icon.FontFamily.Source, "Segoe MDL2 Assets", "Expected font family to be Segoe UI"); + Assert.AreEqual(icon.FontWeight, FontWeights.Bold, "Expected bold font weight"); + Assert.AreEqual(icon.FontStyle, FontStyle.Italic, "Expected italic font style"); + Assert.AreEqual(icon.IsTextScaleFactorEnabled, true, "Expected IsTextScaleFactorEnabled set to true"); + Assert.AreEqual(icon.MirroredWhenRightToLeft, true, "Expected MirroredWhenRightToLeft set to true"); + } + } +} diff --git a/UnitTests/Extensions/Test_FontIconSourceExtensionMarkupExtension.cs b/UnitTests/Extensions/Test_FontIconSourceExtensionMarkupExtension.cs new file mode 100644 index 00000000000..1c1c81852a7 --- /dev/null +++ b/UnitTests/Extensions/Test_FontIconSourceExtensionMarkupExtension.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics.CodeAnalysis; +using Windows.UI.Text; +using Microsoft.Toolkit.Uwp.UI.Extensions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Markup; + +namespace UnitTests.Extensions +{ + [TestClass] + public class Test_FontIconSourceExtensionMarkupExtension + { + [TestCategory("FontIconSourceExtensionMarkupExtension")] + [UITestMethod] + public void Test_FontIconSourceExtension_MarkupExtension_ProvideSegoeMdl2Asset() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("Check") as MockSwipeItem; + + Assert.IsNotNull(button, $"Could not find the {nameof(MockSwipeItem)} control in tree."); + + var icon = button.IconSource as FontIconSource; + + Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button."); + + Assert.AreEqual(icon.Glyph, "\uE105", "Expected icon glyph to be E105."); + Assert.AreEqual(icon.FontFamily.Source, "Segoe MDL2 Assets", "Expected font family to be Segoe MDL2 Assets"); + } + + [TestCategory("FontIconSourceExtensionMarkupExtension")] + [UITestMethod] + public void Test_FontIconSourceExtension_MarkupExtension_ProvideSegoeUI() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("Check") as MockSwipeItem; + + Assert.IsNotNull(button, $"Could not find the {nameof(MockSwipeItem)} control in tree."); + + var icon = button.IconSource as FontIconSource; + + Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button."); + + Assert.AreEqual(icon.Glyph, "\uE14D", "Expected icon glyph to be E14D."); + Assert.AreEqual(icon.FontFamily.Source, "Segoe UI", "Expected font family to be Segoe UI"); + } + + [TestCategory("FontIconSourceExtensionMarkupExtension")] + [UITestMethod] + public void Test_FontIconSourceExtension_MarkupExtension_ProvideCustomFontIcon() + { + var treeroot = XamlReader.Load(@" + +") as FrameworkElement; + + var button = treeroot.FindChildByName("Check") as MockSwipeItem; + + Assert.IsNotNull(button, $"Could not find the {nameof(MockSwipeItem)} control in tree."); + + var icon = button.IconSource as FontIconSource; + + Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button."); + + Assert.AreEqual(icon.Glyph, "\uE14D", "Expected icon glyph to be E14D."); + Assert.AreEqual(icon.FontSize, 7.0, "Expected font size of 7"); + Assert.AreEqual(icon.FontFamily.Source, "Segoe MDL2 Assets", "Expected font family to be Segoe UI"); + Assert.AreEqual(icon.FontWeight, FontWeights.Bold, "Expected bold font weight"); + Assert.AreEqual(icon.FontStyle, FontStyle.Italic, "Expected italic font style"); + Assert.AreEqual(icon.IsTextScaleFactorEnabled, true, "Expected IsTextScaleFactorEnabled set to true"); + Assert.AreEqual(icon.MirroredWhenRightToLeft, true, "Expected MirroredWhenRightToLeft set to true"); + } + } + + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402", Justification = "Mock control for tests")] + public class MockSwipeItem : Control + { + public IconSource IconSource + { + get => (IconSource)GetValue(IconSourceProperty); + set => SetValue(IconSourceProperty, value); + } + + public static readonly DependencyProperty IconSourceProperty = + DependencyProperty.Register( + nameof(IconSource), + typeof(IconSource), + typeof(MockSwipeItem), + new PropertyMetadata(default(IconSource))); + } +} \ No newline at end of file diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index b4208dc4fef..acabdafd438 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -136,9 +136,12 @@ + + +