diff --git a/demo/Ursa.Demo/Pages/AvatarDemo.axaml b/demo/Ursa.Demo/Pages/AvatarDemo.axaml index c3046c37..1524a7dd 100644 --- a/demo/Ursa.Demo/Pages/AvatarDemo.axaml +++ b/demo/Ursa.Demo/Pages/AvatarDemo.axaml @@ -93,5 +93,11 @@ + + + + + + \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/BadgeDemo.axaml b/demo/Ursa.Demo/Pages/BadgeDemo.axaml index f46673b6..f633f70b 100644 --- a/demo/Ursa.Demo/Pages/BadgeDemo.axaml +++ b/demo/Ursa.Demo/Pages/BadgeDemo.axaml @@ -16,341 +16,306 @@ - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + - - - - + + - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - - + - - - + - - - + - - - + - - - + - - - + + - - - + - - - + - - - + - - - + - - - + - - - + + - - - + - - - + - - - + - - - + - - - + - - - + + - - - + - - - + - - - + - - - + - - - + - - - + + - - - + - - - + - - - + - - - + - - - + - - - + - + + - - - + - - - + - - - + - - - + - - - + - - - + diff --git a/demo/Ursa.Demo/Pages/IntroductionDemo.axaml b/demo/Ursa.Demo/Pages/IntroductionDemo.axaml index ac0a9f20..cfdd29b3 100644 --- a/demo/Ursa.Demo/Pages/IntroductionDemo.axaml +++ b/demo/Ursa.Demo/Pages/IntroductionDemo.axaml @@ -103,24 +103,24 @@ Content="Step 1" Header="ToDo" Type="Default" - Time="2023-01-14 09:24:05"/> + Time="2023-01-14 09:24:05" /> + Time="2024-01-04 22:32:58" /> + Time="2024-01-05 00:08:29" /> + Type="Success" + Time="2024-01-05 00:27:44" /> @@ -133,58 +133,38 @@ - Badge + + + - - - - + + - - - - + + - - - - + + - - - - - - - - - + + - - - - + + - - - - + + - - - - + + + + - DualBadge + + + diff --git a/src/Ursa.Themes.Semi/Controls/Avatar.axaml b/src/Ursa.Themes.Semi/Controls/Avatar.axaml index 4fe9705c..68a9b78c 100644 --- a/src/Ursa.Themes.Semi/Controls/Avatar.axaml +++ b/src/Ursa.Themes.Semi/Controls/Avatar.axaml @@ -1,14 +1,20 @@  - + xmlns:u="https://irihi.tech/ursa"> + + + + + + + + @@ -25,13 +31,18 @@ BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding Background}" /> - + + + - + + + + + + + + + + + + + + + + + + + + + + @@ -22,7 +45,7 @@ - @@ -39,16 +62,19 @@ MinWidth="{DynamicResource BadgeMinWidth}" MinHeight="{DynamicResource BadgeMinHeight}" Padding="{DynamicResource BadgePadding}" - HorizontalAlignment="Right" - VerticalAlignment="Top" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" - IsVisible="{Binding Header, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static ObjectConverters.IsNotNull}}" RenderTransformOrigin=".5,.5" Theme="{TemplateBinding BadgeTheme}" UseLayoutRounding="False"> + + + + + + - + - + + + diff --git a/src/Ursa.Themes.Semi/Themes/Dark/Badge.axaml b/src/Ursa.Themes.Semi/Themes/Dark/Badge.axaml index 37c65848..5c2b5e95 100644 --- a/src/Ursa.Themes.Semi/Themes/Dark/Badge.axaml +++ b/src/Ursa.Themes.Semi/Themes/Dark/Badge.axaml @@ -3,32 +3,32 @@ - - - - - - + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + \ No newline at end of file diff --git a/src/Ursa.Themes.Semi/Themes/Light/Badge.axaml b/src/Ursa.Themes.Semi/Themes/Light/Badge.axaml index 403f1375..ff148f72 100644 --- a/src/Ursa.Themes.Semi/Themes/Light/Badge.axaml +++ b/src/Ursa.Themes.Semi/Themes/Light/Badge.axaml @@ -3,32 +3,32 @@ - + + - - + - + - + + + - + - - - + - + + - \ No newline at end of file diff --git a/src/Ursa.Themes.Semi/Themes/Shared/Badge.axaml b/src/Ursa.Themes.Semi/Themes/Shared/Badge.axaml index 7c397860..b69c74a8 100644 --- a/src/Ursa.Themes.Semi/Themes/Shared/Badge.axaml +++ b/src/Ursa.Themes.Semi/Themes/Shared/Badge.axaml @@ -6,9 +6,9 @@ 18 8 8 - 6,0 + 4,0 1 - 10 + 12 100 TopRight \ No newline at end of file diff --git a/src/Ursa/Controls/Badge.cs b/src/Ursa/Controls/Badge.cs index 6092f97e..440781d4 100644 --- a/src/Ursa/Controls/Badge.cs +++ b/src/Ursa/Controls/Badge.cs @@ -10,7 +10,7 @@ namespace Ursa.Controls; [TemplatePart(PART_BadgeContainer, typeof(Border))] -public class Badge: HeaderedContentControl +public class Badge : HeaderedContentControl { public const string PART_ContentPresenter = "PART_ContentPresenter"; public const string PART_BadgeContainer = "PART_BadgeContainer"; @@ -18,40 +18,44 @@ public class Badge: HeaderedContentControl private Border? _badgeContainer; - public static readonly StyledProperty BadgeThemeProperty = AvaloniaProperty.Register( - nameof(BadgeTheme)); + public static readonly StyledProperty BadgeThemeProperty = + AvaloniaProperty.Register(nameof(BadgeTheme)); + public ControlTheme BadgeTheme { get => GetValue(BadgeThemeProperty); set => SetValue(BadgeThemeProperty, value); } - public static readonly StyledProperty DotProperty = AvaloniaProperty.Register( - nameof(Dot)); + public static readonly StyledProperty DotProperty = + AvaloniaProperty.Register(nameof(Dot)); + public bool Dot { get => GetValue(DotProperty); set => SetValue(DotProperty, value); } - public static readonly StyledProperty CornerPositionProperty = AvaloniaProperty.Register( - nameof(CornerPosition)); + public static readonly StyledProperty CornerPositionProperty = + AvaloniaProperty.Register(nameof(CornerPosition)); + public CornerPosition CornerPosition { get => GetValue(CornerPositionProperty); set => SetValue(CornerPositionProperty, value); } - public static readonly StyledProperty OverflowCountProperty = AvaloniaProperty.Register( - nameof(OverflowCount)); + public static readonly StyledProperty OverflowCountProperty = + AvaloniaProperty.Register(nameof(OverflowCount)); + public int OverflowCount { get => GetValue(OverflowCountProperty); set => SetValue(OverflowCountProperty, value); } - public static readonly StyledProperty BadgeFontSizeProperty = AvaloniaProperty.Register( - nameof(BadgeFontSize)); + public static readonly StyledProperty BadgeFontSizeProperty = + AvaloniaProperty.Register(nameof(BadgeFontSize)); public double BadgeFontSize { @@ -62,6 +66,7 @@ public double BadgeFontSize static Badge() { HeaderProperty.Changed.AddClassHandler((badge, _) => badge.UpdateBadgePosition()); + DotProperty.Changed.AddClassHandler((badge, _) => badge.UpdateBadgePosition()); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) @@ -88,12 +93,14 @@ private void UpdateBadgePosition() var horizontal = CornerPosition is CornerPosition.TopRight or CornerPosition.BottomRight ? 1 : -1; if (_badgeContainer is not null && Presenter?.Child is not null) { - _badgeContainer.RenderTransform = new TransformGroup() + _badgeContainer.RenderTransform = new TransformGroup { - Children = new Transforms() - { - new TranslateTransform(horizontal*_badgeContainer.Bounds.Width/2,vertical*_badgeContainer.Bounds.Height/2) - } + Children = + [ + new TranslateTransform( + horizontal * _badgeContainer.Bounds.Width / 2, + vertical * _badgeContainer.Bounds.Height / 2) + ] }; } } diff --git a/src/Ursa/Converters/BadgeContentOverflowConverter.cs b/src/Ursa/Converters/BadgeContentOverflowConverter.cs index 922c44fd..e44d902a 100644 --- a/src/Ursa/Converters/BadgeContentOverflowConverter.cs +++ b/src/Ursa/Converters/BadgeContentOverflowConverter.cs @@ -3,18 +3,19 @@ namespace Ursa.Converters; -public class BadgeContentOverflowConverter: IMultiValueConverter +public class BadgeContentOverflowConverter : IMultiValueConverter { public object? Convert(IList values, Type targetType, object? parameter, CultureInfo culture) { - string overflowMark = parameter is string s ? s : "+"; - if (double.TryParse(values[0]?.ToString(), out var b) && values[1] is int i and > 0) + var overflowMark = parameter as string ?? "+"; + if (double.TryParse(values[0]?.ToString(), out var b) && values[1] is int count and > 0) { - if (b > i) + if (b > count) { - return i + overflowMark; + return $"{count}{overflowMark}"; } } + return values[0]; } } \ No newline at end of file diff --git a/src/Ursa/Converters/DivideByTwoConverter.cs b/src/Ursa/Converters/DivideByTwoConverter.cs deleted file mode 100644 index 15c2aa3e..00000000 --- a/src/Ursa/Converters/DivideByTwoConverter.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Globalization; -using Avalonia.Data.Converters; - -namespace Ursa.Converters; - -public class DivideByTwoConverter : IValueConverter -{ - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value is double d) - { - return d / 2; - } - - return value; - } - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/tests/HeadlessTest.Ursa/Controls/BadgeTests/BadgeTests.cs b/tests/HeadlessTest.Ursa/Controls/BadgeTests/BadgeTests.cs new file mode 100644 index 00000000..f2d4c886 --- /dev/null +++ b/tests/HeadlessTest.Ursa/Controls/BadgeTests/BadgeTests.cs @@ -0,0 +1,79 @@ +using Avalonia.Controls; +using Avalonia.Controls.Presenters; +using Avalonia.Controls.Templates; +using Avalonia.Headless.XUnit; +using UrsaControls = Ursa.Controls; + +namespace HeadlessTest.Ursa.Controls.BadgeTests; + +public class BadgeTests +{ + [AvaloniaFact] + public void Badge_Container_Should_DisAppear_If_Header_Is_Null_And_Dot_Equals_False() + { + // Arrange + var window = new Window(); + var badge = new UrsaControls.Badge + { + Header = string.Empty, + Dot = true + }; + window.Content = badge; + window.Show(); + + Assert.True(badge.IsVisible); + + var badgeContainer = badge.GetTemplateChildren().OfType() + .FirstOrDefault(a => a.Name == UrsaControls.Badge.PART_BadgeContainer); + + Assert.NotNull(badgeContainer); + + Assert.True(badgeContainer.IsVisible); + + // Act + badge.Header = null; + // Assert + Assert.True(badgeContainer.IsVisible); + + // Act + badge.Dot = false; + // Assert + Assert.False(badgeContainer.IsVisible); + } + + [AvaloniaFact] + public void Badge_Container_Should_Overflow_If_Number_Larger_Than_OverflowCount() + { + // Arrange + var window = new Window(); + var badge = new UrsaControls.Badge + { + Header = 0, + OverflowCount = 10 + }; + window.Content = badge; + window.Show(); + + Assert.True(badge.IsVisible); + + var header = badge.GetTemplateChildren().OfType() + .FirstOrDefault(a => a.Name == UrsaControls.Badge.PART_HeaderPresenter); + + Assert.NotNull(header); + Assert.Equal(header.Content, 0); + + // Act + badge.Header = 10; + + // Assert + Assert.Equal(header.Content, 10); + + // Act + badge.Header = 11; + Assert.Equal(header.Content, "10+"); + + // Act + badge.OverflowCount = 100; + Assert.Equal(header.Content, 11); + } +} \ No newline at end of file