99 changed files with 2255 additions and 376 deletions
@ -1,13 +1,9 @@ |
|||||
using System.Reflection; |
|
||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
using Avalonia.Metadata; |
using Avalonia.Metadata; |
||||
#if SIGNED_BUILD
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
#else
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Controls.DataGrid.UnitTests")] |
|
||||
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport")] |
|
||||
#endif
|
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Collections")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Collections")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")] |
||||
|
|||||
@ -1,9 +1,7 @@ |
|||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
using Avalonia.Metadata; |
using Avalonia.Metadata; |
||||
#if SIGNED_BUILD
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Layout.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Layout.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
#else
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Layout.UnitTests")] |
|
||||
#endif
|
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Layout")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Layout")] |
||||
|
|
||||
|
|||||
@ -0,0 +1,26 @@ |
|||||
|
#nullable enable |
||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.LogicalTree |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Event args for <see cref="IChildIndexProvider.ChildIndexChanged"/> event.
|
||||
|
/// </summary>
|
||||
|
public class ChildIndexChangedEventArgs : EventArgs |
||||
|
{ |
||||
|
public ChildIndexChangedEventArgs() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public ChildIndexChangedEventArgs(ILogical child) |
||||
|
{ |
||||
|
Child = child; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Logical child which index was changed.
|
||||
|
/// If null, all children should be reset.
|
||||
|
/// </summary>
|
||||
|
public ILogical? Child { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
#nullable enable |
||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.LogicalTree |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Child's index and total count information provider used by list-controls (ListBox, StackPanel, etc.)
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// Used by nth-child and nth-last-child selectors.
|
||||
|
/// </remarks>
|
||||
|
public interface IChildIndexProvider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets child's actual index in order of the original source.
|
||||
|
/// </summary>
|
||||
|
/// <param name="child">Logical child.</param>
|
||||
|
/// <returns>Index or -1 if child was not found.</returns>
|
||||
|
int GetChildIndex(ILogical child); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Total children count or null if source is infinite.
|
||||
|
/// Some Avalonia features might not work if <see cref="TryGetTotalCount"/> returns false, for instance: nth-last-child selector.
|
||||
|
/// </summary>
|
||||
|
bool TryGetTotalCount(out int count); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Notifies subscriber when child's index or total count was changed.
|
||||
|
/// </summary>
|
||||
|
event EventHandler<ChildIndexChangedEventArgs>? ChildIndexChanged; |
||||
|
} |
||||
|
} |
||||
@ -1,12 +1,9 @@ |
|||||
using System.Reflection; |
|
||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
using Avalonia.Metadata; |
using Avalonia.Metadata; |
||||
|
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.LogicalTree")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.LogicalTree")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Styling")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Styling")] |
||||
#if SIGNED_BUILD
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
#else
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Styling.UnitTests")] |
|
||||
#endif
|
|
||||
|
|||||
@ -0,0 +1,56 @@ |
|||||
|
#nullable enable |
||||
|
using Avalonia.LogicalTree; |
||||
|
|
||||
|
namespace Avalonia.Styling.Activators |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// An <see cref="IStyleActivator"/> which is active when control's index was changed.
|
||||
|
/// </summary>
|
||||
|
internal sealed class NthChildActivator : StyleActivatorBase |
||||
|
{ |
||||
|
private readonly ILogical _control; |
||||
|
private readonly IChildIndexProvider _provider; |
||||
|
private readonly int _step; |
||||
|
private readonly int _offset; |
||||
|
private readonly bool _reversed; |
||||
|
|
||||
|
public NthChildActivator( |
||||
|
ILogical control, |
||||
|
IChildIndexProvider provider, |
||||
|
int step, int offset, bool reversed) |
||||
|
{ |
||||
|
_control = control; |
||||
|
_provider = provider; |
||||
|
_step = step; |
||||
|
_offset = offset; |
||||
|
_reversed = reversed; |
||||
|
} |
||||
|
|
||||
|
protected override void Initialize() |
||||
|
{ |
||||
|
PublishNext(IsMatching()); |
||||
|
_provider.ChildIndexChanged += ChildIndexChanged; |
||||
|
} |
||||
|
|
||||
|
protected override void Deinitialize() |
||||
|
{ |
||||
|
_provider.ChildIndexChanged -= ChildIndexChanged; |
||||
|
} |
||||
|
|
||||
|
private void ChildIndexChanged(object sender, ChildIndexChangedEventArgs e) |
||||
|
{ |
||||
|
// Run matching again if:
|
||||
|
// 1. Selector is reversed, so other item insertion/deletion might affect total count without changing subscribed item index.
|
||||
|
// 2. e.Child is null, when all children indeces were changed.
|
||||
|
// 3. Subscribed child index was changed.
|
||||
|
if (_reversed |
||||
|
|| e.Child is null |
||||
|
|| e.Child == _control) |
||||
|
{ |
||||
|
PublishNext(IsMatching()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private bool IsMatching() => NthChildSelector.Evaluate(_control, _provider, _step, _offset, _reversed).IsMatch; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,145 @@ |
|||||
|
#nullable enable |
||||
|
using System; |
||||
|
using System.Text; |
||||
|
using Avalonia.LogicalTree; |
||||
|
using Avalonia.Styling.Activators; |
||||
|
|
||||
|
namespace Avalonia.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The :nth-child() pseudo-class matches elements based on their position in a group of siblings.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// Element indices are 1-based.
|
||||
|
/// </remarks>
|
||||
|
public class NthChildSelector : Selector |
||||
|
{ |
||||
|
private const string NthChildSelectorName = "nth-child"; |
||||
|
private const string NthLastChildSelectorName = "nth-last-child"; |
||||
|
private readonly Selector? _previous; |
||||
|
private readonly bool _reversed; |
||||
|
|
||||
|
internal protected NthChildSelector(Selector? previous, int step, int offset, bool reversed) |
||||
|
{ |
||||
|
_previous = previous; |
||||
|
Step = step; |
||||
|
Offset = offset; |
||||
|
_reversed = reversed; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates an instance of <see cref="NthChildSelector"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="previous">Previous selector.</param>
|
||||
|
/// <param name="step">Position step.</param>
|
||||
|
/// <param name="offset">Initial index offset.</param>
|
||||
|
public NthChildSelector(Selector? previous, int step, int offset) |
||||
|
: this(previous, step, offset, false) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public override bool InTemplate => _previous?.InTemplate ?? false; |
||||
|
|
||||
|
public override bool IsCombinator => false; |
||||
|
|
||||
|
public override Type? TargetType => _previous?.TargetType; |
||||
|
|
||||
|
public int Step { get; } |
||||
|
public int Offset { get; } |
||||
|
|
||||
|
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
||||
|
{ |
||||
|
if (!(control is ILogical logical)) |
||||
|
{ |
||||
|
return SelectorMatch.NeverThisType; |
||||
|
} |
||||
|
|
||||
|
var controlParent = logical.LogicalParent; |
||||
|
|
||||
|
if (controlParent is IChildIndexProvider childIndexProvider) |
||||
|
{ |
||||
|
return subscribe |
||||
|
? new SelectorMatch(new NthChildActivator(logical, childIndexProvider, Step, Offset, _reversed)) |
||||
|
: Evaluate(logical, childIndexProvider, Step, Offset, _reversed); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return SelectorMatch.NeverThisInstance; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
internal static SelectorMatch Evaluate( |
||||
|
ILogical logical, IChildIndexProvider childIndexProvider, |
||||
|
int step, int offset, bool reversed) |
||||
|
{ |
||||
|
var index = childIndexProvider.GetChildIndex(logical); |
||||
|
if (index < 0) |
||||
|
{ |
||||
|
return SelectorMatch.NeverThisInstance; |
||||
|
} |
||||
|
|
||||
|
if (reversed) |
||||
|
{ |
||||
|
if (childIndexProvider.TryGetTotalCount(out var totalCountValue)) |
||||
|
{ |
||||
|
index = totalCountValue - index; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return SelectorMatch.NeverThisInstance; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// nth child index is 1-based
|
||||
|
index += 1; |
||||
|
} |
||||
|
|
||||
|
var n = Math.Sign(step); |
||||
|
|
||||
|
var diff = index - offset; |
||||
|
var match = diff == 0 || (Math.Sign(diff) == n && diff % step == 0); |
||||
|
|
||||
|
return match ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance; |
||||
|
} |
||||
|
|
||||
|
protected override Selector? MovePrevious() => _previous; |
||||
|
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
var expectedCapacity = NthLastChildSelectorName.Length + 8; |
||||
|
var stringBuilder = new StringBuilder(_previous?.ToString(), expectedCapacity); |
||||
|
|
||||
|
stringBuilder.Append(':'); |
||||
|
stringBuilder.Append(_reversed ? NthLastChildSelectorName : NthChildSelectorName); |
||||
|
stringBuilder.Append('('); |
||||
|
|
||||
|
var hasStep = false; |
||||
|
if (Step != 0) |
||||
|
{ |
||||
|
hasStep = true; |
||||
|
stringBuilder.Append(Step); |
||||
|
stringBuilder.Append('n'); |
||||
|
} |
||||
|
|
||||
|
if (Offset > 0) |
||||
|
{ |
||||
|
if (hasStep) |
||||
|
{ |
||||
|
stringBuilder.Append('+'); |
||||
|
} |
||||
|
stringBuilder.Append(Offset); |
||||
|
} |
||||
|
else if (Offset < 0) |
||||
|
{ |
||||
|
stringBuilder.Append('-'); |
||||
|
stringBuilder.Append(-Offset); |
||||
|
} |
||||
|
|
||||
|
stringBuilder.Append(')'); |
||||
|
|
||||
|
return stringBuilder.ToString(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The :nth-child() pseudo-class matches elements based on their position among a group of siblings, counting from the end.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// Element indices are 1-based.
|
||||
|
/// </remarks>
|
||||
|
public class NthLastChildSelector : NthChildSelector |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Creates an instance of <see cref="NthLastChildSelector"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="previous">Previous selector.</param>
|
||||
|
/// <param name="step">Position step.</param>
|
||||
|
/// <param name="offset">Initial index offset, counting from the end.</param>
|
||||
|
public NthLastChildSelector(Selector? previous, int step, int offset) : base(previous, step, offset, true) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,23 +1,21 @@ |
|||||
<Style xmlns="https://github.com/avaloniaui" |
<Style xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
Selector="OverlayPopupHost"> |
Selector="OverlayPopupHost"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/> |
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" /> |
||||
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}"/> |
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}" /> |
||||
<Setter Property="FontFamily" Value="{x:Static FontFamily.Default}" /> |
<Setter Property="FontFamily" Value="{x:Static FontFamily.Default}" /> |
||||
<Setter Property="FontWeight" Value="400" /> |
<Setter Property="FontWeight" Value="400" /> |
||||
<Setter Property="FontStyle" Value="Normal" /> |
<Setter Property="FontStyle" Value="Normal" /> |
||||
<Setter Property="Template"> |
<Setter Property="Template"> |
||||
<ControlTemplate> |
<ControlTemplate> |
||||
<Panel> |
<!-- Do not forget to update Templated_Control_With_Popup_In_Template_Should_Set_TemplatedParent test --> |
||||
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" /> |
<VisualLayerManager IsPopup="True"> |
||||
<VisualLayerManager IsPopup="True"> |
<ContentPresenter Name="PART_ContentPresenter" |
||||
<ContentPresenter Name="PART_ContentPresenter" |
Background="{TemplateBinding Background}" |
||||
Background="{TemplateBinding Background}" |
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
ContentTemplate="{TemplateBinding ContentTemplate}" |
Content="{TemplateBinding Content}" |
||||
Content="{TemplateBinding Content}" |
Padding="{TemplateBinding Padding}"/> |
||||
Padding="{TemplateBinding Padding}"/> |
</VisualLayerManager> |
||||
</VisualLayerManager> |
|
||||
</Panel> |
|
||||
</ControlTemplate> |
</ControlTemplate> |
||||
</Setter> |
</Setter> |
||||
</Style> |
</Style> |
||||
|
|||||
@ -0,0 +1,47 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Controls.Platform; |
||||
|
using Avalonia.Logging; |
||||
|
using Avalonia.Platform; |
||||
|
|
||||
|
namespace Avalonia.X11 |
||||
|
{ |
||||
|
internal class XEmbedTrayIconImpl : ITrayIconImpl |
||||
|
{ |
||||
|
|
||||
|
private bool _isCalled; |
||||
|
|
||||
|
private void NotImplemented() |
||||
|
{ |
||||
|
if(_isCalled) return; |
||||
|
|
||||
|
Logger.TryGet(LogEventLevel.Error, LogArea.X11Platform) |
||||
|
?.Log(this, |
||||
|
"TODO: XEmbed System Tray Icons is not implemented yet. Tray icons won't be available on this system."); |
||||
|
|
||||
|
_isCalled = true; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
NotImplemented(); |
||||
|
} |
||||
|
|
||||
|
public void SetIcon(IWindowIconImpl icon) |
||||
|
{ |
||||
|
NotImplemented(); |
||||
|
} |
||||
|
|
||||
|
public void SetToolTipText(string text) |
||||
|
{ |
||||
|
NotImplemented(); |
||||
|
} |
||||
|
|
||||
|
public void SetIsVisible(bool visible) |
||||
|
{ |
||||
|
NotImplemented(); |
||||
|
} |
||||
|
|
||||
|
public INativeMenuExporter MenuExporter { get; } |
||||
|
public Action OnClicked { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -1,12 +1,9 @@ |
|||||
using System.Reflection; |
|
||||
using Avalonia.Metadata; |
using Avalonia.Metadata; |
||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
|
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.MarkupExtensions")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.MarkupExtensions")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Styling")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Styling")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Templates")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Templates")] |
||||
#if SIGNED_BUILD
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
#else
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Markup.Xaml.UnitTests")] |
|
||||
#endif
|
|
||||
|
|||||
@ -1,11 +1,8 @@ |
|||||
using System.Reflection; |
|
||||
using Avalonia.Metadata; |
using Avalonia.Metadata; |
||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
|
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data")] |
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Data")] |
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Data")] |
||||
#if SIGNED_BUILD
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Markup.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Markup.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
#else
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Markup.UnitTests")] |
|
||||
#endif
|
|
||||
|
|||||
@ -1,8 +1,5 @@ |
|||||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||||
#if SIGNED_BUILD
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
||||
#else
|
|
||||
[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests")] |
|
||||
[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests")] |
|
||||
#endif
|
|
||||
|
|||||
@ -0,0 +1,291 @@ |
|||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Avalonia.Controls; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Styling.UnitTests |
||||
|
{ |
||||
|
public class SelectorTests_NthChild |
||||
|
{ |
||||
|
[Theory] |
||||
|
[InlineData(2, 0, ":nth-child(2n)")] |
||||
|
[InlineData(2, 1, ":nth-child(2n+1)")] |
||||
|
[InlineData(1, 0, ":nth-child(1n)")] |
||||
|
[InlineData(4, -1, ":nth-child(4n-1)")] |
||||
|
[InlineData(0, 1, ":nth-child(1)")] |
||||
|
[InlineData(0, -1, ":nth-child(-1)")] |
||||
|
[InlineData(int.MaxValue, int.MinValue + 1, ":nth-child(2147483647n-2147483647)")] |
||||
|
public void Not_Selector_Should_Have_Correct_String_Representation(int step, int offset, string expected) |
||||
|
{ |
||||
|
var target = default(Selector).NthChild(step, offset); |
||||
|
|
||||
|
Assert.Equal(expected, target.ToString()); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(2, 0); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(2, 1); |
||||
|
|
||||
|
Assert.True(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Negative_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(4, -1); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Singular_Step() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(1, 2); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Singular_Step_With_Negative_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(1, -1); |
||||
|
|
||||
|
Assert.True(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Zero_Step_With_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(0, 2); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Doesnt_Match_Control_In_Panel_With_Zero_Step_With_Negative_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthChild(0, -2); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Previous_Selector() |
||||
|
{ |
||||
|
Border b1, b2; |
||||
|
Button b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new Control[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Button(), |
||||
|
b4 = new Button() |
||||
|
}); |
||||
|
|
||||
|
var previous = default(Selector).OfType<Border>(); |
||||
|
var target = previous.NthChild(2, 0); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.Null(target.Match(b3).Activator); |
||||
|
Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(b3).Result); |
||||
|
Assert.Null(target.Match(b4).Activator); |
||||
|
Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(b4).Result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Nth_Child_Doesnt_Match_Control_Out_Of_Panel_Parent() |
||||
|
{ |
||||
|
Border b1; |
||||
|
var contentControl = new ContentControl(); |
||||
|
contentControl.Content = b1 = new Border(); |
||||
|
|
||||
|
var target = default(Selector).NthChild(1, 0); |
||||
|
|
||||
|
Assert.Equal(SelectorMatch.NeverThisInstance, target.Match(b1)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
[Theory] // http://nthmaster.com/
|
||||
|
[InlineData(+0, 8, false, false, false, false, false, false, false, true , false, false, false)] |
||||
|
[InlineData(+1, 6, false, false, false, false, false, true , true , true , true , true , true )] |
||||
|
[InlineData(-1, 9, true , true , true , true , true , true , true , true , true , false, false)] |
||||
|
public async Task Nth_Child_Master_Com_Test_Sigle_Selector( |
||||
|
int step, int offset, params bool[] items) |
||||
|
{ |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(items.Select(_ => new Border())); |
||||
|
|
||||
|
var previous = default(Selector).OfType<Border>(); |
||||
|
var target = previous.NthChild(step, offset); |
||||
|
|
||||
|
var results = new bool[items.Length]; |
||||
|
for (int index = 0; index < items.Length; index++) |
||||
|
{ |
||||
|
var border = panel.Children[index]; |
||||
|
results[index] = await target.Match(border).Activator!.Take(1); |
||||
|
} |
||||
|
|
||||
|
Assert.Equal(items, results); |
||||
|
} |
||||
|
|
||||
|
[Theory] // http://nthmaster.com/
|
||||
|
[InlineData(+1, 4, -1, 8, false, false, false, true , true , true , true , true , false, false, false)] |
||||
|
[InlineData(+3, 1, +2, 0, false, false, false, true , false, false, false, false, false, true , false)] |
||||
|
public async Task Nth_Child_Master_Com_Test_Double_Selector( |
||||
|
int step1, int offset1, int step2, int offset2, params bool[] items) |
||||
|
{ |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(items.Select(_ => new Border())); |
||||
|
|
||||
|
var previous = default(Selector).OfType<Border>(); |
||||
|
var middle = previous.NthChild(step1, offset1); |
||||
|
var target = middle.NthChild(step2, offset2); |
||||
|
|
||||
|
var results = new bool[items.Length]; |
||||
|
for (int index = 0; index < items.Length; index++) |
||||
|
{ |
||||
|
var border = panel.Children[index]; |
||||
|
results[index] = await target.Match(border).Activator!.Take(1); |
||||
|
} |
||||
|
|
||||
|
Assert.Equal(items, results); |
||||
|
} |
||||
|
|
||||
|
[Theory] // http://nthmaster.com/
|
||||
|
[InlineData(+1, 2, 2, 1, -1, 9, false, false, true , false, true , false, true , false, true , false, false)] |
||||
|
public async Task Nth_Child_Master_Com_Test_Triple_Selector( |
||||
|
int step1, int offset1, int step2, int offset2, int step3, int offset3, params bool[] items) |
||||
|
{ |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(items.Select(_ => new Border())); |
||||
|
|
||||
|
var previous = default(Selector).OfType<Border>(); |
||||
|
var middle1 = previous.NthChild(step1, offset1); |
||||
|
var middle2 = middle1.NthChild(step2, offset2); |
||||
|
var target = middle2.NthChild(step3, offset3); |
||||
|
|
||||
|
var results = new bool[items.Length]; |
||||
|
for (int index = 0; index < items.Length; index++) |
||||
|
{ |
||||
|
var border = panel.Children[index]; |
||||
|
results[index] = await target.Match(border).Activator!.Take(1); |
||||
|
} |
||||
|
|
||||
|
Assert.Equal(items, results); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Returns_Correct_TargetType() |
||||
|
{ |
||||
|
var target = new NthChildSelector(default(Selector).OfType<Control1>(), 1, 0); |
||||
|
|
||||
|
Assert.Equal(typeof(Control1), target.TargetType); |
||||
|
} |
||||
|
|
||||
|
public class Control1 : Control |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,220 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Avalonia.Controls; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Avalonia.Styling.UnitTests |
||||
|
{ |
||||
|
public class SelectorTests_NthLastChild |
||||
|
{ |
||||
|
[Theory] |
||||
|
[InlineData(2, 0, ":nth-last-child(2n)")] |
||||
|
[InlineData(2, 1, ":nth-last-child(2n+1)")] |
||||
|
[InlineData(1, 0, ":nth-last-child(1n)")] |
||||
|
[InlineData(4, -1, ":nth-last-child(4n-1)")] |
||||
|
[InlineData(0, 1, ":nth-last-child(1)")] |
||||
|
[InlineData(0, -1, ":nth-last-child(-1)")] |
||||
|
[InlineData(int.MaxValue, int.MinValue + 1, ":nth-last-child(2147483647n-2147483647)")] |
||||
|
public void Not_Selector_Should_Have_Correct_String_Representation(int step, int offset, string expected) |
||||
|
{ |
||||
|
var target = default(Selector).NthLastChild(step, offset); |
||||
|
|
||||
|
Assert.Equal(expected, target.ToString()); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(2, 0); |
||||
|
|
||||
|
Assert.True(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(2, 1); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Negative_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(4, -1); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Singular_Step() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(1, 2); |
||||
|
|
||||
|
Assert.True(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Singular_Step_With_Negative_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(1, -2); |
||||
|
|
||||
|
Assert.True(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Zero_Step_With_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(0, 2); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.True(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Doesnt_Match_Control_In_Panel_With_Zero_Step_With_Negative_Offset() |
||||
|
{ |
||||
|
Border b1, b2, b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Border(), |
||||
|
b4 = new Border() |
||||
|
}); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(0, -2); |
||||
|
|
||||
|
Assert.False(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b3).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b4).Activator!.Take(1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Nth_Child_Match_Control_In_Panel_With_Previous_Selector() |
||||
|
{ |
||||
|
Border b1, b2; |
||||
|
Button b3, b4; |
||||
|
var panel = new StackPanel(); |
||||
|
panel.Children.AddRange(new Control[] |
||||
|
{ |
||||
|
b1 = new Border(), |
||||
|
b2 = new Border(), |
||||
|
b3 = new Button(), |
||||
|
b4 = new Button() |
||||
|
}); |
||||
|
|
||||
|
var previous = default(Selector).OfType<Border>(); |
||||
|
var target = previous.NthLastChild(2, 0); |
||||
|
|
||||
|
Assert.True(await target.Match(b1).Activator!.Take(1)); |
||||
|
Assert.False(await target.Match(b2).Activator!.Take(1)); |
||||
|
Assert.Null(target.Match(b3).Activator); |
||||
|
Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(b3).Result); |
||||
|
Assert.Null(target.Match(b4).Activator); |
||||
|
Assert.Equal(SelectorMatchResult.NeverThisType, target.Match(b4).Result); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Nth_Child_Doesnt_Match_Control_Out_Of_Panel_Parent() |
||||
|
{ |
||||
|
Border b1; |
||||
|
var contentControl = new ContentControl(); |
||||
|
contentControl.Content = b1 = new Border(); |
||||
|
|
||||
|
var target = default(Selector).NthLastChild(1, 0); |
||||
|
|
||||
|
Assert.Equal(SelectorMatch.NeverThisInstance, target.Match(b1)); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Returns_Correct_TargetType() |
||||
|
{ |
||||
|
var target = new NthLastChildSelector(default(Selector).OfType<Control1>(), 1, 0); |
||||
|
|
||||
|
Assert.Equal(typeof(Control1), target.TargetType); |
||||
|
} |
||||
|
|
||||
|
public class Control1 : Control |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue