summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 23:40:54 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-18 23:40:54 +0000
commitd9b46d768e64c24beb0497902e47b2a9d4a54af7 (patch)
tree315ad2dd05dd0168c9fcae9b692a3a071c72fdc7
parent3c0b93897f5745a0c18f751938a536a931d10234 (diff)
downloadchromium_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.cc111
-rw-r--r--chrome/browser/gtk/tabs/tab_renderer_gtk.h18
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_;