using System;
using Avalonia.Data;
using Avalonia.Reactive;
#nullable enable
namespace Avalonia.Styling
{
///
/// A which has been instanced on a control.
///
/// The target property type.
internal class PropertySetterInstance : SingleSubscriberObservableBase>,
ISetterInstance
{
private readonly IStyleable _target;
private readonly StyledPropertyBase? _styledProperty;
private readonly DirectPropertyBase? _directProperty;
private readonly T _value;
private IDisposable? _subscription;
private State _state;
public PropertySetterInstance(
IStyleable target,
StyledPropertyBase property,
T value)
{
_target = target;
_styledProperty = property;
_value = value;
}
public PropertySetterInstance(
IStyleable target,
DirectPropertyBase property,
T value)
{
_target = target;
_directProperty = property;
_value = value;
}
private bool IsActive => _state == State.Active;
public void Start(bool hasActivator)
{
if (hasActivator)
{
if (_styledProperty is not null)
{
_subscription = _target.Bind(_styledProperty, this, BindingPriority.StyleTrigger);
}
else
{
_subscription = _target.Bind(_directProperty!, this);
}
}
else
{
var target = (AvaloniaObject) _target;
if (_styledProperty is not null)
{
_subscription = target.SetValue(_styledProperty!, _value, BindingPriority.Style);
}
else
{
target.SetValue(_directProperty!, _value);
}
}
}
public void Activate()
{
if (!IsActive)
{
_state = State.Active;
PublishNext();
}
}
public void Deactivate()
{
if (IsActive)
{
_state = State.Inactive;
PublishNext();
}
}
public override void Dispose()
{
if (_state == State.Disposed)
return;
_state = State.Disposed;
if (_subscription is object)
{
var sub = _subscription;
_subscription = null;
sub.Dispose();
}
else if (IsActive)
{
if (_styledProperty is object)
{
_target.ClearValue(_styledProperty);
}
else
{
_target.ClearValue(_directProperty!);
}
}
base.Dispose();
}
protected override void Subscribed() => PublishNext();
protected override void Unsubscribed() { }
private void PublishNext()
{
PublishNext(IsActive ? new BindingValue(_value) : default);
}
private enum State
{
Inactive,
Active,
Disposed,
}
}
}