|
|
|
@ -1,12 +1,16 @@ |
|
|
|
using Xunit; |
|
|
|
using System; |
|
|
|
using System.Collections; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using Avalonia.Controls.Primitives; |
|
|
|
using Avalonia.Input; |
|
|
|
using Avalonia.UnitTests; |
|
|
|
|
|
|
|
#nullable enable |
|
|
|
|
|
|
|
namespace Avalonia.Controls.UnitTests |
|
|
|
{ |
|
|
|
public class CalendarTests |
|
|
|
public class CalendarTests : ScopedTestBase |
|
|
|
{ |
|
|
|
private static bool CompareDates(DateTime first, DateTime second) |
|
|
|
{ |
|
|
|
@ -142,12 +146,12 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
/// <summary>
|
|
|
|
/// The days added to the SelectedDates collection.
|
|
|
|
/// </summary>
|
|
|
|
private IList<object> _selectedDatesChangedAddedDays; |
|
|
|
private IList<object>? _selectedDatesChangedAddedDays; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The days removed from the SelectedDates collection.
|
|
|
|
/// </summary>
|
|
|
|
private IList<object> _selectedDateChangedRemovedDays; |
|
|
|
private IList<object>? _selectedDatesChangedRemovedDays; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The number of times the SelectedDatesChanged event has been fired.
|
|
|
|
@ -159,13 +163,13 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
/// </summary>
|
|
|
|
/// <param name="sender">The calendar.</param>
|
|
|
|
/// <param name="e">Event arguments.</param>
|
|
|
|
private void OnSelectedDatesChanged(object sender, SelectionChangedEventArgs e) |
|
|
|
private void OnSelectedDatesChanged(object? sender, SelectionChangedEventArgs e) |
|
|
|
{ |
|
|
|
_selectedDatesChangedAddedDays = |
|
|
|
e.AddedItems |
|
|
|
.Cast<object>() |
|
|
|
.ToList(); |
|
|
|
_selectedDateChangedRemovedDays = |
|
|
|
_selectedDatesChangedRemovedDays = |
|
|
|
e.RemovedItems |
|
|
|
.Cast<object>() |
|
|
|
.ToList(); |
|
|
|
@ -182,9 +186,9 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
_selectedDatesChangedAddedDays.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
if (_selectedDateChangedRemovedDays != null) |
|
|
|
if (_selectedDatesChangedRemovedDays != null) |
|
|
|
{ |
|
|
|
_selectedDateChangedRemovedDays.Clear(); |
|
|
|
_selectedDatesChangedRemovedDays.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
_selectedDatesChangedCount = 0; |
|
|
|
@ -202,8 +206,10 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Assert.True(calendar.SelectedDates.Count == 1); |
|
|
|
Assert.True(CompareDates(calendar.SelectedDates[0], DateTime.Today)); |
|
|
|
Assert.True(_selectedDatesChangedCount == 1); |
|
|
|
Assert.NotNull(_selectedDatesChangedAddedDays); |
|
|
|
Assert.True(_selectedDatesChangedAddedDays.Count == 1); |
|
|
|
Assert.True(_selectedDateChangedRemovedDays.Count == 0); |
|
|
|
Assert.NotNull(_selectedDatesChangedRemovedDays); |
|
|
|
Assert.True(_selectedDatesChangedRemovedDays.Count == 0); |
|
|
|
ResetSelectedDatesChanged(); |
|
|
|
|
|
|
|
calendar.SelectedDate = DateTime.Today; |
|
|
|
@ -240,8 +246,10 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Assert.True(calendar.SelectedDates.Count == 1); |
|
|
|
Assert.True(CompareDates(calendar.SelectedDates[0], DateTime.Today)); |
|
|
|
Assert.True(_selectedDatesChangedCount == 1); |
|
|
|
Assert.NotNull(_selectedDatesChangedAddedDays); |
|
|
|
Assert.True(_selectedDatesChangedAddedDays.Count == 1); |
|
|
|
Assert.True(_selectedDateChangedRemovedDays.Count == 0); |
|
|
|
Assert.NotNull(_selectedDatesChangedRemovedDays); |
|
|
|
Assert.True(_selectedDatesChangedRemovedDays.Count == 0); |
|
|
|
ResetSelectedDatesChanged(); |
|
|
|
|
|
|
|
calendar.SelectedDates.Clear(); |
|
|
|
@ -263,7 +271,7 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Assert.True(calendar.SelectedDates.Count == 21); |
|
|
|
Assert.True(_selectedDatesChangedCount == 1); |
|
|
|
Assert.True(_selectedDatesChangedAddedDays.Count == 21); |
|
|
|
Assert.True(_selectedDateChangedRemovedDays.Count == 11); |
|
|
|
Assert.True(_selectedDatesChangedRemovedDays.Count == 11); |
|
|
|
ResetSelectedDatesChanged(); |
|
|
|
|
|
|
|
calendar.SelectedDates.Add(DateTime.Today.AddDays(100)); |
|
|
|
@ -362,5 +370,77 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Assert.True(calendar.SelectedDates.Contains(earlierDate)); |
|
|
|
Assert.True(calendar.SelectedDates.Contains(laterDate)); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void CalendarItem_Should_Reset_Mouse_Down_Flag_On_Detach_From_Visual_Tree() |
|
|
|
{ |
|
|
|
var calendar = new Calendar(); |
|
|
|
calendar.SelectionMode = CalendarSelectionMode.SingleDate; |
|
|
|
|
|
|
|
var calendarItem = new CalendarItem(); |
|
|
|
calendarItem.Owner = calendar; |
|
|
|
|
|
|
|
// Attach CalendarItem to a visual tree
|
|
|
|
var root = new TestRoot(calendarItem); |
|
|
|
|
|
|
|
// Create a day button and simulate mouse left button down,
|
|
|
|
// which sets the internal _isMouseLeftButtonDown flag to true.
|
|
|
|
var date1 = new DateTime(2024, 1, 15); |
|
|
|
var dayButton1 = new CalendarDayButton { DataContext = date1 }; |
|
|
|
|
|
|
|
var pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); |
|
|
|
var props = new PointerPointProperties(RawInputModifiers.LeftMouseButton, |
|
|
|
PointerUpdateKind.LeftButtonPressed); |
|
|
|
var pressArgs = new PointerPressedEventArgs(dayButton1, pointer, root, |
|
|
|
default, 0, props, KeyModifiers.None); |
|
|
|
|
|
|
|
calendarItem.Cell_MouseLeftButtonDown(dayButton1, pressArgs); |
|
|
|
|
|
|
|
// date1 should now be selected
|
|
|
|
Assert.Equal(1, calendar.SelectedDates.Count); |
|
|
|
Assert.Equal(date1, calendar.SelectedDates[0]); |
|
|
|
|
|
|
|
// Detach CalendarItem from visual tree (simulates popup closing
|
|
|
|
// during date selection without a PointerReleased event).
|
|
|
|
root.Child = null; |
|
|
|
|
|
|
|
// Create a different day button and simulate mouse enter.
|
|
|
|
// Before the fix, _isMouseLeftButtonDown would still be true,
|
|
|
|
// causing hover to auto-select dates.
|
|
|
|
var date2 = new DateTime(2024, 1, 20); |
|
|
|
var dayButton2 = new CalendarDayButton { DataContext = date2 }; |
|
|
|
|
|
|
|
calendarItem.Cell_MouseEntered(dayButton2, null!); |
|
|
|
|
|
|
|
// The selected date should NOT have changed to date2,
|
|
|
|
// because the mouse-down flag was reset when detaching.
|
|
|
|
Assert.Equal(1, calendar.SelectedDates.Count); |
|
|
|
Assert.Equal(date1, calendar.SelectedDates[0]); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void CalendarItem_Should_Reset_YearView_Mouse_Down_Flag_On_Detach_From_Visual_Tree() |
|
|
|
{ |
|
|
|
var calendar = new Calendar(); |
|
|
|
var calendarItem = new CalendarItem(); |
|
|
|
calendarItem.Owner = calendar; |
|
|
|
|
|
|
|
// Attach CalendarItem to a visual tree
|
|
|
|
var root = new TestRoot(calendarItem); |
|
|
|
|
|
|
|
// Use reflection to set the _isMouseLeftButtonDownYearView flag,
|
|
|
|
// since Month_CalendarButtonMouseDown is private.
|
|
|
|
var field = typeof(CalendarItem).GetField("_isMouseLeftButtonDownYearView", |
|
|
|
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); |
|
|
|
Assert.NotNull(field); |
|
|
|
field!.SetValue(calendarItem, true); |
|
|
|
Assert.True((bool)field.GetValue(calendarItem)!); |
|
|
|
|
|
|
|
// Detach CalendarItem from visual tree
|
|
|
|
root.Child = null; |
|
|
|
|
|
|
|
// Verify the flag was reset
|
|
|
|
Assert.False((bool)field.GetValue(calendarItem)!); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|