1// Copyright (c) 2012 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 "chrome/browser/download/download_started_animation.h" 6 7#include "content/public/browser/web_contents.h" 8#include "grit/theme_resources.h" 9#include "ui/base/resource/resource_bundle.h" 10#include "ui/gfx/animation/linear_animation.h" 11#include "ui/gfx/rect.h" 12#include "ui/views/controls/image_view.h" 13#include "ui/views/widget/widget.h" 14 15// How long to spend moving downwards and fading out after waiting. 16const int kMoveTimeMs = 600; 17 18// The animation framerate. 19const int kFrameRateHz = 60; 20 21namespace { 22 23// DownloadStartAnimation creates an animation (which begins running 24// immediately) that animates an image downward from the center of the frame 25// provided on the constructor, while simultaneously fading it out. To use, 26// simply call "new DownloadStartAnimation"; the class cleans itself up when it 27// finishes animating. 28class DownloadStartedAnimationViews : public gfx::LinearAnimation, 29 public views::ImageView { 30 public: 31 explicit DownloadStartedAnimationViews(content::WebContents* web_contents); 32 33 private: 34 // Move the animation to wherever it should currently be. 35 void Reposition(); 36 37 // Shut down the animation cleanly. 38 void Close(); 39 40 // Animation 41 virtual void AnimateToState(double state) OVERRIDE; 42 43 // We use a TYPE_POPUP for the popup so that it may float above any windows in 44 // our UI. 45 views::Widget* popup_; 46 47 // The content area at the start of the animation. We store this so that the 48 // download shelf's resizing of the content area doesn't cause the animation 49 // to move around. This means that once started, the animation won't move 50 // with the parent window, but it's so fast that this shouldn't cause too 51 // much heartbreak. 52 gfx::Rect web_contents_bounds_; 53 54 DISALLOW_COPY_AND_ASSIGN(DownloadStartedAnimationViews); 55}; 56 57DownloadStartedAnimationViews::DownloadStartedAnimationViews( 58 content::WebContents* web_contents) 59 : gfx::LinearAnimation(kMoveTimeMs, kFrameRateHz, NULL), 60 popup_(NULL) { 61 static gfx::ImageSkia* kDownloadImage = NULL; 62 if (!kDownloadImage) { 63 kDownloadImage = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 64 IDR_DOWNLOAD_ANIMATION_BEGIN); 65 } 66 67 // If we're too small to show the download image, then don't bother - 68 // the shelf will be enough. 69 web_contents_bounds_= web_contents->GetContainerBounds(); 70 if (web_contents_bounds_.height() < kDownloadImage->height()) 71 return; 72 73 SetImage(kDownloadImage); 74 75 popup_ = new views::Widget; 76 77 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 78 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 79 params.accept_events = false; 80 params.parent = web_contents->GetNativeView(); 81 popup_->Init(params); 82 popup_->SetOpacity(0x00); 83 popup_->SetContentsView(this); 84 Reposition(); 85 popup_->Show(); 86 87 Start(); 88} 89 90void DownloadStartedAnimationViews::Reposition() { 91 // Align the image with the bottom left of the web contents (so that it 92 // points to the newly created download). 93 gfx::Size size = GetPreferredSize(); 94 int x = base::i18n::IsRTL() ? 95 web_contents_bounds_.right() - size.width() : web_contents_bounds_.x(); 96 popup_->SetBounds(gfx::Rect( 97 x, 98 static_cast<int>(web_contents_bounds_.bottom() - 99 size.height() - size.height() * (1 - GetCurrentValue())), 100 size.width(), 101 size.height())); 102} 103 104void DownloadStartedAnimationViews::Close() { 105 popup_->Close(); 106} 107 108void DownloadStartedAnimationViews::AnimateToState(double state) { 109 if (state >= 1.0) { 110 Close(); 111 } else { 112 Reposition(); 113 114 // Start at zero, peak halfway and end at zero. 115 double opacity = std::min(1.0 - pow(GetCurrentValue() - 0.5, 2) * 4.0, 116 static_cast<double>(1.0)); 117 118 popup_->SetOpacity(static_cast<unsigned char>(opacity * 255.0)); 119 } 120} 121 122} // namespace 123 124// static 125void DownloadStartedAnimation::Show(content::WebContents* web_contents) { 126 // The animation will delete itself when it's finished. 127 new DownloadStartedAnimationViews(web_contents); 128} 129