|
|
|
@ -1,4 +1,5 @@ |
|
|
|
using System.Collections.Generic; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Diagnostics; |
|
|
|
using System.Diagnostics.CodeAnalysis; |
|
|
|
using Avalonia.Data; |
|
|
|
@ -15,12 +16,31 @@ namespace Avalonia.PropertyStore |
|
|
|
internal sealed class EffectiveValue<T> : EffectiveValue |
|
|
|
{ |
|
|
|
private T? _baseValue; |
|
|
|
private UncommonFields? _uncommon; |
|
|
|
|
|
|
|
public EffectiveValue(T value, BindingPriority priority) |
|
|
|
public EffectiveValue( |
|
|
|
AvaloniaObject owner, |
|
|
|
StyledPropertyBase<T> property, |
|
|
|
T value, |
|
|
|
BindingPriority priority) |
|
|
|
{ |
|
|
|
Value = value; |
|
|
|
Priority = priority; |
|
|
|
|
|
|
|
if (property.HasCoercion && |
|
|
|
property.GetMetadata(owner.GetType()) is { } metadata && |
|
|
|
metadata.CoerceValue is { } coerce) |
|
|
|
{ |
|
|
|
_uncommon = new() |
|
|
|
{ |
|
|
|
_coerce = coerce, |
|
|
|
_uncoercedValue = value, |
|
|
|
_uncoercedBaseValue = value, |
|
|
|
}; |
|
|
|
|
|
|
|
value = coerce(owner, value); |
|
|
|
} |
|
|
|
|
|
|
|
if (priority >= BindingPriority.LocalValue && priority < BindingPriority.Inherited) |
|
|
|
{ |
|
|
|
_baseValue = value; |
|
|
|
@ -88,19 +108,27 @@ namespace Avalonia.PropertyStore |
|
|
|
var oldValue = Value; |
|
|
|
var valueChanged = false; |
|
|
|
var baseValueChanged = false; |
|
|
|
var v = value; |
|
|
|
|
|
|
|
if (_uncommon?._coerce is { } coerce) |
|
|
|
v = coerce(owner.Owner, value); |
|
|
|
|
|
|
|
if (priority <= Priority) |
|
|
|
{ |
|
|
|
valueChanged = !EqualityComparer<T>.Default.Equals(Value, value); |
|
|
|
Value = value; |
|
|
|
valueChanged = !EqualityComparer<T>.Default.Equals(Value, v); |
|
|
|
Value = v; |
|
|
|
Priority = priority; |
|
|
|
if (_uncommon is not null) |
|
|
|
_uncommon._uncoercedValue = value; |
|
|
|
} |
|
|
|
|
|
|
|
if (priority <= BasePriority && priority >= BindingPriority.LocalValue) |
|
|
|
{ |
|
|
|
baseValueChanged = !EqualityComparer<T>.Default.Equals(_baseValue, value); |
|
|
|
_baseValue = value; |
|
|
|
baseValueChanged = !EqualityComparer<T>.Default.Equals(_baseValue, v); |
|
|
|
_baseValue = v; |
|
|
|
BasePriority = priority; |
|
|
|
if (_uncommon is not null) |
|
|
|
_uncommon._uncoercedBaseValue = value; |
|
|
|
} |
|
|
|
|
|
|
|
if (valueChanged) |
|
|
|
@ -135,22 +163,36 @@ namespace Avalonia.PropertyStore |
|
|
|
{ |
|
|
|
Debug.Assert(priority < BindingPriority.Inherited); |
|
|
|
Debug.Assert(basePriority > BindingPriority.Animation); |
|
|
|
Debug.Assert(priority <= basePriority); |
|
|
|
|
|
|
|
var oldValue = Value; |
|
|
|
var valueChanged = false; |
|
|
|
var baseValueChanged = false; |
|
|
|
var v = value; |
|
|
|
var bv = baseValue; |
|
|
|
|
|
|
|
if (!EqualityComparer<T>.Default.Equals(Value, value)) |
|
|
|
if (_uncommon?._coerce is { } coerce) |
|
|
|
{ |
|
|
|
Value = value; |
|
|
|
v = coerce(owner.Owner, value); |
|
|
|
bv = coerce(owner.Owner, baseValue); |
|
|
|
} |
|
|
|
|
|
|
|
if (priority != BindingPriority.Unset && !EqualityComparer<T>.Default.Equals(Value, v)) |
|
|
|
{ |
|
|
|
Value = v; |
|
|
|
valueChanged = true; |
|
|
|
if (_uncommon is not null) |
|
|
|
_uncommon._uncoercedValue = value; |
|
|
|
} |
|
|
|
|
|
|
|
if (BasePriority == BindingPriority.Unset || |
|
|
|
!EqualityComparer<T>.Default.Equals(_baseValue, baseValue)) |
|
|
|
if (priority != BindingPriority.Unset && |
|
|
|
(BasePriority == BindingPriority.Unset || |
|
|
|
!EqualityComparer<T>.Default.Equals(_baseValue, bv))) |
|
|
|
{ |
|
|
|
_baseValue = value; |
|
|
|
_baseValue = v; |
|
|
|
baseValueChanged = true; |
|
|
|
if (_uncommon is not null) |
|
|
|
_uncommon._uncoercedValue = baseValue; |
|
|
|
} |
|
|
|
|
|
|
|
Priority = priority; |
|
|
|
@ -193,6 +235,19 @@ namespace Avalonia.PropertyStore |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public override void CoerceValue(ValueStore owner, AvaloniaProperty property) |
|
|
|
{ |
|
|
|
if (_uncommon is null) |
|
|
|
return; |
|
|
|
SetAndRaise( |
|
|
|
owner, |
|
|
|
(StyledPropertyBase<T>)property, |
|
|
|
_uncommon._uncoercedValue!, |
|
|
|
Priority, |
|
|
|
_uncommon._uncoercedBaseValue!, |
|
|
|
BasePriority); |
|
|
|
} |
|
|
|
|
|
|
|
public override void DisposeAndRaiseUnset(ValueStore owner, AvaloniaProperty property) |
|
|
|
{ |
|
|
|
DisposeAndRaiseUnset(owner, (StyledPropertyBase<T>)property); |
|
|
|
@ -216,5 +271,12 @@ namespace Avalonia.PropertyStore |
|
|
|
{ |
|
|
|
return BasePriority != BindingPriority.Unset ? _baseValue : AvaloniaProperty.UnsetValue; |
|
|
|
} |
|
|
|
|
|
|
|
private class UncommonFields |
|
|
|
{ |
|
|
|
public Func<IAvaloniaObject, T, T>? _coerce; |
|
|
|
public T? _uncoercedValue; |
|
|
|
public T? _uncoercedBaseValue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|