feat: work around .net standard 2.0 formatting to H

This commit is contained in:
rabbitism
2024-04-26 17:57:53 +08:00
parent 68545dbf54
commit 41b530b7bf
2 changed files with 172 additions and 40 deletions

View File

@@ -4,7 +4,7 @@
xmlns:u="https://irihi.tech/ursa">
<!-- Add Resources Here -->
<Design.PreviewWith>
<u:TimePickerPresenter Width="300" Height="300" />
<u:TimePickerPresenter Height="300" />
</Design.PreviewWith>
<ControlTheme x:Key="{x:Type u:TimePickerPresenter}" TargetType="u:TimePickerPresenter">
<Setter Property="HorizontalAlignment" Value="Left" />
@@ -12,32 +12,39 @@
<Setter Property="MaxHeight" Value="300" />
<Setter Property="Template">
<ControlTemplate TargetType="u:TimePickerPresenter">
<Grid
Name="{x:Static u:TimePickerPresenter.PART_PickerContainer}"
ColumnDefinitions="*, *, *, *, Auto">
<Grid Name="{x:Static u:TimePickerPresenter.PART_PickerContainer}" ColumnDefinitions="*, Auto, *, Auto, *, Auto, *">
<Grid.Styles>
<Style Selector="u|UrsaDateTimeScrollPanel > ListBoxItem">
<Setter Property="Theme" Value="{DynamicResource DateTimePickerItem}"/>
<Style Selector="u|UrsaDateTimeScrollPanel &gt; ListBoxItem">
<Setter Property="Theme" Value="{DynamicResource DateTimePickerItem}" />
</Style>
</Grid.Styles>
<ScrollViewer
Name="{x:Static u:TimePickerPresenter.PART_HourScrollPanel}"
Grid.Column="0"
HorizontalContentAlignment="Left"
HorizontalAlignment="Left"
HorizontalContentAlignment="Left"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<u:UrsaDateTimeScrollPanel
Name="{x:Static u:TimePickerPresenter.PART_HourSelector}"
HorizontalAlignment="Left"
MinWidth="64"
HorizontalAlignment="Left"
ItemHeight="32"
PanelType="Hour"
ShouldLoop="True" />
</ScrollViewer>
<ScrollViewer
<Rectangle
Grid.Column="1"
HorizontalContentAlignment="Left"
Name="{x:Static u:TimePickerPresenter.PART_FirstSeparator}"
Width="1"
Margin="0,4"
Fill="{DynamicResource DateTimePickerSeparatorBackground}"
VerticalAlignment="Stretch" />
<ScrollViewer
Name="{x:Static u:TimePickerPresenter.PART_MinuteScrollPanel}"
Grid.Column="2"
HorizontalAlignment="Left"
HorizontalContentAlignment="Left"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<u:UrsaDateTimeScrollPanel
@@ -47,8 +54,16 @@
PanelType="Minute"
ShouldLoop="True" />
</ScrollViewer>
<Rectangle
Grid.Column="3"
Name="{x:Static u:TimePickerPresenter.PART_SecondSeparator}"
Width="1"
Margin="0,4"
Fill="{DynamicResource DateTimePickerSeparatorBackground}"
VerticalAlignment="Stretch" />
<ScrollViewer
Grid.Column="2"
Name="{x:Static u:TimePickerPresenter.PART_SecondScrollPanel}"
Grid.Column="4"
HorizontalAlignment="Left"
HorizontalContentAlignment="Left"
HorizontalScrollBarVisibility="Disabled"
@@ -60,8 +75,16 @@
PanelType="Minute"
ShouldLoop="True" />
</ScrollViewer>
<Rectangle
Grid.Column="5"
Name="{x:Static u:TimePickerPresenter.PART_ThirdSeparator}"
Width="1"
Margin="0,4"
Fill="{DynamicResource DateTimePickerSeparatorBackground}"
VerticalAlignment="Stretch" />
<ScrollViewer
Grid.Column="3"
Name="{x:Static u:TimePickerPresenter.PART_AmPmScrollPanel}"
Grid.Column="6"
HorizontalAlignment="Left"
HorizontalContentAlignment="Left"
HorizontalScrollBarVisibility="Disabled"

View File

