progress_indicator_animation_registry.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/system/progress_indicator/progress_indicator_animation_registry.h"
  5. #include <set>
  6. namespace ash {
  7. namespace {
  8. // Type aliases ----------------------------------------------------------------
  9. template <typename AnimationType>
  10. using KeyedAnimationMap = std::map<const void*, std::unique_ptr<AnimationType>>;
  11. template <typename CallbackListType>
  12. using KeyedAnimationChangedCallbackListMap =
  13. std::map<const void*, CallbackListType>;
  14. // Helpers ---------------------------------------------------------------------
  15. // Notifies any animation changed callbacks registered for the specified `key`
  16. // that the associated animation has changed.
  17. template <typename AnimationType, typename CallbackListType>
  18. void NotifyAnimationChangedForKey(
  19. KeyedAnimationMap<AnimationType>* animations_by_key,
  20. KeyedAnimationChangedCallbackListMap<CallbackListType>*
  21. animation_changed_callback_lists_by_key,
  22. const void* key) {
  23. auto callback_lists_it = animation_changed_callback_lists_by_key->find(key);
  24. if (callback_lists_it == animation_changed_callback_lists_by_key->end())
  25. return;
  26. auto animations_it = animations_by_key->find(key);
  27. callback_lists_it->second.Notify(animations_it != animations_by_key->end()
  28. ? animations_it->second.get()
  29. : nullptr);
  30. }
  31. // Implements:
  32. // * `AddProgressIconAnimationChangedCallbackForKey()`
  33. // * `AddProgressRingAnimationChangedCallbackForKey()`
  34. template <typename CallbackListType>
  35. base::CallbackListSubscription AddAnimationChangedCallbackForKey(
  36. KeyedAnimationChangedCallbackListMap<CallbackListType>*
  37. animation_changed_callback_lists_by_key,
  38. const void* key,
  39. typename CallbackListType::CallbackType callback) {
  40. auto it = animation_changed_callback_lists_by_key->find(key);
  41. // If this is the first time that an animation changed callback is being
  42. // registered for the specified `key`, set a callback to destroy the created
  43. // callback list when it becomes empty.
  44. if (it == animation_changed_callback_lists_by_key->end()) {
  45. it = animation_changed_callback_lists_by_key
  46. ->emplace(std::piecewise_construct, std::forward_as_tuple(key),
  47. std::forward_as_tuple())
  48. .first;
  49. it->second.set_removal_callback(base::BindRepeating(
  50. [](KeyedAnimationChangedCallbackListMap<CallbackListType>*
  51. animation_changed_callback_lists_by_key,
  52. const void* key) {
  53. auto it = animation_changed_callback_lists_by_key->find(key);
  54. if (it != animation_changed_callback_lists_by_key->end() &&
  55. it->second.empty()) {
  56. animation_changed_callback_lists_by_key->erase(it);
  57. }
  58. },
  59. base::Unretained(animation_changed_callback_lists_by_key),
  60. base::Unretained(key)));
  61. }
  62. return it->second.Add(std::move(callback));
  63. }
  64. // Implements:
  65. // * `GetProgressIconAnimationForKey()`
  66. // * `GetProgressRingAnimationForKey()`
  67. template <typename AnimationType>
  68. AnimationType* GetAnimationForKey(
  69. KeyedAnimationMap<AnimationType>* animations_by_key,
  70. const void* key) {
  71. auto it = animations_by_key->find(key);
  72. return it != animations_by_key->end() ? it->second.get() : nullptr;
  73. }
  74. // Implements:
  75. // * `SetProgressIconAnimationForKey()`
  76. // * `SetProgressRingAnimationForKey()`
  77. template <typename AnimationType, typename CallbackListType>
  78. AnimationType* SetAnimationForKey(
  79. KeyedAnimationMap<AnimationType>* animations_by_key,
  80. KeyedAnimationChangedCallbackListMap<CallbackListType>*
  81. animation_changed_callback_lists_by_key,
  82. const void* key,
  83. std::unique_ptr<AnimationType> animation) {
  84. AnimationType* animation_ptr = animation.get();
  85. if (animation) {
  86. (*animations_by_key)[key] = std::move(animation);
  87. NotifyAnimationChangedForKey(animations_by_key,
  88. animation_changed_callback_lists_by_key, key);
  89. } else {
  90. auto it = animations_by_key->find(key);
  91. if (it != animations_by_key->end()) {
  92. animations_by_key->erase(it);
  93. NotifyAnimationChangedForKey(
  94. animations_by_key, animation_changed_callback_lists_by_key, key);
  95. }
  96. }
  97. return animation_ptr;
  98. }
  99. } // namespace
  100. // ProgressIndicatorAnimationRegistry ------------------------------------------
  101. ProgressIndicatorAnimationRegistry::ProgressIndicatorAnimationRegistry() =
  102. default;
  103. ProgressIndicatorAnimationRegistry::~ProgressIndicatorAnimationRegistry() =
  104. default;
  105. base::CallbackListSubscription ProgressIndicatorAnimationRegistry::
  106. AddProgressIconAnimationChangedCallbackForKey(
  107. const void* key,
  108. ProgressIconAnimationChangedCallbackList::CallbackType callback) {
  109. return AddAnimationChangedCallbackForKey(
  110. &icon_animation_changed_callback_lists_by_key_, key, std::move(callback));
  111. }
  112. base::CallbackListSubscription ProgressIndicatorAnimationRegistry::
  113. AddProgressRingAnimationChangedCallbackForKey(
  114. const void* key,
  115. ProgressRingAnimationChangedCallbackList::CallbackType callback) {
  116. return AddAnimationChangedCallbackForKey(
  117. &ring_animation_changed_callback_lists_by_key_, key, std::move(callback));
  118. }
  119. ProgressIconAnimation*
  120. ProgressIndicatorAnimationRegistry::GetProgressIconAnimationForKey(
  121. const void* key) {
  122. return GetAnimationForKey(&icon_animations_by_key_, key);
  123. }
  124. ProgressRingAnimation*
  125. ProgressIndicatorAnimationRegistry::GetProgressRingAnimationForKey(
  126. const void* key) {
  127. return GetAnimationForKey(&ring_animations_by_key_, key);
  128. }
  129. ProgressIconAnimation*
  130. ProgressIndicatorAnimationRegistry::SetProgressIconAnimationForKey(
  131. const void* key,
  132. std::unique_ptr<ProgressIconAnimation> animation) {
  133. return SetAnimationForKey(&icon_animations_by_key_,
  134. &icon_animation_changed_callback_lists_by_key_, key,
  135. std::move(animation));
  136. }
  137. ProgressRingAnimation*
  138. ProgressIndicatorAnimationRegistry::SetProgressRingAnimationForKey(
  139. const void* key,
  140. std::unique_ptr<ProgressRingAnimation> animation) {
  141. return SetAnimationForKey(&ring_animations_by_key_,
  142. &ring_animation_changed_callback_lists_by_key_, key,
  143. std::move(animation));
  144. }
  145. void ProgressIndicatorAnimationRegistry::EraseAllAnimations() {
  146. EraseAllAnimationsForKeyIf(
  147. base::BindRepeating([](const void* key) { return true; }));
  148. }
  149. void ProgressIndicatorAnimationRegistry::EraseAllAnimationsForKey(
  150. const void* key) {
  151. SetProgressIconAnimationForKey(key, nullptr);
  152. SetProgressRingAnimationForKey(key, nullptr);
  153. }
  154. void ProgressIndicatorAnimationRegistry::EraseAllAnimationsForKeyIf(
  155. base::RepeatingCallback<bool(const void* key)> predicate) {
  156. std::set<const void*> keys_to_erase;
  157. for (const auto& icon_animation_by_key : icon_animations_by_key_) {
  158. const void* key = icon_animation_by_key.first;
  159. if (predicate.Run(key))
  160. keys_to_erase.insert(key);
  161. }
  162. for (const auto& ring_animation_by_key : ring_animations_by_key_) {
  163. const void* key = ring_animation_by_key.first;
  164. if (predicate.Run(key))
  165. keys_to_erase.insert(key);
  166. }
  167. for (const void* key : keys_to_erase)
  168. EraseAllAnimationsForKey(key);
  169. }
  170. } // namespace ash