Files
Wino-Mail/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarView.cs
T

151 lines
5.8 KiB
C#
Raw Normal View History

2025-12-26 20:46:48 +01:00
using System;
using System.Windows.Input;
using CommunityToolkit.Diagnostics;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Windows.UI;
using Wino.Core.Domain.Models.Calendar;
using Wino.Helpers;
namespace Wino.Calendar.Controls;
public partial class WinoCalendarView : Control
{
private const string PART_DayViewItemBorder = nameof(PART_DayViewItemBorder);
private const string PART_CalendarView = nameof(PART_CalendarView);
public static readonly DependencyProperty HighlightedDateRangeProperty = DependencyProperty.Register(nameof(HighlightedDateRange), typeof(DateRange), typeof(WinoCalendarView), new PropertyMetadata(null, new PropertyChangedCallback(OnHighlightedDateRangeChanged)));
public static readonly DependencyProperty VisibleDateBackgroundProperty = DependencyProperty.Register(nameof(VisibleDateBackground), typeof(Brush), typeof(WinoCalendarView), new PropertyMetadata(null, new PropertyChangedCallback(OnPropertiesChanged)));
public static readonly DependencyProperty DateClickedCommandProperty = DependencyProperty.Register(nameof(DateClickedCommand), typeof(ICommand), typeof(WinoCalendarView), new PropertyMetadata(null));
public static readonly DependencyProperty TodayBackgroundColorProperty = DependencyProperty.Register(nameof(TodayBackgroundColor), typeof(Color), typeof(WinoCalendarView), new PropertyMetadata(new Color()));
2025-12-26 20:46:48 +01:00
public Color TodayBackgroundColor
{
get { return (Color)GetValue(TodayBackgroundColorProperty); }
set { SetValue(TodayBackgroundColorProperty, value); }
}
/// <summary>
/// Gets or sets the command to execute when a date is picked.
/// Unused.
/// </summary>
public ICommand? DateClickedCommand
2025-12-26 20:46:48 +01:00
{
get { return (ICommand?)GetValue(DateClickedCommandProperty); }
2025-12-26 20:46:48 +01:00
set { SetValue(DateClickedCommandProperty, value); }
}
/// <summary>
/// Gets or sets the highlighted range of dates.
/// </summary>
public DateRange? HighlightedDateRange
2025-12-26 20:46:48 +01:00
{
get { return (DateRange?)GetValue(HighlightedDateRangeProperty); }
2025-12-26 20:46:48 +01:00
set { SetValue(HighlightedDateRangeProperty, value); }
}
public Brush? VisibleDateBackground
2025-12-26 20:46:48 +01:00
{
get { return (Brush?)GetValue(VisibleDateBackgroundProperty); }
2025-12-26 20:46:48 +01:00
set { SetValue(VisibleDateBackgroundProperty, value); }
}
private CalendarView? CalendarView;
2025-12-26 20:46:48 +01:00
public WinoCalendarView()
{
DefaultStyleKey = typeof(WinoCalendarView);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
CalendarView = GetTemplateChild(PART_CalendarView) as CalendarView;
Guard.IsNotNull(CalendarView, nameof(CalendarView));
if (CalendarView == null) return;
2025-12-26 20:46:48 +01:00
CalendarView.SelectedDatesChanged -= InternalCalendarViewSelectionChanged;
CalendarView.SelectedDatesChanged += InternalCalendarViewSelectionChanged;
// TODO: Should come from settings.
CalendarView.FirstDayOfWeek = Windows.Globalization.DayOfWeek.Monday;
// Everytime display mode changes, update the visible date range backgrounds.
// If users go back from year -> month -> day, we need to update the visible date range backgrounds.
CalendarView.RegisterPropertyChangedCallback(CalendarView.DisplayModeProperty, (s, e) => UpdateVisibleDateRangeBackgrounds());
}
private void InternalCalendarViewSelectionChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
{
if (args.AddedDates?.Count > 0)
{
var clickedDate = args.AddedDates[0].Date;
SetInnerDisplayDate(clickedDate);
var clickArgs = new CalendarViewDayClickedEventArgs(clickedDate);
DateClickedCommand?.Execute(clickArgs);
}
// Reset selection, we don't show selected dates but react to them.
CalendarView?.SelectedDates.Clear();
2025-12-26 20:46:48 +01:00
}
private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is WinoCalendarView control)
{
control.UpdateVisibleDateRangeBackgrounds();
}
}
private void SetInnerDisplayDate(DateTime dateTime) => CalendarView?.SetDisplayDate(dateTime);
// Changing selected dates will trigger the selection changed event.
// It will behave like user clicked the date.
public void GoToDay(DateTime dateTime) => CalendarView?.SelectedDates.Add(dateTime);
2025-12-26 20:46:48 +01:00
private static void OnHighlightedDateRangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is WinoCalendarView control)
{
if (control.HighlightedDateRange == null) return;
2025-12-26 20:46:48 +01:00
control.SetInnerDisplayDate(control.HighlightedDateRange.StartDate);
control.UpdateVisibleDateRangeBackgrounds();
}
}
public void UpdateVisibleDateRangeBackgrounds()
{
if (HighlightedDateRange == null || VisibleDateBackground == null || CalendarView == null) return;
2025-12-26 20:46:48 +01:00
var markDateCalendarDayItems = WinoVisualTreeHelper.FindDescendants<CalendarViewDayItem>(CalendarView);
foreach (var calendarDayItem in markDateCalendarDayItems)
{
var border = WinoVisualTreeHelper.GetChildObject<Border>(calendarDayItem, PART_DayViewItemBorder);
if (border == null) return;
if (calendarDayItem.Date.Date == DateTime.Today.Date)
{
border.Background = new SolidColorBrush(TodayBackgroundColor);
}
else if (calendarDayItem.Date.Date >= HighlightedDateRange.StartDate.Date && calendarDayItem.Date.Date < HighlightedDateRange.EndDate.Date)
{
border.Background = VisibleDateBackground;
}
else
{
border.Background = null;
}
}
}
}