diff options
author | arv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-18 13:29:15 +0000 |
---|---|---|
committer | arv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-18 13:29:15 +0000 |
commit | 214594aee1595c3f44046c94152fc09fafde0b02 (patch) | |
tree | 35d73ca25cadd00791e59971e074fa0200eea675 /chrome/browser | |
parent | 03c379af76cb72a4f59dc4631182104da6bbdd4f (diff) | |
download | chromium_src-214594aee1595c3f44046c94152fc09fafde0b02.zip chromium_src-214594aee1595c3f44046c94152fc09fafde0b02.tar.gz chromium_src-214594aee1595c3f44046c94152fc09fafde0b02.tar.bz2 |
NTP: Adds an app launched animation.
This uses a popup window that is carefully positioned to be placed over the icon on the NTP. The popup fades out after a short delay.
BUG=None
TEST=Start with --enable-apps and launch an app. The icon should *stick* for a very short period and then fade out.
Review URL: http://codereview.chromium.org/2095008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47508 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/app_launched_animation.h | 28 | ||||
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.cc | 63 | ||||
-rw-r--r-- | chrome/browser/dom_ui/app_launcher_handler.h | 7 | ||||
-rw-r--r-- | chrome/browser/download/download_started_animation.h | 4 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 16 | ||||
-rw-r--r-- | chrome/browser/views/app_launched_animation_win.cc | 134 | ||||
-rw-r--r-- | chrome/browser/views/app_launcher.h | 2 | ||||
-rw-r--r-- | chrome/browser/views/info_bubble.cc | 4 |
8 files changed, 246 insertions, 12 deletions
diff --git a/chrome/browser/app_launched_animation.h b/chrome/browser/app_launched_animation.h new file mode 100644 index 0000000..b31a25d --- /dev/null +++ b/chrome/browser/app_launched_animation.h @@ -0,0 +1,28 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_APP_LAUNCHED_ANIMATION_H_ +#define CHROME_BROWSER_APP_LAUNCHED_ANIMATION_H_ + +#include "base/basictypes.h" + +class Extension; + +namespace gfx { + class Rect; +} + +class AppLaunchedAnimation { + public: + // Starts an animation of the |extension| being launched. The |rect| is the + // rect of the app icon. + static void Show(Extension* extension, const gfx::Rect& rect); + + private: + AppLaunchedAnimation() { } + + DISALLOW_COPY_AND_ASSIGN(AppLaunchedAnimation); +}; + +#endif // CHROME_BROWSER_APP_LAUNCHED_ANIMATION_H_ diff --git a/chrome/browser/dom_ui/app_launcher_handler.cc b/chrome/browser/dom_ui/app_launcher_handler.cc index 2726cf6..df3a776 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.cc +++ b/chrome/browser/dom_ui/app_launcher_handler.cc @@ -4,19 +4,23 @@ #include "chrome/browser/dom_ui/app_launcher_handler.h" +#include "app/animation.h" #include "app/resource_bundle.h" #include "base/base64.h" #include "base/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/app_launched_animation.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_resource.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" #include "chrome/common/url_constants.h" +#include "gfx/rect.h" #include "grit/browser_resources.h" namespace { @@ -25,10 +29,21 @@ bool TreatAsApp(const Extension* extension) { return !extension->GetFullLaunchURL().is_empty(); } +// This extracts an int from a ListValue at the given |index|. +bool ExtractInt(const ListValue* list, size_t index, int* out_int) { + std::string string_value; + + if (list->GetString(index, &string_value)) { + *out_int = StringToInt(string_value); + return true; + } + + return false; +} + } // namespace -AppLauncherHandler::AppLauncherHandler( - ExtensionsService* extension_service) +AppLauncherHandler::AppLauncherHandler(ExtensionsService* extension_service) : extensions_service_(extension_service) { } @@ -63,7 +78,7 @@ void AppLauncherHandler::Observe(NotificationType type, // static void AppLauncherHandler::CreateAppInfo(Extension* extension, - DictionaryValue* value) { + DictionaryValue* value) { value->Clear(); value->SetString(L"id", extension->id()); value->SetString(L"name", extension->name()); @@ -132,25 +147,41 @@ void AppLauncherHandler::HandleLaunchApp(const Value* value) { std::string extension_id; std::string launch_container; + int left; + int top; + int width; + int height; const ListValue* list = static_cast<const ListValue*>(value); if (!list->GetString(0, &extension_id) || - !list->GetString(1, &launch_container)) { + !list->GetString(1, &launch_container) || + !ExtractInt(list, 2, &left) || + !ExtractInt(list, 3, &top) || + !ExtractInt(list, 4, &width) || + !ExtractInt(list, 5, &height)) { NOTREACHED(); return; } - Profile* profile = extensions_service_->profile(); - if (launch_container.empty()) { - Browser::OpenApplication(profile, extension_id); - return; - } + // The rect we get from the client is relative to the browser client viewport. + // Offset the rect by the tab contents bounds. + gfx::Rect rect(left, top, width, height); + gfx::Rect tab_contents_bounds; + dom_ui_->tab_contents()->GetContainerBounds(&tab_contents_bounds); + rect.Offset(tab_contents_bounds.origin()); // Override the default launch container. Extension* extension = extensions_service_->GetExtensionById(extension_id, false); DCHECK(extension); + Profile* profile = extensions_service_->profile(); + if (launch_container.empty()) { + AnimateAppIcon(extension, rect); + Browser::OpenApplication(profile, extension_id); + return; + } + Extension::LaunchContainer container = Extension::LAUNCH_TAB; if (launch_container == "tab") container = Extension::LAUNCH_TAB; @@ -168,6 +199,7 @@ void AppLauncherHandler::HandleLaunchApp(const Value* value) { if (browser) old_contents = browser->GetSelectedTabContents(); + AnimateAppIcon(extension, rect); Browser::OpenApplication(profile, extension, container); if (old_contents && @@ -176,3 +208,16 @@ void AppLauncherHandler::HandleLaunchApp(const Value* value) { browser->CloseTabContents(old_contents); } } + +void AppLauncherHandler::AnimateAppIcon(Extension* extension, + const gfx::Rect& rect) { + // We make this check for the case of minimized windows, unit tests, etc. + if (platform_util::IsVisible(dom_ui_->tab_contents()->GetNativeView()) && + Animation::ShouldRenderRichAnimation()) { +#if defined(OS_WIN) + AppLaunchedAnimation::Show(extension, rect); +#else + NOTIMPLEMENTED(); +#endif + } +} diff --git a/chrome/browser/dom_ui/app_launcher_handler.h b/chrome/browser/dom_ui/app_launcher_handler.h index 460bcda..f169580 100644 --- a/chrome/browser/dom_ui/app_launcher_handler.h +++ b/chrome/browser/dom_ui/app_launcher_handler.h @@ -11,6 +11,10 @@ class Extension; class ExtensionsService; +namespace gfx { + class Rect; +} + // The handler for Javascript messages related to the "apps" view. class AppLauncherHandler : public DOMMessageHandler, @@ -38,6 +42,9 @@ class AppLauncherHandler void HandleLaunchApp(const Value* value); private: + // Starts the animation of the app icon. + void AnimateAppIcon(Extension* extension, const gfx::Rect& rect); + // The apps are represented in the extensions model. scoped_refptr<ExtensionsService> extensions_service_; diff --git a/chrome/browser/download/download_started_animation.h b/chrome/browser/download/download_started_animation.h index 9ae1f713..f44dece 100644 --- a/chrome/browser/download/download_started_animation.h +++ b/chrome/browser/download/download_started_animation.h @@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STARTED_ANIMATION_H_ #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STARTED_ANIMATION_H_ +#include "base/basictypes.h" + class TabContents; class DownloadStartedAnimation { @@ -13,6 +15,8 @@ class DownloadStartedAnimation { private: DownloadStartedAnimation() { } + + DISALLOW_COPY_AND_ASSIGN(DownloadStartedAnimation); }; #endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STARTED_ANIMATION_H_ diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js index 936fb13..4721d58 100644 --- a/chrome/browser/resources/new_new_tab.js +++ b/chrome/browser/resources/new_new_tab.js @@ -53,7 +53,21 @@ var apps = { break; } } - chrome.send('launchApp', [this.id, launchType]); + + // TODO(arv): Handle zoom? + var rect = this.getBoundingClientRect(); + var cs = getComputedStyle(this); + var size = cs.backgroundSize.split(/\s+/); // background-size has the + // format '123px 456px'. + var width = parseInt(size[0], 10); + var height = parseInt(size[1], 10); + // We are using background-position-x 50%. + var left = rect.left + ((rect.width - width) >> 1); // Integer divide by 2. + var top = rect.top + parseInt(cs.backgroundPositionY, 10); + + chrome.send('launchApp', [this.id, launchType, + String(left), String(top), + String(width), String(height)]); return false; }, diff --git a/chrome/browser/views/app_launched_animation_win.cc b/chrome/browser/views/app_launched_animation_win.cc new file mode 100644 index 0000000..5637fc5 --- /dev/null +++ b/chrome/browser/views/app_launched_animation_win.cc @@ -0,0 +1,134 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/app_launched_animation.h" + +#include "app/animation.h" +#include "app/slide_animation.h" +#include "chrome/browser/extensions/image_loading_tracker.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_resource.h" +#include "gfx/rect.h" +#include "views/controls/image_view.h" +#include "views/widget/widget_win.h" + +namespace { + +// Start at 1, end at 0 +// 0ms You click the icon +// 0ms The launcher and contents begins to fade out, the icon +// you clicked does not (stays opaque) +// 0ms The app begins loading behind the launcher +// +100ms The app icon begins to fade out. +// +200ms The launcher finishes fading out +// +350ms The app icon finishes fading out + +// How long the fade should take. +static const int kDurationMS = 250; + +// The delay before the fade out should start. +static const int kDelayMS = 100; + +// AppLaunchedAnimation creates an animation. It loads the icon for the +// extension and once the image is loaded the animation starts. The icon fades +// out after a short delay. +class AppLaunchedAnimationWin : public AnimationDelegate, + public ImageLoadingTracker::Observer, + public views::ImageView { + public: + AppLaunchedAnimationWin(Extension* extension, const gfx::Rect& rect); + + private: + // AnimationDelegate + virtual void AnimationProgressed(const Animation* animation); + virtual void AnimationCanceled(const Animation* animation); + virtual void AnimationEnded(const Animation* animation); + + // We use a HWND for the popup so that it may float above any HWNDs in our UI. + views::WidgetWin* popup_; + + // The rect to use for the popup. + gfx::Rect rect_; + + // Used for loading extension application icon. + ImageLoadingTracker app_icon_loader_; + + // ImageLoadingTracker::Observer. + virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource, + int index); + + // Hover animation. + scoped_ptr<SlideAnimation> animation_; + + DISALLOW_COPY_AND_ASSIGN(AppLaunchedAnimationWin); +}; + +AppLaunchedAnimationWin::AppLaunchedAnimationWin(Extension* extension, + const gfx::Rect& rect) + : popup_(NULL), + rect_(rect), + ALLOW_THIS_IN_INITIALIZER_LIST(app_icon_loader_(this)) { + DCHECK(extension); + app_icon_loader_.LoadImage( + extension, + extension->GetIconPath(Extension::EXTENSION_ICON_LARGE), + rect_.size(), + ImageLoadingTracker::DONT_CACHE); +} + +void AppLaunchedAnimationWin::AnimationCanceled(const Animation* animation) { + AnimationEnded(animation); +} + +void AppLaunchedAnimationWin::AnimationEnded(const Animation* animation) { + popup_->Close(); +} + +void AppLaunchedAnimationWin::AnimationProgressed(const Animation* animation) { + // GetCurrentValue goes from 1 to 0 since we are hiding. + const double current_value = 1.0 - animation->GetCurrentValue(); + const double current_time = current_value * (kDelayMS + kDurationMS); + + double opacity = 1.0 - + std::max(0.0, static_cast<double>(current_time - kDelayMS)) / + static_cast<double>(kDurationMS); + + popup_->SetOpacity(static_cast<SkColor>(opacity * 255.0)); + SchedulePaint(); +} + +void AppLaunchedAnimationWin::OnImageLoaded(SkBitmap* image, + ExtensionResource resource, + int index) { + if (image) { + SetImage(image); + + popup_ = new views::WidgetWin; + popup_->set_window_style(WS_POPUP); + popup_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | + WS_EX_TRANSPARENT); + popup_->SetOpacity(static_cast<SkColor>(255)); + + popup_->Init(NULL, rect_); + popup_->SetContentsView(this); + popup_->Show(); + + // Start animation. + animation_.reset(new SlideAnimation(this)); + animation_->SetSlideDuration(kDelayMS + kDurationMS); + animation_->SetTweenType(Tween::LINEAR); + animation_->Reset(1.0); + animation_->Hide(); + } else { + popup_->Close(); + } +} + +} // namespace + +// static +void AppLaunchedAnimation::Show(Extension* extension, const gfx::Rect& rect) { + // The animation will delete itself when it's finished. + new AppLaunchedAnimationWin(extension, rect); +} diff --git a/chrome/browser/views/app_launcher.h b/chrome/browser/views/app_launcher.h index a9cbf1d..954a154 100644 --- a/chrome/browser/views/app_launcher.h +++ b/chrome/browser/views/app_launcher.h @@ -69,6 +69,8 @@ class AppLauncher : public AnimationDelegate, bool closed_by_escape); virtual bool CloseOnEscape() { return true; } virtual bool FadeOutOnClose() { + // If this is changed we also need to update + // AppLauncherHandler::AnimateAppIcon. #if defined(OS_WIN) return true; #else diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc index 4894f1a..495ee2b 100644 --- a/chrome/browser/views/info_bubble.cc +++ b/chrome/browser/views/info_bubble.cc @@ -303,7 +303,7 @@ void InfoBubble::Init(views::Widget* parent, parent_window->DisableInactiveRendering(); set_window_style(WS_POPUP | WS_CLIPCHILDREN); set_window_ex_style(WS_EX_TOOLWINDOW); - + DCHECK(!border_); border_ = new BorderWidget(); border_->Init(CreateBorderContents(), parent->GetNativeView()); @@ -457,7 +457,7 @@ void InfoBubble::FadeOut() { #endif animation_.reset(new SlideAnimation(this)); - animation_->SetDuration(kHideFadeDurationMS); + animation_->SetSlideDuration(kHideFadeDurationMS); animation_->SetTweenType(Tween::LINEAR); animation_->Reset(1.0); |