Browse Source

Fix TimePicker empty designator on 12 hour clock (#13469)

* Test - On empty PM/AM designator on culture info the time picker should show AM/PM

* On empty PM/AM designator on culture info the time picker should show AM/PM
pull/13515/merge
Marko Prosen 3 years ago
committed by GitHub
parent
commit
f6c5720e7a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
  2. 7
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  3. 16
      src/Avalonia.Controls/Utils/TimeUtils.cs
  4. 34
      tests/Avalonia.Controls.UnitTests/TimePickerTests.cs
  5. 37
      tests/Avalonia.UnitTests/UseEmptyDesignatorCultureAttribute.cs

4
src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs

@ -2,6 +2,7 @@
using System.Globalization;
using System.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Utils;
using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Interactivity;
@ -516,8 +517,7 @@ namespace Avalonia.Controls.Primitives
case DateTimePickerPanelType.Minute:
return new TimeSpan(0, value, 0).ToString(ItemFormat);
case DateTimePickerPanelType.TimePeriod:
return value == MinimumValue ? CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator :
CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator;
return value == MinimumValue ? TimeUtils.GetAMDesignator() : TimeUtils.GetPMDesignator();
default:
return "";
}

7
src/Avalonia.Controls/DateTimePickers/TimePicker.cs

@ -5,6 +5,7 @@ using Avalonia.Data;
using Avalonia.Layout;
using System;
using System.Globalization;
using Avalonia.Controls.Utils;
namespace Avalonia.Controls
{
@ -227,8 +228,7 @@ namespace Avalonia.Controls
_minuteText.Text = newTime.ToString("mm");
PseudoClasses.Set(":hasnotime", false);
_periodText.Text = time.Value.Hours >= 12 ? CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator :
CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator;
_periodText.Text = time.Value.Hours >= 12 ? TimeUtils.GetPMDesignator() : TimeUtils.GetAMDesignator();
}
else
{
@ -236,8 +236,7 @@ namespace Avalonia.Controls
_minuteText.Text = "minute";
PseudoClasses.Set(":hasnotime", true);
_periodText.Text = DateTime.Now.Hour >= 12 ? CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator :
CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator;
_periodText.Text = DateTime.Now.Hour >= 12 ? TimeUtils.GetPMDesignator() : TimeUtils.GetAMDesignator();
}
}

16
src/Avalonia.Controls/Utils/TimeUtils.cs

@ -0,0 +1,16 @@
using System.Globalization;
namespace Avalonia.Controls.Utils;
internal static class TimeUtils
{
public static string GetPMDesignator() =>
!string.IsNullOrEmpty(CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator) ?
CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator :
CultureInfo.InvariantCulture.DateTimeFormat.PMDesignator;
public static string GetAMDesignator() =>
!string.IsNullOrEmpty(CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator) ?
CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator :
CultureInfo.InvariantCulture.DateTimeFormat.AMDesignator;
}

34
tests/Avalonia.Controls.UnitTests/TimePickerTests.cs

@ -98,6 +98,40 @@ namespace Avalonia.Controls.UnitTests
Assert.True(minuteText.Text == "minute");
}
}
[Fact]
[UseEmptyDesignatorCulture]
public void Using_12HourClock_On_Culture_With_Empty_Period_Should_Show_Period()
{
using (UnitTestApplication.Start(Services))
{
TimePicker timePicker = new TimePicker()
{
Template = CreateTemplate(), ClockIdentifier = "12HourClock",
};
timePicker.ApplyTemplate();
var desc = timePicker.GetVisualDescendants();
Assert.True(desc.Count() > 1); //Should be layoutroot grid & button
Assert.True(desc.ElementAt(1) is Button);
var container = (desc.ElementAt(1) as Button).Content as Grid;
Assert.True(container != null);
var periodTextHost = container.Children[4] as Border;
Assert.NotNull(periodTextHost);
var periodText = periodTextHost.Child as TextBlock;
Assert.NotNull(periodTextHost);
TimeSpan ts = TimeSpan.FromHours(10);
timePicker.SelectedTime = ts;
Assert.False(string.IsNullOrEmpty(periodText.Text));
timePicker.SelectedTime = null;
Assert.False(string.IsNullOrEmpty(periodText.Text));
}
}
private static TestServices Services => TestServices.MockThreadingInterface.With(
fontManagerImpl: new HeadlessFontManagerStub(),

37
tests/Avalonia.UnitTests/UseEmptyDesignatorCultureAttribute.cs

@ -0,0 +1,37 @@
#nullable enable
using System;
using System.Globalization;
using System.Reflection;
using Xunit.Sdk;
namespace Avalonia.UnitTests;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class UseEmptyDesignatorCultureAttribute : BeforeAfterTestAttribute
{
private CultureInfo? _previousCulture;
private CultureInfo? _previousUICulture;
private CultureInfo CultureInfo { get; } =
new(string.Empty, false) { DateTimeFormat = { AMDesignator = string.Empty, PMDesignator = string.Empty } };
public override void Before(MethodInfo methodUnderTest)
{
base.Before(methodUnderTest);
_previousCulture = CultureInfo.CurrentCulture;
_previousUICulture = CultureInfo.CurrentUICulture;
CultureInfo.CurrentCulture = CultureInfo;
CultureInfo.CurrentUICulture = CultureInfo;
}
public override void After(MethodInfo methodUnderTest)
{
CultureInfo.CurrentCulture = _previousCulture!;
CultureInfo.CurrentUICulture = _previousUICulture!;
base.After(methodUnderTest);
}
}
Loading…
Cancel
Save