top_icon_animation_view.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2014 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/app_list/views/top_icon_animation_view.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/app_list/views/app_list_item_view.h"
  8. #include "ash/app_list/views/apps_grid_view.h"
  9. #include "ash/public/cpp/app_list/app_list_color_provider.h"
  10. #include "ash/public/cpp/app_list/app_list_config.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "ui/compositor/layer.h"
  13. #include "ui/compositor/scoped_layer_animation_settings.h"
  14. #include "ui/gfx/image/image_skia_operations.h"
  15. #include "ui/views/controls/image_view.h"
  16. #include "ui/views/controls/label.h"
  17. namespace ash {
  18. TopIconAnimationView::TopIconAnimationView(AppsGridView* grid,
  19. const gfx::ImageSkia& icon,
  20. const std::u16string& title,
  21. const gfx::Rect& scaled_rect,
  22. bool open_folder,
  23. bool item_in_folder_icon)
  24. : grid_(grid),
  25. icon_(nullptr),
  26. title_(nullptr),
  27. scaled_rect_(scaled_rect),
  28. open_folder_(open_folder),
  29. item_in_folder_icon_(item_in_folder_icon) {
  30. icon_size_ = grid->app_list_config()->grid_icon_size();
  31. DCHECK(!icon.isNull());
  32. gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage(
  33. icon, skia::ImageOperations::RESIZE_BEST, icon_size_));
  34. auto icon_image = std::make_unique<views::ImageView>();
  35. icon_image->SetImage(resized);
  36. icon_ = AddChildView(std::move(icon_image));
  37. auto title_label = std::make_unique<views::Label>();
  38. title_label->SetBackgroundColor(SK_ColorTRANSPARENT);
  39. title_label->SetAutoColorReadabilityEnabled(false);
  40. title_label->SetHandlesTooltips(false);
  41. title_label->SetFontList(grid_->app_list_config()->app_title_font());
  42. title_label->SetLineHeight(
  43. grid_->app_list_config()->app_title_max_line_height());
  44. title_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
  45. title_label->SetEnabledColor(
  46. AppListColorProvider::Get()->GetAppListItemTextColor(
  47. /*is_in_folder=*/true));
  48. title_label->SetText(title);
  49. if (item_in_folder_icon_) {
  50. // The title's opacity of the item should be changed separately if it is in
  51. // the folder item's icon.
  52. title_label->SetPaintToLayer();
  53. title_label->layer()->SetFillsBoundsOpaquely(false);
  54. }
  55. title_ = AddChildView(std::move(title_label));
  56. SetPaintToLayer();
  57. layer()->SetFillsBoundsOpaquely(false);
  58. }
  59. TopIconAnimationView::~TopIconAnimationView() {
  60. // Required due to RequiresNotificationWhenAnimatorDestroyed() returning true.
  61. // See ui::LayerAnimationObserver for details.
  62. StopObservingImplicitAnimations();
  63. }
  64. void TopIconAnimationView::AddObserver(TopIconAnimationObserver* observer) {
  65. observers_.AddObserver(observer);
  66. }
  67. void TopIconAnimationView::RemoveObserver(TopIconAnimationObserver* observer) {
  68. observers_.RemoveObserver(observer);
  69. }
  70. void TopIconAnimationView::TransformView(base::TimeDelta duration) {
  71. // Transform used for scaling down the icon and move it back inside to the
  72. // original folder icon. The transform's origin is this view's origin.
  73. gfx::Transform transform;
  74. transform.Translate(scaled_rect_.x() - GetMirroredX(),
  75. scaled_rect_.y() - bounds().y());
  76. transform.Scale(
  77. static_cast<double>(scaled_rect_.width()) / bounds().width(),
  78. static_cast<double>(scaled_rect_.height()) / bounds().height());
  79. if (open_folder_) {
  80. // Transform to a scaled down icon inside the original folder icon.
  81. layer()->SetTransform(transform);
  82. }
  83. if (!item_in_folder_icon_)
  84. layer()->SetOpacity(open_folder_ ? 0.0f : 1.0f);
  85. // Animate the icon to its target location and scale when opening or
  86. // closing a folder.
  87. ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
  88. settings.AddObserver(this);
  89. settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
  90. settings.SetTransitionDuration(duration);
  91. layer()->SetTransform(open_folder_ ? gfx::Transform() : transform);
  92. if (!item_in_folder_icon_)
  93. layer()->SetOpacity(open_folder_ ? 1.0f : 0.0f);
  94. if (item_in_folder_icon_) {
  95. // Animate the opacity of the title.
  96. title_->layer()->SetOpacity(open_folder_ ? 0.0f : 1.0f);
  97. ui::ScopedLayerAnimationSettings title_settings(
  98. title_->layer()->GetAnimator());
  99. title_settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
  100. title_settings.SetTransitionDuration(duration);
  101. title_->layer()->SetOpacity(open_folder_ ? 1.0f : 0.0f);
  102. }
  103. }
  104. const char* TopIconAnimationView::GetClassName() const {
  105. return "TopIconAnimationView";
  106. }
  107. gfx::Size TopIconAnimationView::CalculatePreferredSize() const {
  108. return gfx::Size(grid_->app_list_config()->grid_tile_width(),
  109. grid_->app_list_config()->grid_tile_height());
  110. }
  111. void TopIconAnimationView::Layout() {
  112. // This view's layout should be the same as AppListItemView's.
  113. gfx::Rect rect(GetContentsBounds());
  114. if (rect.IsEmpty())
  115. return;
  116. icon_->SetBoundsRect(AppListItemView::GetIconBoundsForTargetViewBounds(
  117. grid_->app_list_config(), rect, icon_->GetImage().size(),
  118. /*icon_scale=*/1.0f));
  119. title_->SetBoundsRect(AppListItemView::GetTitleBoundsForTargetViewBounds(
  120. grid_->app_list_config(), rect, title_->GetPreferredSize(),
  121. /*icon_scale=*/1.0f));
  122. }
  123. void TopIconAnimationView::OnImplicitAnimationsCompleted() {
  124. SetVisible(false);
  125. for (auto& observer : observers_)
  126. observer.OnTopIconAnimationsComplete(this);
  127. DCHECK(parent());
  128. base::ThreadTaskRunnerHandle::Get()->DeleteSoon(
  129. FROM_HERE, parent()->RemoveChildViewT(this));
  130. }
  131. bool TopIconAnimationView::RequiresNotificationWhenAnimatorDestroyed() const {
  132. return true;
  133. }
  134. } // namespace ash