Skip to content

Commit

Permalink
feat: move classhelper to shared library.
Browse files Browse the repository at this point in the history
  • Loading branch information
rabbitism committed Nov 2, 2024
1 parent 79fa7ae commit e7a50a4
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
65 changes: 65 additions & 0 deletions src/Irihi.Avalonia.Shared.Public/Helpers/ClassHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Collections;

namespace Irihi.Avalonia.Shared.Helpers;

public class ClassHelper
{
public static readonly AttachedProperty<string> ClassesProperty =
AvaloniaProperty.RegisterAttached<ClassHelper, StyledElement, string>("Classes");

public static readonly AttachedProperty<StyledElement> ClassSourceProperty =
AvaloniaProperty.RegisterAttached<ClassHelper, StyledElement, StyledElement>("ClassSource");

static ClassHelper()
{
ClassesProperty.Changed.AddClassHandler<StyledElement>(OnClassesChanged);
ClassSourceProperty.Changed.AddClassHandler<StyledElement>(OnClassSourceChanged);
}

private static void OnClassSourceChanged(StyledElement arg1, AvaloniaPropertyChangedEventArgs arg2)
{
if (arg2.NewValue is not StyledElement styledElement) return;
arg1.Classes.Clear();
var nonPseudoClasses = styledElement.Classes.Where(c => !c.StartsWith(":"));
arg1.Classes.AddRange(nonPseudoClasses);
styledElement.Classes.WeakSubscribe((o, e) => OnSourceClassesChanged(o, e, arg1));
}

private static void OnSourceClassesChanged(object sender, NotifyCollectionChangedEventArgs e, StyledElement target)
{
if (sender is not AvaloniaList<string> classes) return;
target.Classes.Clear();
var nonPseudoClasses = classes.Where(c => !c.StartsWith(":"));
target.Classes.AddRange(nonPseudoClasses);
}

public static void SetClasses(AvaloniaObject obj, string value)
{
obj.SetValue(ClassesProperty, value);
}

public static string GetClasses(AvaloniaObject obj)
{
return obj.GetValue(ClassesProperty);
}

private static void OnClassesChanged(StyledElement sender, AvaloniaPropertyChangedEventArgs value)
{
var classes = value.GetNewValue<string?>();
if (classes is null) return;
sender.Classes.Clear();
sender.Classes.Add(classes);
}

public static void SetClassSource(StyledElement obj, StyledElement value)
{
obj.SetValue(ClassSourceProperty, value);
}

public static StyledElement GetClassSource(StyledElement obj)
{
return obj.GetValue(ClassSourceProperty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Converters\ResourceConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\AvaloniaPropertyExtension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\BindingExtension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ClassHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\LogicalHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\MathHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ObservableExtension.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Avalonia.Controls;
using Avalonia.Styling;
using Irihi.Avalonia.Shared.Helpers;

namespace Irihi.Avalonia.Shared.UnitTest.Helpers;

public class ClassHelperTests
{
[Fact]
public void ClassesProperty_Should_Set_And_Get_Value()
{
var control = new Button();
ClassHelper.SetClasses(control, "test-class");
Assert.Equal("test-class", ClassHelper.GetClasses(control));
}

[Fact]
public void ClassSourceProperty_Should_Set_And_Get_Value()
{
var sourceControl = new Button();
var targetControl = new Button();
ClassHelper.SetClassSource(targetControl, sourceControl);
Assert.Equal(sourceControl, ClassHelper.GetClassSource(targetControl));
}

[Fact]
public void OnClassSourceChanged_Should_Copy_Classes()
{
var sourceControl = new Button();
sourceControl.Classes.Add("source-class");
var targetControl = new Button();
ClassHelper.SetClassSource(targetControl, sourceControl);
Assert.Contains("source-class", targetControl.Classes);
}

[Fact]
public void OnClassSourceChanged_Should_Not_Copy_PseudoClasses()
{
var sourceControl = new Button();
IPseudoClasses pseudoClasses = sourceControl.Classes;
pseudoClasses.Add(":pseudo-class");
var targetControl = new Button();
ClassHelper.SetClassSource(targetControl, sourceControl);
Assert.DoesNotContain(":pseudo-class", targetControl.Classes);
}

[Fact]
public void OnClassesChanged_Should_Update_Classes()
{
var control = new Button();
ClassHelper.SetClasses(control, "initial-class");
ClassHelper.SetClasses(control, "updated-class");
Assert.Contains("updated-class", control.Classes);
Assert.DoesNotContain("initial-class", control.Classes);
}

[Fact]
public void OnSourceClassesChanged_Should_Update_Target_Classes()
{
var sourceControl = new Button();
var targetControl = new Button();
ClassHelper.SetClassSource(targetControl, sourceControl);
sourceControl.Classes.Add("new-class");
Assert.Contains("new-class", targetControl.Classes);
}

[Fact]
public void OnClassesChanged_Should_Not_Remove_PseudoClasses()
{
var control = new Button();
IPseudoClasses pseudoClasses = control.Classes;
pseudoClasses.Add(":pseudo-class");
pseudoClasses.Add(":pseudo-class2");
ClassHelper.SetClasses(control, "initial-class");
Assert.Contains(":pseudo-class", control.Classes);
Assert.Contains(":pseudo-class2", control.Classes);
}

[Fact]
public void ClassesProperty_Should_Not_Throw_Exception_When_Null()
{
var control = new Button();
ClassHelper.SetClasses(control, null);
Assert.Null(ClassHelper.GetClasses(control));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Helpers\AffectsPseudoClassTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\AvaloniaPropertyExtensionTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\BindingExtensionTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ClassHelperTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\LogicalHelpersTest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\MathHelperTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ObservableExtensionTest.cs" />
Expand Down

0 comments on commit e7a50a4

Please sign in to comment.