Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: ui/views/animation/ink_drop_animation_controller_impl.cc

Issue 1280953003: Enhance the material design ripple API so the ripple's state can be controlled by it's owning View. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Replaced raw ui::Layer* with ui::LayerOwners. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/animation/ink_drop_animation_controller.h" 5 #include "ui/views/animation/ink_drop_animation_controller_impl.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "ui/base/ui_base_switches.h" 8 #include "ui/base/ui_base_switches.h"
9 #include "ui/compositor/layer.h" 9 #include "ui/compositor/layer.h"
10 #include "ui/compositor/layer_animation_observer.h" 10 #include "ui/compositor/layer_animation_observer.h"
11 #include "ui/compositor/layer_animation_sequence.h" 11 #include "ui/compositor/layer_animation_sequence.h"
12 #include "ui/compositor/paint_recorder.h" 12 #include "ui/compositor/paint_recorder.h"
13 #include "ui/compositor/scoped_layer_animation_settings.h" 13 #include "ui/compositor/scoped_layer_animation_settings.h"
14 #include "ui/events/event.h" 14 #include "ui/events/event.h"
15 #include "ui/gfx/canvas.h" 15 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/geometry/size.h"
17 #include "ui/views/animation/ink_drop_delegate.h"
18 #include "ui/views/animation/ink_drop_host.h"
16 #include "ui/views/view.h" 19 #include "ui/views/view.h"
17 20
18 namespace { 21 namespace {
19 22
20 // Animation constants 23 // Animation constants
21 const float kMinimumScale = 0.1f; 24 const float kMinimumScale = 0.1f;
22 const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f; 25 const float kMinimumScaleCenteringOffset = 0.5f - kMinimumScale / 2.0f;
23 26
24 const int kHideAnimationDurationFastMs = 100; 27 const int kHideAnimationDurationFastMs = 100;
25 const int kHideAnimationDurationSlowMs = 1000; 28 const int kHideAnimationDurationSlowMs = 1000;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 ui::Layer* background_layer_; 109 ui::Layer* background_layer_;
107 110
108 // If true the hide animation will immediately be scheduled upon completion of 111 // If true the hide animation will immediately be scheduled upon completion of
109 // the observed animation. 112 // the observed animation.
110 bool hide_; 113 bool hide_;
111 114
112 DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver); 115 DISALLOW_COPY_AND_ASSIGN(AppearAnimationObserver);
113 }; 116 };
114 117
115 AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide) 118 AppearAnimationObserver::AppearAnimationObserver(ui::Layer* layer, bool hide)
116 : layer_(layer), background_layer_(nullptr), hide_(hide) { 119 : layer_(layer), background_layer_(nullptr), hide_(hide) {}
117 }
118 120
119 AppearAnimationObserver::~AppearAnimationObserver() { 121 AppearAnimationObserver::~AppearAnimationObserver() {
120 StopObserving(); 122 StopObserving();
121 } 123 }
122 124
123 bool AppearAnimationObserver::IsAnimationActive() { 125 bool AppearAnimationObserver::IsAnimationActive() {
124 // Initial animation ongoing 126 // Initial animation ongoing
125 if (!attached_sequences().empty()) 127 if (!attached_sequences().empty())
126 return true; 128 return true;
127 // Maintain the animation until told to hide. 129 // Maintain the animation until told to hide.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 StartHideAnimation(); 177 StartHideAnimation();
176 } 178 }
177 179
178 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed() 180 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed()
179 const { 181 const {
180 // Ensures that OnImplicitAnimationsCompleted is called even if the observed 182 // Ensures that OnImplicitAnimationsCompleted is called even if the observed
181 // animation is deleted. Allows for setting the proper state on |layer_|. 183 // animation is deleted. Allows for setting the proper state on |layer_|.
182 return true; 184 return true;
183 } 185 }
184 186
185 // Renders the visual feedback. Will render a circle if |circle_| is true, 187 InkDropAnimationControllerImpl::InkDropAnimationControllerImpl(
186 // otherwise renders a rounded rectangle. 188 InkDropHost* ink_drop_host)
187 class InkDropDelegate : public ui::LayerDelegate { 189 : ink_drop_host_(ink_drop_host),
188 public: 190 appear_animation_observer_(nullptr),
189 InkDropDelegate(ui::Layer* layer, SkColor color); 191 long_press_animation_observer_(nullptr),
190 ~InkDropDelegate() override; 192 ink_drop_bounds_(0, 0, 0, 0) {
193 root_layer_owner_.SetLayer(new ui::Layer(ui::LAYER_NOT_DRAWN));
194 ink_drop_layer_owner_.SetLayer(new ui::Layer());
195 long_press_layer_owner_.SetLayer(new ui::Layer());
191 196
192 // Sets the visual style of the feedback. 197 ink_drop_delegate_.reset(new InkDropDelegate(ink_drop_layer_owner_.layer(),
193 void set_should_render_circle(bool should_render_circle) { 198 kInkDropColor, kCircleRadius,
194 should_render_circle_ = should_render_circle; 199 kRoundedRectCorners));
195 } 200 long_press_delegate_.reset(
201 new InkDropDelegate(long_press_layer_owner_.layer(), kLongPressColor,
202 kCircleRadius, kRoundedRectCorners)),
196 203
197 // ui::LayerDelegate: 204 SetupAnimationLayer(long_press_layer_owner_.layer(),
198 void OnPaintLayer(const ui::PaintContext& context) override; 205 long_press_delegate_.get());
199 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override; 206 SetupAnimationLayer(ink_drop_layer_owner_.layer(), ink_drop_delegate_.get());
200 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
201 base::Closure PrepareForLayerBoundsChange() override;
202 207
203 private: 208 root_layer_owner_.layer()->Add(ink_drop_layer_owner_.layer());
204 // The ui::Layer being rendered to. 209 root_layer_owner_.layer()->Add(long_press_layer_owner_.layer());
205 ui::Layer* layer_;
206 210
207 // The color to paint. 211 ink_drop_host_->AddInkDropLayer(root_layer_owner_.layer());
208 SkColor color_;
209
210 // When true renders a circle, otherwise renders a rounded rectangle.
211 bool should_render_circle_;
212
213 DISALLOW_COPY_AND_ASSIGN(InkDropDelegate);
214 };
215
216 InkDropDelegate::InkDropDelegate(ui::Layer* layer, SkColor color)
217 : layer_(layer), color_(color), should_render_circle_(true) {
218 } 212 }
219 213
220 InkDropDelegate::~InkDropDelegate() { 214 InkDropAnimationControllerImpl::~InkDropAnimationControllerImpl() {
215 // TODO(bruthig): Change this to be called when the ink drop becomes hidden.
216 ink_drop_host_->RemoveInkDropLayer(root_layer_owner_.layer());
221 } 217 }
222 218
223 void InkDropDelegate::OnPaintLayer(const ui::PaintContext& context) { 219 void InkDropAnimationControllerImpl::AnimateToState(InkDropState state) {
224 SkPaint paint; 220 // TODO(bruthig): Do not transition if we are already in |state| and restrict
225 paint.setColor(color_); 221 // any state transition that don't make sense or wouldn't look visually
226 paint.setFlags(SkPaint::kAntiAlias_Flag); 222 // appealing.
227 paint.setStyle(SkPaint::kFill_Style); 223 switch (state) {
228 224 case InkDropState::HIDDEN:
229 gfx::Rect bounds = layer_->bounds(); 225 AnimateHide();
230 226 break;
231 ui::PaintRecorder recorder(context, layer_->size()); 227 case InkDropState::ACTION_PENDING:
232 gfx::Canvas* canvas = recorder.canvas(); 228 AnimateTapDown();
233 if (should_render_circle_) { 229 break;
234 gfx::Point midpoint(bounds.width() * 0.5f, bounds.height() * 0.5f); 230 case InkDropState::QUICK_ACTION:
235 canvas->DrawCircle(midpoint, kCircleRadius, paint); 231 AnimateTapDown();
236 } else { 232 AnimateHide();
237 canvas->DrawRoundRect(bounds, kRoundedRectCorners, paint); 233 break;
234 case InkDropState::SLOW_ACTION:
235 AnimateLongPress();
236 break;
237 case InkDropState::ACTIVATED:
238 AnimateLongPress();
239 break;
238 } 240 }
239 } 241 }
240 242
241 void InkDropDelegate::OnDelegatedFrameDamage( 243 void InkDropAnimationControllerImpl::SetInkDropSize(const gfx::Size& size) {
242 const gfx::Rect& damage_rect_in_dip) { 244 SetInkDropBounds(gfx::Rect(ink_drop_bounds_.origin(), size));
243 } 245 }
244 246
245 void InkDropDelegate::OnDeviceScaleFactorChanged(float device_scale_factor) { 247 gfx::Rect InkDropAnimationControllerImpl::GetInkDropBounds() const {
248 return ink_drop_bounds_;
246 } 249 }
247 250
248 base::Closure InkDropDelegate::PrepareForLayerBoundsChange() { 251 void InkDropAnimationControllerImpl::SetInkDropBounds(const gfx::Rect& bounds) {
249 return base::Closure(); 252 ink_drop_bounds_ = bounds;
253 SetLayerBounds(ink_drop_layer_owner_.layer());
254 SetLayerBounds(long_press_layer_owner_.layer());
250 } 255 }
251 256
252 InkDropAnimationController::InkDropAnimationController(views::View* view) 257 void InkDropAnimationControllerImpl::AnimateTapDown() {
253 : ink_drop_layer_(new ui::Layer()),
254 ink_drop_delegate_(
255 new InkDropDelegate(ink_drop_layer_.get(), kInkDropColor)),
256 appear_animation_observer_(nullptr),
257 long_press_layer_(new ui::Layer()),
258 long_press_delegate_(
259 new InkDropDelegate(long_press_layer_.get(), kLongPressColor)),
260 long_press_animation_observer_(nullptr),
261 view_(view) {
262 view_->SetPaintToLayer(true);
263 view_->AddPreTargetHandler(this);
264 ui::Layer* layer = view_->layer();
265 layer->SetMasksToBounds(!UseCircularFeedback());
266 SetupAnimationLayer(layer, long_press_layer_.get(),
267 long_press_delegate_.get());
268 SetupAnimationLayer(layer, ink_drop_layer_.get(), ink_drop_delegate_.get());
269 ink_drop_delegate_->set_should_render_circle(UseCircularFeedback());
270 }
271
272 InkDropAnimationController::~InkDropAnimationController() {
273 view_->RemovePreTargetHandler(this);
274 }
275
276 void InkDropAnimationController::AnimateTapDown() {
277 if ((appear_animation_observer_ && 258 if ((appear_animation_observer_ &&
278 appear_animation_observer_->IsAnimationActive()) || 259 appear_animation_observer_->IsAnimationActive()) ||
279 (long_press_animation_observer_ && 260 (long_press_animation_observer_ &&
280 long_press_animation_observer_->IsAnimationActive())) { 261 long_press_animation_observer_->IsAnimationActive())) {
281 // Only one animation at a time. Subsequent tap downs are ignored until the 262 // Only one animation at a time. Subsequent tap downs are ignored until the
282 // current animation completes. 263 // current animation completes.
283 return; 264 return;
284 } 265 }
285 appear_animation_observer_.reset( 266 appear_animation_observer_.reset(
286 new AppearAnimationObserver(ink_drop_layer_.get(), false)); 267 new AppearAnimationObserver(ink_drop_layer_owner_.layer(), false));
287 AnimateShow(ink_drop_layer_.get(), appear_animation_observer_.get(), 268 AnimateShow(ink_drop_layer_owner_.layer(), appear_animation_observer_.get(),
288 UseCircularFeedback(),
289 base::TimeDelta::FromMilliseconds( 269 base::TimeDelta::FromMilliseconds(
290 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs 270 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs
291 : kShowInkDropAnimationDurationSlowMs))); 271 : kShowInkDropAnimationDurationSlowMs)));
292 } 272 }
293 273
294 void InkDropAnimationController::AnimateHide() { 274 void InkDropAnimationControllerImpl::AnimateHide() {
295 if (appear_animation_observer_) 275 if (appear_animation_observer_ &&
276 appear_animation_observer_->IsAnimationActive()) {
296 appear_animation_observer_->HideNowIfDoneOrOnceCompleted(); 277 appear_animation_observer_->HideNowIfDoneOrOnceCompleted();
278 } else if (long_press_animation_observer_) {
279 long_press_animation_observer_->HideNowIfDoneOrOnceCompleted();
280 }
297 } 281 }
298 282
299 void InkDropAnimationController::AnimateLongPress() { 283 void InkDropAnimationControllerImpl::AnimateLongPress() {
300 // Only one animation at a time. Subsequent long presses are ignored until the 284 // Only one animation at a time. Subsequent long presses are ignored until the
301 // current animation completes. 285 // current animation completes.
302 if (long_press_animation_observer_ && 286 if (long_press_animation_observer_ &&
303 long_press_animation_observer_->IsAnimationActive()) { 287 long_press_animation_observer_->IsAnimationActive()) {
304 return; 288 return;
305 } 289 }
306 appear_animation_observer_.reset(); 290 appear_animation_observer_.reset();
307 long_press_animation_observer_.reset( 291 long_press_animation_observer_.reset(
308 new AppearAnimationObserver(long_press_layer_.get(), true)); 292 new AppearAnimationObserver(long_press_layer_owner_.layer(), false));
309 long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_.get()); 293 long_press_animation_observer_->SetBackgroundToHide(
310 AnimateShow(long_press_layer_.get(), long_press_animation_observer_.get(), 294 ink_drop_layer_owner_.layer());
311 true, 295 AnimateShow(long_press_layer_owner_.layer(),
296 long_press_animation_observer_.get(),
312 base::TimeDelta::FromMilliseconds( 297 base::TimeDelta::FromMilliseconds(
313 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs 298 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs
314 : kShowLongPressAnimationDurationSlowMs)); 299 : kShowLongPressAnimationDurationSlowMs));
315 } 300 }
316 301
317 void InkDropAnimationController::AnimateShow(ui::Layer* layer, 302 void InkDropAnimationControllerImpl::AnimateShow(
318 AppearAnimationObserver* observer, 303 ui::Layer* layer,
319 bool circle, 304 AppearAnimationObserver* observer,
320 base::TimeDelta duration) { 305 base::TimeDelta duration) {
321 SetLayerBounds(layer, circle, view_->width(), view_->height());
322 layer->SetVisible(true); 306 layer->SetVisible(true);
323 layer->SetOpacity(1.0f); 307 layer->SetOpacity(1.0f);
324 308
325 float start_x = layer->bounds().width() * kMinimumScaleCenteringOffset; 309 float start_x = ink_drop_bounds_.x() +
326 float start_y = layer->bounds().height() * kMinimumScaleCenteringOffset; 310 layer->bounds().width() * kMinimumScaleCenteringOffset;
311 float start_y = ink_drop_bounds_.y() +
312 layer->bounds().height() * kMinimumScaleCenteringOffset;
327 313
328 gfx::Transform initial_transform; 314 gfx::Transform initial_transform;
329 initial_transform.Translate(start_x, start_y); 315 initial_transform.Translate(start_x, start_y);
330 initial_transform.Scale(kMinimumScale, kMinimumScale); 316 initial_transform.Scale(kMinimumScale, kMinimumScale);
331 layer->SetTransform(initial_transform); 317 layer->SetTransform(initial_transform);
332 318
333 ui::LayerAnimator* animator = layer->GetAnimator(); 319 ui::LayerAnimator* animator = layer->GetAnimator();
334 ui::ScopedLayerAnimationSettings animation(animator); 320 ui::ScopedLayerAnimationSettings animation(animator);
335 animation.SetPreemptionStrategy( 321 animation.SetPreemptionStrategy(
336 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 322 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
337 323
338 gfx::Transform identity_transform; 324 gfx::Transform target_transform;
325 target_transform.Translate(ink_drop_bounds_.x(), ink_drop_bounds_.y());
339 ui::LayerAnimationElement* element = 326 ui::LayerAnimationElement* element =
340 ui::LayerAnimationElement::CreateTransformElement(identity_transform, 327 ui::LayerAnimationElement::CreateTransformElement(target_transform,
341 duration); 328 duration);
342 ui::LayerAnimationSequence* sequence = 329 ui::LayerAnimationSequence* sequence =
343 new ui::LayerAnimationSequence(element); 330 new ui::LayerAnimationSequence(element);
344 sequence->AddObserver(observer); 331 sequence->AddObserver(observer);
345 animator->StartAnimation(sequence); 332 animator->StartAnimation(sequence);
346 } 333 }
347 334
348 void InkDropAnimationController::SetLayerBounds(ui::Layer* layer, 335 void InkDropAnimationControllerImpl::SetLayerBounds(ui::Layer* layer) {
349 bool circle, 336 bool circle = UseCircularFeedback();
350 int width, 337 gfx::Size size = ink_drop_bounds_.size();
351 int height) { 338 float circle_width = circle ? 2.0f * kCircleRadius : size.width();
352 float circle_width = circle ? 2.0f * kCircleRadius : width; 339 float circle_height = circle ? 2.0f * kCircleRadius : size.height();
353 float circle_height = circle ? 2.0f * kCircleRadius : height; 340 float circle_x = circle ? (size.width() - circle_width) * 0.5f : 0;
354 float circle_x = circle ? (width - circle_width) * 0.5f : 0; 341 float circle_y = circle ? (size.height() - circle_height) * 0.5f : 0;
355 float circle_y = circle ? (height - circle_height) * 0.5f : 0;
356 layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height)); 342 layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height));
357 } 343 }
358 344
359 void InkDropAnimationController::SetupAnimationLayer( 345 void InkDropAnimationControllerImpl::SetupAnimationLayer(
360 ui::Layer* parent,
361 ui::Layer* layer, 346 ui::Layer* layer,
362 InkDropDelegate* delegate) { 347 InkDropDelegate* delegate) {
363 layer->SetFillsBoundsOpaquely(false); 348 layer->SetFillsBoundsOpaquely(false);
364 layer->set_delegate(delegate); 349 layer->set_delegate(delegate);
365 layer->SetVisible(false); 350 layer->SetVisible(false);
366 layer->SetBounds(gfx::Rect()); 351 layer->SetBounds(gfx::Rect());
367 parent->Add(layer); 352 delegate->set_should_render_circle(UseCircularFeedback());
368 parent->StackAtBottom(layer);
369 }
370
371 void InkDropAnimationController::OnGestureEvent(ui::GestureEvent* event) {
372 if (event->target() != view_)
373 return;
374
375 switch (event->type()) {
376 case ui::ET_GESTURE_TAP_DOWN:
377 AnimateTapDown();
378 break;
379 case ui::ET_GESTURE_LONG_PRESS:
380 AnimateLongPress();
381 break;
382 case ui::ET_GESTURE_END:
383 case ui::ET_GESTURE_TAP_CANCEL:
384 case ui::ET_GESTURE_TAP:
385 AnimateHide();
386 break;
387 default:
388 break;
389 }
390 } 353 }
391 354
392 } // namespace views 355 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698