提交双 CalendarItem 方案

This commit is contained in:
polarboy
2024-09-11 11:53:27 +08:00
parent 9bc03c841f
commit 2cf49de2a4
4 changed files with 154 additions and 41 deletions
+25 -20
View File
@@ -569,7 +569,7 @@ public class Calendar : TemplatedControl
}
}
internal DateTime DisplayDateInternal { get; private set; }
internal DateTime DisplayDateInternal { get; set; }
#endregion
@@ -807,7 +807,7 @@ public class Calendar : TemplatedControl
RemovedItems = new Collection<DateTime>();
}
private void OnDisplayDateChanged(AvaloniaPropertyChangedEventArgs e)
protected virtual void OnDisplayDateChanged(AvaloniaPropertyChangedEventArgs e)
{
UpdateDisplayDate(this, (DateTime)e.NewValue!, (DateTime)e.OldValue!);
}
@@ -833,7 +833,7 @@ public class Calendar : TemplatedControl
c.OnDisplayDate(new CalendarDateChangedEventArgs(removedDate, addedDate));
}
private void OnDisplayDate(CalendarDateChangedEventArgs e)
protected void OnDisplayDate(CalendarDateChangedEventArgs e)
{
DisplayDateChanged?.Invoke(this, e);
}
@@ -1073,26 +1073,31 @@ public class Calendar : TemplatedControl
}
}
internal void UpdateMonths()
protected internal virtual void UpdateMonths()
{
CalendarItem? monthControl = MonthControl;
if (monthControl != null) {
switch (DisplayMode) {
case CalendarMode.Month:
{
monthControl.UpdateMonthMode();
break;
}
case CalendarMode.Year:
{
monthControl.UpdateYearMode();
break;
}
case CalendarMode.Decade:
{
monthControl.UpdateDecadeMode();
break;
}
UpdateCalendarMonths(monthControl);
}
}
internal void UpdateCalendarMonths(CalendarItem calendarItem)
{
switch (DisplayMode) {
case CalendarMode.Month:
{
calendarItem.UpdateMonthMode();
break;
}
case CalendarMode.Year:
{
calendarItem.UpdateYearMode();
break;
}
case CalendarMode.Decade:
{
calendarItem.UpdateDecadeMode();
break;
}
}
}
+39 -21
View File
@@ -25,7 +25,7 @@ namespace AtomUI.Controls;
[PseudoClasses(CalendarDisabledPC)]
internal class CalendarItem : TemplatedControl
{
private const string CalendarDisabledPC = ":calendardisabled";
internal const string CalendarDisabledPC = ":calendardisabled";
#region 公共属性定义
@@ -182,20 +182,20 @@ internal class CalendarItem : TemplatedControl
/// <summary>
/// The number of days per week.
/// </summary>
private const int NumberOfDaysPerWeek = 7;
internal const int NumberOfDaysPerWeek = 7;
private HeadTextButton? _headerButton;
private IconButton? _nextButton;
private IconButton? _previousButton;
private IconButton? _nextMonthButton;
private IconButton? _previousMonthButton;
protected HeadTextButton? _headerButton;
protected IconButton? _nextButton;
protected IconButton? _previousButton;
protected IconButton? _nextMonthButton;
protected IconButton? _previousMonthButton;
private DateTime _currentMonth;
private bool _isMouseLeftButtonDown;
private bool _isMouseLeftButtonDownYearView;
private bool _isControlPressed;
protected DateTime _currentMonth;
protected bool _isMouseLeftButtonDown;
protected bool _isMouseLeftButtonDownYearView;
protected bool _isControlPressed;
private readonly System.Globalization.Calendar _calendar = new GregorianCalendar();
protected readonly System.Globalization.Calendar _calendar = new GregorianCalendar();
internal Calendar? Owner { get; set; }
internal CalendarDayButton? CurrentButton { get; set; }
@@ -328,7 +328,7 @@ internal class CalendarItem : TemplatedControl
}
}
private void SetDayTitles()
protected void SetDayTitles()
{
for (int childIndex = 0; childIndex < Calendar.ColumnsPerMonth; childIndex++) {
var daytitle = MonthView!.Children[childIndex];
@@ -364,7 +364,7 @@ internal class CalendarItem : TemplatedControl
}
}
internal void UpdateMonthMode()
protected internal virtual void UpdateMonthMode()
{
if (Owner != null) {
_currentMonth = Owner.DisplayDateInternal;
@@ -382,7 +382,7 @@ internal class CalendarItem : TemplatedControl
}
}
private void SetMonthModeHeaderButton()
protected virtual void SetMonthModeHeaderButton()
{
if (HeaderButton != null) {
if (Owner != null) {
@@ -394,7 +394,7 @@ internal class CalendarItem : TemplatedControl
}
}
private void SetMonthModeNextButton(DateTime firstDayOfMonth)
protected void SetMonthModeNextButton(DateTime firstDayOfMonth)
{
if (Owner != null && NextButton != null) {
// DisplayDate is equal to DateTime.MaxValue
@@ -409,7 +409,7 @@ internal class CalendarItem : TemplatedControl
}
}
private void SetMonthModePreviousButton(DateTime firstDayOfMonth)
protected void SetMonthModePreviousButton(DateTime firstDayOfMonth)
{
if (Owner != null && PreviousButton != null) {
PreviousButton.IsEnabled = (DateTimeHelper.CompareDays(Owner.DisplayDateRangeStart, firstDayOfMonth) < 0);
@@ -441,10 +441,10 @@ internal class CalendarItem : TemplatedControl
// SET IF THE DAY IS INACTIVE OR NOT: set if the day is a
// trailing day or not
childButton.IsInactive = (DateTimeHelper.CompareYearMonth(dateToAdd, Owner.DisplayDateInternal) != 0);
childButton.IsInactive = CheckDayInactiveState(dateToAdd);
// SET IF THE DAY IS TODAY OR NOT
childButton.IsToday = (Owner.IsTodayHighlighted && dateToAdd == DateTime.Today);
childButton.IsToday = CheckDayIsTodayState(dateToAdd);
// SET IF THE DAY IS SELECTED OR NOT
childButton.IsSelected = false;
@@ -474,7 +474,25 @@ internal class CalendarItem : TemplatedControl
}
}
private void SetCalendarDayButtons(DateTime firstDayOfMonth)
protected virtual bool CheckDayInactiveState(DateTime dateToAdd)
{
if (Owner is not null) {
return DateTimeHelper.CompareYearMonth(dateToAdd, Owner.DisplayDateInternal) != 0;
}
return false;
}
protected virtual bool CheckDayIsTodayState(DateTime dateToAdd)
{
if (Owner is not null) {
return Owner.IsTodayHighlighted && dateToAdd == DateTime.Today;
}
return false;
}
protected void SetCalendarDayButtons(DateTime firstDayOfMonth)
{
int lastMonthToDisplay = PreviousMonthDays(firstDayOfMonth);
DateTime dateToAdd;
@@ -6,6 +6,13 @@ namespace AtomUI.Controls;
public class RangeCalendar : Calendar
{
public RangeCalendar()
{
SelectionMode = CalendarSelectionMode.SingleRange;
}
internal DateTime SecondaryDisplayDateInternal { get; private set; }
internal CalendarItem? SecondaryMonthControl
{
get
@@ -17,7 +24,34 @@ public class RangeCalendar : Calendar
return null;
}
}
protected override void OnDisplayDateChanged(AvaloniaPropertyChangedEventArgs e)
{
UpdateDisplayDate(this, (DateTime)e.NewValue!, (DateTime)e.OldValue!);
}
private static void UpdateDisplayDate(RangeCalendar c, DateTime addedDate, DateTime removedDate)
{
_ = c ?? throw new ArgumentNullException(nameof(c));
// If DisplayDate < DisplayDateStart, DisplayDate = DisplayDateStart
if (DateTime.Compare(addedDate, c.DisplayDateRangeStart) < 0) {
c.DisplayDate = c.DisplayDateRangeStart;
return;
}
// If DisplayDate > DisplayDateEnd, DisplayDate = DisplayDateEnd
if (DateTime.Compare(addedDate, c.DisplayDateRangeEnd) > 0) {
c.DisplayDate = c.DisplayDateRangeEnd;
return;
}
c.DisplayDateInternal = DateTimeHelper.DiscardDayTime(addedDate);
c.SecondaryDisplayDateInternal = DateTimeHelper.AddMonths(DateTimeHelper.DiscardDayTime(addedDate), 1) ?? c.DisplayDateInternal;
c.UpdateMonths();
c.OnDisplayDate(new CalendarDateChangedEventArgs(removedDate, addedDate));
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
@@ -56,4 +90,12 @@ public class RangeCalendar : Calendar
}
}
}
protected internal override void UpdateMonths()
{
base.UpdateMonths();
if (SecondaryMonthControl is not null) {
UpdateCalendarMonths(SecondaryMonthControl);
}
}
}
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
@@ -54,6 +55,12 @@ internal class RangeCalendarItem : CalendarItem
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
SetupNextButtonVisible();
}
private void SetupNextButtonVisible()
{
IsNextButtonVisible = !IsPrimary || Owner?.DisplayMode == CalendarMode.Decade ||
@@ -77,4 +84,45 @@ internal class RangeCalendarItem : CalendarItem
base.HandleMonthCalendarButtonMouseUp(sender, e);
SetupNextButtonVisible();
}
protected internal override void UpdateMonthMode()
{
if (Owner is RangeCalendar owner) {
_currentMonth = IsPrimary ? owner.DisplayDateInternal : owner.SecondaryDisplayDateInternal;
} else {
_currentMonth = DateTime.Today;
}
SetMonthModeHeaderButton();
SetMonthModePreviousButton(_currentMonth);
SetMonthModeNextButton(_currentMonth);
if (MonthView != null) {
SetDayTitles();
SetCalendarDayButtons(_currentMonth);
}
}
protected override void SetMonthModeHeaderButton()
{
if (HeaderButton != null) {
if (Owner is RangeCalendar owner) {
var targetDate = _isPrimary ? owner.DisplayDateInternal : owner.SecondaryDisplayDateInternal;
HeaderButton.Content = targetDate.ToString("Y", DateTimeHelper.GetCurrentDateFormat());
HeaderButton.IsEnabled = true;
} else {
HeaderButton.Content = DateTime.Today.ToString("Y", DateTimeHelper.GetCurrentDateFormat());
}
}
}
protected override bool CheckDayInactiveState(DateTime dateToAdd)
{
if (Owner is RangeCalendar owner) {
var targetDate = _isPrimary ? owner.DisplayDateInternal : owner.SecondaryDisplayDateInternal;
return DateTimeHelper.CompareYearMonth(dateToAdd, targetDate) != 0;
}
return false;
}
}