Browse Source
To remove `InheritanceFrame` - it was unneeded, we can just point to the nearest ancestor value store with inherited values.refactor/style-priorities
4 changed files with 278 additions and 161 deletions
@ -1,34 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
|
|||
namespace Avalonia.PropertyStore |
|||
{ |
|||
internal class InheritanceFrame : Dictionary<AvaloniaProperty, EffectiveValue> |
|||
{ |
|||
public InheritanceFrame(ValueStore owner, InheritanceFrame? parent = null) |
|||
{ |
|||
Owner = owner; |
|||
Parent = parent; |
|||
} |
|||
|
|||
public ValueStore Owner { get; } |
|||
public InheritanceFrame? Parent { get; private set; } |
|||
|
|||
public bool TryGetFromThisOrAncestor(AvaloniaProperty property, [NotNullWhen(true)] out EffectiveValue? value) |
|||
{ |
|||
var frame = this; |
|||
|
|||
while (frame is object) |
|||
{ |
|||
if (frame.TryGetValue(property, out value)) |
|||
return true; |
|||
frame = frame.Parent; |
|||
} |
|||
|
|||
value = default; |
|||
return false; |
|||
} |
|||
|
|||
public void SetParent(InheritanceFrame? value) => Parent = value; |
|||
} |
|||
} |
|||
@ -0,0 +1,117 @@ |
|||
using Xunit; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Base.UnitTests.PropertyStore |
|||
{ |
|||
public class ValueStoreTests_Inheritance |
|||
{ |
|||
[Fact] |
|||
public void InheritanceAncestor_Is_Initially_Null() |
|||
{ |
|||
var parent = new Class1(); |
|||
var child = new Class1 { Parent = parent }; |
|||
var grandchild = new Class1 { Parent = child }; |
|||
|
|||
Assert.Null(parent.GetValueStore().InheritanceAncestor); |
|||
Assert.Null(child.GetValueStore().InheritanceAncestor); |
|||
Assert.Null(grandchild.GetValueStore().InheritanceAncestor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Setting_Value_In_Parent_Updates_InheritanceAncestor() |
|||
{ |
|||
var parent = new Class1(); |
|||
var child = new Class1 { Parent = parent }; |
|||
var grandchild = new Class1 { Parent = child }; |
|||
|
|||
parent.Foo = "changed"; |
|||
|
|||
var parentStore = parent.GetValueStore(); |
|||
Assert.Null(parentStore.InheritanceAncestor); |
|||
Assert.Same(parentStore, child.GetValueStore().InheritanceAncestor); |
|||
Assert.Same(parentStore, grandchild.GetValueStore().InheritanceAncestor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Setting_Value_In_Parent_Doesnt_Update_Grandchild_InheritanceAncestor_If_Child_Has_Value_Set() |
|||
{ |
|||
var parent = new Class1(); |
|||
var child = new Class1 { Parent = parent }; |
|||
var grandchild = new Class1 { Parent = child }; |
|||
|
|||
child.Foo = "foochanged"; |
|||
parent.Foo = "changed"; |
|||
|
|||
var parentStore = parent.GetValueStore(); |
|||
Assert.Null(parentStore.InheritanceAncestor); |
|||
Assert.Same(parentStore, child.GetValueStore().InheritanceAncestor); |
|||
Assert.Same(child.GetValueStore(), grandchild.GetValueStore().InheritanceAncestor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Clearing_Value_In_Parent_Updates_InheritanceAncestor() |
|||
{ |
|||
var parent = new Class1(); |
|||
var child = new Class1 { Parent = parent }; |
|||
var grandchild = new Class1 { Parent = child }; |
|||
|
|||
parent.Foo = "changed"; |
|||
parent.ClearValue(Class1.FooProperty); |
|||
|
|||
Assert.Null(parent.GetValueStore().InheritanceAncestor); |
|||
Assert.Null(child.GetValueStore().InheritanceAncestor); |
|||
Assert.Null(grandchild.GetValueStore().InheritanceAncestor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Clear_Value_In_Parent_Doesnt_Update_Grandchild_InheritanceAncestor_If_Child_Has_Value_Set() |
|||
{ |
|||
var parent = new Class1(); |
|||
var child = new Class1 { Parent = parent }; |
|||
var grandchild = new Class1 { Parent = child }; |
|||
|
|||
child.Foo = "foochanged"; |
|||
parent.Foo = "changed"; |
|||
parent.ClearValue(Class1.FooProperty); |
|||
|
|||
Assert.Null(parent.GetValueStore().InheritanceAncestor); |
|||
Assert.Null(child.GetValueStore().InheritanceAncestor); |
|||
Assert.Same(child.GetValueStore(), grandchild.GetValueStore().InheritanceAncestor); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Adding_Child_Sets_InheritanceAncestor() |
|||
{ |
|||
var parent = new Class1(); |
|||
var child = new Class1(); |
|||
var grandchild = new Class1 { Parent = child }; |
|||
|
|||
parent.Foo = "changed"; |
|||
child.Parent = parent; |
|||
|
|||
var parentStore = parent.GetValueStore(); |
|||
Assert.Null(parentStore.InheritanceAncestor); |
|||
Assert.Same(parentStore, child.GetValueStore().InheritanceAncestor); |
|||
Assert.Same(parentStore, grandchild.GetValueStore().InheritanceAncestor); |
|||
} |
|||
|
|||
private class Class1 : AvaloniaObject |
|||
{ |
|||
public static readonly StyledProperty<string> FooProperty = |
|||
AvaloniaProperty.Register<Class1, string>("Foo", "foodefault", inherits: true); |
|||
|
|||
public string Foo |
|||
{ |
|||
get => GetValue(FooProperty); |
|||
set => SetValue(FooProperty, value); |
|||
} |
|||
|
|||
public Class1? Parent |
|||
{ |
|||
get { return (Class1?)InheritanceParent; } |
|||
set { InheritanceParent = value; } |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue