1// Copyright 2014 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 5#include "ui/app_list/views/top_icon_animation_view.h" 6 7#include "base/message_loop/message_loop_proxy.h" 8#include "ui/app_list/app_list_constants.h" 9#include "ui/compositor/scoped_layer_animation_settings.h" 10#include "ui/gfx/image/image_skia_operations.h" 11#include "ui/views/controls/image_view.h" 12 13namespace app_list { 14 15TopIconAnimationView::TopIconAnimationView(const gfx::ImageSkia& icon, 16 const gfx::Rect& scaled_rect, 17 bool open_folder) 18 : icon_size_(kPreferredIconDimension, kPreferredIconDimension), 19 icon_(new views::ImageView), 20 scaled_rect_(scaled_rect), 21 open_folder_(open_folder) { 22 DCHECK(!icon.isNull()); 23 gfx::ImageSkia resized(gfx::ImageSkiaOperations::CreateResizedImage( 24 icon, 25 skia::ImageOperations::RESIZE_BEST, icon_size_)); 26 icon_->SetImage(resized); 27 AddChildView(icon_); 28 29 SetPaintToLayer(true); 30 SetFillsBoundsOpaquely(false); 31} 32 33TopIconAnimationView::~TopIconAnimationView() { 34 // Required due to RequiresNotificationWhenAnimatorDestroyed() returning true. 35 // See ui::LayerAnimationObserver for details. 36 StopObservingImplicitAnimations(); 37} 38 39void TopIconAnimationView::AddObserver(TopIconAnimationObserver* observer) { 40 observers_.AddObserver(observer); 41} 42 43void TopIconAnimationView::RemoveObserver(TopIconAnimationObserver* observer) { 44 observers_.RemoveObserver(observer); 45} 46 47void TopIconAnimationView::TransformView() { 48 // This view will delete itself on animation completion. 49 set_owned_by_client(); 50 51 // Transform used for scaling down the icon and move it back inside to the 52 // original folder icon. 53 const float kIconTransformScale = 0.33333f; 54 gfx::Transform transform; 55 transform.Translate(scaled_rect_.x() - layer()->bounds().x(), 56 scaled_rect_.y() - layer()->bounds().y()); 57 transform.Scale(kIconTransformScale, kIconTransformScale); 58 59 if (open_folder_) { 60 // Transform to a scaled down icon inside the original folder icon. 61 layer()->SetTransform(transform); 62 } 63 64 // Animate the icon to its target location and scale when opening or 65 // closing a folder. 66 ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); 67 settings.AddObserver(this); 68 settings.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN); 69 settings.SetTransitionDuration( 70 base::TimeDelta::FromMilliseconds(kFolderTransitionInDurationMs)); 71 layer()->SetTransform(open_folder_ ? gfx::Transform() : transform); 72} 73 74gfx::Size TopIconAnimationView::GetPreferredSize() const { 75 return icon_size_; 76} 77 78void TopIconAnimationView::Layout() { 79 icon_->SetBoundsRect(GetContentsBounds()); 80} 81 82void TopIconAnimationView::OnImplicitAnimationsCompleted() { 83 SetVisible(false); 84 FOR_EACH_OBSERVER(TopIconAnimationObserver, 85 observers_, 86 OnTopIconAnimationsComplete()); 87 base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this); 88} 89 90bool TopIconAnimationView::RequiresNotificationWhenAnimatorDestroyed() const { 91 return true; 92} 93 94} // namespace app_list 95