From 98ec1d696ad50439150d8bd98dbaaa47cd65bfa4 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Fri, 3 May 2024 23:58:54 +0800 Subject: [PATCH 01/42] feat: add new control. --- src/Ursa/Controls/DateTimePicker/Calendar.cs | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/Ursa/Controls/DateTimePicker/Calendar.cs diff --git a/src/Ursa/Controls/DateTimePicker/Calendar.cs b/src/Ursa/Controls/DateTimePicker/Calendar.cs new file mode 100644 index 0000000..5b2e1f6 --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/Calendar.cs @@ -0,0 +1,29 @@ +using Avalonia; +using Avalonia.Controls.Primitives; +using Avalonia.Interactivity; + +namespace Ursa.Controls; + +public class Calendar: TemplatedControl +{ + public static readonly StyledProperty SelectedDateProperty = AvaloniaProperty.Register(nameof(SelectedDate), DateTime.Now); + public DateTime SelectedDate + { + get => GetValue(SelectedDateProperty); + set => SetValue(SelectedDateProperty, value); + } + + public static readonly StyledProperty FirstDayOfWeekProperty = AvaloniaProperty.Register(nameof(FirstDayOfWeek), DayOfWeek.Sunday); + public DayOfWeek FirstDayOfWeek + { + get => GetValue(FirstDayOfWeekProperty); + set => SetValue(FirstDayOfWeekProperty, value); + } + + public static readonly StyledProperty IsTodayHighlightedProperty = AvaloniaProperty.Register(nameof(IsTodayHighlighted), true); + public bool IsTodayHighlighted + { + get => GetValue(IsTodayHighlightedProperty); + set => SetValue(IsTodayHighlightedProperty, value); + } +} \ No newline at end of file From d8358a92154047b789b3c18502e83870832d2c68 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Tue, 7 May 2024 23:15:38 +0800 Subject: [PATCH 02/42] feat: disabled date related feature. --- src/Ursa/Controls/DateTimePicker/Calendar.cs | 26 ++++++++++++-- .../DateTimePicker/CalendarDayButton.cs | 8 +++++ src/Ursa/Controls/DateTimePicker/DateRange.cs | 36 +++++++++++++++++++ .../Controls/DateTimePicker/DateTimeHelper.cs | 17 +++++++++ .../Controls/DateTimePicker/IDateSelector.cs | 17 +++++++++ 5 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs create mode 100644 src/Ursa/Controls/DateTimePicker/DateRange.cs create mode 100644 src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs create mode 100644 src/Ursa/Controls/DateTimePicker/IDateSelector.cs diff --git a/src/Ursa/Controls/DateTimePicker/Calendar.cs b/src/Ursa/Controls/DateTimePicker/Calendar.cs index 5b2e1f6..9aabeb0 100644 --- a/src/Ursa/Controls/DateTimePicker/Calendar.cs +++ b/src/Ursa/Controls/DateTimePicker/Calendar.cs @@ -1,4 +1,5 @@ using Avalonia; +using Avalonia.Collections; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; @@ -12,8 +13,10 @@ public class Calendar: TemplatedControl get => GetValue(SelectedDateProperty); set => SetValue(SelectedDateProperty, value); } - - public static readonly StyledProperty FirstDayOfWeekProperty = AvaloniaProperty.Register(nameof(FirstDayOfWeek), DayOfWeek.Sunday); + + public static readonly StyledProperty FirstDayOfWeekProperty = + AvaloniaProperty.Register(nameof(FirstDayOfWeek), + defaultValue: DateTimeHelper.GetCurrentDateTimeFormatInfo().FirstDayOfWeek); public DayOfWeek FirstDayOfWeek { get => GetValue(FirstDayOfWeekProperty); @@ -26,4 +29,23 @@ public class Calendar: TemplatedControl get => GetValue(IsTodayHighlightedProperty); set => SetValue(IsTodayHighlightedProperty, value); } + + public static readonly StyledProperty?> DisabledDatesProperty = + AvaloniaProperty.Register?>( + nameof(DisabledDates)); + + public AvaloniaList? DisabledDates + { + get => GetValue(DisabledDatesProperty); + set => SetValue(DisabledDatesProperty, value); + } + + public static readonly StyledProperty DisabledDateRuleProperty = AvaloniaProperty.Register( + nameof(DisabledDateRule)); + + public IDateSelector? DisabledDateRule + { + get => GetValue(DisabledDateRuleProperty); + set => SetValue(DisabledDateRuleProperty, value); + } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs b/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs new file mode 100644 index 0000000..1a5d18e --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs @@ -0,0 +1,8 @@ +using Avalonia.Controls; + +namespace Ursa.Controls; + +public class CalendarDayButton: Button +{ + +} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/DateRange.cs b/src/Ursa/Controls/DateTimePicker/DateRange.cs new file mode 100644 index 0000000..9bbb437 --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/DateRange.cs @@ -0,0 +1,36 @@ +namespace Ursa.Controls; + +/// +/// Represents a date range. It can be a single day or a range of days. The range is inclusive. +/// +public sealed record DateRange +{ + public DateRange(DateTime day) + { + Start = day.Date; + End = day.Date; + } + + public DateRange(DateTime start, DateTime end) + { + if (DateTime.Compare(end, start) >= 0) + { + Start = start.Date; + End = end.Date; + } + else + { + Start = start.Date; + End = start.Date; + } + } + + public DateTime Start { get; private set; } + public DateTime End { get; private set; } + + public bool Contains(DateTime? date) + { + if (date is null) return false; + return date >= Start && date <= End; + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs b/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs new file mode 100644 index 0000000..5869891 --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs @@ -0,0 +1,17 @@ +using System.Globalization; + +namespace Ursa.Controls; + +internal static class DateTimeHelper +{ + public static DateTimeFormatInfo GetCurrentDateTimeFormatInfo() + { + if (CultureInfo.CurrentCulture.Calendar is GregorianCalendar) return CultureInfo.CurrentCulture.DateTimeFormat; + System.Globalization.Calendar? calendar = + CultureInfo.CurrentCulture.OptionalCalendars.OfType().FirstOrDefault(); + string cultureName = calendar is null ? CultureInfo.InvariantCulture.Name : CultureInfo.CurrentCulture.Name; + var dt = new CultureInfo(cultureName).DateTimeFormat; + dt.Calendar = calendar ?? new GregorianCalendar(); + return dt; + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/IDateSelector.cs b/src/Ursa/Controls/DateTimePicker/IDateSelector.cs new file mode 100644 index 0000000..79ec2ef --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/IDateSelector.cs @@ -0,0 +1,17 @@ +namespace Ursa.Controls; + +public interface IDateSelector +{ + public bool IsValid(DateTime? date); +} + +public class WeekendDateSelector: IDateSelector +{ + public static WeekendDateSelector Instance { get; } = new WeekendDateSelector(); + + public bool IsValid(DateTime? date) + { + if (date is null) return false; + return date.Value.DayOfWeek == DayOfWeek.Saturday || date.Value.DayOfWeek == DayOfWeek.Sunday; + } +} \ No newline at end of file From 5dea738c7911f532d4f43b95ce0ae684673aee66 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Wed, 8 May 2024 22:41:43 +0800 Subject: [PATCH 03/42] feat: add date button theme. --- demo/Ursa.Demo/Pages/DatePickerDemo.axaml | 34 +++++ demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs | 13 ++ .../ViewModels/DatePickerDemoViewModel.cs | 6 + .../Ursa.Demo/ViewModels/MainViewViewModel.cs | 1 + demo/Ursa.Demo/ViewModels/MenuViewModel.cs | 2 + src/Ursa.Themes.Semi/Controls/Calendar.axaml | 134 ++++++++++++++++++ src/Ursa.Themes.Semi/Controls/_index.axaml | 1 + src/Ursa/Controls/DateTimePicker/Calendar.cs | 20 +-- .../DateTimePicker/CalendarDayButton.cs | 126 +++++++++++++++- src/Ursa/Controls/DateTimePicker/DateRange.cs | 9 ++ 10 files changed, 334 insertions(+), 12 deletions(-) create mode 100644 demo/Ursa.Demo/Pages/DatePickerDemo.axaml create mode 100644 demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs create mode 100644 demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs create mode 100644 src/Ursa.Themes.Semi/Controls/Calendar.axaml diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml new file mode 100644 index 0000000..4a29a6a --- /dev/null +++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs new file mode 100644 index 0000000..fa6e70c --- /dev/null +++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml.cs @@ -0,0 +1,13 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Ursa.Demo.Pages; + +public partial class DatePickerDemo : UserControl +{ + public DatePickerDemo() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs new file mode 100644 index 0000000..f77041c --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/DatePickerDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class DatePickerDemoViewModel +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs index f981fa6..c3cc88c 100644 --- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs @@ -31,6 +31,7 @@ public class MainViewViewModel : ViewModelBase MenuKeys.MenuKeyBreadcrumb => new BreadcrumbDemoViewModel(), MenuKeys.MenuKeyClassInput => new ClassInputDemoViewModel(), MenuKeys.MenuKeyClock => new ClockDemoViewModel(), + MenuKeys.MenuKeyDatePicker => new DatePickerDemoViewModel(), MenuKeys.MenuKeyDialog => new DialogDemoViewModel(), MenuKeys.MenuKeyDivider => new DividerDemoViewModel(), MenuKeys.MenuKeyDisableContainer => new DisableContainerDemoViewModel(), diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs index ead5ab8..b466005 100644 --- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs @@ -18,6 +18,7 @@ public class MenuViewModel: ViewModelBase new() { MenuHeader = "Button Group", Key = MenuKeys.MenuKeyButtonGroup }, new() { MenuHeader = "Class Input", Key = MenuKeys.MenuKeyClassInput }, new() { MenuHeader = "Clock", Key = MenuKeys.MenuKeyClock, Status = "New" }, + new() { MenuHeader = "Date Picker", Key = MenuKeys.MenuKeyDatePicker }, new() { MenuHeader = "Dialog", Key = MenuKeys.MenuKeyDialog }, new() { MenuHeader = "Disable Container", Key = MenuKeys.MenuKeyDisableContainer }, new() { MenuHeader = "Divider", Key = MenuKeys.MenuKeyDivider }, @@ -63,6 +64,7 @@ public static class MenuKeys public const string MenuKeyBreadcrumb= "Breadcrumb"; public const string MenuKeyClassInput = "Class Input"; public const string MenuKeyClock = "Clock"; + public const string MenuKeyDatePicker = "DatePicker"; public const string MenuKeyDialog = "Dialog"; public const string MenuKeyDivider = "Divider"; public const string MenuKeyDisableContainer = "DisableContainer"; diff --git a/src/Ursa.Themes.Semi/Controls/Calendar.axaml b/src/Ursa.Themes.Semi/Controls/Calendar.axaml new file mode 100644 index 0000000..13830c1 --- /dev/null +++ b/src/Ursa.Themes.Semi/Controls/Calendar.axaml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ursa.Themes.Semi/Controls/_index.axaml b/src/Ursa.Themes.Semi/Controls/_index.axaml index bf6acad..24549cf 100644 --- a/src/Ursa.Themes.Semi/Controls/_index.axaml +++ b/src/Ursa.Themes.Semi/Controls/_index.axaml @@ -5,6 +5,7 @@ + diff --git a/src/Ursa/Controls/DateTimePicker/Calendar.cs b/src/Ursa/Controls/DateTimePicker/Calendar.cs index 9aabeb0..daceb40 100644 --- a/src/Ursa/Controls/DateTimePicker/Calendar.cs +++ b/src/Ursa/Controls/DateTimePicker/Calendar.cs @@ -30,22 +30,22 @@ public class Calendar: TemplatedControl set => SetValue(IsTodayHighlightedProperty, value); } - public static readonly StyledProperty?> DisabledDatesProperty = + public static readonly StyledProperty?> BlackoutDatesProperty = AvaloniaProperty.Register?>( - nameof(DisabledDates)); + nameof(BlackoutDates)); - public AvaloniaList? DisabledDates + public AvaloniaList? BlackoutDates { - get => GetValue(DisabledDatesProperty); - set => SetValue(DisabledDatesProperty, value); + get => GetValue(BlackoutDatesProperty); + set => SetValue(BlackoutDatesProperty, value); } - public static readonly StyledProperty DisabledDateRuleProperty = AvaloniaProperty.Register( - nameof(DisabledDateRule)); + public static readonly StyledProperty BlackoutDateRuleProperty = AvaloniaProperty.Register( + nameof(BlackoutDateRule)); - public IDateSelector? DisabledDateRule + public IDateSelector? BlackoutDateRule { - get => GetValue(DisabledDateRuleProperty); - set => SetValue(DisabledDateRuleProperty, value); + get => GetValue(BlackoutDateRuleProperty); + set => SetValue(BlackoutDateRuleProperty, value); } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs b/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs index 1a5d18e..06ab696 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs @@ -1,8 +1,130 @@ -using Avalonia.Controls; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Metadata; +using Avalonia.Controls.Mixins; +using Avalonia.Controls.Primitives; +using Avalonia.Input; +using Irihi.Avalonia.Shared.Common; +using Irihi.Avalonia.Shared.Helpers; namespace Ursa.Controls; -public class CalendarDayButton: Button +[PseudoClasses(PseudoClassName.PC_Pressed, PseudoClassName.PC_Selected, + PC_StartDate, PC_EndDate, PC_PreviewStartDate, PC_PreviewEndDate, PC_InRange, PC_Today, PC_Blackout)] +public class CalendarDayButton: ContentControl { + public const string PC_StartDate = ":start-date"; + public const string PC_EndDate = ":end-date"; + public const string PC_PreviewStartDate = ":preview-start-date"; + public const string PC_PreviewEndDate = ":preview-end-date"; + public const string PC_InRange = ":in-range"; + public const string PC_Today = ":today"; + public const string PC_Blackout = ":blackout"; + + private bool _isToday; + public bool IsToday + { + get => _isToday; + set + { + _isToday = value; + PseudoClasses.Set(PC_Today, value); + } + } + private bool _isStartDate; + public bool IsStartDate + { + get => _isStartDate; + set + { + _isStartDate = value; + PseudoClasses.Set(PC_StartDate, value); + } + } + + private bool _isEndDate; + public bool IsEndDate + { + get => _isEndDate; + set + { + _isEndDate = value; + PseudoClasses.Set(PC_EndDate, value); + } + } + + private bool _isPreviewStartDate; + public bool IsPreviewStartDate + { + get => _isPreviewStartDate; + set + { + _isPreviewStartDate = value; + PseudoClasses.Set(PC_PreviewStartDate, value); + } + } + + private bool _isPreviewEndDate; + public bool IsPreviewEndDate + { + get => _isPreviewEndDate; + set + { + _isPreviewEndDate = value; + PseudoClasses.Set(PC_PreviewEndDate, value); + } + } + + private bool _isInRange; + public bool IsInRange + { + get => _isInRange; + set + { + _isInRange = value; + PseudoClasses.Set(PC_InRange, value); + } + } + + private bool _isSelected; + public bool IsSelected + { + get => _isSelected; + set + { + _isSelected = value; + PseudoClasses.Set(PseudoClassName.PC_Selected, value); + } + } + + private bool _isBlackout; + public bool IsBlackout + { + get => _isBlackout; + set + { + _isBlackout = value; + PseudoClasses.Set(PC_Blackout, value); + } + } + + static CalendarDayButton() + { + PressedMixin.Attach(); + } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + PseudoClasses.Set(PseudoClassName.PC_Disabled, IsEnabled); + PseudoClasses.Set(PC_Today, IsToday); + PseudoClasses.Set(PC_StartDate, IsStartDate); + PseudoClasses.Set(PC_EndDate, IsEndDate); + PseudoClasses.Set(PC_PreviewStartDate, IsPreviewStartDate); + PseudoClasses.Set(PC_PreviewEndDate, IsPreviewEndDate); + PseudoClasses.Set(PC_InRange, IsInRange); + PseudoClasses.Set(PseudoClassName.PC_Selected, IsSelected); + + } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/DateRange.cs b/src/Ursa/Controls/DateTimePicker/DateRange.cs index 9bbb437..d0ec637 100644 --- a/src/Ursa/Controls/DateTimePicker/DateRange.cs +++ b/src/Ursa/Controls/DateTimePicker/DateRange.cs @@ -33,4 +33,13 @@ public sealed record DateRange if (date is null) return false; return date >= Start && date <= End; } +} + +internal static class DateRangeExtension +{ + public static bool Contains(this IEnumerable? ranges, DateTime? date) + { + if (date is null || ranges is null) return false; + return ranges.Any(range => range.Contains(date)); + } } \ No newline at end of file From f3abf8a49691156667b8dd421fc88cb4a0ce1eea Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 9 May 2024 21:01:35 +0800 Subject: [PATCH 04/42] feat: try layout. --- demo/Ursa.Demo/Pages/DatePickerDemo.axaml | 3 +- src/Ursa.Themes.Semi/Controls/Calendar.axaml | 168 +++++++++++++++--- src/Ursa/Controls/DateTimePicker/Calendar.cs | 20 +++ .../DateTimePicker/CalendarDayButton.cs | 4 +- 4 files changed, 173 insertions(+), 22 deletions(-) diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml index 4a29a6a..358e74c 100644 --- a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml +++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml @@ -5,7 +5,7 @@ xmlns:u="https://irihi.tech/ursa" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Ursa.Demo.Pages.DatePickerDemo"> - + @@ -30,5 +30,6 @@ + diff --git a/src/Ursa.Themes.Semi/Controls/Calendar.axaml b/src/Ursa.Themes.Semi/Controls/Calendar.axaml index 13830c1..50186f9 100644 --- a/src/Ursa.Themes.Semi/Controls/Calendar.axaml +++ b/src/Ursa.Themes.Semi/Controls/Calendar.axaml @@ -28,17 +28,19 @@ + + - - - - - + + + + + @@ -52,8 +54,8 @@ Name="PART_ContentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" - Foreground="{TemplateBinding Foreground}" - Content="1" /> + Content="{TemplateBinding Content}" + Foreground="{TemplateBinding Foreground}" /> @@ -64,19 +66,19 @@ - + - + @@ -87,7 +89,7 @@ @@ -113,22 +115,148 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ursa/Controls/DateTimePicker/Calendar.cs b/src/Ursa/Controls/DateTimePicker/Calendar.cs index daceb40..4cdc3c3 100644 --- a/src/Ursa/Controls/DateTimePicker/Calendar.cs +++ b/src/Ursa/Controls/DateTimePicker/Calendar.cs @@ -1,12 +1,32 @@ using Avalonia; using Avalonia.Collections; +using Avalonia.Controls; +using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; namespace Ursa.Controls; +[TemplatePart(PART_NextYearButton, typeof(Button))] +[TemplatePart(PART_PreviousYearButton, typeof(Button))] +[TemplatePart(PART_NextButton, typeof(Button))] +[TemplatePart(PART_PreviousButton, typeof(Button))] +[TemplatePart(PART_HeaderButton, typeof(Button))] +[TemplatePart(PART_BackButton, typeof(Button))] +[TemplatePart(PART_MonthView, typeof(Panel))] +[TemplatePart(PART_YearView, typeof(Panel))] public class Calendar: TemplatedControl { + public const string PART_NextYearButton = "PART_NextYearButton"; + public const string PART_PreviousYearButton = "PART_PreviousYearButton"; + public const string PART_NextButton = "PART_NextButton"; + public const string PART_PreviousButton = "PART_PreviousButton"; + public const string PART_HeaderButton = "PART_HeaderButton"; + public const string PART_BackButton = "PART_BackButton"; + public const string PART_MonthView = "PART_MonthView"; + public const string PART_YearView = "PART_YearView"; + + public static readonly StyledProperty SelectedDateProperty = AvaloniaProperty.Register(nameof(SelectedDate), DateTime.Now); public DateTime SelectedDate { diff --git a/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs b/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs index 06ab696..8bdebec 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarDayButton.cs @@ -99,6 +99,9 @@ public class CalendarDayButton: ContentControl } private bool _isBlackout; + /// + /// Notice: IsBlackout is not equivalent to not IsEnabled. Blackout dates still react to pointerover actions. + /// public bool IsBlackout { get => _isBlackout; @@ -117,7 +120,6 @@ public class CalendarDayButton: ContentControl protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); - PseudoClasses.Set(PseudoClassName.PC_Disabled, IsEnabled); PseudoClasses.Set(PC_Today, IsToday); PseudoClasses.Set(PC_StartDate, IsStartDate); PseudoClasses.Set(PC_EndDate, IsEndDate); From 2045723e47d774bdfb3ec51e0128176238357083 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Fri, 10 May 2024 16:17:10 +0800 Subject: [PATCH 05/42] feat: change layout WIP --- src/Ursa/Controls/DateTimePicker/Calendar.cs | 20 +++++++- .../DateTimePicker/CalendarMonthView.cs | 49 +++++++++++++++++++ .../DateTimePicker/CalendarYearView.cs | 12 +++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs create mode 100644 src/Ursa/Controls/DateTimePicker/CalendarYearView.cs diff --git a/src/Ursa/Controls/DateTimePicker/Calendar.cs b/src/Ursa/Controls/DateTimePicker/Calendar.cs index 4cdc3c3..70de6e7 100644 --- a/src/Ursa/Controls/DateTimePicker/Calendar.cs +++ b/src/Ursa/Controls/DateTimePicker/Calendar.cs @@ -13,8 +13,8 @@ namespace Ursa.Controls; [TemplatePart(PART_PreviousButton, typeof(Button))] [TemplatePart(PART_HeaderButton, typeof(Button))] [TemplatePart(PART_BackButton, typeof(Button))] -[TemplatePart(PART_MonthView, typeof(Panel))] -[TemplatePart(PART_YearView, typeof(Panel))] +[TemplatePart(PART_MonthView, typeof(CalendarMonthView))] +[TemplatePart(PART_YearView, typeof(CalendarYearView))] public class Calendar: TemplatedControl { public const string PART_NextYearButton = "PART_NextYearButton"; @@ -25,6 +25,8 @@ public class Calendar: TemplatedControl public const string PART_BackButton = "PART_BackButton"; public const string PART_MonthView = "PART_MonthView"; public const string PART_YearView = "PART_YearView"; + + private Grid? _monthGrid; public static readonly StyledProperty SelectedDateProperty = AvaloniaProperty.Register(nameof(SelectedDate), DateTime.Now); @@ -68,4 +70,18 @@ public class Calendar: TemplatedControl get => GetValue(BlackoutDateRuleProperty); set => SetValue(BlackoutDateRuleProperty, value); } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + _monthGrid = e.NameScope.Find(PART_MonthView); + } + + private void InitializeGrid() + { + if (_monthGrid is not null) + { + + } + } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs b/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs new file mode 100644 index 0000000..9757a9f --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs @@ -0,0 +1,49 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Metadata; +using Avalonia.Controls.Primitives; + +namespace Ursa.Controls; + +/// +/// Show days in a month. +/// +[TemplatePart(PART_Grid, typeof(Grid))] +public class CalendarMonthView: TemplatedControl +{ + public const string PART_Grid = "PART_Grid"; + + private Grid? _grid; + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + _grid = e.NameScope.Find(PART_Grid); + // GenerateGridElements(); + } + + private int _month; + public int Month + { + get => _month; + set + { + _month = value; + // Update(); + } + } + + public static readonly StyledProperty FirstDayOfWeekProperty = AvaloniaProperty.Register( + nameof(FirstDayOfWeek)); + + public DayOfWeek FirstDayOfWeek + { + get => GetValue(FirstDayOfWeekProperty); + set => SetValue(FirstDayOfWeekProperty, value); + } + + private void GenerateGridElements() + { + // Generate Day titles (Sun, Mon, Tue, Wed, Thu, Fri, Sat) based on FirstDayOfWeek and culture. + + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarYearView.cs b/src/Ursa/Controls/DateTimePicker/CalendarYearView.cs new file mode 100644 index 0000000..4cdc0cc --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/CalendarYearView.cs @@ -0,0 +1,12 @@ +namespace Ursa.Controls; + +/// +/// Three modes: +/// 1. show 12 months in a year +/// 2. show 12 years, one year per button (but only 10 buttons clickable) +/// 3. show 120 years, ten year per button (but only 10 buttons clickable) +/// +public class CalendarYearView +{ + +} \ No newline at end of file From 342d81fdc33484fc412e7ba6692feb04556aae92 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Sat, 11 May 2024 01:59:18 +0800 Subject: [PATCH 06/42] feat: day button initialization. --- demo/Ursa.Demo/Pages/DatePickerDemo.axaml | 1 + src/Ursa.Themes.Semi/Controls/Calendar.axaml | 114 +++++---------- .../DateTimePicker/CalendarDayButton.cs | 20 ++- .../DateTimePicker/CalendarMonthView.cs | 132 +++++++++++++++++- .../Controls/DateTimePicker/DateTimeHelper.cs | 19 +++ 5 files changed, 195 insertions(+), 91 deletions(-) diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml index 358e74c..b3f4a56 100644 --- a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml +++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml @@ -6,6 +6,7 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Ursa.Demo.Pages.DatePickerDemo"> + diff --git a/src/Ursa.Themes.Semi/Controls/Calendar.axaml b/src/Ursa.Themes.Semi/Controls/Calendar.axaml index 50186f9..409efa3 100644 --- a/src/Ursa.Themes.Semi/Controls/Calendar.axaml +++ b/src/Ursa.Themes.Semi/Controls/Calendar.axaml @@ -4,38 +4,14 @@ xmlns:u="https://irihi.tech/ursa"> - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + @@ -66,6 +42,16 @@ + + + + - + - + @@ -121,6 +121,7 @@ + @@ -152,13 +153,20 @@ Foreground="{DynamicResource CalendarItemIconForeground}" /> - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ursa/Controls/DateTimePicker/Calendar.cs b/src/Ursa/Controls/DateTimePicker/Calendar.cs index 02288ba..0c79d3b 100644 --- a/src/Ursa/Controls/DateTimePicker/Calendar.cs +++ b/src/Ursa/Controls/DateTimePicker/Calendar.cs @@ -4,6 +4,7 @@ using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; +using Irihi.Avalonia.Shared.Helpers; namespace Ursa.Controls; @@ -11,8 +12,9 @@ namespace Ursa.Controls; [TemplatePart(PART_PreviousYearButton, typeof(Button))] [TemplatePart(PART_NextButton, typeof(Button))] [TemplatePart(PART_PreviousButton, typeof(Button))] +[TemplatePart(PART_YearButton, typeof(Button))] +[TemplatePart(PART_MonthButton, typeof(Button))] [TemplatePart(PART_HeaderButton, typeof(Button))] -[TemplatePart(PART_BackButton, typeof(Button))] [TemplatePart(PART_MonthView, typeof(CalendarMonthView))] [TemplatePart(PART_YearView, typeof(CalendarYearView))] public class Calendar: TemplatedControl @@ -21,14 +23,18 @@ public class Calendar: TemplatedControl public const string PART_PreviousYearButton = "PART_PreviousYearButton"; public const string PART_NextButton = "PART_NextButton"; public const string PART_PreviousButton = "PART_PreviousButton"; - public const string PART_HeaderButton = "PART_HeaderButton"; - public const string PART_BackButton = "PART_BackButton"; + public const string PART_YearButton = "PART_YearButton"; + public const string PART_MonthButton = "PART_MonthButton"; public const string PART_MonthView = "PART_MonthView"; public const string PART_YearView = "PART_YearView"; + public const string PART_HeaderButton = "PART_HeaderButton"; private CalendarMonthView? _monthView; private CalendarYearView? _yearView; private DatePickerState _state = DatePickerState.None; + private Button? _yearButton; + private Button? _monthButton; + private Button? _headerButton; public static readonly StyledProperty SelectedDateProperty = AvaloniaProperty.Register(nameof(SelectedDate), DateTime.Now); @@ -73,6 +79,17 @@ public class Calendar: TemplatedControl set => SetValue(BlackoutDateRuleProperty, value); } + private bool _isMonthMode = true; + + public static readonly DirectProperty IsMonthModeProperty = AvaloniaProperty.RegisterDirect( + nameof(IsMonthMode), o => o.IsMonthMode, (o, v) => o.IsMonthMode = v); + + public bool IsMonthMode + { + get => _isMonthMode; + set => SetAndRaise(IsMonthModeProperty, ref _isMonthMode, value); + } + internal DateTime? StartDate; internal DateTime? EndDate; @@ -84,13 +101,50 @@ public class Calendar: TemplatedControl _monthView.OnDateSelected -= OnDateSelected; _monthView.OnDatePreviewed -= OnDatePreviewed; } + + if (_yearView is not null) + { + _yearView.OnMonthSelected -= OnMonthSelected; + } + Button.ClickEvent.RemoveHandler(OnYearButtonClick, _yearButton); + Button.ClickEvent.RemoveHandler(OnMonthButtonClick, _monthButton); _monthView = e.NameScope.Find(PART_MonthView); _yearView = e.NameScope.Find(PART_YearView); + _yearButton = e.NameScope.Find - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -298,4 +159,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs b/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs index 29c010e..b8b1235 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarMonthView.cs @@ -8,6 +8,7 @@ using Avalonia.Layout; namespace Ursa.Controls; +/* /// /// Show days in a month. CalendarMonthView itself doesn't handle any date range selection logic. /// it provides a method to mark preview range and selection range. The range limit may out of current displayed month. @@ -226,4 +227,6 @@ public class CalendarMonthView : TemplatedControl button.IsInRange = false; } } -} \ No newline at end of file +} + +*/ \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarView.cs b/src/Ursa/Controls/DateTimePicker/CalendarView.cs index 9b9a921..bd3ddeb 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarView.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarView.cs @@ -1,14 +1,13 @@ -using System.Globalization; -using System.Reflection; +using System.Diagnostics; +using System.Globalization; using Avalonia; -using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; using Avalonia.Layout; -using Avalonia.Media.TextFormatting; using Irihi.Avalonia.Shared.Helpers; +using Calendar = System.Globalization.Calendar; namespace Ursa.Controls; @@ -19,11 +18,10 @@ namespace Ursa.Controls; [TemplatePart(PART_YearButton, typeof(Button))] [TemplatePart(PART_MonthButton, typeof(Button))] [TemplatePart(PART_HeaderButton, typeof(Button))] -[TemplatePart(PART_MonthView, typeof(CalendarMonthView))] -[TemplatePart(PART_YearView, typeof(CalendarYearView))] [TemplatePart(PART_MonthGrid, typeof(Grid))] [TemplatePart(PART_YearGrid, typeof(Grid))] -public class CalendarView: TemplatedControl +[PseudoClasses(PC_Month)] +public class CalendarView : TemplatedControl { public const string PART_NextYearButton = "PART_NextYearButton"; public const string PART_PreviousYearButton = "PART_PreviousYearButton"; @@ -31,51 +29,79 @@ public class CalendarView: TemplatedControl public const string PART_PreviousButton = "PART_PreviousButton"; public const string PART_YearButton = "PART_YearButton"; public const string PART_MonthButton = "PART_MonthButton"; - public const string PART_MonthView = "PART_MonthView"; - public const string PART_YearView = "PART_YearView"; public const string PART_HeaderButton = "PART_HeaderButton"; public const string PART_MonthGrid = "PART_MonthGrid"; - public const string PART_YearGrid = "PART_YearGried"; - + public const string PART_YearGrid = "PART_YearGrid"; + public const string PC_Month = ":month"; + private const string ShortestDayName = "ShortestDayName"; - - private readonly System.Globalization.Calendar _calendar = new GregorianCalendar(); - internal CalendarViewMode Mode; - - //private CalendarMonthView? _monthView; - //private CalendarYearView? _yearView; - private Grid? _monthGrid; - private Grid? _yearGrid; - // Year button only shows the year in month mode. - private Button? _yearButton; - // Month button only shows the month in month mode. - private Button? _monthButton; - // Header button shows year in year mode, and year range in higher mode. - private Button? _headerButton; - - public DateContext ContextDate { get; set; } = new DateContext(); - - public event EventHandler? OnDateSelected; - public event EventHandler? OnDatePreviewed; + internal static readonly DirectProperty ModeProperty = + AvaloniaProperty.RegisterDirect( + nameof(Mode), o => o.Mode, (o, v) => o.Mode = v, unsetValue: CalendarViewMode.Month); public static readonly StyledProperty IsTodayHighlightedProperty = DatePickerBase.IsTodayHighlightedProperty.AddOwner(); + + public static readonly StyledProperty FirstDayOfWeekProperty = + DatePickerBase.FirstDayOfWeekProperty.AddOwner(); + + private readonly Calendar _calendar = new GregorianCalendar(); + + // Header button shows year in year mode, and year range in higher mode. + private Button? _headerButton; + + private CalendarViewMode _mode; + + // Month button only shows the month in month mode. + private Button? _monthButton; + + private Grid? _monthGrid; + + // Year button only shows the year in month mode. + private Button? _yearButton; + private Grid? _yearGrid; + + static CalendarView() + { + FirstDayOfWeekProperty.Changed.AddClassHandler((view, args) => + view.OnFirstDayOfWeekChanged(args)); + ModeProperty.Changed.AddClassHandler((view, args) => + { + view.PseudoClasses.Set(PC_Month, args.NewValue.Value == CalendarViewMode.Month); + Debug.WriteLine(args.NewValue.Value); + }); + } + + internal CalendarViewMode Mode + { + get => _mode; + set => SetAndRaise(ModeProperty, ref _mode, value); + } + + public DateContext ContextDate { get; set; } = new(); + public bool IsTodayHighlighted { get => GetValue(IsTodayHighlightedProperty); set => SetValue(IsTodayHighlightedProperty, value); } - public static readonly StyledProperty FirstDayOfWeekProperty = - DatePickerBase.FirstDayOfWeekProperty.AddOwner(); - public DayOfWeek FirstDayOfWeek { get => GetValue(FirstDayOfWeekProperty); set => SetValue(FirstDayOfWeekProperty, value); } - + + public event EventHandler? OnDateSelected; + public event EventHandler? OnDatePreviewed; + + private void OnFirstDayOfWeekChanged(AvaloniaPropertyChangedEventArgs args) + { + UpdateMonthViewHeader(args.NewValue.Value); + RefreshDayButtons(); + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -83,7 +109,7 @@ public class CalendarView: TemplatedControl Button.ClickEvent.RemoveHandler(OnHeaderYearButtonClick, _yearButton); Button.ClickEvent.RemoveHandler(OnHeaderMonthButtonClick, _monthButton); Button.ClickEvent.RemoveHandler(OnHeaderButtonClick, _headerButton); - + _monthGrid = e.NameScope.Find(PART_MonthGrid); _yearGrid = e.NameScope.Find(PART_YearGrid); _yearButton = e.NameScope.Find @@ -209,10 +212,10 @@ diff --git a/src/Ursa.Themes.Semi/Themes/Shared/DatePicker.axaml b/src/Ursa.Themes.Semi/Themes/Shared/DatePicker.axaml new file mode 100644 index 0000000..1a1d32f --- /dev/null +++ b/src/Ursa.Themes.Semi/Themes/Shared/DatePicker.axaml @@ -0,0 +1,6 @@ + + + M12.6185 4.39653C13.1272 4.92524 13.1272 5.78245 12.6185 6.31116L7.14483 12L12.6185 17.6888C13.1272 18.2176 13.1272 19.0748 12.6185 19.6035C12.1098 20.1322 11.285 20.1322 10.7763 19.6035L4.38153 12.9573C3.87282 12.4286 3.87282 11.5714 4.38153 11.0427L10.7763 4.39653C11.285 3.86782 12.1098 3.86782 12.6185 4.39653Z M19.6185 4.39653C20.1272 4.92524 20.1272 5.78245 19.6185 6.31116L14.1448 12L19.6185 17.6888C20.1272 18.2176 20.1272 19.0748 19.6185 19.6035C19.1098 20.1322 18.285 20.1322 17.7763 19.6035L11.3815 12.9573C10.8728 12.4286 10.8728 11.5714 11.3815 11.0427L17.7763 4.39653C18.285 3.86782 19.1098 3.86782 19.6185 4.39653Z + M4.38153 4.39653C4.89024 3.86782 5.71502 3.86782 6.22373 4.39653L12.6185 11.0427C13.1272 11.5714 13.1272 12.4286 12.6185 12.9573L6.22373 19.6035C5.71502 20.1322 4.89024 20.1322 4.38153 19.6035C3.87282 19.0748 3.87282 18.2176 4.38153 17.6888L9.85517 12L4.38153 6.31116C3.87282 5.78245 3.87282 4.92524 4.38153 4.39653Z M11.3815 4.39653C11.8902 3.86782 12.715 3.86782 13.2237 4.39653L19.6185 11.0427C20.1272 11.5714 20.1272 12.4286 19.6185 12.9573L13.2237 19.6035C12.715 20.1322 11.8902 20.1322 11.3815 19.6035C10.8728 19.0748 10.8728 18.2176 11.3815 17.6888L16.8552 12L11.3815 6.31116C10.8728 5.78245 10.8728 4.92524 11.3815 4.39653Z + diff --git a/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml b/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml index 658f6ae..63174ae 100644 --- a/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml +++ b/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml @@ -4,6 +4,7 @@ + diff --git a/src/Ursa/Controls/DateTimePicker/CalendarView.cs b/src/Ursa/Controls/DateTimePicker/CalendarView.cs index 5138a3a..265eeba 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarView.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarView.cs @@ -529,5 +529,10 @@ public class CalendarView : TemplatedControl _monthButton?.SetValue(ContentControl.ContentProperty, DateTimeHelper.GetCurrentDateTimeFormatInfo().AbbreviatedMonthNames[ContextCalendar.Month-1 ?? 0]); } + + bool canForward = !(ContextCalendar.EndYear <= 0) && !(ContextCalendar.Year <= 0); + bool canNext = !(ContextCalendar.StartYear > 9999) && !(ContextCalendar.EndYear > 9999); + IsEnabledProperty.SetValue(canForward, _previousButton, _fastPreviousButton); + IsEnabledProperty.SetValue(canNext, _nextButton, _fastNextButton); } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs b/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs index 8677bd8..917beb4 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs @@ -39,15 +39,27 @@ public class CalendarYearButton : ContentControl CalendarContext.Year = context.Year; CalendarContext.StartYear = context.StartYear; CalendarContext.EndYear = context.EndYear; - this.Mode = mode; - Content = Mode switch + Mode = mode; + switch (Mode) { - CalendarViewMode.Year => DateTimeHelper.GetCurrentDateTimeFormatInfo().AbbreviatedMonthNames[ CalendarContext.Month ?? 0 ], - CalendarViewMode.Decade => CalendarContext.Year?.ToString(), - CalendarViewMode.Century => CalendarContext.StartYear + "-" + CalendarContext.EndYear, - // CalendarViewMode.Century => CalendarContext.StartYear + "-" + CalendarContext.EndYear, - _ => Content - }; + case CalendarViewMode.Year: + Content = DateTimeHelper.GetCurrentDateTimeFormatInfo() + .AbbreviatedMonthNames[CalendarContext.Month ?? 0]; + break; + case CalendarViewMode.Decade: + Content = CalendarContext.Year <= 0 || CalendarContext.Year > 9999 + ? null + : CalendarContext.Year?.ToString(); + break; + case CalendarViewMode.Century: + Content = CalendarContext.EndYear <= 0 || CalendarContext.StartYear > 9999 + ? null + : CalendarContext.StartYear + "-" + CalendarContext.EndYear; + break; + default: + Content = null; + break; + } IsEnabled = Content != null; } From e6b23312ba39f081d8a1b714bcbb30121eeb6377 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 20 Jun 2024 16:21:36 +0800 Subject: [PATCH 23/42] feat: implement single date selector. --- demo/Ursa.Demo/Pages/DatePickerDemo.axaml | 3 + src/Ursa.Themes.Semi/Controls/Calendar.axaml | 3 + .../Controls/DatePicker.axaml | 124 ++++++++++++++ src/Ursa.Themes.Semi/Controls/_index.axaml | 1 + .../DateTimePicker/CalendarDayButton.cs | 19 +-- .../Controls/DateTimePicker/CalendarView.cs | 52 ++++++ .../Controls/DateTimePicker/DatePicker.cs | 158 +++++++++++++++++- .../Controls/DateTimePicker/DatePickerBase.cs | 93 +++++++++-- 8 files changed, 422 insertions(+), 31 deletions(-) create mode 100644 src/Ursa.Themes.Semi/Controls/DatePicker.axaml diff --git a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml index 254a1ea..d7810a5 100644 --- a/demo/Ursa.Demo/Pages/DatePickerDemo.axaml +++ b/demo/Ursa.Demo/Pages/DatePickerDemo.axaml @@ -7,5 +7,8 @@ x:Class="Ursa.Demo.Pages.DatePickerDemo"> + + + diff --git a/src/Ursa.Themes.Semi/Controls/Calendar.axaml b/src/Ursa.Themes.Semi/Controls/Calendar.axaml index 1264422..b8184d4 100644 --- a/src/Ursa.Themes.Semi/Controls/Calendar.axaml +++ b/src/Ursa.Themes.Semi/Controls/Calendar.axaml @@ -15,6 +15,7 @@ + @@ -118,6 +119,7 @@ + @@ -159,6 +161,7 @@ + diff --git a/src/Ursa.Themes.Semi/Controls/DatePicker.axaml b/src/Ursa.Themes.Semi/Controls/DatePicker.axaml new file mode 100644 index 0000000..260bb58 --- /dev/null +++ b/src/Ursa.Themes.Semi/Controls/DatePicker.axaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + +