feat: work around .net standard 2.0 formatting to H
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<!-- Add Resources Here -->
|
<!-- Add Resources Here -->
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<u:TimePickerPresenter Width="300" Height="300" />
|
<u:TimePickerPresenter Height="300" />
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
<ControlTheme x:Key="{x:Type u:TimePickerPresenter}" TargetType="u:TimePickerPresenter">
|
<ControlTheme x:Key="{x:Type u:TimePickerPresenter}" TargetType="u:TimePickerPresenter">
|
||||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
@@ -12,32 +12,39 @@
|
|||||||
<Setter Property="MaxHeight" Value="300" />
|
<Setter Property="MaxHeight" Value="300" />
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:TimePickerPresenter">
|
<ControlTemplate TargetType="u:TimePickerPresenter">
|
||||||
<Grid
|
<Grid Name="{x:Static u:TimePickerPresenter.PART_PickerContainer}" ColumnDefinitions="*, Auto, *, Auto, *, Auto, *">
|
||||||
Name="{x:Static u:TimePickerPresenter.PART_PickerContainer}"
|
|
||||||
ColumnDefinitions="*, *, *, *, Auto">
|
|
||||||
<Grid.Styles>
|
<Grid.Styles>
|
||||||
<Style Selector="u|UrsaDateTimeScrollPanel > ListBoxItem">
|
<Style Selector="u|UrsaDateTimeScrollPanel > ListBoxItem">
|
||||||
<Setter Property="Theme" Value="{DynamicResource DateTimePickerItem}" />
|
<Setter Property="Theme" Value="{DynamicResource DateTimePickerItem}" />
|
||||||
</Style>
|
</Style>
|
||||||
</Grid.Styles>
|
</Grid.Styles>
|
||||||
<ScrollViewer
|
<ScrollViewer
|
||||||
|
Name="{x:Static u:TimePickerPresenter.PART_HourScrollPanel}"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
HorizontalContentAlignment="Left"
|
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
HorizontalContentAlignment="Left"
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
VerticalScrollBarVisibility="Hidden">
|
VerticalScrollBarVisibility="Hidden">
|
||||||
<u:UrsaDateTimeScrollPanel
|
<u:UrsaDateTimeScrollPanel
|
||||||
Name="{x:Static u:TimePickerPresenter.PART_HourSelector}"
|
Name="{x:Static u:TimePickerPresenter.PART_HourSelector}"
|
||||||
HorizontalAlignment="Left"
|
|
||||||
MinWidth="64"
|
MinWidth="64"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
ItemHeight="32"
|
ItemHeight="32"
|
||||||
PanelType="Hour"
|
PanelType="Hour"
|
||||||
ShouldLoop="True" />
|
ShouldLoop="True" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
<ScrollViewer
|
<Rectangle
|
||||||
Grid.Column="1"
|
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"
|
HorizontalAlignment="Left"
|
||||||
|
HorizontalContentAlignment="Left"
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
VerticalScrollBarVisibility="Hidden">
|
VerticalScrollBarVisibility="Hidden">
|
||||||
<u:UrsaDateTimeScrollPanel
|
<u:UrsaDateTimeScrollPanel
|
||||||
@@ -47,8 +54,16 @@
|
|||||||
PanelType="Minute"
|
PanelType="Minute"
|
||||||
ShouldLoop="True" />
|
ShouldLoop="True" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
<Rectangle
|
||||||
|
Grid.Column="3"
|
||||||
|
Name="{x:Static u:TimePickerPresenter.PART_SecondSeparator}"
|
||||||
|
Width="1"
|
||||||
|
Margin="0,4"
|
||||||
|
Fill="{DynamicResource DateTimePickerSeparatorBackground}"
|
||||||
|
VerticalAlignment="Stretch" />
|
||||||
<ScrollViewer
|
<ScrollViewer
|
||||||
Grid.Column="2"
|
Name="{x:Static u:TimePickerPresenter.PART_SecondScrollPanel}"
|
||||||
|
Grid.Column="4"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
HorizontalContentAlignment="Left"
|
HorizontalContentAlignment="Left"
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
@@ -60,8 +75,16 @@
|
|||||||
PanelType="Minute"
|
PanelType="Minute"
|
||||||
ShouldLoop="True" />
|
ShouldLoop="True" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
<Rectangle
|
||||||
|
Grid.Column="5"
|
||||||
|
Name="{x:Static u:TimePickerPresenter.PART_ThirdSeparator}"
|
||||||
|
Width="1"
|
||||||
|
Margin="0,4"
|
||||||
|
Fill="{DynamicResource DateTimePickerSeparatorBackground}"
|
||||||
|
VerticalAlignment="Stretch" />
|
||||||
<ScrollViewer
|
<ScrollViewer
|
||||||
Grid.Column="3"
|
Name="{x:Static u:TimePickerPresenter.PART_AmPmScrollPanel}"
|
||||||
|
Grid.Column="6"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
HorizontalContentAlignment="Left"
|
HorizontalContentAlignment="Left"
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Irihi.Avalonia.Shared.Helpers;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
@@ -10,6 +11,13 @@ namespace Ursa.Controls;
|
|||||||
[TemplatePart(PART_MinuteSelector, typeof(DateTimePickerPanel))]
|
[TemplatePart(PART_MinuteSelector, typeof(DateTimePickerPanel))]
|
||||||
[TemplatePart(PART_SecondSelector, typeof(DateTimePickerPanel))]
|
[TemplatePart(PART_SecondSelector, typeof(DateTimePickerPanel))]
|
||||||
[TemplatePart(PART_AmPmSelector, 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 class TimePickerPresenter: TemplatedControl
|
||||||
{
|
{
|
||||||
public const string PART_HourSelector = "PART_HourSelector";
|
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_AmPmSelector = "PART_AmPmSelector";
|
||||||
public const string PART_PickerContainer = "PART_PickerContainer";
|
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? _hourSelector;
|
||||||
private DateTimePickerPanel? _minuteSelector;
|
private DateTimePickerPanel? _minuteSelector;
|
||||||
private DateTimePickerPanel? _secondSelector;
|
private DateTimePickerPanel? _secondSelector;
|
||||||
private DateTimePickerPanel? _ampmSelector;
|
private DateTimePickerPanel? _ampmSelector;
|
||||||
private Grid? _pickerContainer;
|
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>(
|
public static readonly StyledProperty<bool> NeedsConfirmationProperty = AvaloniaProperty.Register<TimePickerPresenter, bool>(
|
||||||
nameof(NeedsConfirmation));
|
nameof(NeedsConfirmation));
|
||||||
@@ -51,17 +77,8 @@ public class TimePickerPresenter: TemplatedControl
|
|||||||
set => SetValue(TimeProperty, value);
|
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>(
|
public static readonly StyledProperty<string> PanelFormatProperty = AvaloniaProperty.Register<TimePickerPresenter, string>(
|
||||||
nameof(PanelFormat));
|
nameof(PanelFormat), defaultValue: "hh mm ss t");
|
||||||
|
|
||||||
public string PanelFormat
|
public string PanelFormat
|
||||||
{
|
{
|
||||||
@@ -69,6 +86,72 @@ public class TimePickerPresenter: TemplatedControl
|
|||||||
set => SetValue(PanelFormatProperty, value);
|
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()
|
public TimePickerPresenter()
|
||||||
{
|
{
|
||||||
SetCurrentValue(TimeProperty, DateTime.Now.TimeOfDay);
|
SetCurrentValue(TimeProperty, DateTime.Now.TimeOfDay);
|
||||||
@@ -82,48 +165,74 @@ public class TimePickerPresenter: TemplatedControl
|
|||||||
_secondSelector = e.NameScope.Find<DateTimePickerPanel>(PART_SecondSelector);
|
_secondSelector = e.NameScope.Find<DateTimePickerPanel>(PART_SecondSelector);
|
||||||
_ampmSelector = e.NameScope.Find<DateTimePickerPanel>(PART_AmPmSelector);
|
_ampmSelector = e.NameScope.Find<DateTimePickerPanel>(PART_AmPmSelector);
|
||||||
_pickerContainer = e.NameScope.Find<Grid>(PART_PickerContainer);
|
_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();
|
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()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
if (_pickerContainer is null) return;
|
if (_pickerContainer is null) return;
|
||||||
var use12Clock = Use12Hours;
|
|
||||||
if (_hourSelector is not null)
|
if (_hourSelector is not null)
|
||||||
{
|
{
|
||||||
_hourSelector.MaximumValue = use12Clock ? 12 : 23;
|
|
||||||
_hourSelector.MinimumValue = use12Clock ? 1 : 0;
|
|
||||||
_hourSelector.ItemFormat = "%h";
|
_hourSelector.ItemFormat = "%h";
|
||||||
var hour = Time?.Hours;
|
_hourSelector.MaximumValue = _use12Clock ? 12 : 23;
|
||||||
_hourSelector.SelectedValue = hour ?? 0;
|
_hourSelector.MinimumValue = _use12Clock ? 1 : 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
if(_minuteSelector is not null)
|
if(_minuteSelector is not null)
|
||||||
{
|
{
|
||||||
|
_minuteSelector.ItemFormat = "mm";
|
||||||
_minuteSelector.MaximumValue = 59;
|
_minuteSelector.MaximumValue = 59;
|
||||||
_minuteSelector.MinimumValue = 0;
|
_minuteSelector.MinimumValue = 0;
|
||||||
_minuteSelector.ItemFormat = "mm";
|
|
||||||
var minute = Time?.Minutes;
|
|
||||||
_minuteSelector.SelectedValue = minute ?? 0;
|
|
||||||
}
|
}
|
||||||
if(_secondSelector is not null)
|
if(_secondSelector is not null)
|
||||||
{
|
{
|
||||||
|
_secondSelector.ItemFormat = "mm";
|
||||||
_secondSelector.MaximumValue = 59;
|
_secondSelector.MaximumValue = 59;
|
||||||
_secondSelector.MinimumValue = 0;
|
_secondSelector.MinimumValue = 0;
|
||||||
_secondSelector.ItemFormat = "mm";
|
|
||||||
var second = Time?.Seconds;
|
|
||||||
_secondSelector.SelectedValue = second ?? 0;
|
|
||||||
}
|
}
|
||||||
if(_ampmSelector is not null)
|
if(_ampmSelector is not null)
|
||||||
{
|
{
|
||||||
|
_ampmSelector.ItemFormat = "t";
|
||||||
_ampmSelector.MaximumValue = 1;
|
_ampmSelector.MaximumValue = 1;
|
||||||
_ampmSelector.MinimumValue = 0;
|
_ampmSelector.MinimumValue = 0;
|
||||||
_ampmSelector.ItemFormat = "%t";
|
|
||||||
var ampm = Time?.Hours switch
|
|
||||||
{
|
|
||||||
>= 12 => 1,
|
|
||||||
_ => 0
|
|
||||||
};
|
|
||||||
_ampmSelector.SelectedValue = ampm;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user