From 742cbef6831a8ecdad02afdee3db2247d8d73dd5 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 20 Jun 2024 01:07:24 +0800 Subject: [PATCH] feat: finally. --- src/Ursa.Themes.Semi/Controls/Calendar.axaml | 17 +- .../DateTimePicker/CalendarContext.cs | 16 ++ .../Controls/DateTimePicker/CalendarView.cs | 179 ++++++++++++------ .../DateTimePicker/CalendarYearButton.cs | 36 ++-- .../CalendarYearButtonEventArgs.cs | 12 +- .../Controls/DateTimePicker/DateContext.cs | 8 - .../Controls/DateTimePicker/DateTimeHelper.cs | 12 ++ 7 files changed, 166 insertions(+), 114 deletions(-) create mode 100644 src/Ursa/Controls/DateTimePicker/CalendarContext.cs delete mode 100644 src/Ursa/Controls/DateTimePicker/DateContext.cs diff --git a/src/Ursa.Themes.Semi/Controls/Calendar.axaml b/src/Ursa.Themes.Semi/Controls/Calendar.axaml index 411ad1b..d850e23 100644 --- a/src/Ursa.Themes.Semi/Controls/Calendar.axaml +++ b/src/Ursa.Themes.Semi/Controls/Calendar.axaml @@ -161,6 +161,7 @@ + @@ -256,22 +257,6 @@ - - - - - - diff --git a/src/Ursa/Controls/DateTimePicker/CalendarContext.cs b/src/Ursa/Controls/DateTimePicker/CalendarContext.cs new file mode 100644 index 0000000..19ff533 --- /dev/null +++ b/src/Ursa/Controls/DateTimePicker/CalendarContext.cs @@ -0,0 +1,16 @@ +namespace Ursa.Controls; + +public class CalendarContext(int? year = null, int? month = null, int? day = null) +{ + public int? Year = year; + public int? Month = month; + public int? Day = day; + public int? StartYear; + public int? EndYear; + + + public CalendarContext Clone() + { + return new CalendarContext(Year, Month, Day) { StartYear = StartYear, EndYear = EndYear }; + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarView.cs b/src/Ursa/Controls/DateTimePicker/CalendarView.cs index bd3ddeb..d034cac 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarView.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarView.cs @@ -69,7 +69,6 @@ public class CalendarView : TemplatedControl ModeProperty.Changed.AddClassHandler((view, args) => { view.PseudoClasses.Set(PC_Month, args.NewValue.Value == CalendarViewMode.Month); - Debug.WriteLine(args.NewValue.Value); }); } @@ -79,7 +78,7 @@ public class CalendarView : TemplatedControl set => SetAndRaise(ModeProperty, ref _mode, value); } - public DateContext ContextDate { get; set; } = new(); + public CalendarContext ContextCalendar { get; set; } = new(); public bool IsTodayHighlighted { @@ -99,7 +98,7 @@ public class CalendarView : TemplatedControl private void OnFirstDayOfWeekChanged(AvaloniaPropertyChangedEventArgs args) { UpdateMonthViewHeader(args.NewValue.Value); - RefreshDayButtons(); + UpdateDayButtons(); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) @@ -120,11 +119,12 @@ public class CalendarView : TemplatedControl Button.ClickEvent.AddHandler(OnHeaderMonthButtonClick, _monthButton); Button.ClickEvent.AddHandler(OnHeaderButtonClick, _headerButton); - ContextDate = new DateContext(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day); + ContextCalendar = new CalendarContext(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day); PseudoClasses.Set(PC_Month, Mode == CalendarViewMode.Month); - GenerateGridElements(); - RefreshDayButtons(); - RefreshYearButtons(); + InitializeGridButtons(); + UpdateDayButtons(); + UpdateYearButtons(); + UpdateHeaderButtons(); } /// @@ -139,23 +139,32 @@ public class CalendarView : TemplatedControl if (Mode == CalendarViewMode.Year) { Mode = CalendarViewMode.Decade; - RefreshYearButtons(); + var range = DateTimeHelper.GetDecadeViewRangeByYear(ContextCalendar.Year!.Value); + ContextCalendar.StartYear = range.start; + ContextCalendar.EndYear = range.end; + UpdateHeaderButtons(); + UpdateYearButtons(); return; } if(Mode == CalendarViewMode.Decade) { Mode = CalendarViewMode.Century; - RefreshYearButtons(); + var range = DateTimeHelper.GetCenturyViewRangeByYear(ContextCalendar.StartYear!.Value); + ContextCalendar.StartYear = range.start; + ContextCalendar.EndYear = range.end; + UpdateHeaderButtons(); + UpdateYearButtons(); return; } if (Mode == CalendarViewMode.Century) return; } /// - /// Generate Buttons and labels for MonthView. - /// Generate Buttons for YearView. + /// Generate Buttons and labels for MonthView. + /// Generate Buttons for YearView. + /// This method should be called only once. /// - private void GenerateGridElements() + private void InitializeGridButtons() { // Generate Day titles (Sun, Mon, Tue, Wed, Thu, Fri, Sat) based on FirstDayOfWeek and culture. var count = 7 + 7 * 7; @@ -197,14 +206,13 @@ public class CalendarView : TemplatedControl } } - private void RefreshDayButtons() + private void UpdateDayButtons() { if (_monthGrid is null) return; var children = _monthGrid.Children; var info = DateTimeHelper.GetCurrentDateTimeFormatInfo(); - var date = new DateTime(ContextDate.Year.Value, ContextDate.Month.Value, ContextDate.Day.Value); - var dayBefore = - PreviousMonthDays(date); + var date = new DateTime(ContextCalendar.Year.Value, ContextCalendar.Month.Value, ContextCalendar.Day.Value); + var dayBefore = PreviousMonthDays(date); var dateToSet = date.GetFirstDayOfMonth().AddDays(-dayBefore); for (var i = 7; i < children.Count; i++) { @@ -216,32 +224,44 @@ public class CalendarView : TemplatedControl cell.Content = day.Day.ToString(info); dateToSet = dateToSet.AddDays(1); } - FadeOutDayButtons(); } - private void RefreshYearButtons() + private void UpdateYearButtons() { if (_yearGrid is null) return; var mode = Mode; - var contextDate = ContextDate; - for (var i = 0; i < 12; i++) + var contextDate = ContextCalendar; + if (mode == CalendarViewMode.Century && contextDate.StartYear.HasValue) { - var child = _yearGrid.Children[i] as CalendarYearButton; - if (child is null) continue; - switch (mode) + var range = DateTimeHelper.GetCenturyViewRangeByYear(contextDate.StartYear.Value); + int start = range.start-10; + for (int i = 0; i < 12; i++) { - case CalendarViewMode.Month: - child.SetValues(CalendarViewMode.Year, i); - break; - case CalendarViewMode.Year: - child.SetValues(CalendarViewMode.Decade, year: ContextDate.Year / 10 * 10 + i - 1); - break; - case CalendarViewMode.Decade: - var startYear = (ContextDate.Year / 10 + i - 1) * 10; - var endYear = (ContextDate.Year / 10 + i - 1) * 10 + 10; - child.SetValues(CalendarViewMode.Century, startYear: startYear, endYear: endYear); - break; + var child = _yearGrid.Children[i] as CalendarYearButton; + child?.SetContext(CalendarViewMode.Century, + new CalendarContext() { StartYear = start, EndYear = start + 10 }); + start+= 10; + } + } + else if(mode == CalendarViewMode.Decade && contextDate.StartYear.HasValue) + { + var range = DateTimeHelper.GetDecadeViewRangeByYear(contextDate.StartYear.Value); + int year = range.start - 1; + for (int i = 0; i < 12; i++) + { + var child = _yearGrid.Children[i] as CalendarYearButton; + child?.SetContext(CalendarViewMode.Decade, + new CalendarContext() { Year = year}); + year++; + } + } + else if (mode == CalendarViewMode.Year) + { + for (var i = 0; i < 12; i++) + { + var child = _yearGrid.Children[i] as CalendarYearButton; + child?.SetContext(CalendarViewMode.Year, new CalendarContext() { Month = i }); } } } @@ -251,7 +271,7 @@ public class CalendarView : TemplatedControl if (_monthGrid is null) return; var children = _monthGrid.Children; for (var i = 7; i < children.Count; i++) - if (children[i] is CalendarDayButton { DataContext: DateTime d } button && d.Month != ContextDate.Month) + if (children[i] is CalendarDayButton { DataContext: DateTime d } button && d.Month != ContextCalendar.Month) button.IsNotCurrentMonth = true; } @@ -297,8 +317,9 @@ public class CalendarView : TemplatedControl /// private void OnHeaderMonthButtonClick(object sender, RoutedEventArgs e) { - _headerButton?.SetValue(ContentControl.ContentProperty, ContextDate.Year); SetCurrentValue(ModeProperty, CalendarViewMode.Year); + UpdateHeaderButtons(); + UpdateYearButtons(); } /// @@ -309,9 +330,12 @@ public class CalendarView : TemplatedControl private void OnHeaderYearButtonClick(object sender, RoutedEventArgs e) { if (_yearGrid is null) return; - var decadeStart = ContextDate.Year / 10 * 10; - _headerButton?.SetValue(ContentControl.ContentProperty, decadeStart + "-" + (decadeStart + 10)); SetCurrentValue(ModeProperty, CalendarViewMode.Decade); + var range = DateTimeHelper.GetDecadeViewRangeByYear(ContextCalendar.Year!.Value); + ContextCalendar.StartYear = range.start; + ContextCalendar.EndYear = range.end; + UpdateHeaderButtons(); + UpdateYearButtons(); } /// @@ -328,31 +352,66 @@ public class CalendarView : TemplatedControl { if (_yearGrid is null) return; var buttons = _yearGrid.Children.OfType().ToList(); - if (Mode == CalendarViewMode.Year) - { - Mode = CalendarViewMode.Month; - if (e.Month is null) return; - var day = MathHelpers.SafeClamp(e.Month.Value, 0, - DateTime.DaysInMonth(ContextDate.Year!.Value, e.Month.Value + 1)); - ContextDate = new DateContext { Year = ContextDate.Year, Month = e.Month + 1, Day = day }; - } - else if (Mode == CalendarViewMode.Decade) - { - Mode = CalendarViewMode.Year; - for (var i = 0; i < 12; i++) buttons[i].SetValues(CalendarViewMode.Year, i); - ContextDate = new DateContext { Year = e.Year!.Value, Month = null, Day = null }; - } - else if (Mode == CalendarViewMode.Century) + if (Mode == CalendarViewMode.Century) { Mode = CalendarViewMode.Decade; - for (var i = 0; i < 12; i++) - { - if (e.StartYear is null || e.EndYear is null) continue; - var year = e.StartYear.Value - 1 + i; - buttons[i].SetValues(CalendarViewMode.Decade, year: year); - } + ContextCalendar.Year = null; + ContextCalendar.StartYear = e.Context.StartYear; + ContextCalendar.EndYear = e.Context.EndYear; } + else if(Mode == CalendarViewMode.Decade) + { + Mode = CalendarViewMode.Year; + ContextCalendar.Year = e.Context.Year; + ContextCalendar.StartYear = e.Context.StartYear; + ContextCalendar.EndYear = e.Context.EndYear; + } + else if (Mode == CalendarViewMode.Year) + { + Mode = CalendarViewMode.Month; + ContextCalendar.StartYear = null; + ContextCalendar.EndYear = null; + // ContextCalendar.Year = e.Context.Year; + ContextCalendar.Month = e.Context.Month; + UpdateDayButtons(); + } + else if (Mode == CalendarViewMode.Month) + { + throw new NotImplementedException(); + } + UpdateHeaderButtons(); + UpdateYearButtons(); + } - RefreshYearButtons(); + private void UpdateHeaderButtons() + { + if (this.Mode == CalendarViewMode.Century) + { + IsVisibleProperty.SetValue(true, _headerButton, _yearGrid); + IsVisibleProperty.SetValue(false, _yearButton, _monthButton, _monthGrid); + _headerButton?.SetValue(ContentControl.ContentProperty, ContextCalendar.StartYear + "-" + ContextCalendar.EndYear); + } + else if (this.Mode == CalendarViewMode.Decade) + { + IsVisibleProperty.SetValue(true, _headerButton, _yearGrid); + IsVisibleProperty.SetValue(false, _yearButton, _monthButton, _monthGrid); + _headerButton?.SetValue(ContentControl.ContentProperty, ContextCalendar.StartYear + "-" + ContextCalendar.EndYear); + } + else if (this.Mode == CalendarViewMode.Year) + { + IsVisibleProperty.SetValue(true, _headerButton, _yearGrid); + IsVisibleProperty.SetValue(false, _yearButton, _monthButton, _monthGrid); + _headerButton?.SetValue(ContentControl.ContentProperty, ContextCalendar.Year); + } + else if (this.Mode == CalendarViewMode.Month) + { + IsVisibleProperty.SetValue(false, _headerButton, _yearGrid); + IsVisibleProperty.SetValue(true, _yearButton, _monthButton, _monthGrid); + // _headerButton?.SetValue(ContentControl.ContentProperty, ContextCalendar.Year); + _yearButton?.SetValue(ContentControl.ContentProperty, ContextCalendar.Year); + _monthButton?.SetValue(ContentControl.ContentProperty, + DateTimeHelper.GetCurrentDateTimeFormatInfo().AbbreviatedMonthNames[ContextCalendar.Month ?? 0]); + } + } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs b/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs index 9b76f98..8677bd8 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarYearButton.cs @@ -22,13 +22,7 @@ public class CalendarYearButton : ContentControl PressedMixin.Attach(); } - internal int? Year { get; private set; } - - internal int? Month { get; private set; } - - internal int? StartYear { get; private set; } - - internal int? EndYear { get; private set; } + internal CalendarContext CalendarContext { get; set; } = new (); internal CalendarViewMode Mode { get; private set; } @@ -37,30 +31,30 @@ public class CalendarYearButton : ContentControl add => AddHandler(ItemSelectedEvent, value); remove => RemoveHandler(ItemSelectedEvent, value); } - - internal void SetValues(CalendarViewMode mode, int? month = null, int? year = null, - int? startYear = null, int? endYear = null) + + internal void SetContext(CalendarViewMode mode, CalendarContext context) { - Debug.Assert(!(month is null && year is null && startYear is null && endYear is null)); - Mode = mode; - Month = month ?? 0; - Year = year ?? 0; - StartYear = startYear ?? 0; - EndYear = endYear ?? 0; + CalendarContext = context.Clone(); + CalendarContext.Month = context.Month; + CalendarContext.Year = context.Year; + CalendarContext.StartYear = context.StartYear; + CalendarContext.EndYear = context.EndYear; + this.Mode = mode; Content = Mode switch { - CalendarViewMode.Month => DateTimeHelper.GetCurrentDateTimeFormatInfo().AbbreviatedMonthNames[Month.Value], - CalendarViewMode.Year => Year.ToString(), - CalendarViewMode.Decade => StartYear + "-" + EndYear, - CalendarViewMode.Century => StartYear + "-" + EndYear, + 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 }; + IsEnabled = Content != null; } protected override void OnPointerPressed(PointerPressedEventArgs e) { base.OnPointerPressed(e); - RaiseEvent(new CalendarYearButtonEventArgs(Mode, Year, Month, StartYear, EndYear) + RaiseEvent(new CalendarYearButtonEventArgs(Mode, this.CalendarContext.Clone()) { RoutedEvent = ItemSelectedEvent, Source = this }); } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/CalendarYearButtonEventArgs.cs b/src/Ursa/Controls/DateTimePicker/CalendarYearButtonEventArgs.cs index 40ecbe5..dbfea71 100644 --- a/src/Ursa/Controls/DateTimePicker/CalendarYearButtonEventArgs.cs +++ b/src/Ursa/Controls/DateTimePicker/CalendarYearButtonEventArgs.cs @@ -4,19 +4,13 @@ namespace Ursa.Controls; public class CalendarYearButtonEventArgs: RoutedEventArgs { - public int? Year { get; } - public int? Month { get; } - public int? StartYear { get; } - public int? EndYear { get; } + internal CalendarContext Context { get; } internal CalendarViewMode Mode { get; } /// - internal CalendarYearButtonEventArgs(CalendarViewMode mode, int? year, int? month, int? startYear, int? endYear ) + internal CalendarYearButtonEventArgs(CalendarViewMode mode, CalendarContext context) { - Year = year; - Month = month; - StartYear = startYear; - EndYear = endYear; + Context = context; Mode = mode; } } \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/DateContext.cs b/src/Ursa/Controls/DateTimePicker/DateContext.cs deleted file mode 100644 index 3275a8a..0000000 --- a/src/Ursa/Controls/DateTimePicker/DateContext.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ursa.Controls; - -public class DateContext(int? year = null, int? month = null, int? day = null) -{ - public int? Year = year; - public int? Month = month; - public int? Day = day; -} \ No newline at end of file diff --git a/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs b/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs index 5e10713..4fbe89f 100644 --- a/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs +++ b/src/Ursa/Controls/DateTimePicker/DateTimeHelper.cs @@ -42,4 +42,16 @@ internal static class DateTimeHelper { return d1.Ticks < d2.Ticks ? d2 : d1; } + + public static (int start, int end) GetDecadeViewRangeByYear(int year) + { + int start = year / 10 * 10; + return new ValueTuple(start, start + 10); + } + + public static (int start, int end) GetCenturyViewRangeByYear(int year) + { + int start = year / 100 * 100; + return new ValueTuple(start, start + 100); + } } \ No newline at end of file