2024-11-10 23:28:25 +01:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
|
using Windows.UI.Xaml;
|
|
|
|
|
|
using Windows.UI.Xaml.Controls;
|
|
|
|
|
|
using Wino.Calendar.Args;
|
|
|
|
|
|
using Wino.Core.Domain.Models.Calendar;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Wino.Calendar.Controls
|
|
|
|
|
|
{
|
|
|
|
|
|
public class WinoCalendarControl : Control
|
|
|
|
|
|
{
|
|
|
|
|
|
private const string PART_WinoFlipView = nameof(PART_WinoFlipView);
|
2024-12-31 15:32:03 +01:00
|
|
|
|
private const string PART_IdleGrid = nameof(PART_IdleGrid);
|
2024-11-10 23:28:25 +01:00
|
|
|
|
|
|
|
|
|
|
public event EventHandler<TimelineCellSelectedArgs> TimelineCellSelected;
|
|
|
|
|
|
public event EventHandler<TimelineCellUnselectedArgs> TimelineCellUnselected;
|
|
|
|
|
|
|
|
|
|
|
|
#region Dependency Properties
|
|
|
|
|
|
|
|
|
|
|
|
public static readonly DependencyProperty DayRangesProperty = DependencyProperty.Register(nameof(DayRanges), typeof(ObservableCollection<DayRangeRenderModel>), typeof(WinoCalendarControl), new PropertyMetadata(null));
|
|
|
|
|
|
public static readonly DependencyProperty SelectedFlipViewIndexProperty = DependencyProperty.Register(nameof(SelectedFlipViewIndex), typeof(int), typeof(WinoCalendarControl), new PropertyMetadata(-1));
|
|
|
|
|
|
public static readonly DependencyProperty SelectedFlipViewDayRangeProperty = DependencyProperty.Register(nameof(SelectedFlipViewDayRange), typeof(DayRangeRenderModel), typeof(WinoCalendarControl), new PropertyMetadata(null));
|
2024-12-28 16:39:43 +01:00
|
|
|
|
public static readonly DependencyProperty ActiveCanvasProperty = DependencyProperty.Register(nameof(ActiveCanvas), typeof(WinoDayTimelineCanvas), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnActiveCanvasChanged)));
|
2024-12-31 15:32:03 +01:00
|
|
|
|
public static readonly DependencyProperty IsFlipIdleProperty = DependencyProperty.Register(nameof(IsFlipIdle), typeof(bool), typeof(WinoCalendarControl), new PropertyMetadata(true, new PropertyChangedCallback(OnIdleStateChanged)));
|
2024-11-10 23:28:25 +01:00
|
|
|
|
|
|
|
|
|
|
public DayRangeRenderModel SelectedFlipViewDayRange
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return (DayRangeRenderModel)GetValue(SelectedFlipViewDayRangeProperty); }
|
|
|
|
|
|
set { SetValue(SelectedFlipViewDayRangeProperty, value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
public WinoDayTimelineCanvas ActiveCanvas
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return (WinoDayTimelineCanvas)GetValue(ActiveCanvasProperty); }
|
|
|
|
|
|
set { SetValue(ActiveCanvasProperty, value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-31 15:32:03 +01:00
|
|
|
|
public bool IsFlipIdle
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return (bool)GetValue(IsFlipIdleProperty); }
|
|
|
|
|
|
set { SetValue(IsFlipIdleProperty, value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-10 23:28:25 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets or sets the collection of day ranges to render.
|
|
|
|
|
|
/// Each day range usually represents a week, but it may support other ranges.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public ObservableCollection<DayRangeRenderModel> DayRanges
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return (ObservableCollection<DayRangeRenderModel>)GetValue(DayRangesProperty); }
|
|
|
|
|
|
set { SetValue(DayRangesProperty, value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public int SelectedFlipViewIndex
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return (int)GetValue(SelectedFlipViewIndexProperty); }
|
|
|
|
|
|
set { SetValue(SelectedFlipViewIndexProperty, value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
private WinoCalendarFlipView InternalFlipView;
|
2024-12-31 15:32:03 +01:00
|
|
|
|
private Grid IdleGrid;
|
2024-11-10 23:28:25 +01:00
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
public WinoCalendarControl()
|
2024-11-10 23:28:25 +01:00
|
|
|
|
{
|
2024-12-28 16:39:43 +01:00
|
|
|
|
DefaultStyleKey = typeof(WinoCalendarControl);
|
|
|
|
|
|
SizeChanged += CalendarSizeChanged;
|
|
|
|
|
|
}
|
2024-11-10 23:28:25 +01:00
|
|
|
|
|
2024-12-31 15:32:03 +01:00
|
|
|
|
private static void OnIdleStateChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (calendar is WinoCalendarControl calendarControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
calendarControl.UpdateIdleState();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
private static void OnActiveCanvasChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (calendar is WinoCalendarControl calendarControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (e.OldValue is WinoDayTimelineCanvas oldCanvas)
|
2024-11-10 23:28:25 +01:00
|
|
|
|
{
|
|
|
|
|
|
// Dismiss any selection on the old canvas.
|
2024-12-28 16:39:43 +01:00
|
|
|
|
calendarControl.DeregisterCanvas(oldCanvas);
|
2024-11-10 23:28:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
if (e.NewValue is WinoDayTimelineCanvas newCanvas)
|
2024-11-10 23:28:25 +01:00
|
|
|
|
{
|
2024-12-28 16:39:43 +01:00
|
|
|
|
calendarControl.RegisterCanvas(newCanvas);
|
2024-11-10 23:28:25 +01:00
|
|
|
|
}
|
2024-12-28 16:39:43 +01:00
|
|
|
|
|
|
|
|
|
|
calendarControl.ManageHighlightedDateRange();
|
2024-11-10 23:28:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
private void ManageHighlightedDateRange()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ActiveCanvas == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedFlipViewDayRange = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedFlipViewDayRange = InternalFlipView.SelectedItem as DayRangeRenderModel;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-11-10 23:28:25 +01:00
|
|
|
|
|
2024-12-28 16:39:43 +01:00
|
|
|
|
private void DeregisterCanvas(WinoDayTimelineCanvas canvas)
|
2024-11-10 23:28:25 +01:00
|
|
|
|
{
|
2024-12-28 16:39:43 +01:00
|
|
|
|
if (canvas == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
canvas.SelectedDateTime = null;
|
|
|
|
|
|
canvas.TimelineCellSelected -= ActiveTimelineCellSelected;
|
|
|
|
|
|
canvas.TimelineCellUnselected -= ActiveTimelineCellUnselected;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void RegisterCanvas(WinoDayTimelineCanvas canvas)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (canvas == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
canvas.SelectedDateTime = null;
|
|
|
|
|
|
canvas.TimelineCellSelected += ActiveTimelineCellSelected;
|
|
|
|
|
|
canvas.TimelineCellUnselected += ActiveTimelineCellUnselected;
|
2024-11-10 23:28:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void CalendarSizeChanged(object sender, SizeChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ActiveCanvas == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
ActiveCanvas.SelectedDateTime = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnApplyTemplate()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnApplyTemplate();
|
|
|
|
|
|
|
|
|
|
|
|
InternalFlipView = GetTemplateChild(PART_WinoFlipView) as WinoCalendarFlipView;
|
2024-12-31 15:32:03 +01:00
|
|
|
|
IdleGrid = GetTemplateChild(PART_IdleGrid) as Grid;
|
|
|
|
|
|
|
|
|
|
|
|
UpdateIdleState();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateIdleState()
|
|
|
|
|
|
{
|
2025-01-01 17:28:29 +01:00
|
|
|
|
InternalFlipView.Opacity = IsFlipIdle ? 0 : 1;
|
2024-12-31 15:32:03 +01:00
|
|
|
|
IdleGrid.Visibility = IsFlipIdle ? Visibility.Visible : Visibility.Collapsed;
|
2024-11-10 23:28:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ActiveTimelineCellUnselected(object sender, TimelineCellUnselectedArgs e)
|
|
|
|
|
|
=> TimelineCellUnselected?.Invoke(this, e);
|
|
|
|
|
|
|
|
|
|
|
|
private void ActiveTimelineCellSelected(object sender, TimelineCellSelectedArgs e)
|
|
|
|
|
|
=> TimelineCellSelected?.Invoke(this, e);
|
|
|
|
|
|
|
|
|
|
|
|
public void NavigateToDay(DateTime dateTime) => InternalFlipView.NavigateToDay(dateTime);
|
|
|
|
|
|
|
|
|
|
|
|
public void ResetTimelineSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ActiveCanvas == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
ActiveCanvas.SelectedDateTime = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void GoNextRange()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (InternalFlipView == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
InternalFlipView.GoNextFlip();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void GoPreviousRange()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (InternalFlipView == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
InternalFlipView.GoPreviousFlip();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|