download_started_animation_views.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// Copyright (c) 2012 The Chromium Authors. All rights reserved. 242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// Use of this source code is governed by a BSD-style license that can be 342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// found in the LICENSE file. 442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "chrome/browser/download/download_started_animation.h" 642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "content/public/browser/web_contents.h" 842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "content/public/browser/web_contents_view.h" 942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "grit/theme_resources.h" 1042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "ui/base/resource/resource_bundle.h" 1142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "ui/gfx/animation/linear_animation.h" 1242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "ui/gfx/rect.h" 1342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "ui/views/controls/image_view.h" 1442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com#include "ui/views/widget/widget.h" 1542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 1642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// How long to spend moving downwards and fading out after waiting. 1742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.comconst int kMoveTimeMs = 600; 1842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 1942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// The animation framerate. 2042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.comconst int kFrameRateHz = 60; 2142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 2263ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.comnamespace { 2342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 2442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// DownloadStartAnimation creates an animation (which begins running 2563ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com// immediately) that animates an image downward from the center of the frame 2642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// provided on the constructor, while simultaneously fading it out. To use, 2742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com// simply call "new DownloadStartAnimation"; the class cleans itself up when it 2863ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com// finishes animating. 2942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.comclass DownloadStartedAnimationViews : public gfx::LinearAnimation, 3042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com public views::ImageView { 3163ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com public: 3242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com explicit DownloadStartedAnimationViews(content::WebContents* web_contents); 3342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 3463ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com private: 3542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // Move the animation to wherever it should currently be. 3642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com void Reposition(); 3763ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com 3842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // Shut down the animation cleanly. 3942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com void Close(); 4063ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com 4142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // Animation 4242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com virtual void AnimateToState(double state) OVERRIDE; 4363ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com 4442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // We use a TYPE_POPUP for the popup so that it may float above any windows in 4542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // our UI. 4663ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com views::Widget* popup_; 4742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 4842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // The content area at the start of the animation. We store this so that the 4963ba31948392a56c191607d62a2414f16253e47bskia.committer@gmail.com // download shelf's resizing of the content area doesn't cause the animation 5042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // to move around. This means that once started, the animation won't move 5142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // with the parent window, but it's so fast that this shouldn't cause too 5242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // much heartbreak. 5342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com gfx::Rect web_contents_bounds_; 5442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 5542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com DISALLOW_COPY_AND_ASSIGN(DownloadStartedAnimationViews); 5642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com}; 5742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 5842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.comDownloadStartedAnimationViews::DownloadStartedAnimationViews( 5942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com content::WebContents* web_contents) 6042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com : gfx::LinearAnimation(kMoveTimeMs, kFrameRateHz, NULL), 6142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_(NULL) { 6242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com static gfx::ImageSkia* kDownloadImage = NULL; 6342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com if (!kDownloadImage) { 6442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com kDownloadImage = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 6542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com IDR_DOWNLOAD_ANIMATION_BEGIN); 6642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com } 6742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 6842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // If we're too small to show the download image, then don't bother - 6942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // the shelf will be enough. 7042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com web_contents->GetView()->GetContainerBounds(&web_contents_bounds_); 7142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com if (web_contents_bounds_.height() < kDownloadImage->height()) 7242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com return; 7342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 7442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com SetImage(kDownloadImage); 7542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 7642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_ = new views::Widget; 7742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 7842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 7942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 8042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com params.accept_events = false; 8142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com params.parent = web_contents->GetView()->GetNativeView(); 8242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_->Init(params); 8342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_->SetOpacity(0x00); 8442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_->SetContentsView(this); 8542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com Reposition(); 8642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_->Show(); 8742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 8842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com Start(); 8942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com} 9042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com 9142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.comvoid DownloadStartedAnimationViews::Reposition() { 9242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // Align the image with the bottom left of the web contents (so that it 9342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com // points to the newly created download). 9442cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com gfx::Size size = GetPreferredSize(); 9542cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com int x = base::i18n::IsRTL() ? 9642cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com web_contents_bounds_.right() - size.width() : web_contents_bounds_.x(); 9742cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com popup_->SetBounds(gfx::Rect( 9842cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com x, 9942cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com static_cast<int>(web_contents_bounds_.bottom() - 10042cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com size.height() - size.height() * (1 - GetCurrentValue())), 10142cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com size.width(), 10242cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com size.height())); 10342cc237caf9f02eaf59ad685e4529c184be78a37robertphillips@google.com} 104befb499da5ddf9df7c1986b56d7647f55f97f297robertphillips@google.com 105void DownloadStartedAnimationViews::Close() { 106 popup_->Close(); 107} 108 109void DownloadStartedAnimationViews::AnimateToState(double state) { 110 if (state >= 1.0) { 111 Close(); 112 } else { 113 Reposition(); 114 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)); 118 119 popup_->SetOpacity(static_cast<unsigned char>(opacity * 255.0)); 120 } 121} 122 123} // namespace 124 125// static 126void DownloadStartedAnimation::Show(content::WebContents* web_contents) { 127 // The animation will delete itself when it's finished. 128 new DownloadStartedAnimationViews(web_contents); 129} 130