camera_roll_view.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2021 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/phonehub/camera_roll_view.h"
  5. #include <string>
  6. #include "ash/strings/grit/ash_strings.h"
  7. #include "ash/style/ash_color_provider.h"
  8. #include "ash/system/phonehub/camera_roll_thumbnail.h"
  9. #include "ash/system/phonehub/phone_hub_metrics.h"
  10. #include "ash/system/phonehub/phone_hub_view_ids.h"
  11. #include "ash/system/phonehub/ui_constants.h"
  12. #include "ash/system/tray/tray_constants.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "ui/base/l10n/l10n_util.h"
  15. #include "ui/gfx/text_constants.h"
  16. #include "ui/views/animation/animation_builder.h"
  17. #include "ui/views/controls/label.h"
  18. #include "ui/views/layout/box_layout.h"
  19. namespace ash {
  20. namespace {
  21. // Appearance constants in dip.
  22. constexpr int kCameraRollItemsInRow = 4;
  23. constexpr int kCameraRollItemHorizontalSpacing = 8;
  24. constexpr int kCameraRollItemVerticalSpacing = 8;
  25. constexpr int kCameraRollItemHorizontalPadding = 4;
  26. constexpr int kCameraRollItemVerticalPadding = 4;
  27. constexpr int kHeaderLabelLineHeight = 48;
  28. // Typography.
  29. constexpr int kHeaderTextFontSizeDip = 15;
  30. gfx::Size GetCameraRollItemSize() {
  31. int dimension =
  32. (kTrayMenuWidth - kBubbleHorizontalSidePaddingDip * 2 -
  33. kCameraRollItemHorizontalPadding * 2 -
  34. kCameraRollItemHorizontalSpacing * (kCameraRollItemsInRow - 1)) /
  35. kCameraRollItemsInRow;
  36. return gfx::Size(dimension, dimension);
  37. }
  38. class HeaderView : public views::Label {
  39. public:
  40. HeaderView() {
  41. SetText(l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_CAMERA_ROLL_TITLE));
  42. SetLineHeight(kHeaderLabelLineHeight);
  43. SetFontList(font_list()
  44. .DeriveWithSizeDelta(kHeaderTextFontSizeDip -
  45. font_list().GetFontSize())
  46. .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
  47. SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
  48. SetVerticalAlignment(gfx::VerticalAlignment::ALIGN_MIDDLE);
  49. SetAutoColorReadabilityEnabled(false);
  50. SetSubpixelRenderingEnabled(false);
  51. SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
  52. AshColorProvider::ContentLayerType::kTextColorPrimary));
  53. }
  54. ~HeaderView() override = default;
  55. HeaderView(HeaderView&) = delete;
  56. HeaderView operator=(HeaderView&) = delete;
  57. // views::View:
  58. const char* GetClassName() const override { return "HeaderView"; }
  59. };
  60. } // namespace
  61. CameraRollView::CameraRollView(
  62. phonehub::CameraRollManager* camera_roll_manager,
  63. phonehub::UserActionRecorder* user_action_recorder)
  64. : camera_roll_manager_(camera_roll_manager),
  65. user_action_recorder_(user_action_recorder) {
  66. SetID(PhoneHubViewID::kCameraRollView);
  67. auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
  68. views::BoxLayout::Orientation::kVertical));
  69. layout->set_cross_axis_alignment(
  70. views::BoxLayout::CrossAxisAlignment::kStart);
  71. AddChildView(std::make_unique<HeaderView>());
  72. items_view_ = AddChildView(std::make_unique<CameraRollItemsView>());
  73. Update();
  74. camera_roll_manager_->AddObserver(this);
  75. }
  76. CameraRollView::~CameraRollView() {
  77. camera_roll_manager_->RemoveObserver(this);
  78. }
  79. void CameraRollView::OnCameraRollViewUiStateUpdated() {
  80. Update();
  81. }
  82. const char* CameraRollView::GetClassName() const {
  83. return "CameraRollView";
  84. }
  85. CameraRollView::CameraRollItemsView::CameraRollItemsView() = default;
  86. CameraRollView::CameraRollItemsView::~CameraRollItemsView() = default;
  87. void CameraRollView::CameraRollItemsView::AddCameraRollItem(
  88. views::View* camera_roll_item) {
  89. size_t view_size = camera_roll_items_.view_size();
  90. camera_roll_items_.Add(camera_roll_item, view_size);
  91. AddChildView(camera_roll_item);
  92. }
  93. void CameraRollView::CameraRollItemsView::Reset() {
  94. camera_roll_items_.Clear();
  95. RemoveAllChildViews();
  96. }
  97. // views::View:
  98. gfx::Size CameraRollView::CameraRollItemsView::CalculatePreferredSize() const {
  99. auto item_size = GetCameraRollItemSize();
  100. int width = item_size.width() * kCameraRollItemsInRow +
  101. kCameraRollItemHorizontalSpacing * (kCameraRollItemsInRow - 1) +
  102. kCameraRollItemHorizontalPadding * 2;
  103. int rows_num =
  104. std::ceil((double)camera_roll_items_.view_size() / kCameraRollItemsInRow);
  105. int height = (item_size.height() + kCameraRollItemVerticalSpacing) *
  106. std::max(0, rows_num - 1) +
  107. item_size.height() + kCameraRollItemVerticalPadding * 2;
  108. return gfx::Size(width, height);
  109. }
  110. void CameraRollView::CameraRollItemsView::Layout() {
  111. views::View::Layout();
  112. CalculateIdealBounds();
  113. for (size_t i = 0; i < camera_roll_items_.view_size(); ++i) {
  114. auto* thumbnail = camera_roll_items_.view_at(i);
  115. thumbnail->SetBoundsRect(camera_roll_items_.ideal_bounds(i));
  116. }
  117. }
  118. const char* CameraRollView::CameraRollItemsView::GetClassName() const {
  119. return "CameraRollItemsView";
  120. }
  121. gfx::Point CameraRollView::CameraRollItemsView::GetCameraRollItemPosition(
  122. int index) {
  123. auto item_size = GetCameraRollItemSize();
  124. int row = index / kCameraRollItemsInRow;
  125. int column = index % kCameraRollItemsInRow;
  126. int x = (item_size.width() + kCameraRollItemHorizontalSpacing) * column +
  127. kCameraRollItemHorizontalPadding;
  128. int y = (item_size.height() + kCameraRollItemVerticalSpacing) * row +
  129. kCameraRollItemVerticalPadding;
  130. return gfx::Point(x, y);
  131. }
  132. void CameraRollView::CameraRollItemsView::CalculateIdealBounds() {
  133. for (size_t i = 0; i < camera_roll_items_.view_size(); ++i) {
  134. gfx::Rect camera_roll_item_bounds =
  135. gfx::Rect(GetCameraRollItemPosition(i), GetCameraRollItemSize());
  136. camera_roll_items_.set_ideal_bounds(i, camera_roll_item_bounds);
  137. }
  138. }
  139. void CameraRollView::Update() {
  140. items_view_->Reset();
  141. phonehub::CameraRollManager::CameraRollUiState current_ui_state =
  142. camera_roll_manager_->ui_state();
  143. switch (current_ui_state) {
  144. case phonehub::CameraRollManager::CameraRollUiState::SHOULD_HIDE:
  145. case phonehub::CameraRollManager::CameraRollUiState::NO_STORAGE_PERMISSION:
  146. SetVisible(false);
  147. break;
  148. case phonehub::CameraRollManager::CameraRollUiState::ITEMS_VISIBLE:
  149. items_view_->SetVisible(true);
  150. SetVisible(true);
  151. const std::vector<phonehub::CameraRollItem> camera_roll_items =
  152. camera_roll_manager_->current_items();
  153. for (size_t index = 0; index < camera_roll_items.size(); index++) {
  154. CameraRollThumbnail* item_thumbnail = new CameraRollThumbnail(
  155. index, camera_roll_items.at(index), camera_roll_manager_,
  156. user_action_recorder_);
  157. const std::u16string accessible_name = l10n_util::GetStringFUTF16(
  158. IDS_ASH_PHONE_HUB_CAMERA_ROLL_THUMBNAIL_ACCESSIBLE_NAME,
  159. base::NumberToString16(index + 1),
  160. base::NumberToString16(camera_roll_items.size()));
  161. item_thumbnail->SetAccessibleName(accessible_name);
  162. item_thumbnail->SetTooltipText(accessible_name);
  163. items_view_->AddCameraRollItem(item_thumbnail);
  164. }
  165. if (!content_present_metric_emitted_) {
  166. phone_hub_metrics::LogCameraRollContentPresent();
  167. content_present_metric_emitted_ = true;
  168. }
  169. break;
  170. }
  171. PreferredSizeChanged();
  172. }
  173. } // namespace ash