channel_indicator_quick_settings_view.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // Copyright 2022 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/channel_indicator/channel_indicator_quick_settings_view.h"
  5. #include <algorithm>
  6. #include "ash/public/cpp/system_tray_client.h"
  7. #include "ash/resources/vector_icons/vector_icons.h"
  8. #include "ash/shell.h"
  9. #include "ash/strings/grit/ash_strings.h"
  10. #include "ash/style/icon_button.h"
  11. #include "ash/system/channel_indicator/channel_indicator_utils.h"
  12. #include "ash/system/model/system_tray_model.h"
  13. #include "ash/system/tray/tray_constants.h"
  14. #include "ui/gfx/canvas.h"
  15. #include "ui/gfx/geometry/insets.h"
  16. #include "ui/gfx/geometry/skia_conversions.h"
  17. #include "ui/views/border.h"
  18. #include "ui/views/controls/button/label_button.h"
  19. #include "ui/views/controls/highlight_path_generator.h"
  20. #include "ui/views/layout/box_layout.h"
  21. #include "ui/views/view.h"
  22. namespace ash {
  23. namespace {
  24. constexpr int kVersionButtonHeight = 32;
  25. constexpr int kVersionButtonBorderRadius = 4;
  26. constexpr int kVersionButtonImageLabelSpacing = 8;
  27. constexpr int kVersionButtonMarginVertical = 6;
  28. constexpr int kVersionButtonMarginHorizontal = 16;
  29. constexpr int kVersionButtonLargeCornerRadius = 16;
  30. constexpr int kVersionButtonSmallCornerRadius = 4;
  31. constexpr size_t kNumVersionButtonCornerRadii = 8;
  32. constexpr SkScalar
  33. kPartneredVersionButtonCorners[kNumVersionButtonCornerRadii] = {
  34. kVersionButtonLargeCornerRadius, kVersionButtonLargeCornerRadius,
  35. kVersionButtonSmallCornerRadius, kVersionButtonSmallCornerRadius,
  36. kVersionButtonSmallCornerRadius, kVersionButtonSmallCornerRadius,
  37. kVersionButtonLargeCornerRadius, kVersionButtonLargeCornerRadius};
  38. constexpr SkScalar
  39. kStandaloneVersionButtonCorners[kNumVersionButtonCornerRadii] = {
  40. kVersionButtonLargeCornerRadius, kVersionButtonLargeCornerRadius,
  41. kVersionButtonLargeCornerRadius, kVersionButtonLargeCornerRadius,
  42. kVersionButtonLargeCornerRadius, kVersionButtonLargeCornerRadius,
  43. kVersionButtonLargeCornerRadius, kVersionButtonLargeCornerRadius};
  44. constexpr int kSubmitFeedbackButtonMarginVertical = 6;
  45. constexpr int kSubmitFeedbackButtonMarginHorizontal = 16;
  46. constexpr int kSubmitFeedbackButtonLargeCornerRadius = 16;
  47. constexpr int kSubmitFeedbackButtonSmallCornerRadius = 4;
  48. constexpr SkScalar kSubmitFeedbackButtonCorners[] = {
  49. kSubmitFeedbackButtonSmallCornerRadius,
  50. kSubmitFeedbackButtonSmallCornerRadius,
  51. kSubmitFeedbackButtonLargeCornerRadius,
  52. kSubmitFeedbackButtonLargeCornerRadius,
  53. kSubmitFeedbackButtonLargeCornerRadius,
  54. kSubmitFeedbackButtonLargeCornerRadius,
  55. kSubmitFeedbackButtonSmallCornerRadius,
  56. kSubmitFeedbackButtonSmallCornerRadius};
  57. constexpr int kButtonSpacing = 2;
  58. // VersionButton is a base class that provides a styled button, for devices on a
  59. // non-stable release track, that has a label for the channel and ChromeOS
  60. // version.
  61. class VersionButton : public views::LabelButton {
  62. public:
  63. VersionButton(version_info::Channel channel,
  64. const SkScalar (&corners)[kNumVersionButtonCornerRadii])
  65. : LabelButton(
  66. base::BindRepeating([] {
  67. Shell::Get()
  68. ->system_tray_model()
  69. ->client()
  70. ->ShowChannelInfoAdditionalDetails();
  71. }),
  72. channel_indicator_utils::GetFullReleaseTrackString(channel)),
  73. channel_(channel) {
  74. std::copy(corners, corners + kNumVersionButtonCornerRadii, corners_);
  75. SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(
  76. kVersionButtonMarginVertical, kVersionButtonMarginHorizontal)));
  77. SetImageLabelSpacing(kVersionButtonImageLabelSpacing);
  78. SetMinSize(gfx::Size(0, kVersionButtonHeight));
  79. SetFocusBehavior(FocusBehavior::ALWAYS);
  80. SetInstallFocusRingOnFocus(true);
  81. views::FocusRing::Get(this)->SetColorId(ui::kColorAshFocusRing);
  82. views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(),
  83. kVersionButtonBorderRadius);
  84. }
  85. VersionButton(const VersionButton&) = delete;
  86. VersionButton& operator=(const VersionButton&) = delete;
  87. ~VersionButton() override = default;
  88. // views::LabelButton:
  89. void PaintButtonContents(gfx::Canvas* canvas) override {
  90. cc::PaintFlags flags;
  91. flags.setColor(channel_indicator_utils::GetBgColor(channel_));
  92. flags.setStyle(cc::PaintFlags::kFill_Style);
  93. canvas->DrawPath(SkPath().addRoundRect(gfx::RectToSkRect(GetLocalBounds()),
  94. corners_, SkPathDirection::kCW),
  95. flags);
  96. }
  97. void OnThemeChanged() override {
  98. views::LabelButton::OnThemeChanged();
  99. SetBackgroundAndFont();
  100. }
  101. private:
  102. void SetBackgroundAndFont() {
  103. label()->SetFontList(
  104. gfx::FontList().DeriveWithWeight(gfx::Font::Weight::MEDIUM));
  105. SetEnabledTextColors(channel_indicator_utils::GetFgColor(channel_));
  106. }
  107. // The channel itself, BETA, DEV, or CANARY.
  108. const version_info::Channel channel_;
  109. // Array of values that represents the rounded rect corners.
  110. SkScalar corners_[kNumVersionButtonCornerRadii];
  111. };
  112. // SubmitFeedbackButton provides a styled button, for devices on a
  113. // non-stable release track, that allows the user to submit feedback.
  114. class SubmitFeedbackButton : public IconButton {
  115. public:
  116. explicit SubmitFeedbackButton(version_info::Channel channel)
  117. : IconButton(base::BindRepeating([] {
  118. Shell::Get()
  119. ->system_tray_model()
  120. ->client()
  121. ->ShowChannelInfoGiveFeedback();
  122. }),
  123. IconButton::Type::kSmall,
  124. &kRequestFeedbackIcon,
  125. IDS_ASH_STATUS_TRAY_REPORT_FEEDBACK),
  126. channel_(channel) {
  127. SetBorder(views::CreateEmptyBorder(
  128. gfx::Insets::VH(kSubmitFeedbackButtonMarginVertical,
  129. kSubmitFeedbackButtonMarginHorizontal)));
  130. SetIconColor(channel_indicator_utils::GetFgColor(channel_));
  131. }
  132. SubmitFeedbackButton(const SubmitFeedbackButton&) = delete;
  133. SubmitFeedbackButton& operator=(const SubmitFeedbackButton&) = delete;
  134. ~SubmitFeedbackButton() override = default;
  135. // views::LabelButton:
  136. void PaintButtonContents(gfx::Canvas* canvas) override {
  137. cc::PaintFlags flags;
  138. flags.setColor(channel_indicator_utils::GetBgColor(channel_));
  139. flags.setStyle(cc::PaintFlags::kFill_Style);
  140. canvas->DrawPath(SkPath().addRoundRect(gfx::RectToSkRect(GetLocalBounds()),
  141. kSubmitFeedbackButtonCorners,
  142. SkPathDirection::kCW),
  143. flags);
  144. IconButton::PaintButtonContents(canvas);
  145. }
  146. private:
  147. const version_info::Channel channel_;
  148. };
  149. } // namespace
  150. ChannelIndicatorQuickSettingsView::ChannelIndicatorQuickSettingsView(
  151. version_info::Channel channel,
  152. bool allow_user_feedback) {
  153. auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
  154. views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
  155. kUnifiedSystemInfoSpacing));
  156. // kCenter align the layout for this view because it is a container for the
  157. // buttons.
  158. layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kCenter);
  159. layout->set_cross_axis_alignment(
  160. views::BoxLayout::CrossAxisAlignment::kCenter);
  161. layout->set_between_child_spacing(kButtonSpacing);
  162. version_button_ = AddChildView(std::make_unique<VersionButton>(
  163. channel, allow_user_feedback ? kPartneredVersionButtonCorners
  164. : kStandaloneVersionButtonCorners));
  165. if (allow_user_feedback) {
  166. feedback_button_ =
  167. AddChildView(std::make_unique<SubmitFeedbackButton>(channel));
  168. }
  169. }
  170. bool ChannelIndicatorQuickSettingsView::IsVersionButtonVisibleForTesting() {
  171. return version_button_ && version_button_->GetVisible();
  172. }
  173. bool ChannelIndicatorQuickSettingsView::
  174. IsSubmitFeedbackButtonVisibleForTesting() {
  175. return feedback_button_ && feedback_button_->GetVisible();
  176. }
  177. } // namespace ash