feat: add a single state machine to manage selection. WIP.
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Ursa.Demo.Pages.DatePickerDemo">
|
x:Class="Ursa.Demo.Pages.DatePickerDemo">
|
||||||
<StackPanel Margin="20" HorizontalAlignment="Left">
|
<StackPanel Margin="20" HorizontalAlignment="Left">
|
||||||
<u:CalendarMonthView/>
|
<u:CalendarMonthView />
|
||||||
<u:CalendarDayButton />
|
<u:CalendarDayButton />
|
||||||
<u:CalendarDayButton IsSelected="True" />
|
<u:CalendarDayButton IsSelected="True" />
|
||||||
<u:CalendarDayButton IsBlackout="True" />
|
<u:CalendarDayButton IsBlackout="True" />
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<u:CalendarDayButton IsInRange="True" />
|
<u:CalendarDayButton IsInRange="True" />
|
||||||
<u:CalendarDayButton IsEndDate="True" />
|
<u:CalendarDayButton IsEndDate="True" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal" DataValidationErrors.Errors="{Binding items}">
|
||||||
<u:CalendarDayButton IsPreviewStartDate="True" />
|
<u:CalendarDayButton IsPreviewStartDate="True" />
|
||||||
<u:CalendarDayButton IsInRange="True" />
|
<u:CalendarDayButton IsInRange="True" />
|
||||||
<u:CalendarDayButton IsInRange="True" />
|
<u:CalendarDayButton IsInRange="True" />
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Avalonia;
|
using System.Diagnostics;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Ursa.Controls;
|
||||||
|
|
||||||
namespace Ursa.Demo.Pages;
|
namespace Ursa.Demo.Pages;
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@
|
|||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:Calendar">
|
<ControlTemplate TargetType="u:Calendar">
|
||||||
<Panel>
|
<Panel>
|
||||||
<Grid Name="{x:Static u:Calendar.PART_MonthView}" RowDefinitions="Auto, *">
|
<Grid RowDefinitions="Auto, *">
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, Auto,*, Auto, Auto">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto, Auto,*, Auto, Auto">
|
||||||
<Button
|
<Button
|
||||||
Name="{x:Static u:Calendar.PART_PreviousYearButton}"
|
Name="{x:Static u:Calendar.PART_PreviousYearButton}"
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<u:CalendarMonthView Grid.Row="1"></u:CalendarMonthView>
|
<u:CalendarMonthView Grid.Row="1" Name="{x:Static u:Calendar.PART_MonthView}"></u:CalendarMonthView>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ public class Calendar: TemplatedControl
|
|||||||
public const string PART_MonthView = "PART_MonthView";
|
public const string PART_MonthView = "PART_MonthView";
|
||||||
public const string PART_YearView = "PART_YearView";
|
public const string PART_YearView = "PART_YearView";
|
||||||
|
|
||||||
private Grid? _monthGrid;
|
private CalendarMonthView? _monthGrid;
|
||||||
|
private DatePickerState _state = DatePickerState.None;
|
||||||
|
|
||||||
|
|
||||||
public static readonly StyledProperty<DateTime> SelectedDateProperty = AvaloniaProperty.Register<Calendar, DateTime>(nameof(SelectedDate), DateTime.Now);
|
public static readonly StyledProperty<DateTime> SelectedDateProperty = AvaloniaProperty.Register<Calendar, DateTime>(nameof(SelectedDate), DateTime.Now);
|
||||||
@@ -71,17 +72,68 @@ public class Calendar: TemplatedControl
|
|||||||
set => SetValue(BlackoutDateRuleProperty, value);
|
set => SetValue(BlackoutDateRuleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal DateTime? StartDate;
|
||||||
|
internal DateTime? EndDate;
|
||||||
|
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
_monthGrid = e.NameScope.Find<Grid>(PART_MonthView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeGrid()
|
|
||||||
{
|
|
||||||
if (_monthGrid is not null)
|
if (_monthGrid is not null)
|
||||||
{
|
{
|
||||||
|
_monthGrid.OnCalendarDayButtonPressed -= OnCalendarDayButtonPressed;
|
||||||
|
_monthGrid.OnCalendarDayButtonPointerEnter -= OnCalendarDayButtonPointerEnter;
|
||||||
|
}
|
||||||
|
_monthGrid = e.NameScope.Find<CalendarMonthView>(PART_MonthView);
|
||||||
|
if(_monthGrid is not null)
|
||||||
|
{
|
||||||
|
_monthGrid.OnCalendarDayButtonPressed += OnCalendarDayButtonPressed;
|
||||||
|
_monthGrid.OnCalendarDayButtonPointerEnter += OnCalendarDayButtonPointerEnter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private void OnCalendarDayButtonPointerEnter(object sender, CalendarDayButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if(_monthGrid is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var date = e.Date;
|
||||||
|
if (_state is DatePickerState.None) return;
|
||||||
|
if (_state == DatePickerState.PreviewStart)
|
||||||
|
{
|
||||||
|
_monthGrid.MarkPreview(date, EndDate);
|
||||||
|
}
|
||||||
|
else if (_state == DatePickerState.PreviewEnd)
|
||||||
|
{
|
||||||
|
_monthGrid.MarkPreview(StartDate, date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCalendarDayButtonPressed(object sender, CalendarDayButtonEventArgs e)
|
||||||
|
{
|
||||||
|
if(_monthGrid is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var date = e.Date;
|
||||||
|
if (_state == DatePickerState.None)
|
||||||
|
{
|
||||||
|
_monthGrid.ClearSelection();
|
||||||
|
_monthGrid.MarkSelection(date, null);
|
||||||
|
_state = DatePickerState.PreviewEnd;
|
||||||
|
StartDate = date;
|
||||||
|
}
|
||||||
|
else if (_state == DatePickerState.PreviewStart)
|
||||||
|
{
|
||||||
|
_monthGrid.MarkSelection(date, EndDate);
|
||||||
|
_state = DatePickerState.SelectStart;
|
||||||
|
StartDate = date;
|
||||||
|
}
|
||||||
|
else if (_state == DatePickerState.PreviewEnd)
|
||||||
|
{
|
||||||
|
_monthGrid.MarkSelection(StartDate, date);
|
||||||
|
_state = DatePickerState.None;
|
||||||
|
EndDate = date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,23 +4,52 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Irihi.Avalonia.Shared;
|
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Show days in a month.
|
/// Show days in a month.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[TemplatePart(PART_Grid, typeof(Grid))]
|
[TemplatePart(PART_Grid, typeof(Grid))]
|
||||||
public class CalendarMonthView: TemplatedControl
|
public class CalendarMonthView : TemplatedControl
|
||||||
{
|
{
|
||||||
public const string PART_Grid = "PART_Grid";
|
public const string PART_Grid = "PART_Grid";
|
||||||
internal Calendar? Owner { get; set; }
|
|
||||||
|
public static readonly StyledProperty<DayOfWeek> FirstDayOfWeekProperty =
|
||||||
private Grid? _grid;
|
AvaloniaProperty.Register<CalendarMonthView, DayOfWeek>(
|
||||||
|
nameof(FirstDayOfWeek));
|
||||||
|
|
||||||
private readonly System.Globalization.Calendar _calendar = new GregorianCalendar();
|
private readonly System.Globalization.Calendar _calendar = new GregorianCalendar();
|
||||||
|
|
||||||
|
private DateTime _contextDate = DateTime.Today;
|
||||||
|
|
||||||
|
private Grid? _grid;
|
||||||
|
|
||||||
|
static CalendarMonthView()
|
||||||
|
{
|
||||||
|
FirstDayOfWeekProperty.Changed.AddClassHandler<CalendarMonthView, DayOfWeek>((view, args) =>
|
||||||
|
view.OnDayOfWeekChanged(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Calendar? Owner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The DateTime used to generate the month view. This date will be within the month.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime ContextDate
|
||||||
|
{
|
||||||
|
get => _contextDate;
|
||||||
|
set => _contextDate = value;
|
||||||
|
// GenerateGridElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DayOfWeek FirstDayOfWeek
|
||||||
|
{
|
||||||
|
get => GetValue(FirstDayOfWeekProperty);
|
||||||
|
set => SetValue(FirstDayOfWeekProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
@@ -29,80 +58,50 @@ public class CalendarMonthView: TemplatedControl
|
|||||||
SetDayButtons(DateTime.Today);
|
SetDayButtons(DateTime.Today);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime _contextDate = DateTime.Today;
|
|
||||||
/// <summary>
|
|
||||||
/// The DateTime used to generate the month view. This date will be within the month.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime ContextDate
|
|
||||||
{
|
|
||||||
get => _contextDate;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_contextDate = value;
|
|
||||||
// GenerateGridElements();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<DayOfWeek> FirstDayOfWeekProperty = AvaloniaProperty.Register<CalendarMonthView, DayOfWeek>(
|
|
||||||
nameof(FirstDayOfWeek));
|
|
||||||
|
|
||||||
public DayOfWeek FirstDayOfWeek
|
|
||||||
{
|
|
||||||
get => GetValue(FirstDayOfWeekProperty);
|
|
||||||
set => SetValue(FirstDayOfWeekProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CalendarMonthView()
|
|
||||||
{
|
|
||||||
FirstDayOfWeekProperty.Changed.AddClassHandler<CalendarMonthView, DayOfWeek>((view, args) => view.OnDayOfWeekChanged(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDayOfWeekChanged(AvaloniaPropertyChangedEventArgs<DayOfWeek> args)
|
private void OnDayOfWeekChanged(AvaloniaPropertyChangedEventArgs<DayOfWeek> args)
|
||||||
{
|
{
|
||||||
// throw new NotImplementedException();
|
// throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void GenerateGridElements()
|
private void GenerateGridElements()
|
||||||
{
|
{
|
||||||
// Generate Day titles (Sun, Mon, Tue, Wed, Thu, Fri, Sat) based on FirstDayOfWeek and culture.
|
// Generate Day titles (Sun, Mon, Tue, Wed, Thu, Fri, Sat) based on FirstDayOfWeek and culture.
|
||||||
int count = 7 + 7 * 7;
|
var count = 7 + 7 * 7;
|
||||||
var children = new List<Control>(count);
|
var children = new List<Control>(count);
|
||||||
int dayOfWeek = (int)FirstDayOfWeek;
|
var dayOfWeek = (int)FirstDayOfWeek;
|
||||||
var info = DateTimeHelper.GetCurrentDateTimeFormatInfo();
|
var info = DateTimeHelper.GetCurrentDateTimeFormatInfo();
|
||||||
for (int i = 0; i < 7; i++)
|
for (var i = 0; i < 7; i++)
|
||||||
{
|
{
|
||||||
int d = ((dayOfWeek + i) % DateTimeHelper.NumberOfDaysPerWeek);
|
var d = (dayOfWeek + i) % DateTimeHelper.NumberOfDaysPerWeek;
|
||||||
var cell = new TextBlock(){ Text = info.ShortestDayNames[d] };
|
var cell = new TextBlock { Text = info.ShortestDayNames[d] };
|
||||||
cell.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
|
cell.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
|
||||||
cell.SetValue(Grid.RowProperty, 0);
|
cell.SetValue(Grid.RowProperty, 0);
|
||||||
cell.SetValue(Grid.ColumnProperty, i);
|
cell.SetValue(Grid.ColumnProperty, i);
|
||||||
children.Add(cell);
|
children.Add(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate day buttons.
|
// Generate day buttons.
|
||||||
for (int i = 2; i < DateTimeHelper.NumberOfWeeksPerMonth+2; i++)
|
for (var i = 2; i < DateTimeHelper.NumberOfWeeksPerMonth + 2; i++)
|
||||||
|
for (var j = 0; j < DateTimeHelper.NumberOfDaysPerWeek; j++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < DateTimeHelper.NumberOfDaysPerWeek; j++)
|
var cell = new CalendarDayButton();
|
||||||
{
|
cell.SetValue(Grid.RowProperty, i);
|
||||||
var cell = new CalendarDayButton();
|
cell.SetValue(Grid.ColumnProperty, j);
|
||||||
cell.SetValue(Grid.RowProperty, i);
|
cell.PointerPressed += OnDayButtonPressed;
|
||||||
cell.SetValue(Grid.ColumnProperty, j);
|
cell.PointerEntered += OnDayButtonPointerEnter;
|
||||||
cell.PointerPressed += OnDayButtonPressed;
|
children.Add(cell);
|
||||||
cell.PointerEntered += OnDayButtonPointerEnter;
|
|
||||||
children.Add(cell);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_grid?.Children.AddRange(children);
|
_grid?.Children.AddRange(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDayButtons(DateTime date)
|
private void SetDayButtons(DateTime date)
|
||||||
{
|
{
|
||||||
if (_grid is null) return;
|
if (_grid is null) return;
|
||||||
var children = _grid.Children;
|
var children = _grid.Children;
|
||||||
var info = DateTimeHelper.GetCurrentDateTimeFormatInfo();
|
var info = DateTimeHelper.GetCurrentDateTimeFormatInfo();
|
||||||
int dayBefore = PreviousMonthDays(date);
|
var dayBefore = PreviousMonthDays(date);
|
||||||
var dateToSet = date.GetFirstDayOfMonth().AddDays(-dayBefore);
|
var dateToSet = date.GetFirstDayOfMonth().AddDays(-dayBefore);
|
||||||
for (var i = 8; i < children.Count; i++)
|
for (var i = 8; i < children.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -114,75 +113,149 @@ public class CalendarMonthView: TemplatedControl
|
|||||||
cell.Content = day.Day.ToString(info);
|
cell.Content = day.Day.ToString(info);
|
||||||
dateToSet = dateToSet.AddDays(1);
|
dateToSet = dateToSet.AddDays(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FadeOutDayButtons();
|
FadeOutDayButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDayButtonPressed(object sender, PointerPressedEventArgs e)
|
private void OnDayButtonPressed(object sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is CalendarDayButton { DataContext: DateTime d })
|
if (sender is CalendarDayButton { DataContext: DateTime d })
|
||||||
{
|
|
||||||
OnCalendarDayButtonPressed?.Invoke(this, new CalendarDayButtonEventArgs(d));
|
OnCalendarDayButtonPressed?.Invoke(this, new CalendarDayButtonEventArgs(d));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDayButtonPointerEnter(object sender, PointerEventArgs e)
|
private void OnDayButtonPointerEnter(object sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
if(sender is CalendarDayButton {DataContext: DateTime d})
|
if (sender is CalendarDayButton { DataContext: DateTime d })
|
||||||
{
|
|
||||||
OnCalendarDayButtonPointerEnter?.Invoke(this, new CalendarDayButtonEventArgs(d));
|
OnCalendarDayButtonPointerEnter?.Invoke(this, new CalendarDayButtonEventArgs(d));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int PreviousMonthDays(DateTime date)
|
private int PreviousMonthDays(DateTime date)
|
||||||
{
|
{
|
||||||
var firstDay = date.GetFirstDayOfMonth();
|
var firstDay = date.GetFirstDayOfMonth();
|
||||||
var dayOfWeek = _calendar.GetDayOfWeek(firstDay);
|
var dayOfWeek = _calendar.GetDayOfWeek(firstDay);
|
||||||
var firstDayOfWeek = this.FirstDayOfWeek;
|
var firstDayOfWeek = FirstDayOfWeek;
|
||||||
int i = (dayOfWeek - firstDayOfWeek + DateTimeHelper.NumberOfDaysPerWeek) % DateTimeHelper.NumberOfDaysPerWeek;
|
var i = (dayOfWeek - firstDayOfWeek + DateTimeHelper.NumberOfDaysPerWeek) % DateTimeHelper.NumberOfDaysPerWeek;
|
||||||
return i == 0 ? DateTimeHelper.NumberOfDaysPerWeek : i;
|
return i == 0 ? DateTimeHelper.NumberOfDaysPerWeek : i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Make days out of current month fade out. These buttons are not disabled. They are just visually faded out.
|
/// Make days out of current month fade out. These buttons are not disabled. They are just visually faded out.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void FadeOutDayButtons()
|
private void FadeOutDayButtons()
|
||||||
{
|
{
|
||||||
if (_grid is null) return;
|
if (_grid is null) return;
|
||||||
var children = _grid.Children;
|
var children = _grid.Children;
|
||||||
for (var i = 8; i < children.Count; i++)
|
for (var i = 8; 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 != _contextDate.Month)
|
||||||
{
|
|
||||||
button.IsNotCurrentMonth = true;
|
button.IsNotCurrentMonth = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public event EventHandler<CalendarDayButtonEventArgs>? OnCalendarDayButtonPressed;
|
public event EventHandler<CalendarDayButtonEventArgs>? OnCalendarDayButtonPressed;
|
||||||
public event EventHandler<CalendarDayButtonEventArgs>? OnCalendarDayButtonPointerEnter;
|
public event EventHandler<CalendarDayButtonEventArgs>? OnCalendarDayButtonPointerEnter;
|
||||||
|
|
||||||
public void MarkSelection(DateTime start, DateTime end)
|
public void MarkSelection(DateTime? start, DateTime? end)
|
||||||
{
|
{
|
||||||
if(_grid?.Children is null) return;
|
if (_grid?.Children is null) return;
|
||||||
foreach (var child in _grid.Children)
|
foreach (var child in _grid.Children)
|
||||||
{
|
|
||||||
if (child is CalendarDayButton { DataContext: DateTime d } button)
|
if (child is CalendarDayButton { DataContext: DateTime d } button)
|
||||||
{
|
{
|
||||||
|
if (d.Month != _contextDate.Month) continue;
|
||||||
if (d == start)
|
if (d == start)
|
||||||
{
|
{
|
||||||
button.IsStartDate = true;
|
button.IsStartDate = true;
|
||||||
|
button.IsEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
}
|
}
|
||||||
else if (d == end)
|
else if (d == end)
|
||||||
{
|
{
|
||||||
button.IsEndDate = true;
|
button.IsEndDate = true;
|
||||||
|
button.IsStartDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
}
|
}
|
||||||
else if (d > start && d < end)
|
else if (d > start && d < end)
|
||||||
{
|
{
|
||||||
button.IsInRange = true;
|
button.IsInRange = true;
|
||||||
|
button.IsStartDate = false;
|
||||||
|
button.IsEndDate = false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button.IsStartDate = false;
|
||||||
|
button.IsEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkPreview(DateTime? start, DateTime? end)
|
||||||
|
{
|
||||||
|
if (_grid?.Children is null) return;
|
||||||
|
foreach (var child in _grid.Children)
|
||||||
|
{
|
||||||
|
if (child is not CalendarDayButton { DataContext: DateTime d } button) continue;
|
||||||
|
if (d == start)
|
||||||
|
{
|
||||||
|
button.IsPreviewStartDate = true;
|
||||||
|
button.IsPreviewEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
|
}
|
||||||
|
else if (d == end)
|
||||||
|
{
|
||||||
|
button.IsPreviewEndDate = true;
|
||||||
|
button.IsPreviewStartDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
|
}
|
||||||
|
else if (d > start && d < end)
|
||||||
|
{
|
||||||
|
button.IsInRange = true;
|
||||||
|
button.IsPreviewStartDate = false;
|
||||||
|
button.IsPreviewEndDate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button.IsPreviewStartDate = false;
|
||||||
|
button.IsPreviewEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearSelection()
|
||||||
|
{
|
||||||
|
if (_grid?.Children is null) return;
|
||||||
|
foreach (var child in _grid.Children)
|
||||||
|
{
|
||||||
|
if (child is not CalendarDayButton button) continue;
|
||||||
|
button.IsStartDate = false;
|
||||||
|
button.IsEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearPreview()
|
||||||
|
{
|
||||||
|
if (_grid?.Children is null) return;
|
||||||
|
foreach (var child in _grid.Children)
|
||||||
|
{
|
||||||
|
if (child is not CalendarDayButton button) continue;
|
||||||
|
button.IsPreviewStartDate = false;
|
||||||
|
button.IsPreviewEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MarkSelection(DateTime date)
|
||||||
|
{
|
||||||
|
if (_grid?.Children is null) return;
|
||||||
|
foreach (var child in _grid.Children)
|
||||||
|
{
|
||||||
|
if (child is not CalendarDayButton { DataContext: DateTime d } button) continue;
|
||||||
|
button.IsStartDate = false;
|
||||||
|
button.IsEndDate = false;
|
||||||
|
button.IsInRange = false;
|
||||||
|
if (d.Month != _contextDate.Month) continue;
|
||||||
|
button.IsSelected = d == date;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
8
src/Ursa/Controls/DateTimePicker/DatePicker.cs
Normal file
8
src/Ursa/Controls/DateTimePicker/DatePicker.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
|
||||||
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
public class DatePicker: TemplatedControl
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
11
src/Ursa/Controls/DateTimePicker/DatePickerState.cs
Normal file
11
src/Ursa/Controls/DateTimePicker/DatePickerState.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
|
public enum DatePickerState
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
SelectSingle,
|
||||||
|
SelectStart,
|
||||||
|
SelectEnd,
|
||||||
|
PreviewStart,
|
||||||
|
PreviewEnd,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user