task_continuation_view.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright 2020 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/task_continuation_view.h"
  5. #include "ash/strings/grit/ash_strings.h"
  6. #include "ash/style/ash_color_provider.h"
  7. #include "ash/system/phonehub/continue_browsing_chip.h"
  8. #include "ash/system/phonehub/phone_hub_view_ids.h"
  9. #include "ash/system/phonehub/ui_constants.h"
  10. #include "ash/system/tray/tray_constants.h"
  11. #include "ui/base/l10n/l10n_util.h"
  12. #include "ui/gfx/geometry/insets.h"
  13. #include "ui/gfx/text_constants.h"
  14. #include "ui/views/controls/label.h"
  15. #include "ui/views/layout/box_layout.h"
  16. namespace ash {
  17. namespace {
  18. // Appearance constants in dip.
  19. constexpr int kTaskContinuationChipHeight = 96;
  20. constexpr int kTaskContinuationChipsInRow = 2;
  21. constexpr int kTaskContinuationChipSpacing = 8;
  22. constexpr int kTaskContinuationChipHorizontalSidePadding = 4;
  23. constexpr int kTaskContinuationChipVerticalPadding = 4;
  24. constexpr int kHeaderLabelLineHeight = 48;
  25. // Typography.
  26. constexpr int kHeaderTextFontSizeDip = 15;
  27. gfx::Size GetTaskContinuationChipSize() {
  28. int width =
  29. (kTrayMenuWidth - kBubbleHorizontalSidePaddingDip * 2 -
  30. kTaskContinuationChipHorizontalSidePadding * 2 -
  31. kTaskContinuationChipSpacing * (kTaskContinuationChipsInRow - 1)) /
  32. kTaskContinuationChipsInRow;
  33. return gfx::Size(width, kTaskContinuationChipHeight);
  34. }
  35. class HeaderView : public views::Label {
  36. public:
  37. HeaderView() {
  38. SetText(
  39. l10n_util::GetStringUTF16(IDS_ASH_PHONE_HUB_TASK_CONTINUATION_TITLE));
  40. SetLineHeight(kHeaderLabelLineHeight);
  41. SetFontList(font_list()
  42. .DeriveWithSizeDelta(kHeaderTextFontSizeDip -
  43. font_list().GetFontSize())
  44. .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
  45. SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
  46. SetVerticalAlignment(gfx::VerticalAlignment::ALIGN_MIDDLE);
  47. SetAutoColorReadabilityEnabled(false);
  48. SetSubpixelRenderingEnabled(false);
  49. SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
  50. AshColorProvider::ContentLayerType::kTextColorPrimary));
  51. }
  52. ~HeaderView() override = default;
  53. HeaderView(HeaderView&) = delete;
  54. HeaderView operator=(HeaderView&) = delete;
  55. // views::View:
  56. const char* GetClassName() const override { return "HeaderView"; }
  57. };
  58. } // namespace
  59. TaskContinuationView::TaskContinuationView(
  60. phonehub::PhoneModel* phone_model,
  61. phonehub::UserActionRecorder* user_action_recorder)
  62. : phone_model_(phone_model), user_action_recorder_(user_action_recorder) {
  63. SetID(PhoneHubViewID::kTaskContinuationView);
  64. phone_model_->AddObserver(this);
  65. auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
  66. views::BoxLayout::Orientation::kVertical));
  67. layout->set_cross_axis_alignment(
  68. views::BoxLayout::CrossAxisAlignment::kStart);
  69. AddChildView(std::make_unique<HeaderView>());
  70. chips_view_ = AddChildView(std::make_unique<TaskChipsView>());
  71. Update();
  72. }
  73. TaskContinuationView::~TaskContinuationView() {
  74. phone_model_->RemoveObserver(this);
  75. }
  76. void TaskContinuationView::OnModelChanged() {
  77. Update();
  78. }
  79. const char* TaskContinuationView::GetClassName() const {
  80. return "TaskContinuationView";
  81. }
  82. TaskContinuationView::TaskChipsView::TaskChipsView() = default;
  83. TaskContinuationView::TaskChipsView::~TaskChipsView() = default;
  84. void TaskContinuationView::TaskChipsView::AddTaskChip(views::View* task_chip) {
  85. size_t view_size = task_chips_.view_size();
  86. task_chips_.Add(task_chip, view_size);
  87. AddChildView(task_chip);
  88. }
  89. // views::View:
  90. gfx::Size TaskContinuationView::TaskChipsView::CalculatePreferredSize() const {
  91. auto chip_size = GetTaskContinuationChipSize();
  92. int width = chip_size.width() * kTaskContinuationChipsInRow +
  93. kTaskContinuationChipSpacing +
  94. 2 * kTaskContinuationChipHorizontalSidePadding;
  95. int rows_num =
  96. std::ceil((double)task_chips_.view_size() / kTaskContinuationChipsInRow);
  97. int height = (chip_size.height() + kTaskContinuationChipVerticalPadding) *
  98. std::max(0, rows_num - 1) +
  99. chip_size.height() +
  100. 2 * kTaskContinuationChipHorizontalSidePadding;
  101. return gfx::Size(width, height);
  102. }
  103. void TaskContinuationView::TaskChipsView::Layout() {
  104. views::View::Layout();
  105. CalculateIdealBounds();
  106. for (size_t i = 0; i < task_chips_.view_size(); ++i) {
  107. auto* button = task_chips_.view_at(i);
  108. button->SetBoundsRect(task_chips_.ideal_bounds(i));
  109. }
  110. }
  111. const char* TaskContinuationView::TaskChipsView::GetClassName() const {
  112. return "TaskChipsView";
  113. }
  114. void TaskContinuationView::TaskChipsView::Reset() {
  115. task_chips_.Clear();
  116. RemoveAllChildViews();
  117. }
  118. gfx::Point TaskContinuationView::TaskChipsView::GetButtonPosition(int index) {
  119. auto chip_size = GetTaskContinuationChipSize();
  120. int row = index / kTaskContinuationChipsInRow;
  121. int column = index % kTaskContinuationChipsInRow;
  122. int x = (chip_size.width() + kTaskContinuationChipSpacing) * column +
  123. kTaskContinuationChipHorizontalSidePadding;
  124. int y = (chip_size.height() + kTaskContinuationChipVerticalPadding) * row +
  125. kTaskContinuationChipVerticalPadding;
  126. return gfx::Point(x, y);
  127. }
  128. void TaskContinuationView::TaskChipsView::CalculateIdealBounds() {
  129. for (size_t i = 0; i < task_chips_.view_size(); ++i) {
  130. gfx::Rect tile_bounds =
  131. gfx::Rect(GetButtonPosition(i), GetTaskContinuationChipSize());
  132. task_chips_.set_ideal_bounds(i, tile_bounds);
  133. }
  134. }
  135. void TaskContinuationView::Update() {
  136. chips_view_->Reset();
  137. if (!phone_model_->browser_tabs_model()) {
  138. SetVisible(false);
  139. return;
  140. }
  141. const phonehub::BrowserTabsModel& browser_tabs =
  142. phone_model_->browser_tabs_model().value();
  143. if (!browser_tabs.is_tab_sync_enabled() ||
  144. browser_tabs.most_recent_tabs().empty()) {
  145. SetVisible(false);
  146. return;
  147. }
  148. int index = 0;
  149. for (const phonehub::BrowserTabsModel::BrowserTabMetadata& metadata :
  150. browser_tabs.most_recent_tabs()) {
  151. chips_view_->AddTaskChip(new ContinueBrowsingChip(
  152. metadata, index, browser_tabs.most_recent_tabs().size(),
  153. user_action_recorder_));
  154. index++;
  155. }
  156. PreferredSizeChanged();
  157. SetVisible(true);
  158. }
  159. } // namespace ash