@@ -2,6 +2,7 @@
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls;
@@ -10,6 +11,13 @@ namespace Ursa.Controls;
[TemplatePart(PART_MinuteSelector, typeof(DateTimePickerPanel))]
[TemplatePart(PART_SecondSelector, typeof(DateTimePickerPanel))]
[TemplatePart(PART_AmPmSelector, typeof(DateTimePickerPanel))]
[TemplatePart(PART_HourScrollPanel, typeof(Control))]
[TemplatePart(PART_MinuteScrollPanel, typeof(Control))]
[TemplatePart(PART_SecondScrollPanel, typeof(Control))]
[TemplatePart(PART_AmPmScrollPanel, typeof(Control))]
[TemplatePart(PART_FirstSeparator, typeof(Control))]
[TemplatePart(PART_SecondSeparator, typeof(Control))]
[TemplatePart(PART_ThirdSeparator, typeof(Control))]
public class TimePickerPresenter: TemplatedControl
{
public const string PART_HourSelector = "PART_HourSelector";
@@ -18,11 +26,29 @@ public class TimePickerPresenter: TemplatedControl
public const string PART_AmPmSelector = "PART_AmPmSelector";
public const string PART_PickerContainer = "PART_PickerContainer";
public const string PART_HourScrollPanel = "PART_HourScrollPanel";
public const string PART_MinuteScrollPanel = "PART_MinuteScrollPanel";
public const string PART_SecondScrollPanel = "PART_SecondScrollPanel";
public const string PART_AmPmScrollPanel = "PART_AmPmScrollPanel";
public const string PART_FirstSeparator = "PART_FirstSeparator";
public const string PART_SecondSeparator = "PART_SecondSeparator";
public const string PART_ThirdSeparator = "PART_ThirdSeparator";
private DateTimePickerPanel? _hourSelector;
private DateTimePickerPanel? _minuteSelector;
private DateTimePickerPanel? _secondSelector;
private DateTimePickerPanel? _ampmSelector;
private Grid? _pickerContainer;
private Control? _hourScrollPanel;
private Control? _minuteScrollPanel;
private Control? _secondScrollPanel;
private Control? _ampmScrollPanel;
private Control? _firstSeparator;
private Control? _secondSeparator;
private Control? _thirdSeparator;
private bool _use12Clock;
public static readonly StyledProperty<bool> NeedsConfirmationProperty = AvaloniaProperty.Register<TimePickerPresenter, bool>(
nameof(NeedsConfirmation));
@@ -51,17 +77,8 @@ public class TimePickerPresenter: TemplatedControl
set => SetValue(TimeProperty, value);
}
public static readonly StyledProperty<bool> Use12HoursProperty = AvaloniaProperty.Register<TimePickerPresenter, bool>(
nameof(Use12Hours));
public bool Use12Hours
{
get => GetValue(Use12HoursProperty);
set => SetValue(Use12HoursProperty, value);
}
public static readonly StyledProperty<string> PanelFormatProperty = AvaloniaProperty.Register<TimePickerPresenter, string>(
nameof(PanelFormat));
nameof(PanelFormat), defaultValue: "hh mm ss t");
public string PanelFormat
{
@@ -69,6 +86,72 @@ public class TimePickerPresenter: TemplatedControl
set => SetValue(PanelFormatProperty, value);
}
static TimePickerPresenter()
{
PanelFormatProperty.Changed.AddClassHandler<TimePickerPresenter, string>((presenter, args) => presenter.OnPanelFormatChanged(args));
}
private void OnPanelFormatChanged(AvaloniaPropertyChangedEventArgs<string> args)
{
var format = args.NewValue.Value;
UpdatePanelLayout(format);
}
private void UpdatePanelLayout(string panelFormat)
{
var parts = panelFormat.Split(' ', '-', ':');
var panels = new List<Control?>();
foreach (var part in parts)
{
if (part.Length < 1) continue;
if ((part.Contains('h') || part.Contains('H')) && !panels.Contains(_hourScrollPanel))
{
panels.Add(_hourScrollPanel);
_use12Clock = part.Contains('h');
_hourSelector?.SetValue(DateTimePickerPanel.ItemFormatProperty, part.ToLower());
if (_hourSelector is not null)
{
_hourSelector.MaximumValue = _use12Clock ? 12 : 23;
_hourSelector.MinimumValue = _use12Clock ? 1 : 0;
}
}
else if (part[0] == 'm' && !panels.Contains(_minuteSelector))
{
panels.Add(_minuteScrollPanel);
_minuteSelector?.SetValue(DateTimePickerPanel.ItemFormatProperty, part);
}
else if (part[0] == 's' && !panels.Contains(_secondScrollPanel))
{
panels.Add(_secondScrollPanel);
_secondSelector?.SetValue(DateTimePickerPanel.ItemFormatProperty, part.Replace('s', 'm'));
}
else if (part[0] == 't' && !panels.Contains(_ampmScrollPanel))
{
panels.Add(_ampmScrollPanel);
_ampmSelector?.SetValue(DateTimePickerPanel.ItemFormatProperty, part);
}
}
if (panels.Count < 1) return;
IsVisibleProperty.SetValue(false, _hourScrollPanel, _minuteScrollPanel, _secondScrollPanel, _ampmScrollPanel,
_firstSeparator, _secondSeparator, _thirdSeparator);
for(var i = 0; i< panels.Count; i++)
{
var panel = panels[i];
if (panel is null) continue;
panel.IsVisible = true;
Grid.SetColumn(panel, 2 * i);
var separator = i switch
{
0 => _firstSeparator,
1 => _secondSeparator,
2 => _thirdSeparator,
_ => null,
};
IsVisibleProperty.SetValue(true, separator);
}
}
public TimePickerPresenter()
{
SetCurrentValue(TimeProperty, DateTime.Now.TimeOfDay);
@@ -82,48 +165,74 @@ public class TimePickerPresenter: TemplatedControl
_secondSelector = e.NameScope.Find<DateTimePickerPanel>(PART_SecondSelector);
_ampmSelector = e.NameScope.Find<DateTimePickerPanel>(PART_AmPmSelector);
_pickerContainer = e.NameScope.Find<Grid>(PART_PickerContainer);
_hourScrollPanel = e.NameScope.Find<Control>(PART_HourScrollPanel);
_minuteScrollPanel = e.NameScope.Find<Control>(PART_MinuteScrollPanel);
_secondScrollPanel = e.NameScope.Find<Control>(PART_SecondScrollPanel);
_ampmScrollPanel = e.NameScope.Find<Control>(PART_AmPmScrollPanel);
_firstSeparator = e.NameScope.Find<Control>(PART_FirstSeparator);
_secondSeparator = e.NameScope.Find<Control>(PART_SecondSeparator);
_thirdSeparator = e.NameScope.Find<Control>(PART_ThirdSeparator);
Initialize();
UpdatePanelLayout(PanelFormat);
UpdatePanelsFromSelectedTime();
}
private void UpdatePanelsFromSelectedTime()
{
if (Time is null) return;
var time = Time ?? DateTime.Now.TimeOfDay;
if (_hourSelector is not null)
{
_hourSelector.SelectedValue = _use12Clock ? time.Hours % 12 : time.Hours;
}
if (_minuteSelector is not null)
{
_minuteSelector.SelectedValue = time.Minutes;
}
if (_secondSelector is not null)
{
_secondSelector.SelectedValue = time.Seconds;
}
if (_ampmSelector is not null)
{
_ampmSelector.SelectedValue = time.Hours switch
{
>= 12 => 1,
_ => 0
};
}
}
private void Initialize()
{
if (_pickerContainer is null) return;
var use12Clock = Use12Hours;
if (_hourSelector is not null)
{
_hourSelector.MaximumValue = use12Clock ? 12 : 23;
_hourSelector.MinimumValue = use12Clock ? 1 : 0;
_hourSelector.ItemFormat = "%h";
var hour = Time?.Hours;
_hourSelector.SelectedValue = hour ?? 0;
_hourSelector.MaximumValue = _use12Clock ? 12 : 23;
_hourSelector.MinimumValue = _use12Clock ? 1 : 0;
}
if(_minuteSelector is not null)
{
_minuteSelector.ItemFormat = "mm";
_minuteSelector.MaximumValue = 59;
_minuteSelector.MinimumValue = 0;
_minuteSelector.ItemFormat = "mm";
var minute = Time?.Minutes;
_minuteSelector.SelectedValue = minute ?? 0;
}
if(_secondSelector is not null)
{
_secondSelector.ItemFormat = "mm";
_secondSelector.MaximumValue = 59;
_secondSelector.MinimumValue = 0;
_secondSelector.ItemFormat = "mm";
var second = Time?.Seconds;
_secondSelector.SelectedValue = second ?? 0;
}
if(_ampmSelector is not null)
{
_ampmSelector.ItemFormat = "t";
_ampmSelector.MaximumValue = 1;
_ampmSelector.MinimumValue = 0;
_ampmSelector.ItemFormat = "%t";
var ampm = Time?.Hours switch
{
>= 12 => 1,
_ => 0
};
_ampmSelector.SelectedValue = ampm;
}
}
}