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