ink_drop_host_view.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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 "ui/views/animation/ink_drop_host_view.h"
  5. #include <utility>
  6. #include "ui/base/metadata/metadata_impl_macros.h"
  7. #include "ui/events/event.h"
  8. #include "ui/events/scoped_target_handler.h"
  9. #include "ui/gfx/color_palette.h"
  10. #include "ui/gfx/geometry/size_conversions.h"
  11. #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
  12. #include "ui/views/animation/ink_drop.h"
  13. #include "ui/views/animation/ink_drop_highlight.h"
  14. #include "ui/views/animation/ink_drop_impl.h"
  15. #include "ui/views/animation/ink_drop_mask.h"
  16. #include "ui/views/animation/ink_drop_stub.h"
  17. #include "ui/views/animation/square_ink_drop_ripple.h"
  18. #include "ui/views/controls/focus_ring.h"
  19. #include "ui/views/controls/highlight_path_generator.h"
  20. #include "ui/views/style/platform_style.h"
  21. #include "ui/views/view_class_properties.h"
  22. namespace views {
  23. // static
  24. constexpr gfx::Size InkDropHost::kDefaultSquareInkDropSize;
  25. InkDropHost::InkDropHostEventHandlerDelegate::InkDropHostEventHandlerDelegate(
  26. InkDropHost* ink_drop_host)
  27. : ink_drop_host_(ink_drop_host) {}
  28. bool InkDropHost::InkDropHostEventHandlerDelegate::HasInkDrop() const {
  29. return ink_drop_host_->HasInkDrop();
  30. }
  31. InkDrop* InkDropHost::InkDropHostEventHandlerDelegate::GetInkDrop() {
  32. return ink_drop_host_->GetInkDrop();
  33. }
  34. bool InkDropHost::InkDropHostEventHandlerDelegate::SupportsGestureEvents()
  35. const {
  36. return ink_drop_host_->ink_drop_mode_ == InkDropMode::ON;
  37. }
  38. InkDropHost::ViewLayerTransformObserver::ViewLayerTransformObserver(
  39. InkDropHost* ink_drop_host,
  40. View* host_view)
  41. : ink_drop_host_(ink_drop_host) {
  42. observation_.Observe(host_view);
  43. }
  44. InkDropHost::ViewLayerTransformObserver::~ViewLayerTransformObserver() =
  45. default;
  46. void InkDropHost::ViewLayerTransformObserver::OnViewLayerTransformed(
  47. View* observed_view) {
  48. // Notify the ink drop that we have transformed so it can adapt
  49. // accordingly.
  50. if (ink_drop_host_->HasInkDrop()) {
  51. ink_drop_host_->GetInkDrop()->HostTransformChanged(
  52. observed_view->GetTransform());
  53. }
  54. }
  55. InkDropHost::InkDropHost(View* view)
  56. : host_view_(view),
  57. host_view_transform_observer_(this, view),
  58. ink_drop_event_handler_delegate_(this),
  59. ink_drop_event_handler_(view, &ink_drop_event_handler_delegate_) {}
  60. InkDropHost::~InkDropHost() = default;
  61. std::unique_ptr<InkDrop> InkDropHost::CreateInkDrop() {
  62. if (create_ink_drop_callback_)
  63. return create_ink_drop_callback_.Run();
  64. return InkDrop::CreateInkDropForFloodFillRipple(this);
  65. }
  66. void InkDropHost::SetCreateInkDropCallback(
  67. base::RepeatingCallback<std::unique_ptr<InkDrop>()> callback) {
  68. create_ink_drop_callback_ = std::move(callback);
  69. }
  70. std::unique_ptr<InkDropRipple> InkDropHost::CreateInkDropRipple() const {
  71. if (create_ink_drop_ripple_callback_)
  72. return create_ink_drop_ripple_callback_.Run();
  73. return std::make_unique<views::FloodFillInkDropRipple>(
  74. host_view_->size(), gfx::Insets(), GetInkDropCenterBasedOnLastEvent(),
  75. GetBaseColor(), GetVisibleOpacity());
  76. }
  77. void InkDropHost::SetCreateRippleCallback(
  78. base::RepeatingCallback<std::unique_ptr<InkDropRipple>()> callback) {
  79. create_ink_drop_ripple_callback_ = std::move(callback);
  80. }
  81. gfx::Point InkDropHost::GetInkDropCenterBasedOnLastEvent() const {
  82. return GetEventHandler()->GetLastRippleTriggeringEvent()
  83. ? GetEventHandler()->GetLastRippleTriggeringEvent()->location()
  84. : host_view_->GetMirroredRect(host_view_->GetContentsBounds())
  85. .CenterPoint();
  86. }
  87. std::unique_ptr<InkDropHighlight> InkDropHost::CreateInkDropHighlight() const {
  88. if (create_ink_drop_highlight_callback_)
  89. return create_ink_drop_highlight_callback_.Run();
  90. auto highlight = std::make_unique<views::InkDropHighlight>(
  91. host_view_->size(), 0,
  92. gfx::RectF(host_view_->GetMirroredRect(host_view_->GetLocalBounds()))
  93. .CenterPoint(),
  94. GetBaseColor());
  95. // TODO(pbos): Once |ink_drop_highlight_opacity_| is either always set or
  96. // callers are using the default InkDropHighlight value then make this a
  97. // constructor argument to InkDropHighlight.
  98. if (ink_drop_highlight_opacity_)
  99. highlight->set_visible_opacity(*ink_drop_highlight_opacity_);
  100. return highlight;
  101. }
  102. void InkDropHost::SetCreateHighlightCallback(
  103. base::RepeatingCallback<std::unique_ptr<InkDropHighlight>()> callback) {
  104. create_ink_drop_highlight_callback_ = std::move(callback);
  105. }
  106. std::unique_ptr<views::InkDropMask> InkDropHost::CreateInkDropMask() const {
  107. if (create_ink_drop_mask_callback_)
  108. return create_ink_drop_mask_callback_.Run();
  109. return std::make_unique<views::PathInkDropMask>(host_view_->size(),
  110. GetHighlightPath(host_view_));
  111. }
  112. void InkDropHost::SetCreateMaskCallback(
  113. base::RepeatingCallback<std::unique_ptr<InkDropMask>()> callback) {
  114. create_ink_drop_mask_callback_ = std::move(callback);
  115. }
  116. SkColor InkDropHost::GetBaseColor() const {
  117. if (ink_drop_base_color_callback_)
  118. return ink_drop_base_color_callback_.Run();
  119. DCHECK(ink_drop_base_color_);
  120. return ink_drop_base_color_.value_or(gfx::kPlaceholderColor);
  121. }
  122. void InkDropHost::SetBaseColor(SkColor color) {
  123. ink_drop_base_color_ = color;
  124. }
  125. void InkDropHost::SetBaseColorCallback(
  126. base::RepeatingCallback<SkColor()> callback) {
  127. ink_drop_base_color_callback_ = std::move(callback);
  128. }
  129. void InkDropHost::SetMode(InkDropMode ink_drop_mode) {
  130. ink_drop_mode_ = ink_drop_mode;
  131. ink_drop_.reset();
  132. }
  133. void InkDropHost::SetVisibleOpacity(float visible_opacity) {
  134. if (visible_opacity == ink_drop_visible_opacity_)
  135. return;
  136. ink_drop_visible_opacity_ = visible_opacity;
  137. }
  138. float InkDropHost::GetVisibleOpacity() const {
  139. return ink_drop_visible_opacity_;
  140. }
  141. void InkDropHost::SetHighlightOpacity(absl::optional<float> opacity) {
  142. if (opacity == ink_drop_highlight_opacity_)
  143. return;
  144. ink_drop_highlight_opacity_ = opacity;
  145. }
  146. void InkDropHost::SetSmallCornerRadius(int small_radius) {
  147. if (small_radius == ink_drop_small_corner_radius_)
  148. return;
  149. ink_drop_small_corner_radius_ = small_radius;
  150. }
  151. int InkDropHost::GetSmallCornerRadius() const {
  152. return ink_drop_small_corner_radius_;
  153. }
  154. void InkDropHost::SetLargeCornerRadius(int large_radius) {
  155. if (large_radius == ink_drop_large_corner_radius_)
  156. return;
  157. ink_drop_large_corner_radius_ = large_radius;
  158. }
  159. int InkDropHost::GetLargeCornerRadius() const {
  160. return ink_drop_large_corner_radius_;
  161. }
  162. void InkDropHost::AnimateToState(InkDropState state,
  163. const ui::LocatedEvent* event) {
  164. GetEventHandler()->AnimateToState(state, event);
  165. }
  166. bool InkDropHost::HasInkDrop() const {
  167. return !!ink_drop_;
  168. }
  169. InkDrop* InkDropHost::GetInkDrop() {
  170. if (!ink_drop_) {
  171. if (ink_drop_mode_ == InkDropMode::OFF)
  172. ink_drop_ = std::make_unique<InkDropStub>();
  173. else
  174. ink_drop_ = CreateInkDrop();
  175. }
  176. return ink_drop_.get();
  177. }
  178. bool InkDropHost::GetHighlighted() const {
  179. return ink_drop_ && ink_drop_->IsHighlightFadingInOrVisible();
  180. }
  181. base::CallbackListSubscription InkDropHost::AddHighlightedChangedCallback(
  182. base::RepeatingClosure callback) {
  183. return highlighted_changed_callbacks_.Add(std::move(callback));
  184. }
  185. void InkDropHost::OnInkDropHighlightedChanged() {
  186. highlighted_changed_callbacks_.Notify();
  187. }
  188. void InkDropHost::AddInkDropLayer(ui::Layer* ink_drop_layer) {
  189. // If a clip is provided, use that as it is more performant than a mask.
  190. if (!AddInkDropClip(ink_drop_layer))
  191. InstallInkDropMask(ink_drop_layer);
  192. host_view_->AddLayerBeneathView(ink_drop_layer);
  193. }
  194. void InkDropHost::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
  195. host_view_->RemoveLayerBeneathView(ink_drop_layer);
  196. // Remove clipping.
  197. ink_drop_layer->SetClipRect(gfx::Rect());
  198. ink_drop_layer->SetRoundedCornerRadius(gfx::RoundedCornersF(0.f));
  199. // Layers safely handle destroying a mask layer before the masked layer.
  200. ink_drop_mask_.reset();
  201. }
  202. std::unique_ptr<InkDropRipple> InkDropHost::CreateSquareRipple(
  203. const gfx::Point& center_point,
  204. const gfx::Size& size) const {
  205. constexpr float kLargeInkDropScale = 1.333f;
  206. const gfx::Size large_size = gfx::ScaleToCeiledSize(size, kLargeInkDropScale);
  207. auto ripple = std::make_unique<SquareInkDropRipple>(
  208. large_size, ink_drop_large_corner_radius_, size,
  209. ink_drop_small_corner_radius_, center_point, GetBaseColor(),
  210. GetVisibleOpacity());
  211. return ripple;
  212. }
  213. const InkDropEventHandler* InkDropHost::GetEventHandler() const {
  214. return &ink_drop_event_handler_;
  215. }
  216. InkDropEventHandler* InkDropHost::GetEventHandler() {
  217. return const_cast<InkDropEventHandler*>(
  218. const_cast<const InkDropHost*>(this)->GetEventHandler());
  219. }
  220. bool InkDropHost::AddInkDropClip(ui::Layer* ink_drop_layer) {
  221. absl::optional<gfx::RRectF> clipping_data =
  222. HighlightPathGenerator::GetRoundRectForView(host_view_);
  223. if (!clipping_data)
  224. return false;
  225. ink_drop_layer->SetClipRect(gfx::ToEnclosingRect(clipping_data->rect()));
  226. auto get_corner_radii =
  227. [&clipping_data](gfx::RRectF::Corner corner) -> float {
  228. return clipping_data.value().GetCornerRadii(corner).x();
  229. };
  230. gfx::RoundedCornersF rounded_corners;
  231. rounded_corners.set_upper_left(
  232. get_corner_radii(gfx::RRectF::Corner::kUpperLeft));
  233. rounded_corners.set_upper_right(
  234. get_corner_radii(gfx::RRectF::Corner::kUpperRight));
  235. rounded_corners.set_lower_right(
  236. get_corner_radii(gfx::RRectF::Corner::kLowerRight));
  237. rounded_corners.set_lower_left(
  238. get_corner_radii(gfx::RRectF::Corner::kLowerLeft));
  239. ink_drop_layer->SetRoundedCornerRadius(rounded_corners);
  240. ink_drop_layer->SetIsFastRoundedCorner(true);
  241. return true;
  242. }
  243. void InkDropHost::InstallInkDropMask(ui::Layer* ink_drop_layer) {
  244. ink_drop_mask_ = CreateInkDropMask();
  245. DCHECK(ink_drop_mask_);
  246. ink_drop_layer->SetMaskLayer(ink_drop_mask_->layer());
  247. }
  248. } // namespace views