From 0fc5cc563755d9c363bf8b6f21e9ba35834dee47 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 25 Apr 2024 19:29:39 +0800 Subject: [PATCH] feat: logical scrollable. --- .../Controls/DateTimePicker/TimePicker.cs | 110 ++++++++++++++++++ .../DateTimePicker/UrsaTimePickerPanel.cs | 62 ++++++++++ .../Controls/Panels/UrsaTimePickerPanel.cs | 28 ----- src/Ursa/Controls/TimePicker/TimePicker.cs | 44 ------- src/Ursa/Ursa.csproj | 4 + 5 files changed, 176 insertions(+), 72 deletions(-) create mode 100644 src/Ursa/Controls/DateTimePicker/TimePicker.cs create mode 100644 src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs delete mode 100644 src/Ursa/Controls/Panels/UrsaTimePickerPanel.cs delete mode 100644 src/Ursa/Controls/TimePicker/TimePicker.cs diff --git a/src/Ursa/Controls/DateTimePicker/TimePicker.cs b/src/Ursa/Controls/DateTimePicker/TimePicker.cs new file mode 100644 index 0000000..6650a24 --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/TimePicker.cs @@ -0,0 +1,110 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Data; +using Irihi.Avalonia.Shared.Contracts; + +namespace Ursa.Controls.TimePicker; + +public class TimePicker: TemplatedControl, IClearControl +{ + private TimeSpan? _selectedTimeHolder; + + public static readonly StyledProperty DisplayFormatProperty = AvaloniaProperty.Register( + nameof(DisplayFormat), defaultValue: "HH:mm:ss"); + + public string DisplayFormat + { + get => GetValue(DisplayFormatProperty); + set => SetValue(DisplayFormatProperty, value); + } + + public static readonly StyledProperty PanelFormatProperty = AvaloniaProperty.Register( + nameof(PanelFormat), defaultValue: "HH mm ss"); + + public string PanelFormat + { + get => GetValue(PanelFormatProperty); + set => SetValue(PanelFormatProperty, value); + } + + public static readonly StyledProperty SelectedTimeProperty = AvaloniaProperty.Register( + nameof(SelectedTime)); + + public TimeSpan? SelectedTime + { + get => GetValue(SelectedTimeProperty); + set => SetValue(SelectedTimeProperty, value); + } + + public static readonly StyledProperty NeedConfirmationProperty = AvaloniaProperty.Register( + nameof(NeedConfirmation)); + + public bool NeedConfirmation + { + get => GetValue(NeedConfirmationProperty); + set => SetValue(NeedConfirmationProperty, value); + } + + public static readonly StyledProperty IsLoopingProperty = AvaloniaProperty.Register( + nameof(IsLooping)); + + public bool IsLooping + { + get => GetValue(IsLoopingProperty); + set => SetValue(IsLoopingProperty, value); + } + + static TimePicker() + { + PanelFormatProperty.Changed.AddClassHandler((picker, args)=> picker.OnPanelFormatChanged(args)); + } + + private void OnPanelFormatChanged(AvaloniaPropertyChangedEventArgs args) + { + var format = args.NewValue.Value; + string[] parts = format.Split(new char[] { ' ', '-', ':' }); + } + + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + + } + + private void OnSelectionChanged() + { + if (NeedConfirmation) + { + _selectedTimeHolder = new TimeSpan(); + } + else + { + SelectedTime = new TimeSpan(); + } + } + + public void Clear() + { + SetCurrentValue(SelectedTimeProperty, null); + } + + public void Confirm() + { + if (NeedConfirmation) + { + // TODO: close popup. + SetCurrentValue(SelectedTimeProperty, _selectedTimeHolder); + } + } + + protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error) + { + base.UpdateDataValidation(property, state, error); + if (property == SelectedTimeProperty) + { + DataValidationErrors.SetError(this, error); + } + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs b/src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs new file mode 100644 index 0000000..5f8397c --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs @@ -0,0 +1,62 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Input; +using Avalonia.Interactivity; + +namespace Ursa.Controls.Panels; + +/// +/// The panel to display items for time selection +/// +public class UrsaTimePickerPanel: Panel, ILogicalScrollable +{ + public static readonly StyledProperty ItemHeightProperty = + AvaloniaProperty.Register( + nameof(ItemHeight), defaultValue: 32); + + public double ItemHeight + { + get => GetValue(ItemHeightProperty); + set => SetValue(ItemHeightProperty, value); + } + + public static readonly StyledProperty ShouldLoopProperty = AvaloniaProperty.Register( + nameof(ShouldLoop)); + + public bool ShouldLoop + { + get => GetValue(ShouldLoopProperty); + set => SetValue(ShouldLoopProperty, value); + } + + static UrsaTimePickerPanel() + { + ItemHeightProperty.Changed.AddClassHandler((panel, args) => panel.OnItemHeightChanged(args)); + AffectsArrange(ItemHeightProperty); + AffectsMeasure(ItemHeightProperty); + } + + private Size _scrollSize; + private Size _pageScrollSize; + private void OnItemHeightChanged(AvaloniaPropertyChangedEventArgs args) + { + var newValue = args.NewValue.Value; + _scrollSize = new Size(0, newValue); + _pageScrollSize = new Size(0, newValue * 3); + } + + public event EventHandler? OnSelectionChanged; + public Size Extent { get; private set; } + public Vector Offset { get; set; } + public Size Viewport => Bounds.Size; + public bool BringIntoView(Control target, Rect targetRect) => false; + public Control? GetControlInDirection(NavigationDirection direction, Control? from) => null; + public void RaiseScrollInvalidated(System.EventArgs e) => ScrollInvalidated?.Invoke(this, e); + public bool CanHorizontallyScroll { get => false; set { } } + public bool CanVerticallyScroll { get => false; set {} } + public bool IsLogicalScrollEnabled => true; + public Size ScrollSize => _scrollSize; + public Size PageScrollSize => _pageScrollSize; + public event EventHandler? ScrollInvalidated; +} \ No newline at end of file diff --git a/src/Ursa/Controls/Panels/UrsaTimePickerPanel.cs b/src/Ursa/Controls/Panels/UrsaTimePickerPanel.cs deleted file mode 100644 index d784d0c..0000000 --- a/src/Ursa/Controls/Panels/UrsaTimePickerPanel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.Primitives; -using Avalonia.Input; - -namespace Ursa.Controls.Panels; - -/// -/// The panel to display items for time selection -/// -public class UrsaTimePickerPanel: Panel -{ - /// - /// Defines whether the panel is looping. - /// This is ont applicable for columns like year and AM/PM designation. - /// - public static readonly StyledProperty IsLoopingProperty = AvaloniaProperty.Register( - nameof(IsLooping)); - - /// - /// Gets or sets the value of . - /// - public bool IsLooping - { - get => GetValue(IsLoopingProperty); - set => SetValue(IsLoopingProperty, value); - } -} \ No newline at end of file diff --git a/src/Ursa/Controls/TimePicker/TimePicker.cs b/src/Ursa/Controls/TimePicker/TimePicker.cs deleted file mode 100644 index d1d5a0a..0000000 --- a/src/Ursa/Controls/TimePicker/TimePicker.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Avalonia; -using Avalonia.Controls.Primitives; - -namespace Ursa.Controls.TimePicker; - -public class TimePicker: TemplatedControl -{ - public static readonly StyledProperty DisplayFormatProperty = AvaloniaProperty.Register( - nameof(DisplayFormat), defaultValue:"HH:mm:ss"); - - public string DisplayFormat - { - get => GetValue(DisplayFormatProperty); - set => SetValue(DisplayFormatProperty, value); - } - - public static readonly StyledProperty PanelPlacementProperty = - AvaloniaProperty.Register( - nameof(PanelPlacement), defaultValue: "HH mm ss"); - - public string PanelPlacement - { - get => GetValue(PanelPlacementProperty); - set => SetValue(PanelPlacementProperty, value); - } - - public static readonly StyledProperty SelectedTimeProperty = AvaloniaProperty.Register( - nameof(SelectedTime)); - - public TimeSpan? SelectedTime - { - get => GetValue(SelectedTimeProperty); - set => SetValue(SelectedTimeProperty, value); - } - - public static readonly StyledProperty NeedConfirmProperty = AvaloniaProperty.Register( - nameof(NeedConfirm)); - - public bool NeedConfirm - { - get => GetValue(NeedConfirmProperty); - set => SetValue(NeedConfirmProperty, value); - } -} \ No newline at end of file diff --git a/src/Ursa/Ursa.csproj b/src/Ursa/Ursa.csproj index d56963a..d0aa0df 100644 --- a/src/Ursa/Ursa.csproj +++ b/src/Ursa/Ursa.csproj @@ -24,4 +24,8 @@ + + + +