tray_popup_utils.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // Copyright 2016 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/tray/tray_popup_utils.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <utility>
  8. #include "ash/constants/ash_constants.h"
  9. #include "ash/public/cpp/ash_view_ids.h"
  10. #include "ash/resources/vector_icons/vector_icons.h"
  11. #include "ash/session/session_controller_impl.h"
  12. #include "ash/shell.h"
  13. #include "ash/style/ash_color_provider.h"
  14. #include "ash/system/tray/hover_highlight_view.h"
  15. #include "ash/system/tray/size_range_layout.h"
  16. #include "ash/system/tray/tray_constants.h"
  17. #include "ash/system/tray/tray_utils.h"
  18. #include "ash/system/tray/unfocusable_label.h"
  19. #include "base/bind.h"
  20. #include "chromeos/ui/vector_icons/vector_icons.h"
  21. #include "ui/base/l10n/l10n_util.h"
  22. #include "ui/color/color_id.h"
  23. #include "ui/compositor/layer.h"
  24. #include "ui/gfx/color_palette.h"
  25. #include "ui/gfx/geometry/insets.h"
  26. #include "ui/gfx/geometry/rrect_f.h"
  27. #include "ui/gfx/paint_vector_icon.h"
  28. #include "ui/gfx/vector_icon_utils.h"
  29. #include "ui/views/border.h"
  30. #include "ui/views/controls/button/button.h"
  31. #include "ui/views/controls/button/md_text_button.h"
  32. #include "ui/views/controls/highlight_path_generator.h"
  33. #include "ui/views/controls/image_view.h"
  34. #include "ui/views/controls/label.h"
  35. #include "ui/views/controls/separator.h"
  36. #include "ui/views/controls/slider.h"
  37. #include "ui/views/layout/box_layout.h"
  38. #include "ui/views/layout/fill_layout.h"
  39. #include "ui/views/painter.h"
  40. namespace ash {
  41. namespace {
  42. // Creates a layout manager that positions Views vertically. The Views will be
  43. // stretched horizontally and centered vertically.
  44. std::unique_ptr<views::LayoutManager> CreateDefaultCenterLayoutManager() {
  45. // TODO(bruthig): Use constants instead of magic numbers.
  46. auto box_layout = std::make_unique<views::BoxLayout>(
  47. views::BoxLayout::Orientation::kVertical,
  48. gfx::Insets::VH(8, kTrayPopupLabelHorizontalPadding));
  49. box_layout->set_main_axis_alignment(
  50. views::BoxLayout::MainAxisAlignment::kCenter);
  51. box_layout->set_cross_axis_alignment(
  52. views::BoxLayout::CrossAxisAlignment::kStretch);
  53. return box_layout;
  54. }
  55. // Creates a layout manager that positions Views horizontally. The Views will be
  56. // centered along the horizontal and vertical axis.
  57. std::unique_ptr<views::LayoutManager> CreateDefaultEndsLayoutManager() {
  58. auto box_layout = std::make_unique<views::BoxLayout>(
  59. views::BoxLayout::Orientation::kHorizontal);
  60. box_layout->set_main_axis_alignment(
  61. views::BoxLayout::MainAxisAlignment::kCenter);
  62. box_layout->set_cross_axis_alignment(
  63. views::BoxLayout::CrossAxisAlignment::kCenter);
  64. return box_layout;
  65. }
  66. std::unique_ptr<views::LayoutManager> CreateDefaultLayoutManager(
  67. TriView::Container container) {
  68. switch (container) {
  69. case TriView::Container::START:
  70. case TriView::Container::END:
  71. return CreateDefaultEndsLayoutManager();
  72. case TriView::Container::CENTER:
  73. return CreateDefaultCenterLayoutManager();
  74. }
  75. // Required by some compilers.
  76. NOTREACHED();
  77. return nullptr;
  78. }
  79. // Configures the default size and flex value for the specified |container|
  80. // of the given |tri_view|. Used by CreateDefaultRowView().
  81. void ConfigureDefaultSizeAndFlex(TriView* tri_view,
  82. TriView::Container container) {
  83. int min_width = 0;
  84. switch (container) {
  85. case TriView::Container::START:
  86. min_width = kTrayPopupItemMinStartWidth;
  87. break;
  88. case TriView::Container::CENTER:
  89. tri_view->SetFlexForContainer(TriView::Container::CENTER, 1.f);
  90. break;
  91. case TriView::Container::END:
  92. min_width = kTrayPopupItemMinEndWidth;
  93. break;
  94. }
  95. tri_view->SetMinSize(container,
  96. gfx::Size(min_width, kTrayPopupItemMinHeight));
  97. constexpr int kTrayPopupItemMaxHeight = 144;
  98. tri_view->SetMaxSize(container, gfx::Size(SizeRangeLayout::kAbsoluteMaxSize,
  99. kTrayPopupItemMaxHeight));
  100. }
  101. class HighlightPathGenerator : public views::HighlightPathGenerator {
  102. public:
  103. explicit HighlightPathGenerator(TrayPopupInkDropStyle ink_drop_style)
  104. : ink_drop_style_(ink_drop_style) {}
  105. HighlightPathGenerator(const HighlightPathGenerator&) = delete;
  106. HighlightPathGenerator& operator=(const HighlightPathGenerator&) = delete;
  107. // views::HighlightPathGenerator:
  108. absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override {
  109. gfx::RectF bounds = rect;
  110. bounds.Inset(gfx::InsetsF(GetInkDropInsets(ink_drop_style_)));
  111. float corner_radius = 0.f;
  112. switch (ink_drop_style_) {
  113. case TrayPopupInkDropStyle::HOST_CENTERED:
  114. corner_radius = std::min(bounds.width(), bounds.height()) / 2.f;
  115. bounds.ClampToCenteredSize(gfx::SizeF(corner_radius, corner_radius));
  116. break;
  117. case TrayPopupInkDropStyle::INSET_BOUNDS:
  118. corner_radius = kTrayPopupInkDropCornerRadius;
  119. break;
  120. case TrayPopupInkDropStyle::FILL_BOUNDS:
  121. break;
  122. }
  123. return gfx::RRectF(bounds, corner_radius);
  124. }
  125. private:
  126. const TrayPopupInkDropStyle ink_drop_style_;
  127. };
  128. } // namespace
  129. TriView* TrayPopupUtils::CreateDefaultRowView() {
  130. TriView* tri_view = CreateMultiTargetRowView();
  131. tri_view->SetContainerLayout(
  132. TriView::Container::START,
  133. CreateDefaultLayoutManager(TriView::Container::START));
  134. tri_view->SetContainerLayout(
  135. TriView::Container::CENTER,
  136. CreateDefaultLayoutManager(TriView::Container::CENTER));
  137. tri_view->SetContainerLayout(
  138. TriView::Container::END,
  139. CreateDefaultLayoutManager(TriView::Container::END));
  140. return tri_view;
  141. }
  142. TriView* TrayPopupUtils::CreateSubHeaderRowView(bool start_visible) {
  143. TriView* tri_view = CreateDefaultRowView();
  144. if (!start_visible) {
  145. tri_view->SetInsets(gfx::Insets::TLBR(
  146. 0, kTrayPopupPaddingHorizontal - kTrayPopupLabelHorizontalPadding, 0,
  147. 0));
  148. tri_view->SetContainerVisible(TriView::Container::START, false);
  149. }
  150. return tri_view;
  151. }
  152. TriView* TrayPopupUtils::CreateMultiTargetRowView() {
  153. TriView* tri_view = new TriView(0 /* padding_between_items */);
  154. tri_view->SetInsets(gfx::Insets::TLBR(0, kMenuExtraMarginFromLeftEdge, 0, 0));
  155. ConfigureDefaultSizeAndFlex(tri_view, TriView::Container::START);
  156. ConfigureDefaultSizeAndFlex(tri_view, TriView::Container::CENTER);
  157. ConfigureDefaultSizeAndFlex(tri_view, TriView::Container::END);
  158. tri_view->SetContainerLayout(TriView::Container::START,
  159. std::make_unique<views::FillLayout>());
  160. tri_view->SetContainerLayout(TriView::Container::CENTER,
  161. std::make_unique<views::FillLayout>());
  162. tri_view->SetContainerLayout(TriView::Container::END,
  163. std::make_unique<views::FillLayout>());
  164. return tri_view;
  165. }
  166. views::Label* TrayPopupUtils::CreateDefaultLabel() {
  167. views::Label* label = new views::Label();
  168. label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  169. label->SetSubpixelRenderingEnabled(false);
  170. return label;
  171. }
  172. UnfocusableLabel* TrayPopupUtils::CreateUnfocusableLabel() {
  173. UnfocusableLabel* label = new UnfocusableLabel();
  174. label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  175. label->SetSubpixelRenderingEnabled(false);
  176. return label;
  177. }
  178. views::ImageView* TrayPopupUtils::CreateMainImageView() {
  179. auto* image = new views::ImageView;
  180. image->SetPreferredSize(
  181. gfx::Size(kTrayPopupItemMinStartWidth, kTrayPopupItemMinHeight));
  182. return image;
  183. }
  184. std::unique_ptr<views::Painter> TrayPopupUtils::CreateFocusPainter() {
  185. return views::Painter::CreateSolidFocusPainter(
  186. AshColorProvider::Get()->GetControlsLayerColor(
  187. AshColorProvider::ControlsLayerType::kFocusRingColor),
  188. kFocusBorderThickness, gfx::InsetsF());
  189. }
  190. void TrayPopupUtils::ConfigureAsStickyHeader(views::View* view) {
  191. view->SetID(VIEW_ID_STICKY_HEADER);
  192. view->SetBorder(views::CreateEmptyBorder(
  193. gfx::Insets::VH(kMenuSeparatorVerticalPadding, 0)));
  194. view->SetPaintToLayer();
  195. view->layer()->SetFillsBoundsOpaquely(false);
  196. }
  197. void TrayPopupUtils::ConfigureContainer(TriView::Container container,
  198. views::View* container_view) {
  199. container_view->SetLayoutManager(CreateDefaultLayoutManager(container));
  200. }
  201. views::LabelButton* TrayPopupUtils::CreateTrayPopupButton(
  202. views::Button::PressedCallback callback,
  203. const std::u16string& text) {
  204. auto button =
  205. std::make_unique<views::MdTextButton>(std::move(callback), text);
  206. button->SetProminent(true);
  207. return button.release();
  208. }
  209. views::Separator* TrayPopupUtils::CreateVerticalSeparator() {
  210. views::Separator* separator = new views::Separator();
  211. separator->SetPreferredLength(24);
  212. separator->SetColorId(ui::kColorAshSystemUIMenuSeparator);
  213. return separator;
  214. }
  215. void TrayPopupUtils::InstallHighlightPathGenerator(
  216. views::View* host,
  217. TrayPopupInkDropStyle ink_drop_style) {
  218. views::HighlightPathGenerator::Install(
  219. host, std::make_unique<HighlightPathGenerator>(ink_drop_style));
  220. }
  221. views::Separator* TrayPopupUtils::CreateListSubHeaderSeparator() {
  222. views::Separator* separator = new views::Separator();
  223. separator->SetColorId(ui::kColorAshSystemUIMenuSeparator);
  224. separator->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR(
  225. kMenuSeparatorVerticalPadding - views::Separator::kThickness, 0, 0, 0)));
  226. return separator;
  227. }
  228. views::Separator* TrayPopupUtils::CreateListItemSeparator(bool left_inset) {
  229. views::Separator* separator = new views::Separator();
  230. separator->SetColorId(ui::kColorAshSystemUIMenuSeparator);
  231. separator->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR(
  232. kMenuSeparatorVerticalPadding - views::Separator::kThickness,
  233. left_inset ? kMenuExtraMarginFromLeftEdge + kMenuButtonSize +
  234. kTrayPopupLabelHorizontalPadding
  235. : 0,
  236. kMenuSeparatorVerticalPadding, 0)));
  237. return separator;
  238. }
  239. bool TrayPopupUtils::CanOpenWebUISettings() {
  240. return Shell::Get()->session_controller()->ShouldEnableSettings();
  241. }
  242. void TrayPopupUtils::InitializeAsCheckableRow(HoverHighlightView* container,
  243. bool checked,
  244. bool enterprise_managed) {
  245. const int dip_size = GetDefaultSizeOfVectorIcon(kCheckCircleIcon);
  246. gfx::ImageSkia check_mark = CreateVectorIcon(
  247. kHollowCheckCircleIcon, dip_size,
  248. AshColorProvider::Get()->GetContentLayerColor(
  249. AshColorProvider::ContentLayerType::kIconColorProminent));
  250. if (enterprise_managed) {
  251. gfx::ImageSkia enterprise_managed_icon = CreateVectorIcon(
  252. chromeos::kEnterpriseIcon, dip_size, gfx::kGoogleGrey100);
  253. container->AddRightIcon(enterprise_managed_icon,
  254. enterprise_managed_icon.width());
  255. }
  256. container->AddRightIcon(check_mark, check_mark.width());
  257. UpdateCheckMarkVisibility(container, checked);
  258. }
  259. void TrayPopupUtils::UpdateCheckMarkVisibility(HoverHighlightView* container,
  260. bool visible) {
  261. container->SetRightViewVisible(visible);
  262. container->SetAccessibilityState(
  263. visible ? HoverHighlightView::AccessibilityState::CHECKED_CHECKBOX
  264. : HoverHighlightView::AccessibilityState::UNCHECKED_CHECKBOX);
  265. }
  266. void TrayPopupUtils::SetLabelFontList(views::Label* label, FontStyle style) {
  267. label->SetAutoColorReadabilityEnabled(false);
  268. const gfx::FontList google_sans_font_list({"Google Sans"}, gfx::Font::NORMAL,
  269. 16, gfx::Font::Weight::MEDIUM);
  270. const gfx::FontList roboto_font_list({"Roboto"}, gfx::Font::NORMAL, 16,
  271. gfx::Font::Weight::MEDIUM);
  272. switch (style) {
  273. case FontStyle::kTitle:
  274. label->SetFontList(google_sans_font_list);
  275. break;
  276. case FontStyle::kPodMenuHeader:
  277. label->SetFontList(roboto_font_list);
  278. break;
  279. case FontStyle::kSubHeader:
  280. label->SetFontList(roboto_font_list.Derive(-1, gfx::Font::NORMAL,
  281. gfx::Font::Weight::MEDIUM));
  282. break;
  283. case FontStyle::kSmallTitle:
  284. label->SetFontList(roboto_font_list.Derive(-3, gfx::Font::NORMAL,
  285. gfx::Font::Weight::MEDIUM));
  286. break;
  287. case FontStyle::kDetailedViewLabel:
  288. case FontStyle::kSystemInfo:
  289. label->SetFontList(roboto_font_list.Derive(-4, gfx::Font::NORMAL,
  290. gfx::Font::Weight::NORMAL));
  291. break;
  292. }
  293. }
  294. } // namespace ash