hud_header_view.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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/hud_display/hud_header_view.h"
  5. #include "ash/hud_display/hud_constants.h"
  6. #include "ash/hud_display/hud_display.h"
  7. #include "ash/hud_display/hud_properties.h"
  8. #include "ash/hud_display/solid_source_background.h"
  9. #include "ash/hud_display/tab_strip.h"
  10. #include "base/bind.h"
  11. #include "components/vector_icons/vector_icons.h"
  12. #include "ui/base/metadata/metadata_impl_macros.h"
  13. #include "ui/gfx/canvas.h"
  14. #include "ui/gfx/geometry/skia_conversions.h"
  15. #include "ui/gfx/paint_vector_icon.h"
  16. #include "ui/views/background.h"
  17. #include "ui/views/border.h"
  18. #include "ui/views/controls/button/button.h"
  19. #include "ui/views/controls/button/image_button.h"
  20. #include "ui/views/layout/box_layout.h"
  21. #include "ui/views/layout/layout_manager.h"
  22. namespace ash {
  23. namespace hud_display {
  24. namespace {
  25. // Draws bottom left rounded background triangle.
  26. class BottomLeftOuterBackground : public views::Background {
  27. public:
  28. // Background will have left bottom rounded corner with |top_rounding_radius|.
  29. BottomLeftOuterBackground(SkColor color, SkScalar top_rounding_radius)
  30. : inner_radius_(top_rounding_radius) {
  31. SetNativeControlColor(color);
  32. }
  33. BottomLeftOuterBackground(const BottomLeftOuterBackground&) = delete;
  34. BottomLeftOuterBackground& operator=(const BottomLeftOuterBackground&) =
  35. delete;
  36. ~BottomLeftOuterBackground() override = default;
  37. // views::Background
  38. void Paint(gfx::Canvas* canvas, views::View* view) const override {
  39. const SkScalar circle_size = inner_radius_ * 2;
  40. const SkScalar bottom_edge = view->height();
  41. SkPath path;
  42. path.moveTo(0, bottom_edge);
  43. /* |false| will draw straight line to the start of the arc */
  44. path.arcTo({0, bottom_edge - circle_size, circle_size, bottom_edge}, 90, 90,
  45. false);
  46. path.lineTo(0, bottom_edge);
  47. cc::PaintFlags flags;
  48. flags.setAntiAlias(true);
  49. flags.setBlendMode(SkBlendMode::kSrc);
  50. flags.setStyle(cc::PaintFlags::kFill_Style);
  51. flags.setColor(get_color());
  52. canvas->DrawPath(path, flags);
  53. }
  54. private:
  55. SkScalar inner_radius_;
  56. };
  57. // ImageButton with underline
  58. class SettingsButton : public views::ImageButton {
  59. public:
  60. METADATA_HEADER(SettingsButton);
  61. explicit SettingsButton(views::Button::PressedCallback callback)
  62. : views::ImageButton(callback) {
  63. SetImage(views::Button::ButtonState::STATE_NORMAL,
  64. gfx::CreateVectorIcon(vector_icons::kSettingsIcon,
  65. kHUDSettingsIconSize, kHUDDefaultColor));
  66. SetBorder(views::CreateEmptyBorder(kHUDSettingsIconBorder));
  67. SetProperty(kHUDClickHandler, HTCLIENT);
  68. SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY);
  69. }
  70. SettingsButton(const SettingsButton&) = delete;
  71. SettingsButton& operator=(const SettingsButton&) = delete;
  72. ~SettingsButton() override = default;
  73. protected:
  74. // ImageButton
  75. void PaintButtonContents(gfx::Canvas* canvas) override {
  76. views::ImageButton::PaintButtonContents(canvas);
  77. SkPath path;
  78. path.moveTo(0, height());
  79. path.lineTo(height(), width());
  80. cc::PaintFlags flags;
  81. flags.setAntiAlias(true);
  82. flags.setBlendMode(SkBlendMode::kSrc);
  83. flags.setStyle(cc::PaintFlags::kStroke_Style);
  84. flags.setStrokeWidth(1);
  85. flags.setColor(kHUDDefaultColor);
  86. canvas->DrawPath(path, flags);
  87. }
  88. };
  89. BEGIN_METADATA(SettingsButton, views::ImageButton)
  90. END_METADATA
  91. // Basically FillLayout that matches host size to the given data view.
  92. // Padding will take the rest of the host view to the right.
  93. class HUDHeaderLayout : public views::LayoutManager {
  94. public:
  95. HUDHeaderLayout(const views::View* data_view, views::View* padding)
  96. : data_view_(data_view), padding_(padding) {}
  97. HUDHeaderLayout(const HUDHeaderLayout&) = delete;
  98. HUDHeaderLayout& operator=(const HUDHeaderLayout&) = delete;
  99. ~HUDHeaderLayout() override = default;
  100. // views::LayoutManager:
  101. void Layout(views::View* host) override;
  102. gfx::Size GetPreferredSize(const views::View* host) const override;
  103. private:
  104. const views::View* data_view_;
  105. views::View* padding_;
  106. };
  107. gfx::Size HUDHeaderLayout::GetPreferredSize(const views::View* host) const {
  108. return data_view_->GetPreferredSize() + padding_->GetPreferredSize();
  109. }
  110. void HUDHeaderLayout::Layout(views::View* host) {
  111. // Assume there are only 3 child views (data, background and padding).
  112. DCHECK_EQ(host->children().size(), 3U);
  113. const gfx::Size preferred_size = data_view_->GetPreferredSize();
  114. for (auto* child : host->children()) {
  115. if (child != padding_) {
  116. child->SetPosition({0, 0});
  117. child->SetSize(preferred_size);
  118. }
  119. }
  120. // Layout padding
  121. padding_->SetPosition({preferred_size.width(), 0});
  122. padding_->SetSize({host->width() - preferred_size.width(), host->height()});
  123. }
  124. } // namespace
  125. ////////////////////////////////////////////////////////////////////////////////
  126. // HUDHeaderView
  127. BEGIN_METADATA(HUDHeaderView, views::View)
  128. END_METADATA
  129. HUDHeaderView::HUDHeaderView(HUDDisplayView* hud) {
  130. // Header is rendered as horizontal container with three children:
  131. // background, buttons container and padding.
  132. // Header should have background under the buttons area only.
  133. // To achieve this we have buttons container view to calculate total width,
  134. // and special layout manager that matches size of the background view to the
  135. // size of the buttons.
  136. //
  137. // There is additional "padding" view an the end to draw bottom inner
  138. // rounded piece of background.
  139. views::View* header_background =
  140. AddChildView(std::make_unique<views::View>());
  141. header_background->SetBackground(std::make_unique<SolidSourceBackground>(
  142. kHUDBackground, kHUDTabOverlayCornerRadius));
  143. views::View* header_buttons = AddChildView(std::make_unique<views::View>());
  144. header_buttons
  145. ->SetLayoutManager(std::make_unique<views::BoxLayout>(
  146. views::BoxLayout::Orientation::kHorizontal))
  147. ->set_cross_axis_alignment(
  148. views::BoxLayout::CrossAxisAlignment::kStretch);
  149. // Header does not have margin between header and data.
  150. // Data has its top margin (kHUDGraphsInset).
  151. header_buttons->SetBorder(views::CreateEmptyBorder(
  152. gfx::Insets::TLBR(kHUDInset, kHUDInset, 0, kHUDInset)));
  153. // Add buttons and tab strip.
  154. header_buttons
  155. ->AddChildView(std::make_unique<SettingsButton>(base::BindRepeating(
  156. &HUDDisplayView::OnSettingsToggle, base::Unretained(hud))))
  157. ->SetTooltipText(u"Trigger Ash HUD Settings");
  158. tab_strip_ = header_buttons->AddChildView(std::make_unique<HUDTabStrip>(hud));
  159. // Padding will take the rest of the header and draw bottom inner left
  160. // background padding.
  161. views::View* padding = AddChildView(std::make_unique<views::View>());
  162. padding->SetBackground(std::make_unique<BottomLeftOuterBackground>(
  163. kHUDBackground, kHUDTabOverlayCornerRadius));
  164. SetLayoutManager(std::make_unique<HUDHeaderLayout>(header_buttons, padding));
  165. }
  166. HUDHeaderView::~HUDHeaderView() = default;
  167. } // namespace hud_display
  168. } // namespace ash