close_button.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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/style/close_button.h"
  5. #include "ash/public/cpp/style/scoped_light_mode_as_default.h"
  6. #include "ash/resources/vector_icons/vector_icons.h"
  7. #include "ash/style/ash_color_provider.h"
  8. #include "ash/style/style_util.h"
  9. #include "ui/base/l10n/l10n_util.h"
  10. #include "ui/base/metadata/metadata_impl_macros.h"
  11. #include "ui/compositor/layer.h"
  12. #include "ui/gfx/paint_vector_icon.h"
  13. #include "ui/strings/grit/ui_strings.h"
  14. #include "ui/views/background.h"
  15. #include "ui/views/controls/highlight_path_generator.h"
  16. #include "ui/views/rect_based_targeting_utils.h"
  17. namespace ash {
  18. namespace {
  19. constexpr int kSmallButtonSize = 16;
  20. constexpr int kMediumButtonSize = 20;
  21. constexpr int kLargeButtonSize = 32;
  22. constexpr int kSmallIconSize = 8;
  23. constexpr int kMediumIconSize = 16;
  24. constexpr int kLargeIconSize = 24;
  25. int GetCloseButtonSize(CloseButton::Type type) {
  26. switch (type) {
  27. case CloseButton::Type::kSmall:
  28. case CloseButton::Type::kSmallFloating:
  29. return kSmallButtonSize;
  30. case CloseButton::Type::kMedium:
  31. case CloseButton::Type::kMediumFloating:
  32. return kMediumButtonSize;
  33. case CloseButton::Type::kLarge:
  34. case CloseButton::Type::kLargeFloating:
  35. return kLargeButtonSize;
  36. }
  37. }
  38. int GetIconSize(CloseButton::Type type) {
  39. switch (type) {
  40. case CloseButton::Type::kSmall:
  41. case CloseButton::Type::kSmallFloating:
  42. return kSmallIconSize;
  43. case CloseButton::Type::kMedium:
  44. case CloseButton::Type::kMediumFloating:
  45. return kMediumIconSize;
  46. case CloseButton::Type::kLarge:
  47. case CloseButton::Type::kLargeFloating:
  48. return kLargeIconSize;
  49. }
  50. }
  51. SkColor GetCloseButtonBackgroundColor(bool use_light_colors) {
  52. auto* color_provider = AshColorProvider::Get();
  53. if (use_light_colors) {
  54. ScopedLightModeAsDefault scoped_light_mode_as_default;
  55. return color_provider->GetBaseLayerColor(
  56. AshColorProvider::BaseLayerType::kTransparent80);
  57. }
  58. return color_provider->GetBaseLayerColor(
  59. AshColorProvider::BaseLayerType::kTransparent80);
  60. }
  61. bool IsFloatingCloseButton(CloseButton::Type type) {
  62. return type == CloseButton::Type::kSmallFloating ||
  63. type == CloseButton::Type::kMediumFloating ||
  64. type == CloseButton::Type::kLargeFloating;
  65. }
  66. } // namespace
  67. CloseButton::CloseButton(PressedCallback callback,
  68. CloseButton::Type type,
  69. bool use_light_colors)
  70. : ImageButton(std::move(callback)),
  71. type_(type),
  72. icon_((type == CloseButton::Type::kSmall ||
  73. type == CloseButton::Type::kSmallFloating)
  74. ? &kSmallCloseButtonIcon
  75. : &kMediumOrLargeCloseButtonIcon),
  76. use_light_colors_(use_light_colors) {
  77. SetPaintToLayer();
  78. layer()->SetFillsBoundsOpaquely(false);
  79. SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
  80. SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
  81. SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
  82. StyleUtil::SetUpInkDropForButton(
  83. this, gfx::Insets(),
  84. /*highlight_on_hover=*/true,
  85. /*highlight_on_focus=*/false,
  86. /*background_color=*/
  87. use_light_colors ? SK_ColorBLACK : gfx::kPlaceholderColor);
  88. // Add a rounded rect background. The rounding will be half the button size so
  89. // it is a circle.
  90. if (!IsFloatingCloseButton(type_)) {
  91. SetBackground(views::CreateRoundedRectBackground(
  92. GetCloseButtonBackgroundColor(use_light_colors_),
  93. GetCloseButtonSize(type_) / 2));
  94. }
  95. SetFocusPainter(nullptr);
  96. SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY);
  97. SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
  98. views::InstallCircleHighlightPathGenerator(this);
  99. }
  100. CloseButton::~CloseButton() = default;
  101. bool CloseButton::DoesIntersectScreenRect(const gfx::Rect& screen_rect) const {
  102. gfx::Point origin = screen_rect.origin();
  103. View::ConvertPointFromScreen(this, &origin);
  104. return DoesIntersectRect(this, gfx::Rect(origin, screen_rect.size()));
  105. }
  106. void CloseButton::ResetListener() {
  107. SetCallback(views::Button::PressedCallback());
  108. }
  109. void CloseButton::SetVectorIcon(const gfx::VectorIcon& icon) {
  110. icon_ = &icon;
  111. UpdateVectorIcon();
  112. }
  113. void CloseButton::SetBackgroundColor(const SkColor background_color) {
  114. if (background_color_ == background_color)
  115. return;
  116. background_color_ = background_color;
  117. DCHECK(background());
  118. background()->SetNativeControlColor(background_color_.value());
  119. }
  120. void CloseButton::SetIconColor(const SkColor icon_color) {
  121. if (icon_color_ == icon_color)
  122. return;
  123. icon_color_ = icon_color;
  124. UpdateVectorIcon();
  125. }
  126. void CloseButton::OnThemeChanged() {
  127. views::ImageButton::OnThemeChanged();
  128. if (background()) {
  129. background()->SetNativeControlColor(background_color_.value_or(
  130. GetCloseButtonBackgroundColor(use_light_colors_)));
  131. }
  132. UpdateVectorIcon();
  133. // TODO(minch): Add background blur as per spec. Background blur is quite
  134. // heavy, and we may have many close buttons showing at a time. They'll be
  135. // added separately so its easier to monitor performance.
  136. StyleUtil::ConfigureInkDropAttributes(
  137. this, StyleUtil::kBaseColor | StyleUtil::kInkDropOpacity);
  138. }
  139. gfx::Size CloseButton::CalculatePreferredSize() const {
  140. const int size = GetCloseButtonSize(type_);
  141. return gfx::Size(size, size);
  142. }
  143. bool CloseButton::DoesIntersectRect(const views::View* target,
  144. const gfx::Rect& rect) const {
  145. DCHECK_EQ(target, this);
  146. gfx::Rect button_bounds = target->GetLocalBounds();
  147. const int button_size = GetCloseButtonSize(type_);
  148. // Only increase the hittest area for touch events (which have a non-empty
  149. // bounding box), not for mouse event.
  150. if (!views::UsePointBasedTargeting(rect))
  151. button_bounds.Inset(gfx::Insets::VH(-button_size / 2, -button_size / 2));
  152. return button_bounds.Intersects(rect);
  153. }
  154. void CloseButton::UpdateVectorIcon() {
  155. DCHECK(icon_);
  156. auto* color_provider = AshColorProvider::Get();
  157. SkColor enabled_icon_color =
  158. icon_color_.value_or(color_provider->GetContentLayerColor(
  159. AshColorProvider::ContentLayerType::kButtonIconColor));
  160. if (use_light_colors_) {
  161. ScopedLightModeAsDefault scoped_light_mode_as_default;
  162. enabled_icon_color =
  163. icon_color_.value_or(color_provider->GetContentLayerColor(
  164. AshColorProvider::ContentLayerType::kButtonIconColor));
  165. }
  166. SetImage(
  167. views::Button::STATE_NORMAL,
  168. gfx::CreateVectorIcon(*icon_, GetIconSize(type_), enabled_icon_color));
  169. }
  170. BEGIN_METADATA(CloseButton, views::ImageButton)
  171. END_METADATA
  172. } // namespace ash