diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-18 23:40:54 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-18 23:40:54 +0000 |
commit | d9b46d768e64c24beb0497902e47b2a9d4a54af7 (patch) | |
tree | 315ad2dd05dd0168c9fcae9b692a3a071c72fdc7 | |
parent | 3c0b93897f5745a0c18f751938a536a931d10234 (diff) | |
download | chromium_src-d9b46d768e64c24beb0497902e47b2a9d4a54af7.zip chromium_src-d9b46d768e64c24beb0497902e47b2a9d4a54af7.tar.gz chromium_src-d9b46d768e64c24beb0497902e47b2a9d4a54af7.tar.bz2 |
Implement the sad tab crash animation for tabs in linux.
BUG=11615
Review URL: http://codereview.chromium.org/115489
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16342 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/tabs/tab_renderer_gtk.cc | 111 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_renderer_gtk.h | 18 |
2 files changed, 126 insertions, 3 deletions
diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc index 67212e03..38cba8f 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc @@ -43,6 +43,8 @@ const SkScalar kTabBottomCurveWidth = 3; const int kCloseButtonVertFuzz = 0; const int kCloseButtonHorzFuzz = 5; +SkBitmap* crashed_fav_icon = NULL; + TabRendererGtk::LoadingAnimation::Data loading_animation_data; // Loads the loading animation images and data. @@ -126,6 +128,45 @@ void TabRendererGtk::LoadingAnimation::ValidateLoadingAnimation( } //////////////////////////////////////////////////////////////////////////////// +// FaviconCrashAnimation +// +// A custom animation subclass to manage the favicon crash animation. +class TabRendererGtk::FavIconCrashAnimation : public Animation, + public AnimationDelegate { + public: + explicit FavIconCrashAnimation(TabRendererGtk* target) + : ALLOW_THIS_IN_INITIALIZER_LIST(Animation(1000, 25, this)), + target_(target) { + } + virtual ~FavIconCrashAnimation() {} + + // Animation overrides: + virtual void AnimateToState(double state) { + const double kHidingOffset = 27; + + if (state < .5) { + target_->SetFavIconHidingOffset( + static_cast<int>(floor(kHidingOffset * 2.0 * state))); + } else { + target_->DisplayCrashedFavIcon(); + target_->SetFavIconHidingOffset( + static_cast<int>( + floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); + } + } + + // AnimationDelegate overrides: + virtual void AnimationCanceled(const Animation* animation) { + target_->SetFavIconHidingOffset(0); + } + + private: + TabRendererGtk* target_; + + DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation); +}; + +//////////////////////////////////////////////////////////////////////////////// // TabRendererGtk, public: TabRendererGtk::TabRendererGtk() @@ -172,6 +213,16 @@ void TabRendererGtk::UpdateData(TabContents* contents, bool loading_only) { void TabRendererGtk::UpdateFromModel() { // Force a layout, since the tab may have grown a favicon. Layout(); + SchedulePaint(); + + if (data_.crashed) { + if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) + StartCrashAnimation(); + } else { + if (IsPerformingCrashAnimation()) + StopCrashAnimation(); + ResetCrashedFavIcon(); + } } bool TabRendererGtk::IsSelected() const { @@ -290,6 +341,36 @@ void TabRendererGtk::AnimationEnded(const Animation* animation) { //////////////////////////////////////////////////////////////////////////////// // TabRendererGtk, private: +void TabRendererGtk::StartCrashAnimation() { + if (!crash_animation_.get()) + crash_animation_.reset(new FavIconCrashAnimation(this)); + crash_animation_->Reset(); + crash_animation_->Start(); +} + +void TabRendererGtk::StopCrashAnimation() { + if (!crash_animation_.get()) + return; + crash_animation_->Stop(); +} + +bool TabRendererGtk::IsPerformingCrashAnimation() const { + return crash_animation_.get() && crash_animation_->IsAnimating(); +} + +void TabRendererGtk::SetFavIconHidingOffset(int offset) { + fav_icon_hiding_offset_ = offset; + SchedulePaint(); +} + +void TabRendererGtk::DisplayCrashedFavIcon() { + should_display_crashed_favicon_ = true; +} + +void TabRendererGtk::ResetCrashedFavIcon() { + should_display_crashed_favicon_ = false; +} + void TabRendererGtk::Paint(GdkEventExpose* event) { gfx::CanvasPaint canvas(event, false); if (canvas.isEmpty()) @@ -314,9 +395,31 @@ void TabRendererGtk::Paint(GdkEventExpose* event) { if (show_icon) { if (loading_animation_.animation_state() != ANIMATION_NONE) { PaintLoadingAnimation(&canvas); - } else if (!data_.favicon.isNull()) { - canvas.DrawBitmapInt(data_.favicon, favicon_bounds_.x(), - favicon_bounds_.y() + fav_icon_hiding_offset_); + } else { + canvas.save(); + canvas.ClipRectInt(0, 0, width(), height() - kFavIconTitleSpacing); + if (should_display_crashed_favicon_) { + canvas.DrawBitmapInt(*crashed_fav_icon, 0, 0, + crashed_fav_icon->width(), + crashed_fav_icon->height(), + favicon_bounds_.x(), + favicon_bounds_.y() + fav_icon_hiding_offset_, + kFavIconSize, kFavIconSize, + true); + } else { + if (!data_.favicon.isNull()) { + // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch + // to using that class to render the favicon). + canvas.DrawBitmapInt(data_.favicon, 0, 0, + data_.favicon.width(), + data_.favicon.height(), + favicon_bounds_.x(), + favicon_bounds_.y() + fav_icon_hiding_offset_, + kFavIconSize, kFavIconSize, + true); + } + } + canvas.restore(); } } @@ -607,5 +710,7 @@ void TabRendererGtk::InitResources() { InitializeLoadingAnimationData(&rb, &loading_animation_data); + crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON); + initialized_ = true; } diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h index c449a02..f93681d 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h @@ -145,6 +145,8 @@ class TabRendererGtk : public AnimationDelegate { void OnMouseExited(); private: + class FavIconCrashAnimation; + // Model data. We store this here so that we don't need to ask the underlying // model, which is tricky since instances of this object can outlive the // corresponding objects in the underlying model. @@ -172,6 +174,19 @@ class TabRendererGtk : public AnimationDelegate { virtual void AnimationCanceled(const Animation* animation); virtual void AnimationEnded(const Animation* animation); + // Starts/Stops the crash animation. + void StartCrashAnimation(); + void StopCrashAnimation(); + + // Return true if the crash animation is currently running. + bool IsPerformingCrashAnimation() const; + + // Set the temporary offset for the favicon. This is used during animation. + void SetFavIconHidingOffset(int offset); + + void DisplayCrashedFavIcon(); + void ResetCrashedFavIcon(); + // Generates the bounds for the interior items of the tab. void Layout(); @@ -242,6 +257,9 @@ class TabRendererGtk : public AnimationDelegate { // The offset used to animate the favicon location. int fav_icon_hiding_offset_; + // The animation object used to swap the favicon with the sad tab icon. + scoped_ptr<FavIconCrashAnimation> crash_animation_; + // Set when the crashed favicon should be displayed. bool should_display_crashed_favicon_; |