AndQueryActivator.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System.Collections.Generic;
  2. namespace Avalonia.Styling.Activators
  3. {
  4. /// <summary>
  5. /// An aggregate <see cref="ContainerQueryActivatorBase"/> which is active when all of its inputs are
  6. /// active.
  7. /// </summary>
  8. internal class AndQueryActivator : ContainerQueryActivatorBase, IStyleActivatorSink
  9. {
  10. private List<IStyleActivator>? _sources;
  11. public AndQueryActivator(Visual visual) : base(visual)
  12. {
  13. }
  14. public int Count => _sources?.Count ?? 0;
  15. public void Add(IStyleActivator activator)
  16. {
  17. if (IsSubscribed)
  18. throw new AvaloniaInternalException("AndActivator is already subscribed.");
  19. _sources ??= new List<IStyleActivator>();
  20. _sources.Add(activator);
  21. }
  22. void IStyleActivatorSink.OnNext(bool value) => ReevaluateIsActive();
  23. protected override bool EvaluateIsActive()
  24. {
  25. if (_sources is null || _sources.Count == 0)
  26. return true;
  27. var count = _sources.Count;
  28. var mask = (1ul << count) - 1;
  29. var flags = 0UL;
  30. for (var i = 0; i < count; ++i)
  31. {
  32. if (_sources[i].GetIsActive())
  33. flags |= 1ul << i;
  34. }
  35. return flags == mask;
  36. }
  37. protected override void Initialize()
  38. {
  39. if (_sources is object)
  40. {
  41. foreach (var source in _sources)
  42. {
  43. source.Subscribe(this);
  44. }
  45. }
  46. }
  47. protected override void Deinitialize()
  48. {
  49. if (_sources is object)
  50. {
  51. foreach (var source in _sources)
  52. {
  53. source.Unsubscribe(this);
  54. }
  55. }
  56. }
  57. }
  58. }