using System;
using Avalonia.Data;
using Avalonia.PropertyStore;
namespace Avalonia
{
///
/// Base class for direct properties.
///
/// The type of the property's value.
///
/// Whereas is typed on the owner type, this base
/// class provides a non-owner-typed interface to a direct property.
///
public abstract class DirectPropertyBase : AvaloniaProperty
{
///
/// Initializes a new instance of the class.
///
/// The name of the property.
/// The type of the class that registers the property.
/// The property metadata.
protected DirectPropertyBase(
string name,
Type ownerType,
AvaloniaPropertyMetadata metadata)
: base(name, ownerType, metadata)
{
Owner = ownerType;
}
///
/// Initializes a new instance of the class.
///
/// The property to copy.
/// The new owner type.
/// Optional overridden metadata.
protected DirectPropertyBase(
DirectPropertyBase source,
Type ownerType,
AvaloniaPropertyMetadata metadata)
: base(source, ownerType, metadata)
{
Owner = ownerType;
}
///
/// Gets the type that registered the property.
///
public Type Owner { get; }
///
/// Gets the value of the property on the instance.
///
/// The instance.
/// The property value.
internal abstract TValue InvokeGetter(AvaloniaObject instance);
///
/// Sets the value of the property on the instance.
///
/// The instance.
/// The value.
internal abstract void InvokeSetter(AvaloniaObject instance, BindingValue value);
///
/// Gets the unset value for the property on the specified type.
///
/// The type.
/// The unset value.
public TValue GetUnsetValue(Type type)
{
type = type ?? throw new ArgumentNullException(nameof(type));
return GetMetadata(type).UnsetValue;
}
///
/// Gets the property metadata for the specified type.
///
/// The type.
///
/// The property metadata.
///
public new DirectPropertyMetadata GetMetadata(Type type)
{
return (DirectPropertyMetadata)base.GetMetadata(type);
}
///
/// Overrides the metadata for the property on the specified type.
///
/// The type.
/// The metadata.
public void OverrideMetadata(DirectPropertyMetadata metadata) where T : AvaloniaObject
{
base.OverrideMetadata(typeof(T), metadata);
}
///
/// Overrides the metadata for the property on the specified type.
///
/// The type.
/// The metadata.
public void OverrideMetadata(Type type, DirectPropertyMetadata metadata)
{
base.OverrideMetadata(type, metadata);
}
internal override EffectiveValue CreateEffectiveValue(AvaloniaObject o)
{
throw new InvalidOperationException("Cannot create EffectiveValue for direct property.");
}
///
internal override void RouteClearValue(AvaloniaObject o)
{
o.ClearValue(this);
}
///
internal override object? RouteGetValue(AvaloniaObject o)
{
return o.GetValue(this);
}
internal override object? RouteGetBaseValue(AvaloniaObject o)
{
return o.GetValue(this);
}
///
internal override IDisposable? RouteSetValue(
AvaloniaObject o,
object? value,
BindingPriority priority)
{
var v = TryConvert(value);
if (v.HasValue)
{
o.SetValue(this, (TValue)v.Value!);
}
else if (v.Type == BindingValueType.UnsetValue)
{
o.ClearValue(this);
}
else if (v.HasError)
{
throw v.Error!;
}
return null;
}
internal override void RouteSetCurrentValue(AvaloniaObject o, object? value)
{
RouteSetValue(o, value, BindingPriority.LocalValue);
}
///
/// Routes an untyped Bind call to a typed call.
///
/// The object instance.
/// The binding source.
/// The priority.
internal override IDisposable RouteBind(
AvaloniaObject o,
IObservable