Skip to content

Commit

Permalink
Merge pull request #33 from irihitech/classes
Browse files Browse the repository at this point in the history
ClassHelper
  • Loading branch information
rabbitism authored Nov 3, 2024
2 parents 79fa7ae + 3dec873 commit 2681839
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
13 changes: 13 additions & 0 deletions sample/Sample/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:iri="https://irihi.tech/shared"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:Irihi.Avalonia.Shared.Helpers;assembly=Irihi.Avalonia.Shared"
Title="Sample"
mc:Ignorable="d">
<Window.Styles>
<Style Selector="Button.Alert">
<Setter Property="Background" Value="Red"/>
</Style>
</Window.Styles>
<StackPanel HorizontalAlignment="Left">
<CheckBox Margin="0 0 -7 0"></CheckBox>
<Panel Width="100" Height="100">
Expand All @@ -18,5 +24,12 @@
<Button>Hell World</Button>
<iri:PureRing Diameter="50" InnerDiameter="25" Background="Green"></iri:PureRing>
</Panel>
<Button Content="Alert">
<Button.Styles>
<Style Selector="Button">
<Setter Property="helpers:ClassHelper.Classes" Value="Alert"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</Window>
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 2681839

Please sign in to comment.