summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorarv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-18 13:29:15 +0000
committerarv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-18 13:29:15 +0000
commit214594aee1595c3f44046c94152fc09fafde0b02 (patch)
tree35d73ca25cadd00791e59971e074fa0200eea675 /chrome/browser
parent03c379af76cb72a4f59dc4631182104da6bbdd4f (diff)
downloadchromium_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.h28
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.cc63
-rw-r--r--chrome/browser/dom_ui/app_launcher_handler.h7
-rw-r--r--chrome/browser/download/download_started_animation.h4
-rw-r--r--chrome/browser/resources/new_new_tab.js16
-rw-r--r--chrome/browser/views/app_launched_animation_win.cc134
-rw-r--r--chrome/browser/views/app_launcher.h2
-rw-r--r--chrome/browser/views/info_bubble.cc4
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);