using System.Globalization; using System.Runtime.CompilerServices; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Layout; using Irihi.Avalonia.Shared.Helpers; using Calendar = System.Globalization.Calendar; namespace Ursa.Controls; [TemplatePart(PART_FastNextButton, typeof(Button))] [TemplatePart(PART_FastPreviousButton, 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_MonthGrid, typeof(Grid))] [TemplatePart(PART_YearGrid, typeof(Grid))] [PseudoClasses(PC_Month)] public class CalendarView : TemplatedControl { public const string PART_FastNextButton = "PART_FastNextButton"; public const string PART_FastPreviousButton = "PART_FastPreviousButton"; public const string PART_NextButton = "PART_NextButton"; 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_HeaderButton = "PART_HeaderButton"; public const string PART_MonthGrid = "PART_MonthGrid"; public const string PART_YearGrid = "PART_YearGrid"; public const string PC_Month = ":month"; private const string ShortestDayName = "ShortestDayName"; internal static readonly DirectProperty ModeProperty = AvaloniaProperty.RegisterDirect( nameof(Mode), o => o.Mode, (o, v) => o.Mode = v); public static readonly StyledProperty IsTodayHighlightedProperty = DatePickerBase.IsTodayHighlightedProperty.AddOwner(); public static readonly StyledProperty FirstDayOfWeekProperty = DatePickerBase.FirstDayOfWeekProperty.AddOwner(); private readonly Calendar _calendar = new GregorianCalendar(); private Button? _fastNextButton; private Button? _fastPreviousButton; private Button? _headerButton; private CalendarViewMode _mode; private Button? _monthButton; private Grid? _monthGrid; private Button? _nextButton; private Button? _previousButton; private Button? _yearButton; private Grid? _yearGrid; private DateTime? _start; private DateTime? _end; private DateTime? _previewStart; private DateTime? _previewEnd; 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); }); ContextDateProperty.Changed.AddClassHandler((view, args) => view.OnContextDateChanged(args)); } private void OnContextDateChanged(AvaloniaPropertyChangedEventArgs args) { if (!_dateContextSyncing) { ContextDateChanged?.Invoke(this, args.NewValue.Value); } //UpdateDayButtons(); //UpdateYearButtons(); } internal CalendarViewMode Mode { get => _mode; set => SetAndRaise(ModeProperty, ref _mode, value); } private CalendarContext _contextDate = new(); public static readonly DirectProperty ContextDateProperty = AvaloniaProperty.RegisterDirect( nameof(ContextDate), o => o.ContextDate, (o, v) => o.ContextDate = v); public CalendarContext ContextDate { get => _contextDate; internal set => SetAndRaise(ContextDateProperty, ref _contextDate, value); } public bool IsTodayHighlighted { get => GetValue(IsTodayHighlightedProperty); set => SetValue(IsTodayHighlightedProperty, value); } public DayOfWeek FirstDayOfWeek { get => GetValue(FirstDayOfWeekProperty); set => SetValue(FirstDayOfWeekProperty, value); } public event EventHandler? DateSelected; public event EventHandler? DatePreviewed; internal event EventHandler? ContextDateChanged; private void OnFirstDayOfWeekChanged(AvaloniaPropertyChangedEventArgs args) { UpdateMonthViewHeader(args.NewValue.Value); UpdateDayButtons(); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); Button.ClickEvent.RemoveHandler(OnHeaderYearButtonClick, _yearButton); Button.ClickEvent.RemoveHandler(OnHeaderMonthButtonClick, _monthButton); Button.ClickEvent.RemoveHandler(OnHeaderButtonClick, _headerButton); Button.ClickEvent.RemoveHandler(OnFastPrevious, _fastPreviousButton); Button.ClickEvent.RemoveHandler(OnPrevious, _previousButton); Button.ClickEvent.RemoveHandler(OnNext, _nextButton); Button.ClickEvent.RemoveHandler(OnFastNext, _fastNextButton); _monthGrid = e.NameScope.Find(PART_MonthGrid); _yearGrid = e.NameScope.Find(PART_YearGrid); _yearButton = e.NameScope.Find