-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from irihitech/classes
ClassHelper
- Loading branch information
Showing
5 changed files
with
166 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
test/Irihi.Avalonia.Shared.UnitTest.Public/Helpers/ClassHelperTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters