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, } } }