diff --git a/src/MainDemo.Wpf/Domain/MainWindowViewModel.cs b/src/MainDemo.Wpf/Domain/MainWindowViewModel.cs index 1fc3fea80a..bbb5e3512f 100644 --- a/src/MainDemo.Wpf/Domain/MainWindowViewModel.cs +++ b/src/MainDemo.Wpf/Domain/MainWindowViewModel.cs @@ -237,7 +237,8 @@ private static IEnumerable GenerateDemoItems(ISnackbarMessageQueue sna [ DocumentationLink.DemoPageLink(), DocumentationLink.StyleLink("TextBlock") - ]) + ], + new TypographyViewModel()) { HorizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto }; diff --git a/src/MainDemo.Wpf/Typography.xaml b/src/MainDemo.Wpf/Typography.xaml index 7ae1f25058..512f80ca48 100644 --- a/src/MainDemo.Wpf/Typography.xaml +++ b/src/MainDemo.Wpf/Typography.xaml @@ -2,10 +2,9 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:smtx="clr-namespace:ShowMeTheXAML;assembly=ShowMeTheXAML" - d:DesignHeight="300" - d:DesignWidth="300" mc:Ignorable="d"> @@ -16,306 +15,512 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Light 96sp (Disabled) - - - - - - - - - - - - Light 60sp - - - - - - - - - - - - Regular 48sp - - - - - - - - - - - - Regular 34sp - - - - - - - - - - - - Regular 24sp (Disabled) - - - - - - - - - - - - Medium 20sp (Disabled) - - - - - - - - - - - - Regular 16sp - - - - - - - - - - - - Medium 14sp - - - - - - - - - - - - Regular 16sp (Disabled) - - - - - - - - - - - - Regular 14sp - - - - - - - - - - - - Regular 12sp - - - - - - - - - - - - REGULAR (ALL CAPS) 10sp - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Light 96sp (Disabled) + + + + + + + + + + + + + + + + + + + Light 60sp + + + + + + + + + + + + + + + + + + + Regular 48sp + + + + + + + + + + + + + + + + + + + Regular 34sp + + + + + + + + + + + + + + + + + + + Regular 24sp (Disabled) + + + + + + + + + + + + + + + + + + + Medium 20sp (Disabled) + + + + + + + + + + + + + + + + + + + Regular 16sp + + + + + + + + + + + + + + + + + + + Medium 14sp + + + + + + + + + + + + + + + + + + + Regular 16sp (Disabled) + + + + + + + + + + + + + + + + + + + Regular 14sp + + + + + + + + + + + + + + + + + + + Regular 12sp + + + + + + + + + + + + + + + + + + + REGULAR (ALL CAPS) 10sp + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MaterialDesign3.Demo.Wpf/Domain/IconPackViewModel.cs b/src/MaterialDesign3.Demo.Wpf/Domain/IconPackViewModel.cs index 7f840fbf21..eeef4cb832 100644 --- a/src/MaterialDesign3.Demo.Wpf/Domain/IconPackViewModel.cs +++ b/src/MaterialDesign3.Demo.Wpf/Domain/IconPackViewModel.cs @@ -1,6 +1,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using BluwolfIcons; +using MaterialDesignDemo; using MaterialDesignDemo.Shared.Domain; using MaterialDesignThemes.Wpf; using Microsoft.Win32; diff --git a/src/MaterialDesign3.Demo.Wpf/PackIconKindGroup.cs b/src/MaterialDesign3.Demo.Wpf/PackIconKindGroup.cs deleted file mode 100644 index baa96205fe..0000000000 --- a/src/MaterialDesign3.Demo.Wpf/PackIconKindGroup.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace MaterialDesign3Demo; - -public class PackIconKindGroup -{ - public PackIconKindGroup(IEnumerable kinds) - { - if (kinds is null) throw new ArgumentNullException(nameof(kinds)); - var allValues = kinds.ToList(); - if (!allValues.Any()) throw new ArgumentException($"{nameof(kinds)} must contain at least one value"); - Kind = allValues.First(); - Aliases = allValues - .OrderBy(x => x, StringComparer.InvariantCultureIgnoreCase) - .ToArray(); - } - - public string Kind { get; } - public string[] Aliases { get; } -} diff --git a/src/MainDemo.Wpf/PackIconKindGroup.cs b/src/MaterialDesignDemo.Shared/Domain/PackIconKindGroup.cs similarity index 100% rename from src/MainDemo.Wpf/PackIconKindGroup.cs rename to src/MaterialDesignDemo.Shared/Domain/PackIconKindGroup.cs diff --git a/src/MaterialDesignDemo.Shared/Domain/TypographyViewModel.cs b/src/MaterialDesignDemo.Shared/Domain/TypographyViewModel.cs new file mode 100644 index 0000000000..70269c5873 --- /dev/null +++ b/src/MaterialDesignDemo.Shared/Domain/TypographyViewModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; +using MaterialDesignThemes.Wpf; + +namespace MaterialDesignDemo.Shared.Domain; + +public sealed partial class TypographyViewModel : ObservableObject +{ + public TypographyViewModel() + { + PackIcons = Enum.GetValues(typeof(PackIconKind)) + .Cast() + .Distinct() + .ToList(); + + SelectedPackIcon = PackIconKind.Account; + } + + public IReadOnlyList PackIcons { get; } + + [ObservableProperty] + private PackIconKind _selectedPackIcon; +} diff --git a/src/MaterialDesignThemes.Wpf/PackIcon.cs b/src/MaterialDesignThemes.Wpf/PackIcon.cs index 0aa3d90e0e..4d9a202b5c 100644 --- a/src/MaterialDesignThemes.Wpf/PackIcon.cs +++ b/src/MaterialDesignThemes.Wpf/PackIcon.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using System.Windows.Data; using System.Windows.Media; namespace MaterialDesignThemes.Wpf; @@ -44,6 +45,40 @@ public string? Data private set => SetValue(DataPropertyKey, value); } + public static readonly DependencyProperty MatchSizeWithProperty = + DependencyProperty.Register( + nameof(MatchSizeWith), + typeof(FrameworkElement), + typeof(PackIcon), + new PropertyMetadata(null, OnMatchSizeWithChanged)); + + public FrameworkElement? MatchSizeWith + { + get => (FrameworkElement?)GetValue(MatchSizeWithProperty); + set => SetValue(MatchSizeWithProperty, value); + } + + private static void OnMatchSizeWithChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var icon = (PackIcon)d; + + // Clear old bindings + BindingOperations.ClearBinding(icon, HeightProperty); + BindingOperations.ClearBinding(icon, WidthProperty); + + if (e.NewValue is FrameworkElement source) + { + var heightBinding = new Binding(nameof(FrameworkElement.ActualHeight)) + { + Source = source, + Mode = BindingMode.OneWay + }; + + icon.SetBinding(HeightProperty, heightBinding); + icon.SetBinding(WidthProperty, heightBinding); // Bind the Width to the height, so that the icon is always rectangular + } + } + public override void OnApplyTemplate() { base.OnApplyTemplate(); diff --git a/tests/MaterialDesignThemes.UITests/WPF/PackIcon/PackIconTests.cs b/tests/MaterialDesignThemes.UITests/WPF/PackIcon/PackIconTests.cs new file mode 100644 index 0000000000..472e08aa2d --- /dev/null +++ b/tests/MaterialDesignThemes.UITests/WPF/PackIcon/PackIconTests.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace MaterialDesignThemes.UITests.WPF.PackIcon; + +public class PackIconTests : TestBase +{ + [Test] + [Arguments(14)] + [Arguments(60)] + public async Task PackIcon_MatchSizeWith_SyncsSizeWithSource(double fontSize) + { + await using var recorder = new TestRecorder(App); + + var stackPanel = await LoadXaml($$""" + + + + + """); + + var icon = await stackPanel.GetElement("/PackIcon"); + var textBox = await stackPanel.GetElement("/TextBlock"); + + double iconHeight = await icon.GetActualHeight(); + double iconWidth = await icon.GetActualWidth(); + double textBoxHeight = await textBox.GetActualHeight(); + + await Assert.That(iconHeight).IsEqualTo(iconWidth); + await Assert.That(iconHeight).IsEqualTo(textBoxHeight); + + recorder.Success(); + } +}