feat: fix several selection issue related to 12 clock mode.

This commit is contained in:
rabbitism
2024-04-26 20:34:20 +08:00
parent 1e5da1869c
commit 63b9ccfe5e
4 changed files with 52 additions and 50 deletions

View File

@@ -152,11 +152,16 @@
Placement="BottomEdgeAlignedLeft"
PlacementTarget="Background">
<Border Theme="{DynamicResource CardBorder}">
<u:TimePickerPresenter
Name="{x:Static u:TimePicker.PART_Presenter}"
NeedsConfirmation="{TemplateBinding NeedConfirmation}"
PanelFormat="{TemplateBinding PanelFormat}"
Time="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedTime, Mode=OneWayToSource}" />
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" IsVisible="{TemplateBinding NeedConfirmation}">
<Button Content="Confirm" Command="{Binding $parent[u:TimePicker].Confirm}"></Button>
</StackPanel>
<u:TimePickerPresenter
Name="{x:Static u:TimePicker.PART_Presenter}"
NeedsConfirmation="{TemplateBinding NeedConfirmation}"
PanelFormat="{TemplateBinding PanelFormat}"
Time="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedTime, Mode=OneWayToSource}" />
</DockPanel>
</Border>
</Popup>
</Grid>

View File

@@ -11,23 +11,18 @@ using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls;
[TemplatePart( PART_TextBox, typeof(TextBox))]
[TemplatePart( PART_Popup, typeof(Popup))]
[TemplatePart( PART_Presenter, typeof(TimePickerPresenter))]
[TemplatePart(PART_TextBox, typeof(TextBox))]
[TemplatePart(PART_Popup, typeof(Popup))]
[TemplatePart(PART_Presenter, typeof(TimePickerPresenter))]
public class TimePicker : TemplatedControl, IClearControl, IInnerContentControl, IPopupInnerContent
{
public const string PART_TextBox = "PART_TextBox";
public const string PART_Popup = "PART_Popup";
public const string PART_Presenter = "PART_Presenter";
private TextBox? _textBox;
private Popup? _popup;
private TimePickerPresenter? _presenter;
private bool _updateFromPresenter;
public static readonly StyledProperty<string?> DisplayFormatProperty = AvaloniaProperty.Register<TimePicker, string?>(
nameof(DisplayFormat), "HH:mm:ss");
public static readonly StyledProperty<string?> DisplayFormatProperty =
AvaloniaProperty.Register<TimePicker, string?>(
nameof(DisplayFormat), "HH:mm:ss");
public static readonly StyledProperty<string> PanelFormatProperty = AvaloniaProperty.Register<TimePicker, string>(
nameof(PanelFormat), "HH mm ss");
@@ -62,6 +57,19 @@ public class TimePicker : TemplatedControl, IClearControl, IInnerContentControl,
public static readonly StyledProperty<bool> IsDropdownOpenProperty = AvaloniaProperty.Register<TimePicker, bool>(
nameof(IsDropdownOpen), defaultBindingMode: BindingMode.TwoWay);
private Popup? _popup;
private TimePickerPresenter? _presenter;
private TextBox? _textBox;
private bool _updateFromText;
static TimePicker()
{
SelectedTimeProperty.Changed.AddClassHandler<TimePicker, TimeSpan?>((picker, args) =>
picker.OnSelectionChanged(args));
}
public bool IsDropdownOpen
{
get => GetValue(IsDropdownOpenProperty);
@@ -74,16 +82,6 @@ public class TimePicker : TemplatedControl, IClearControl, IInnerContentControl,
set => SetValue(WatermarkProperty, value);
}
private TimeSpan? _selectedTimeHolder;
static TimePicker()
{
PanelFormatProperty.Changed.AddClassHandler<TimePicker, string>((picker, args) =>
picker.OnPanelFormatChanged(args));
SelectedTimeProperty.Changed.AddClassHandler<TimePicker, TimeSpan?>((picker, args) =>
picker.OnSelectionChanged(args));
}
public string? DisplayFormat
{
get => GetValue(DisplayFormatProperty);
@@ -137,23 +135,18 @@ public class TimePicker : TemplatedControl, IClearControl, IInnerContentControl,
set => SetValue(PopupInnerBottomContentProperty, value);
}
private void OnPanelFormatChanged(AvaloniaPropertyChangedEventArgs<string> args)
{
var format = args.NewValue.Value;
var parts = format.Split(' ', '-', ':');
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
_textBox = e.NameScope.Find<TextBox>(PART_TextBox);
_popup = e.NameScope.Find<Popup>(PART_Popup);
_presenter = e.NameScope.Find<TimePickerPresenter>(PART_Presenter);
TextBox.GotFocusEvent.AddHandler(OnTextBoxGetFocus, _textBox);
GotFocusEvent.AddHandler(OnTextBoxGetFocus, _textBox);
TextBox.TextChangedEvent.AddDisposableHandler(OnTextChanged, _textBox);
TextBox.PointerPressedEvent.AddHandler(OnTextBoxPointerPressed, RoutingStrategies.Tunnel, false, _textBox);
PointerPressedEvent.AddHandler(OnTextBoxPointerPressed, RoutingStrategies.Tunnel, false, _textBox);
SetCurrentValue(SelectedTimeProperty, DateTime.Now.TimeOfDay);
}
private void OnTextBoxPointerPressed(object sender, PointerPressedEventArgs e)
@@ -169,35 +162,38 @@ public class TimePicker : TemplatedControl, IClearControl, IInnerContentControl,
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
_updateFromText = true;
if (DisplayFormat is null || DisplayFormat.Length == 0)
{
if (TimeSpan.TryParse(_textBox?.Text, out var defaultTime))
{
TimePickerPresenter.TimeProperty.SetValue(defaultTime, _presenter);
}
}
else
{
if(DateTime.TryParseExact(_textBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var time))
{
TimePickerPresenter.TimeProperty.SetValue(time.TimeOfDay, _presenter);
}
if (DateTime.TryParseExact(_textBox?.Text, DisplayFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None,
out var time)) TimePickerPresenter.TimeProperty.SetValue(time.TimeOfDay, _presenter);
}
_updateFromText = false;
}
private void OnSelectionChanged(AvaloniaPropertyChangedEventArgs<TimeSpan?> args)
{
if (_textBox is null) return;
var time = args.NewValue.Value;
var text = new DateTime(1,1,1, time?.Hours ?? 0, time?.Minutes ?? 0, time?.Seconds ?? 0).ToString(DisplayFormat);
DateTime date = new DateTime(1, 1, 1, time?.Hours ?? 0, time?.Minutes ?? 0, time?.Seconds ?? 0);
var text = date.ToString(DisplayFormat);
_textBox.Text = text;
}
public void Confirm()
{
if (NeedConfirmation)
// TODO: close popup.
SetCurrentValue(SelectedTimeProperty, _selectedTimeHolder);
_presenter?.Confirm();
SetCurrentValue(IsDropdownOpenProperty, false);
}
public void Dismiss()
{
SetCurrentValue(IsDropdownOpenProperty, false);
}
protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error)

View File

@@ -266,7 +266,9 @@ public class TimePickerPresenter: TemplatedControl
var time = Time ?? DateTime.Now.TimeOfDay;
if (_hourSelector is not null)
{
_hourSelector.SelectedValue = _use12Clock ? time.Hours % 12 : time.Hours;
var index = _use12Clock ? time.Hours % 12 : time.Hours;
if (index == 0) index = 12;
_hourSelector.SelectedValue = index;
}
if (_minuteSelector is not null)
{