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

Side by Side Diff: ui/views/animation/ink_drop_animation_controller.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: Fixed typo. 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.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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 StartHideAnimation(); 178 StartHideAnimation();
176 } 179 }
177 180
178 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed() 181 bool AppearAnimationObserver::RequiresNotificationWhenAnimatorDestroyed()
179 const { 182 const {
180 // Ensures that OnImplicitAnimationsCompleted is called even if the observed 183 // Ensures that OnImplicitAnimationsCompleted is called even if the observed
181 // animation is deleted. Allows for setting the proper state on |layer_|. 184 // animation is deleted. Allows for setting the proper state on |layer_|.
182 return true; 185 return true;
183 } 186 }
184 187
185 // Renders the visual feedback. Will render a circle if |circle_| is true, 188 InkDropAnimationController::InkDropAnimationController(
186 // otherwise renders a rounded rectangle. 189 InkDropHost* ink_drop_host)
187 class InkDropDelegate : public ui::LayerDelegate { 190 : ink_drop_host_(ink_drop_host),
188 public: 191 layer_tree_(new ui::Layer()),
189 InkDropDelegate(ui::Layer* layer, SkColor color); 192 ink_drop_layer_(new ui::Layer()),
190 ~InkDropDelegate() override; 193 ink_drop_delegate_(new InkDropDelegate(ink_drop_layer_,
194 kInkDropColor,
195 kCircleRadius,
196 kRoundedRectCorners)),
197 appear_animation_observer_(nullptr),
198 long_press_layer_(new ui::Layer()),
199 long_press_delegate_(new InkDropDelegate(long_press_layer_,
200 kLongPressColor,
201 kCircleRadius,
202 kRoundedRectCorners)),
203 long_press_animation_observer_(nullptr),
204 bounds_(0, 0, 0, 0) {
205 SetupAnimationLayer(long_press_layer_, long_press_delegate_.get());
206 SetupAnimationLayer(ink_drop_layer_, ink_drop_delegate_.get());
191 207
192 // Sets the visual style of the feedback. 208 layer_tree_.root()->Add(ink_drop_layer_);
193 void set_should_render_circle(bool should_render_circle) { 209 layer_tree_.root()->Add(long_press_layer_);
194 should_render_circle_ = should_render_circle;
195 }
196 210
197 // ui::LayerDelegate: 211 ink_drop_host_->AddInkDropLayer(layer_tree_.root());
198 void OnPaintLayer(const ui::PaintContext& context) override;
199 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
200 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
201 base::Closure PrepareForLayerBoundsChange() override;
202
203 private:
204 // The ui::Layer being rendered to.
205 ui::Layer* layer_;
206
207 // The color to paint.
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 InkDropAnimationController::~InkDropAnimationController() {
215 // TODO(bruthig): Currently this virtual function is going to be called during
216 // ToolbarButton's destructor, is that ok?? This should hopefully change and
217 // be called when the Ink Drop becomes hidden.
218 ink_drop_host_->RemoveInkDropLayer(layer_tree_.root());
221 } 219 }
222 220
223 void InkDropDelegate::OnPaintLayer(const ui::PaintContext& context) { 221 void InkDropAnimationController::AnimateToState(InkDropState state) {
224 SkPaint paint; 222 switch (state) {
jonross 2015/08/07 17:14:31 Do we need to restrict state transitions? I think
bruthig 2015/08/07 22:00:45 All the work for state transitions and the visuals
jonross 2015/08/10 20:32:02 A good plan. Do we have this noted in the bug? Or
bruthig 2015/08/10 21:57:15 Hmmm I'm not sure either of those two places are a
tdanderson 2015/08/11 12:57:36 If you're fairly sure of what you're going to be d
bruthig 2015/08/11 14:31:10 Done.
225 paint.setColor(color_); 223 case InkDropState::HIDDEN:
226 paint.setFlags(SkPaint::kAntiAlias_Flag); 224 AnimateHide();
227 paint.setStyle(SkPaint::kFill_Style); 225 break;
228 226 case InkDropState::ACTION_PENDING:
229 gfx::Rect bounds = layer_->bounds(); 227 AnimateTapDown();
230 228 break;
231 ui::PaintRecorder recorder(context, layer_->size()); 229 case InkDropState::QUICK_ACTION:
232 gfx::Canvas* canvas = recorder.canvas(); 230 AnimateTapDown();
233 if (should_render_circle_) { 231 AnimateHide();
234 gfx::Point midpoint(bounds.width() * 0.5f, bounds.height() * 0.5f); 232 break;
235 canvas->DrawCircle(midpoint, kCircleRadius, paint); 233 case InkDropState::SLOW_ACTION:
236 } else { 234 AnimateLongPress();
237 canvas->DrawRoundRect(bounds, kRoundedRectCorners, paint); 235 break;
236 case InkDropState::ACTIVATED:
237 AnimateLongPress();
238 break;
238 } 239 }
239 } 240 }
240 241
241 void InkDropDelegate::OnDelegatedFrameDamage( 242 void InkDropAnimationController::SetSize(const gfx::Size& size) {
242 const gfx::Rect& damage_rect_in_dip) { 243 SetBounds(gfx::Rect(bounds().x(), bounds().y(), size.width(), size.height()));
243 } 244 }
244 245
245 void InkDropDelegate::OnDeviceScaleFactorChanged(float device_scale_factor) { 246 void InkDropAnimationController::SetBounds(const gfx::Rect& bounds) {
246 } 247 bounds_ = bounds;
247 248 SetLayerBounds(ink_drop_layer_);
248 base::Closure InkDropDelegate::PrepareForLayerBoundsChange() { 249 SetLayerBounds(long_press_layer_);
249 return base::Closure();
250 }
251
252 InkDropAnimationController::InkDropAnimationController(views::View* view)
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 } 250 }
275 251
276 void InkDropAnimationController::AnimateTapDown() { 252 void InkDropAnimationController::AnimateTapDown() {
277 if ((appear_animation_observer_ && 253 if ((appear_animation_observer_ &&
278 appear_animation_observer_->IsAnimationActive()) || 254 appear_animation_observer_->IsAnimationActive()) ||
279 (long_press_animation_observer_ && 255 (long_press_animation_observer_ &&
280 long_press_animation_observer_->IsAnimationActive())) { 256 long_press_animation_observer_->IsAnimationActive())) {
281 // Only one animation at a time. Subsequent tap downs are ignored until the 257 // Only one animation at a time. Subsequent tap downs are ignored until the
282 // current animation completes. 258 // current animation completes.
283 return; 259 return;
284 } 260 }
285 appear_animation_observer_.reset( 261 appear_animation_observer_.reset(
286 new AppearAnimationObserver(ink_drop_layer_.get(), false)); 262 new AppearAnimationObserver(ink_drop_layer_, false));
287 AnimateShow(ink_drop_layer_.get(), appear_animation_observer_.get(), 263 AnimateShow(ink_drop_layer_, appear_animation_observer_.get(),
288 UseCircularFeedback(),
289 base::TimeDelta::FromMilliseconds( 264 base::TimeDelta::FromMilliseconds(
290 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs 265 (UseFastAnimations() ? kShowInkDropAnimationDurationFastMs
291 : kShowInkDropAnimationDurationSlowMs))); 266 : kShowInkDropAnimationDurationSlowMs)));
292 } 267 }
293 268
294 void InkDropAnimationController::AnimateHide() { 269 void InkDropAnimationController::AnimateHide() {
295 if (appear_animation_observer_) 270 if (appear_animation_observer_ &&
271 appear_animation_observer_->IsAnimationActive()) {
296 appear_animation_observer_->HideNowIfDoneOrOnceCompleted(); 272 appear_animation_observer_->HideNowIfDoneOrOnceCompleted();
273 } else if (long_press_animation_observer_) {
274 long_press_animation_observer_->HideNowIfDoneOrOnceCompleted();
275 }
297 } 276 }
298 277
299 void InkDropAnimationController::AnimateLongPress() { 278 void InkDropAnimationController::AnimateLongPress() {
300 // Only one animation at a time. Subsequent long presses are ignored until the 279 // Only one animation at a time. Subsequent long presses are ignored until the
301 // current animation completes. 280 // current animation completes.
302 if (long_press_animation_observer_ && 281 if (long_press_animation_observer_ &&
303 long_press_animation_observer_->IsAnimationActive()) { 282 long_press_animation_observer_->IsAnimationActive()) {
304 return; 283 return;
305 } 284 }
306 appear_animation_observer_.reset(); 285 appear_animation_observer_.reset();
307 long_press_animation_observer_.reset( 286 long_press_animation_observer_.reset(
308 new AppearAnimationObserver(long_press_layer_.get(), true)); 287 new AppearAnimationObserver(long_press_layer_, false));
309 long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_.get()); 288 long_press_animation_observer_->SetBackgroundToHide(ink_drop_layer_);
310 AnimateShow(long_press_layer_.get(), long_press_animation_observer_.get(), 289 AnimateShow(long_press_layer_, long_press_animation_observer_.get(),
311 true,
312 base::TimeDelta::FromMilliseconds( 290 base::TimeDelta::FromMilliseconds(
313 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs 291 UseFastAnimations() ? kShowLongPressAnimationDurationFastMs
314 : kShowLongPressAnimationDurationSlowMs)); 292 : kShowLongPressAnimationDurationSlowMs));
315 } 293 }
316 294
317 void InkDropAnimationController::AnimateShow(ui::Layer* layer, 295 void InkDropAnimationController::AnimateShow(ui::Layer* layer,
318 AppearAnimationObserver* observer, 296 AppearAnimationObserver* observer,
319 bool circle,
320 base::TimeDelta duration) { 297 base::TimeDelta duration) {
321 SetLayerBounds(layer, circle, view_->width(), view_->height());
322 layer->SetVisible(true); 298 layer->SetVisible(true);
323 layer->SetOpacity(1.0f); 299 layer->SetOpacity(1.0f);
324 300
325 float start_x = layer->bounds().width() * kMinimumScaleCenteringOffset; 301 float start_x =
326 float start_y = layer->bounds().height() * kMinimumScaleCenteringOffset; 302 bounds_.x() + layer->bounds().width() * kMinimumScaleCenteringOffset;
303 float start_y =
304 bounds_.y() + layer->bounds().height() * kMinimumScaleCenteringOffset;
327 305
328 gfx::Transform initial_transform; 306 gfx::Transform initial_transform;
329 initial_transform.Translate(start_x, start_y); 307 initial_transform.Translate(start_x, start_y);
330 initial_transform.Scale(kMinimumScale, kMinimumScale); 308 initial_transform.Scale(kMinimumScale, kMinimumScale);
331 layer->SetTransform(initial_transform); 309 layer->SetTransform(initial_transform);
332 310
333 ui::LayerAnimator* animator = layer->GetAnimator(); 311 ui::LayerAnimator* animator = layer->GetAnimator();
334 ui::ScopedLayerAnimationSettings animation(animator); 312 ui::ScopedLayerAnimationSettings animation(animator);
335 animation.SetPreemptionStrategy( 313 animation.SetPreemptionStrategy(
336 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 314 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
337 315
338 gfx::Transform identity_transform; 316 gfx::Transform target_transform;
317 target_transform.Translate(bounds_.x(), bounds_.y());
339 ui::LayerAnimationElement* element = 318 ui::LayerAnimationElement* element =
340 ui::LayerAnimationElement::CreateTransformElement(identity_transform, 319 ui::LayerAnimationElement::CreateTransformElement(target_transform,
341 duration); 320 duration);
342 ui::LayerAnimationSequence* sequence = 321 ui::LayerAnimationSequence* sequence =
343 new ui::LayerAnimationSequence(element); 322 new ui::LayerAnimationSequence(element);
344 sequence->AddObserver(observer); 323 sequence->AddObserver(observer);
345 animator->StartAnimation(sequence); 324 animator->StartAnimation(sequence);
346 } 325 }
347 326
348 void InkDropAnimationController::SetLayerBounds(ui::Layer* layer, 327 void InkDropAnimationController::SetLayerBounds(ui::Layer* layer) {
349 bool circle, 328 bool circle = UseCircularFeedback();
350 int width, 329 gfx::Size size = bounds_.size();
351 int height) { 330 float circle_width = circle ? 2.0f * kCircleRadius : size.width();
352 float circle_width = circle ? 2.0f * kCircleRadius : width; 331 float circle_height = circle ? 2.0f * kCircleRadius : size.height();
353 float circle_height = circle ? 2.0f * kCircleRadius : height; 332 float circle_x = circle ? (size.width() - circle_width) * 0.5f : 0;
354 float circle_x = circle ? (width - circle_width) * 0.5f : 0; 333 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)); 334 layer->SetBounds(gfx::Rect(circle_x, circle_y, circle_width, circle_height));
357 } 335 }
358 336
359 void InkDropAnimationController::SetupAnimationLayer( 337 void InkDropAnimationController::SetupAnimationLayer(
360 ui::Layer* parent,
361 ui::Layer* layer, 338 ui::Layer* layer,
362 InkDropDelegate* delegate) { 339 InkDropDelegate* delegate) {
363 layer->SetFillsBoundsOpaquely(false); 340 layer->SetFillsBoundsOpaquely(false);
364 layer->set_delegate(delegate); 341 layer->set_delegate(delegate);
365 layer->SetVisible(false); 342 layer->SetVisible(false);
366 layer->SetBounds(gfx::Rect()); 343 layer->SetBounds(gfx::Rect());
367 parent->Add(layer); 344 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 } 345 }
391 346
392 } // namespace views 347 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698