Skip to content

Commit

Permalink
Merge pull request irihitech#432 from irihitech/breadcrumb
Browse files Browse the repository at this point in the history
Fix BreadcrumbItem :last pseudo class for dynamic added items.
  • Loading branch information
zdpcdt authored Oct 21, 2024
2 parents c5adf6e + b733621 commit 44e2c97
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 3 deletions.
16 changes: 16 additions & 0 deletions Ursa.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sandbox", "demo\Sandbox\San
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.ReactiveUIExtension", "src\Ursa.ReactiveUIExtension\Ursa.ReactiveUIExtension.csproj", "{8DD57D6B-1C44-4E42-9541-8380DD17A3A4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{49243F14-2D63-4361-BE31-BAF63951DE6F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Ursa", "tests\Test.Ursa\Test.Ursa.csproj", "{AC7B37DC-9B88-42C0-B176-0C274D14C68D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeadlessTest.Ursa", "tests\HeadlessTest.Ursa\HeadlessTest.Ursa.csproj", "{2D1C279E-7FFF-4630-92CC-CB2C33C3F80F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -83,6 +89,14 @@ Global
{8DD57D6B-1C44-4E42-9541-8380DD17A3A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DD57D6B-1C44-4E42-9541-8380DD17A3A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DD57D6B-1C44-4E42-9541-8380DD17A3A4}.Release|Any CPU.Build.0 = Release|Any CPU
{AC7B37DC-9B88-42C0-B176-0C274D14C68D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC7B37DC-9B88-42C0-B176-0C274D14C68D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC7B37DC-9B88-42C0-B176-0C274D14C68D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC7B37DC-9B88-42C0-B176-0C274D14C68D}.Release|Any CPU.Build.0 = Release|Any CPU
{2D1C279E-7FFF-4630-92CC-CB2C33C3F80F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D1C279E-7FFF-4630-92CC-CB2C33C3F80F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D1C279E-7FFF-4630-92CC-CB2C33C3F80F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D1C279E-7FFF-4630-92CC-CB2C33C3F80F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -95,5 +109,7 @@ Global
{D1942476-8473-4608-BB9F-5AC01083BBDA} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
{F99B3D07-4560-4B05-892C-0FF2757FEF2E} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
{1E94BAFD-867E-425F-8E12-7F416D523C94} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
{AC7B37DC-9B88-42C0-B176-0C274D14C68D} = {49243F14-2D63-4361-BE31-BAF63951DE6F}
{2D1C279E-7FFF-4630-92CC-CB2C33C3F80F} = {49243F14-2D63-4361-BE31-BAF63951DE6F}
EndGlobalSection
EndGlobal
15 changes: 12 additions & 3 deletions src/Ursa/Controls/Breadcrumb/Breadcrumb.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
Expand Down Expand Up @@ -83,9 +84,19 @@ protected override Control CreateContainerForItemOverride(object? item, int inde
return new BreadcrumbItem();
}

protected override void LogicalChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
base.LogicalChildrenCollectionChanged(sender, e);
var breadcrumbItems = LogicalChildren.OfType<BreadcrumbItem>().ToList();
for (var i = 0; i < breadcrumbItems.Count; i++)
{
var breadcrumbItem = breadcrumbItems[i];
breadcrumbItem.SetPseudoClassLast(i == breadcrumbItems.Count - 1);
}
}

protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
{
// base.PrepareContainerForItemOverride(container, item, index);
if (container is not BreadcrumbItem breadcrumbItem) return;
if (!breadcrumbItem.IsSet(BreadcrumbItem.SeparatorProperty))
{
Expand All @@ -100,8 +111,6 @@ protected override void PrepareContainerForItemOverride(Control container, objec
});
}

PseudolassesExtensions.Set(container.Classes, BreadcrumbItem.PC_Last, index == ItemCount - 1);

if (container == item) return;
if(!breadcrumbItem.IsSet(ContentControl.ContentProperty))
{
Expand Down
5 changes: 5 additions & 0 deletions src/Ursa/Controls/Breadcrumb/BreadcrumbItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,9 @@ protected override void OnPointerPressed(PointerPressedEventArgs e)
Command?.Execute(CommandParameter);
}
}

internal void SetPseudoClassLast(bool isLast)
{
PseudoClasses.Set(PC_Last, isLast);
}
}
10 changes: 10 additions & 0 deletions tests/HeadlessTest.Ursa/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:semi="https://irihi.tech/semi"
xmlns:u-semi="https://irihi.tech/ursa/themes/semi"
x:Class="HeadlessTest.Ursa.App">
<Application.Styles>
<semi:SemiTheme />
<u-semi:SemiTheme/>
</Application.Styles>
</Application>
13 changes: 13 additions & 0 deletions tests/HeadlessTest.Ursa/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace HeadlessTest.Ursa;

public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System.Collections.ObjectModel;
using Avalonia.Controls;
using Avalonia.Headless.XUnit;
using Avalonia.LogicalTree;
using Ursa.Controls;

namespace HeadlessTest.Ursa.Controls;

public class BreadcrumbTests
{
[AvaloniaFact]
public void BreadcrumbItem_Should_Have_Correct_PseudoClasses()
{
var window = new Window();
var breadcrumb = new Breadcrumb();
window.Content = breadcrumb;
window.Show();
var item1 = new BreadcrumbItem();
var item2 = new BreadcrumbItem();
breadcrumb.Items.Add(item1);
Assert.Contains(":last", item1.Classes);
breadcrumb.Items.Add(item2);
Assert.Contains(":last", item2.Classes);
Assert.DoesNotContain(":last", item1.Classes);
}

[AvaloniaFact]
public void Generated_BreadcrumbItem_Should_Have_Correct_PseudoClasses()
{
var window = new Window();
var breadcrumb = new Breadcrumb();
window.Content = breadcrumb;
window.Show();
var item1 = new TextBlock();
var item2 = new TextBlock();
breadcrumb.Items.Add(item1);
var firstItem = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().FirstOrDefault();
Assert.NotNull(firstItem);
Assert.Contains(":last", firstItem.Classes);
breadcrumb.Items.Add(item2);
var lastItem = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().LastOrDefault();
Assert.NotNull(lastItem);
Assert.Contains(":last", lastItem.Classes);
Assert.DoesNotContain(":last", firstItem.Classes);
}

[AvaloniaFact]
public void BreadcrumbItem_FromItemsSource_Should_Have_Correct_PseudoClasses()
{
var window = new Window();
var breadcrumb = new Breadcrumb();
window.Content = breadcrumb;
window.Show();
var items = new ObservableCollection<string>();
breadcrumb.ItemsSource = items;
items.Add("Item 1");
var item1 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().FirstOrDefault();
Assert.NotNull(item1);
Assert.Contains(":last", item1.Classes);
items.Add("Item 2");
var item2 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().LastOrDefault();
Assert.NotNull(item2);
Assert.Contains(":last", item2.Classes);
Assert.DoesNotContain(":last", item1.Classes);
}

[AvaloniaFact]
public void Bulk_Added_BreadcrumbItem_Should_Have_Correct_PseudoClasses()
{
var window = new Window();
var breadcrumb = new Breadcrumb();
window.Content = breadcrumb;
window.Show();
var items = new ObservableCollection<string>
{
"Item 1",
"Item 2"
};
breadcrumb.ItemsSource = items;
var item1 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().FirstOrDefault();
var item2 = breadcrumb.GetLogicalChildren().OfType<BreadcrumbItem>().LastOrDefault();
Assert.NotNull(item1);
Assert.NotNull(item2);
Assert.Contains(":last", item2.Classes);
Assert.DoesNotContain(":last", item1.Classes);
}
}
30 changes: 30 additions & 0 deletions tests/HeadlessTest.Ursa/HeadlessTest.Ursa.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia.Headless.XUnit" Version="11.1.3" />
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="Semi.Avalonia" Version="11.1.0.4" />
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
</ItemGroup>

<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Ursa\Ursa.csproj" />
<ProjectReference Include="..\..\src\Ursa.Themes.Semi\Ursa.Themes.Semi.csproj" />
</ItemGroup>

</Project>
13 changes: 13 additions & 0 deletions tests/HeadlessTest.Ursa/TestAppBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Headless;
using HeadlessTest.Ursa;

[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]

namespace HeadlessTest.Ursa;

public class TestAppBuilder
{
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>().UseHeadless(new AvaloniaHeadlessPlatformOptions());
}
27 changes: 27 additions & 0 deletions tests/Test.Ursa/Test.Ursa.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
</ItemGroup>

<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Ursa\Ursa.csproj" />
</ItemGroup>

</Project>

0 comments on commit 44e2c97

Please sign in to comment.