holding_space_progress_indicator_util.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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/holding_space/holding_space_progress_indicator_util.h"
  5. #include "ash/public/cpp/holding_space/holding_space_controller.h"
  6. #include "ash/public/cpp/holding_space/holding_space_controller_observer.h"
  7. #include "ash/public/cpp/holding_space/holding_space_item.h"
  8. #include "ash/public/cpp/holding_space/holding_space_model.h"
  9. #include "ash/public/cpp/holding_space/holding_space_model_observer.h"
  10. #include "ash/public/cpp/holding_space/holding_space_progress.h"
  11. #include "ash/system/holding_space/holding_space_animation_registry.h"
  12. #include "ash/system/progress_indicator/progress_indicator.h"
  13. #include "base/threading/sequenced_task_runner_handle.h"
  14. namespace ash {
  15. namespace holding_space_util {
  16. namespace {
  17. // HoldingSpaceControllerProgressIndicator -------------------------------------
  18. // A class owning a `ui::Layer` which paints indication of progress for all
  19. // items in the model attached to its associated holding space `controller_`.
  20. // NOTE: The owned `layer()` is not painted if there are no items in progress.
  21. class HoldingSpaceControllerProgressIndicator
  22. : public ProgressIndicator,
  23. public HoldingSpaceControllerObserver,
  24. public HoldingSpaceModelObserver {
  25. public:
  26. explicit HoldingSpaceControllerProgressIndicator(
  27. HoldingSpaceController* controller)
  28. : ProgressIndicator(
  29. /*animation_registry=*/HoldingSpaceAnimationRegistry::GetInstance(),
  30. /*animation_key=*/controller),
  31. controller_(controller) {
  32. controller_observation_.Observe(controller_);
  33. if (controller_->model())
  34. OnHoldingSpaceModelAttached(controller_->model());
  35. }
  36. private:
  37. // ProgressIndicator:
  38. absl::optional<float> CalculateProgress() const override {
  39. // If there is no `model` attached, then there are no in-progress holding
  40. // space items. Do not paint the progress indication.
  41. const HoldingSpaceModel* model = controller_->model();
  42. if (!model)
  43. return kProgressComplete;
  44. HoldingSpaceProgress cumulative_progress;
  45. // Iterate over all holding space items.
  46. for (const auto& item : model->items()) {
  47. // Ignore any holding space items that are not yet initialized, since
  48. // they are not visible to the user, or items that are not visibly
  49. // in-progress, since they do not contribute to `cumulative_progress`.
  50. if (item->IsInitialized() && !item->progress().IsHidden() &&
  51. !item->progress().IsComplete()) {
  52. cumulative_progress += item->progress();
  53. }
  54. }
  55. return cumulative_progress.GetValue();
  56. }
  57. // HoldingSpaceControllerObserver:
  58. void OnHoldingSpaceModelAttached(HoldingSpaceModel* model) override {
  59. model_observation_.Observe(model);
  60. InvalidateLayer();
  61. }
  62. void OnHoldingSpaceModelDetached(HoldingSpaceModel* model) override {
  63. model_observation_.Reset();
  64. InvalidateLayer();
  65. }
  66. // HoldingSpaceModelObserver:
  67. void OnHoldingSpaceItemsAdded(
  68. const std::vector<const HoldingSpaceItem*>& items) override {
  69. for (const HoldingSpaceItem* item : items) {
  70. if (item->IsInitialized() && !item->progress().IsComplete()) {
  71. InvalidateLayer();
  72. return;
  73. }
  74. }
  75. }
  76. void OnHoldingSpaceItemsRemoved(
  77. const std::vector<const HoldingSpaceItem*>& items) override {
  78. for (const HoldingSpaceItem* item : items) {
  79. if (item->IsInitialized() && !item->progress().IsComplete()) {
  80. InvalidateLayer();
  81. return;
  82. }
  83. }
  84. }
  85. void OnHoldingSpaceItemUpdated(const HoldingSpaceItem* item,
  86. uint32_t updated_fields) override {
  87. if (item->IsInitialized() && (updated_fields & UpdatedField::kProgress))
  88. InvalidateLayer();
  89. }
  90. void OnHoldingSpaceItemInitialized(const HoldingSpaceItem* item) override {
  91. if (!item->progress().IsComplete())
  92. InvalidateLayer();
  93. }
  94. // The associated holding space `controller_` for which to indicate progress
  95. // of all holding space items in its attached model.
  96. HoldingSpaceController* const controller_;
  97. base::ScopedObservation<HoldingSpaceController,
  98. HoldingSpaceControllerObserver>
  99. controller_observation_{this};
  100. base::ScopedObservation<HoldingSpaceModel, HoldingSpaceModelObserver>
  101. model_observation_{this};
  102. };
  103. // HoldingSpaceItemProgressIndicator -------------------------------------------
  104. // A class owning a `ui::Layer` which paints indication of progress for its
  105. // associated holding space `item_`. NOTE: The owned `layer()` is not painted if
  106. // the associated `item_` is not in progress.
  107. class HoldingSpaceItemProgressIndicator : public ProgressIndicator,
  108. public HoldingSpaceModelObserver {
  109. public:
  110. explicit HoldingSpaceItemProgressIndicator(const HoldingSpaceItem* item)
  111. : ProgressIndicator(
  112. /*animation_registry=*/HoldingSpaceAnimationRegistry::GetInstance(),
  113. /*animation_key=*/item),
  114. item_(item) {
  115. model_observation_.Observe(HoldingSpaceController::Get()->model());
  116. }
  117. private:
  118. // ProgressIndicator:
  119. absl::optional<float> CalculateProgress() const override {
  120. // If `item_` is `nullptr` it is being destroyed. Ensure the progress
  121. // indication is not painted in this case. Similarly, ensure the progress
  122. // indication is not painted when progress is hidden.
  123. return item_ && !item_->progress().IsHidden() ? item_->progress().GetValue()
  124. : kProgressComplete;
  125. }
  126. // HoldingSpaceModelObserver:
  127. void OnHoldingSpaceItemUpdated(const HoldingSpaceItem* item,
  128. uint32_t updated_fields) override {
  129. if (item_ == item && (updated_fields & UpdatedField::kProgress))
  130. InvalidateLayer();
  131. }
  132. void OnHoldingSpaceItemsRemoved(
  133. const std::vector<const HoldingSpaceItem*>& items) override {
  134. for (const HoldingSpaceItem* item : items) {
  135. if (item_ == item) {
  136. item_ = nullptr;
  137. return;
  138. }
  139. }
  140. }
  141. // The associated holding space `item` for which to indicate progress.
  142. // NOTE: May temporarily be `nullptr` during the `item`s destruction sequence.
  143. const HoldingSpaceItem* item_ = nullptr;
  144. base::ScopedObservation<HoldingSpaceModel, HoldingSpaceModelObserver>
  145. model_observation_{this};
  146. };
  147. } // namespace
  148. // Utilities -------------------------------------------------------------------
  149. std::unique_ptr<ProgressIndicator> CreateProgressIndicatorForController(
  150. HoldingSpaceController* controller) {
  151. return std::make_unique<HoldingSpaceControllerProgressIndicator>(controller);
  152. }
  153. std::unique_ptr<ProgressIndicator> CreateProgressIndicatorForItem(
  154. const HoldingSpaceItem* item) {
  155. return std::make_unique<HoldingSpaceItemProgressIndicator>(item);
  156. }
  157. } // namespace holding_space_util
  158. } // namespace ash