diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-16 18:52:17 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-16 18:52:17 +0000 |
commit | 080287469804ce94aaf94c87e957fd27315dcf49 (patch) | |
tree | b428654e910fd93bc720246da6eb747fd4a59dd4 | |
parent | eb13aa23e3d5e820fd4f3ff39633b99b30d4b352 (diff) | |
download | chromium_src-080287469804ce94aaf94c87e957fd27315dcf49.zip chromium_src-080287469804ce94aaf94c87e957fd27315dcf49.tar.gz chromium_src-080287469804ce94aaf94c87e957fd27315dcf49.tar.bz2 |
Tweaks to the launcher favicon painting code. Current code resulted in
a lot of flickering as we waited for the favicon for sites. We would
transition to globe, then to real favicon. New code delays for 500ms,
then fades out current icon.
BUG=none
TEST=none
R=ben@chromium.org
Review URL: http://codereview.chromium.org/8967003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114834 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/favicon/favicon_tab_helper.h | 2 | ||||
-rw-r--r-- | chrome/browser/ui/views/aura/launcher_icon_updater.cc | 108 | ||||
-rw-r--r-- | chrome/browser/ui/views/aura/launcher_icon_updater.h | 31 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_model.cc | 5 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_model.h | 4 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_model_observer.h | 4 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_model_unittest.cc | 2 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_view.cc | 7 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_view.h | 1 | ||||
-rw-r--r-- | ui/aura_shell/launcher/tabbed_launcher_button.cc | 54 | ||||
-rw-r--r-- | ui/aura_shell/launcher/tabbed_launcher_button.h | 38 | ||||
-rw-r--r-- | ui/aura_shell/workspace_controller.h | 1 |
12 files changed, 158 insertions, 99 deletions
diff --git a/chrome/browser/favicon/favicon_tab_helper.h b/chrome/browser/favicon/favicon_tab_helper.h index 09dcb29..216fe24 100644 --- a/chrome/browser/favicon/favicon_tab_helper.h +++ b/chrome/browser/favicon/favicon_tab_helper.h @@ -45,7 +45,7 @@ class FaviconTabHelper : public TabContentsObserver, // entries, which should rarely happen. SkBitmap GetFavicon() const; - // Returns true if we are not using the default favicon. + // Returns true if we have the favicon for the page. bool FaviconIsValid() const; // Returns whether the favicon should be displayed. If this returns false, no diff --git a/chrome/browser/ui/views/aura/launcher_icon_updater.cc b/chrome/browser/ui/views/aura/launcher_icon_updater.cc index 3552fd4..afd4115 100644 --- a/chrome/browser/ui/views/aura/launcher_icon_updater.cc +++ b/chrome/browser/ui/views/aura/launcher_icon_updater.cc @@ -4,8 +4,6 @@ #include "chrome/browser/ui/views/aura/launcher_icon_updater.h" -#include <algorithm> - #include "chrome/browser/extensions/extension_tab_helper.h" #include "chrome/browser/favicon/favicon_tab_helper.h" #include "chrome/browser/tabs/tab_strip_model.h" @@ -15,9 +13,6 @@ #include "ui/aura/window.h" #include "ui/base/resource/resource_bundle.h" -// Max number of tabs we'll send icons over for. -const int kMaxCount = 3; - LauncherIconUpdater::LauncherIconUpdater( TabStripModel* tab_model, aura_shell::LauncherModel* launcher_model, @@ -26,81 +21,46 @@ LauncherIconUpdater::LauncherIconUpdater( launcher_model_(launcher_model), window_(window) { tab_model->AddObserver(this); - if (tab_model->GetActiveTabContents()) - tabs_.push_front(tab_model->GetActiveTabContents()); - for (int i = 0; i < tab_model->count(); ++i) { - if (i != tab_model->active_index()) - tabs_.push_back(tab_model->GetTabContentsAt(i)); - } - UpdateLauncher(); + UpdateLauncher(tab_model_->GetActiveTabContents()); } LauncherIconUpdater::~LauncherIconUpdater() { tab_model_->RemoveObserver(this); } -void LauncherIconUpdater::TabInsertedAt(TabContentsWrapper* contents, - int index, - bool foreground) { - if (std::find(tabs_.begin(), tabs_.end(), contents) == tabs_.end()) - tabs_.push_back(contents); -} - -void LauncherIconUpdater::TabDetachedAt(TabContentsWrapper* contents, - int index) { - Tabs::iterator i = std::find(tabs_.begin(), tabs_.end(), contents); - bool update = i != tabs_.end() ? (i - tabs_.begin()) < kMaxCount : false; - if (i != tabs_.end()) - tabs_.erase(i); - if (update) - UpdateLauncher(); -} - -void LauncherIconUpdater::TabSelectionChanged( - TabStripModel* tab_strip_model, - const TabStripSelectionModel& old_model) { - TabContentsWrapper* tab = tab_strip_model->GetActiveTabContents(); - if (!tab) - return; - - Tabs::iterator i = std::find(tabs_.begin(), tabs_.end(), tab); - if (i == tabs_.begin()) - return; // The active tab didn't change, ignore it. - - // Move the active tab to the front. - if (i != tabs_.end()) - tabs_.erase(i); - tabs_.push_front(tab); - UpdateLauncher(); +void LauncherIconUpdater::ActiveTabChanged(TabContentsWrapper* old_contents, + TabContentsWrapper* new_contents, + int index, + bool user_gesture) { + // Update immediately on a tab change. + UpdateLauncher(new_contents); } void LauncherIconUpdater::TabChangedAt( TabContentsWrapper* tab, int index, TabStripModelObserver::TabChangeType change_type) { - if (change_type != TabStripModelObserver::LOADING_ONLY && - change_type != TabStripModelObserver::TITLE_NOT_LOADING) { - Tabs::iterator i = std::find(tabs_.begin(), tabs_.end(), tab); - if (i != tabs_.end() && (i - tabs_.begin()) < kMaxCount) - UpdateLauncher(); + if (index != tab_model_->active_index() || + !(change_type != TabStripModelObserver::LOADING_ONLY && + change_type != TabStripModelObserver::TITLE_NOT_LOADING)) { + return; } -} -void LauncherIconUpdater::TabReplacedAt(TabStripModel* tab_strip_model, - TabContentsWrapper* old_contents, - TabContentsWrapper* new_contents, - int index) { - Tabs::iterator i = std::find(tabs_.begin(), tabs_.end(), old_contents); - if (i != tabs_.end()) { - int pos = i - tabs_.begin(); - tabs_[pos] = new_contents; - if (pos < kMaxCount) - UpdateLauncher(); + if (tab->favicon_tab_helper()->FaviconIsValid()) { + // We have the favicon, update immediately. + UpdateLauncher(tab); + } else { + // Let the model know we're waiting. We delay updating as otherwise the user + // sees flicker as we fetch the favicon. + int item_index = launcher_model_->ItemIndexByWindow(window_); + if (item_index == -1) + return; + launcher_model_->SetPendingUpdate(item_index); } } -void LauncherIconUpdater::UpdateLauncher() { - if (tabs_.empty()) +void LauncherIconUpdater::UpdateLauncher(TabContentsWrapper* tab) { + if (!tab) return; // Assume the window is going to be closed if there are no tabs. int item_index = launcher_model_->ItemIndexByWindow(window_); @@ -110,25 +70,23 @@ void LauncherIconUpdater::UpdateLauncher() { if (launcher_model_->items()[item_index].type == aura_shell::TYPE_APP) { // Use the app icon if we can. SkBitmap image; - if (tabs_[0]->extension_tab_helper()->GetExtensionAppIcon()) - image = *tabs_[0]->extension_tab_helper()->GetExtensionAppIcon(); + if (tab->extension_tab_helper()->GetExtensionAppIcon()) + image = *tab->extension_tab_helper()->GetExtensionAppIcon(); else - image = tabs_[0]->favicon_tab_helper()->GetFavicon(); + image = tab->favicon_tab_helper()->GetFavicon(); launcher_model_->SetAppImage(item_index, image); return; } aura_shell::LauncherTabbedImages images; - size_t count = std::min(static_cast<size_t>(kMaxCount), tabs_.size()); - images.resize(count); - for (size_t i = 0; i < count; ++i) { - // TODO: needs to be updated for apps. - images[i].image = tabs_[i]->favicon_tab_helper()->GetFavicon(); - if (images[i].image.empty()) { - images[i].image = *ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_DEFAULT_FAVICON); + if (tab->favicon_tab_helper()->ShouldDisplayFavicon()) { + images.resize(1); + images[0].image = tab->favicon_tab_helper()->GetFavicon(); + if (images[0].image.empty()) { + images[0].image = *ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_DEFAULT_FAVICON); } - images[i].user_data = tabs_[i]; + images[0].user_data = tab; } launcher_model_->SetTabbedImages(item_index, images); } diff --git a/chrome/browser/ui/views/aura/launcher_icon_updater.h b/chrome/browser/ui/views/aura/launcher_icon_updater.h index 0cef527..0176e2e 100644 --- a/chrome/browser/ui/views/aura/launcher_icon_updater.h +++ b/chrome/browser/ui/views/aura/launcher_icon_updater.h @@ -6,12 +6,12 @@ #define CHROME_BROWSER_UI_VIEWS_AURA_LAUNCHER_ICON_UPDATER_H_ #pragma once -#include <deque> - #include "base/basictypes.h" #include "base/compiler_specific.h" #include "chrome/browser/tabs/tab_strip_model_observer.h" +class TabContentsWrapper; + namespace aura { class Window; } @@ -20,7 +20,7 @@ class LauncherModel; } // LauncherIconUpdater is responsible for keeping the launcher representation -// of a window up to date with the tabs. +// of a window up to date as the tab strip changes. class LauncherIconUpdater : public TabStripModelObserver { public: LauncherIconUpdater(TabStripModel* tab_model, @@ -29,37 +29,26 @@ class LauncherIconUpdater : public TabStripModelObserver { virtual ~LauncherIconUpdater(); // TabStripModel overrides: - virtual void TabInsertedAt(TabContentsWrapper* contents, - int index, - bool foreground) OVERRIDE; - virtual void TabDetachedAt(TabContentsWrapper* contents, int index) OVERRIDE; - virtual void TabSelectionChanged( - TabStripModel* tab_strip_model, - const TabStripSelectionModel& old_model) OVERRIDE; + virtual void ActiveTabChanged(TabContentsWrapper* old_contents, + TabContentsWrapper* new_contents, + int index, + bool user_gesture) OVERRIDE; virtual void TabChangedAt( TabContentsWrapper* tab, int index, TabStripModelObserver::TabChangeType change_type) OVERRIDE; - virtual void TabReplacedAt(TabStripModel* tab_strip_model, - TabContentsWrapper* old_contents, - TabContentsWrapper* new_contents, - int index) OVERRIDE; private: - typedef std::deque<TabContentsWrapper*> Tabs; - - // Updates the launcher from the current set of tabs. - void UpdateLauncher(); + // Updates the launcher from |tab|. + void UpdateLauncher(TabContentsWrapper* tab); TabStripModel* tab_model_; aura_shell::LauncherModel* launcher_model_; + // Used to index into the model. aura::Window* window_; - // The tabs. This is an MRU cache of the tabs in the tabstrip model. - Tabs tabs_; - DISALLOW_COPY_AND_ASSIGN(LauncherIconUpdater); }; diff --git a/ui/aura_shell/launcher/launcher_model.cc b/ui/aura_shell/launcher/launcher_model.cc index d65023b..1380a12 100644 --- a/ui/aura_shell/launcher/launcher_model.cc +++ b/ui/aura_shell/launcher/launcher_model.cc @@ -56,6 +56,11 @@ void LauncherModel::SetAppImage(int index, const SkBitmap& image) { LauncherItemImagesChanged(index)); } +void LauncherModel::SetPendingUpdate(int index) { + FOR_EACH_OBSERVER(LauncherModelObserver, observers_, + LauncherItemImagesWillChange(index)); +} + int LauncherModel::ItemIndexByWindow(aura::Window* window) { LauncherItems::const_iterator i = ItemByWindow(window); return i == items_.end() ? -1 : static_cast<int>((i - items_.begin())); diff --git a/ui/aura_shell/launcher/launcher_model.h b/ui/aura_shell/launcher/launcher_model.h index 1e8c19a..2771950 100644 --- a/ui/aura_shell/launcher/launcher_model.h +++ b/ui/aura_shell/launcher/launcher_model.h @@ -40,6 +40,10 @@ class AURA_SHELL_EXPORT LauncherModel { void SetTabbedImages(int index, const LauncherTabbedImages& images); void SetAppImage(int index, const SkBitmap& image); + // Sends LauncherItemImagesWillChange() to the observers. Used when the images + // are going to change for an item, but not for a while. + void SetPendingUpdate(int index); + // Returns the index of the item with the specified window. int ItemIndexByWindow(aura::Window* window); diff --git a/ui/aura_shell/launcher/launcher_model_observer.h b/ui/aura_shell/launcher/launcher_model_observer.h index 0388aa0..a477872 100644 --- a/ui/aura_shell/launcher/launcher_model_observer.h +++ b/ui/aura_shell/launcher/launcher_model_observer.h @@ -26,6 +26,10 @@ class AURA_SHELL_EXPORT LauncherModelObserver { // Invoked when the images of an item change. virtual void LauncherItemImagesChanged(int index) = 0; + // Signals that LauncherItemImagesChanged() is going to be sent in the + // near future. + virtual void LauncherItemImagesWillChange(int index) = 0; + protected: virtual ~LauncherModelObserver() {} }; diff --git a/ui/aura_shell/launcher/launcher_model_unittest.cc b/ui/aura_shell/launcher/launcher_model_unittest.cc index d8ab3ba..1cc95f3 100644 --- a/ui/aura_shell/launcher/launcher_model_unittest.cc +++ b/ui/aura_shell/launcher/launcher_model_unittest.cc @@ -47,6 +47,8 @@ class TestLauncherModelObserver : public LauncherModelObserver { virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE { moved_count_++; } + virtual void LauncherItemImagesWillChange(int index) OVERRIDE { + } private: void AddToResult(const std::string& format, int count, std::string* result) { diff --git a/ui/aura_shell/launcher/launcher_view.cc b/ui/aura_shell/launcher/launcher_view.cc index 68a8ed8..eb71ef2 100644 --- a/ui/aura_shell/launcher/launcher_view.cc +++ b/ui/aura_shell/launcher/launcher_view.cc @@ -539,6 +539,13 @@ void LauncherView::LauncherItemMoved(int start_index, int target_index) { AnimateToIdealBounds(); } +void LauncherView::LauncherItemImagesWillChange(int index) { + const LauncherItem& item(model_->items()[index]); + views::View* view = view_model_->view_at(index); + if (item.type == TYPE_TABBED) + static_cast<TabbedLauncherButton*>(view)->PrepareForImageChange(); +} + void LauncherView::MousePressedOnButton(views::View* view, const views::MouseEvent& event) { if (view_model_->GetIndexOfView(view) == -1 || view_model_->view_size() <= 1) diff --git a/ui/aura_shell/launcher/launcher_view.h b/ui/aura_shell/launcher/launcher_view.h index 8461921..cfff1b2 100644 --- a/ui/aura_shell/launcher/launcher_view.h +++ b/ui/aura_shell/launcher/launcher_view.h @@ -96,6 +96,7 @@ class LauncherView : public views::WidgetDelegateView, virtual void LauncherItemRemoved(int model_index) OVERRIDE; virtual void LauncherItemImagesChanged(int model_index) OVERRIDE; virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE; + virtual void LauncherItemImagesWillChange(int index) OVERRIDE; // Overridden from LauncherButtonHost: virtual void MousePressedOnButton(views::View* view, diff --git a/ui/aura_shell/launcher/tabbed_launcher_button.cc b/ui/aura_shell/launcher/tabbed_launcher_button.cc index aac9205..404030f 100644 --- a/ui/aura_shell/launcher/tabbed_launcher_button.cc +++ b/ui/aura_shell/launcher/tabbed_launcher_button.cc @@ -8,6 +8,7 @@ #include "grit/ui_resources.h" #include "ui/aura_shell/launcher/launcher_button_host.h" +#include "ui/base/animation/multi_animation.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" @@ -31,6 +32,28 @@ const int kBgLeftInset = 30; const int kBgBottomInset = 12; const int kBgRightInset = 8; +TabbedLauncherButton::AnimationDelegateImpl::AnimationDelegateImpl( + TabbedLauncherButton* host) + : host_(host) { +} + +TabbedLauncherButton::AnimationDelegateImpl::~AnimationDelegateImpl() { +} + +void TabbedLauncherButton::AnimationDelegateImpl::AnimationEnded( + const ui::Animation* animation) { + AnimationProgressed(animation); + // Hide the image when the animation is done. We'll show it again the next + // time SetImages is invoked. + host_->show_image_ = false; +} + +void TabbedLauncherButton::AnimationDelegateImpl::AnimationProgressed( + const ui::Animation* animation) { + if (host_->animation_->current_part_index() == 1) + host_->SchedulePaint(); +} + // static TabbedLauncherButton::ImageSet* TabbedLauncherButton::bg_image_1_ = NULL; TabbedLauncherButton::ImageSet* TabbedLauncherButton::bg_image_2_ = NULL; @@ -39,7 +62,9 @@ TabbedLauncherButton::ImageSet* TabbedLauncherButton::bg_image_3_ = NULL; TabbedLauncherButton::TabbedLauncherButton(views::ButtonListener* listener, LauncherButtonHost* host) : views::ImageButton(listener), - host_(host) { + host_(host), + ALLOW_THIS_IN_INITIALIZER_LIST(animation_delegate_(this)), + show_image_(true) { if (!bg_image_1_) { bg_image_1_ = CreateImageSet(IDR_AURA_LAUNCHER_TABBED_BROWSER_1, IDR_AURA_LAUNCHER_TABBED_BROWSER_1_PUSHED, @@ -58,7 +83,23 @@ TabbedLauncherButton::TabbedLauncherButton(views::ButtonListener* listener, TabbedLauncherButton::~TabbedLauncherButton() { } +void TabbedLauncherButton::PrepareForImageChange() { + if (!show_image_ || (animation_.get() && animation_->is_animating())) + return; + + // Pause for 500ms, then ease out for 200ms. + ui::MultiAnimation::Parts animation_parts; + animation_parts.push_back(ui::MultiAnimation::Part(500, ui::Tween::ZERO)); + animation_parts.push_back(ui::MultiAnimation::Part(200, ui::Tween::EASE_OUT)); + animation_.reset(new ui::MultiAnimation(animation_parts)); + animation_->set_continuous(false); + animation_->set_delegate(&animation_delegate_); + animation_->Start(); +} + void TabbedLauncherButton::SetImages(const LauncherTabbedImages& images) { + animation_.reset(); + show_image_ = true; images_ = images; ImageSet* set; if (images_.size() <= 1) @@ -70,20 +111,29 @@ void TabbedLauncherButton::SetImages(const LauncherTabbedImages& images) { SetImage(BS_NORMAL, set->normal_image); SetImage(BS_HOT, set->hot_image); SetImage(BS_PUSHED, set->pushed_image); + SchedulePaint(); } void TabbedLauncherButton::OnPaint(gfx::Canvas* canvas) { ImageButton::OnPaint(canvas); - if (images_.empty()) + if (images_.empty() || images_[0].image.empty() || !show_image_) return; + bool save_layer = (animation_.get() && animation_->is_animating() && + animation_->current_part_index() == 1); + if (save_layer) + canvas->SaveLayerAlpha(animation_->CurrentValueBetween(255, 0)); + // Only show the first icon. // TODO(sky): if we settle on just 1 icon, then we should simplify surrounding // code (don't use a vector of images). int x = (width() - images_[0].image.width()) / 2; int y = (height() - images_[0].image.height()) / 2 + 1; canvas->DrawBitmapInt(images_[0].image, x, y); + + if (save_layer) + canvas->Restore(); } bool TabbedLauncherButton::OnMousePressed(const views::MouseEvent& event) { diff --git a/ui/aura_shell/launcher/tabbed_launcher_button.h b/ui/aura_shell/launcher/tabbed_launcher_button.h index a945074..589c28a 100644 --- a/ui/aura_shell/launcher/tabbed_launcher_button.h +++ b/ui/aura_shell/launcher/tabbed_launcher_button.h @@ -6,9 +6,16 @@ #define UI_AURA_SHELL_LAUNCHER_TABBED_LAUNCHER_BUTTON_H_ #pragma once +#include "base/memory/scoped_ptr.h" +#include "base/timer.h" #include "ui/aura_shell/launcher/launcher_types.h" +#include "ui/base/animation/animation_delegate.h" #include "ui/views/controls/button/image_button.h" +namespace ui { +class MultiAnimation; +} + namespace aura_shell { namespace internal { @@ -21,6 +28,9 @@ class TabbedLauncherButton : public views::ImageButton { LauncherButtonHost* host); virtual ~TabbedLauncherButton(); + // Notification that the images are about to change. Kicks off an animation. + void PrepareForImageChange(); + // Sets the images to display for this entry. void SetImages(const LauncherTabbedImages& images); @@ -33,6 +43,24 @@ class TabbedLauncherButton : public views::ImageButton { virtual bool OnMouseDragged(const views::MouseEvent& event) OVERRIDE; private: + // Used as the delegate for |animation_|. TabbedLauncherButton doesn't + // directly implement AnimationDelegate as one of it's superclasses already + // does. + class AnimationDelegateImpl : public ui::AnimationDelegate { + public: + explicit AnimationDelegateImpl(TabbedLauncherButton* host); + virtual ~AnimationDelegateImpl(); + + // ui::AnimationDelegateImpl overrides: + virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; + virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; + + private: + TabbedLauncherButton* host_; + + DISALLOW_COPY_AND_ASSIGN(AnimationDelegateImpl); + }; + struct ImageSet { SkBitmap* normal_image; SkBitmap* pushed_image; @@ -47,6 +75,16 @@ class TabbedLauncherButton : public views::ImageButton { LauncherButtonHost* host_; + // Delegate of |animation_|. + AnimationDelegateImpl animation_delegate_; + + // Used to animate image. + scoped_ptr<ui::MultiAnimation> animation_; + + // Should |images_| be shown? This is set to false soon after + // PrepareForImageChange() is invoked without a following call to SetImages(). + bool show_image_; + // Background images. Which one is chosen depends upon how many images are // provided. static ImageSet* bg_image_1_; diff --git a/ui/aura_shell/workspace_controller.h b/ui/aura_shell/workspace_controller.h index fd9e311..e1404da 100644 --- a/ui/aura_shell/workspace_controller.h +++ b/ui/aura_shell/workspace_controller.h @@ -70,6 +70,7 @@ class AURA_SHELL_EXPORT WorkspaceController : virtual void LauncherItemRemoved(int index) OVERRIDE; virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE; virtual void LauncherItemImagesChanged(int index) OVERRIDE; + virtual void LauncherItemImagesWillChange(int index) OVERRIDE {} private: scoped_ptr<WorkspaceManager> workspace_manager_; |