OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/views/tabs/tab_renderer.h" | 5 #include "chrome/browser/views/tabs/tab_renderer.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "app/gfx/canvas.h" | 9 #include "app/gfx/canvas.h" |
10 #include "app/gfx/favicon_size.h" | 10 #include "app/gfx/favicon_size.h" |
11 #include "app/gfx/font.h" | 11 #include "app/gfx/font.h" |
12 #include "app/gfx/skbitmap_operations.h" | 12 #include "app/gfx/skbitmap_operations.h" |
13 #include "app/l10n_util.h" | 13 #include "app/l10n_util.h" |
14 #include "app/resource_bundle.h" | 14 #include "app/resource_bundle.h" |
| 15 #include "app/slide_animation.h" |
| 16 #include "app/throb_animation.h" |
15 #include "chrome/browser/browser.h" | 17 #include "chrome/browser/browser.h" |
16 #include "chrome/browser/browser_theme_provider.h" | 18 #include "chrome/browser/browser_theme_provider.h" |
17 #include "chrome/browser/defaults.h" | 19 #include "chrome/browser/defaults.h" |
18 #include "chrome/browser/profile.h" | 20 #include "chrome/browser/profile.h" |
19 #include "chrome/browser/tab_contents/tab_contents.h" | 21 #include "chrome/browser/tab_contents/tab_contents.h" |
20 #include "chrome/browser/tabs/tab_strip_model.h" | 22 #include "chrome/browser/tabs/tab_strip_model.h" |
21 #include "grit/app_resources.h" | 23 #include "grit/app_resources.h" |
22 #include "grit/generated_resources.h" | 24 #include "grit/generated_resources.h" |
23 #include "grit/theme_resources.h" | 25 #include "grit/theme_resources.h" |
24 #include "views/widget/widget.h" | 26 #include "views/widget/widget.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 static SkBitmap* loading_animation_frames = NULL; | 73 static SkBitmap* loading_animation_frames = NULL; |
72 static SkBitmap* crashed_fav_icon = NULL; | 74 static SkBitmap* crashed_fav_icon = NULL; |
73 static int loading_animation_frame_count = 0; | 75 static int loading_animation_frame_count = 0; |
74 static int waiting_animation_frame_count = 0; | 76 static int waiting_animation_frame_count = 0; |
75 static int waiting_to_loading_frame_count_ratio = 0; | 77 static int waiting_to_loading_frame_count_ratio = 0; |
76 | 78 |
77 TabRenderer::TabImage TabRenderer::tab_alpha = {0}; | 79 TabRenderer::TabImage TabRenderer::tab_alpha = {0}; |
78 TabRenderer::TabImage TabRenderer::tab_active = {0}; | 80 TabRenderer::TabImage TabRenderer::tab_active = {0}; |
79 TabRenderer::TabImage TabRenderer::tab_inactive = {0}; | 81 TabRenderer::TabImage TabRenderer::tab_inactive = {0}; |
80 | 82 |
| 83 // Max opacity for the pinned tab title change animation. |
| 84 const double kPinnedThrobOpacity = 0.75; |
| 85 |
| 86 // Duration for when the title of an inactive pinned tab changes. |
| 87 const int kPinnedDuration = 1000; |
| 88 |
81 namespace { | 89 namespace { |
82 | 90 |
83 void InitResources() { | 91 void InitResources() { |
84 static bool initialized = false; | 92 static bool initialized = false; |
85 if (!initialized) { | 93 if (!initialized) { |
86 // TODO(glen): Allow theming of these. | 94 // TODO(glen): Allow theming of these. |
87 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 95 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
88 title_font = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont)); | 96 title_font = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont)); |
89 title_font_height = title_font->height(); | 97 title_font_height = title_font->height(); |
90 | 98 |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 void TabRenderer::StartPulse() { | 362 void TabRenderer::StartPulse() { |
355 pulse_animation_->Reset(); | 363 pulse_animation_->Reset(); |
356 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); | 364 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); |
357 } | 365 } |
358 | 366 |
359 void TabRenderer::StopPulse() { | 367 void TabRenderer::StopPulse() { |
360 if (pulse_animation_->IsAnimating()) | 368 if (pulse_animation_->IsAnimating()) |
361 pulse_animation_->Stop(); | 369 pulse_animation_->Stop(); |
362 } | 370 } |
363 | 371 |
| 372 void TabRenderer::StartPinnedTabTitleAnimation() { |
| 373 if (!pinned_title_animation_.get()) { |
| 374 pinned_title_animation_.reset(new ThrobAnimation(this)); |
| 375 pinned_title_animation_->SetThrobDuration(kPinnedDuration); |
| 376 } |
| 377 |
| 378 if (!pinned_title_animation_->IsAnimating()) { |
| 379 pinned_title_animation_->StartThrobbing(2); |
| 380 } else if (pinned_title_animation_->cycles_remaining() <= 2) { |
| 381 // The title changed while we're already animating. Add at most one more |
| 382 // cycle. This is done in an attempt to smooth out pages that continuously |
| 383 // change the title. |
| 384 pinned_title_animation_->set_cycles_remaining( |
| 385 pinned_title_animation_->cycles_remaining() + 2); |
| 386 } |
| 387 } |
| 388 |
| 389 void TabRenderer::StopPinnedTabTitleAnimation() { |
| 390 if (pinned_title_animation_.get()) |
| 391 pinned_title_animation_->Stop(); |
| 392 } |
| 393 |
364 // static | 394 // static |
365 gfx::Size TabRenderer::GetMinimumUnselectedSize() { | 395 gfx::Size TabRenderer::GetMinimumUnselectedSize() { |
366 InitResources(); | 396 InitResources(); |
367 | 397 |
368 gfx::Size minimum_size; | 398 gfx::Size minimum_size; |
369 minimum_size.set_width(kLeftPadding + kRightPadding); | 399 minimum_size.set_width(kLeftPadding + kRightPadding); |
370 // Since we use bitmap images, the real minimum height of the image is | 400 // Since we use bitmap images, the real minimum height of the image is |
371 // defined most accurately by the height of the end cap images. | 401 // defined most accurately by the height of the end cap images. |
372 minimum_size.set_height(tab_active.image_l->height()); | 402 minimum_size.set_height(tab_active.image_l->height()); |
373 return minimum_size; | 403 return minimum_size; |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 } | 633 } |
604 } | 634 } |
605 | 635 |
606 void TabRenderer::PaintTabBackground(gfx::Canvas* canvas) { | 636 void TabRenderer::PaintTabBackground(gfx::Canvas* canvas) { |
607 if (IsSelected()) { | 637 if (IsSelected()) { |
608 // Sometimes detaching a tab quickly can result in the model reporting it | 638 // Sometimes detaching a tab quickly can result in the model reporting it |
609 // as not being selected, so is_drag_clone_ ensures that we always paint | 639 // as not being selected, so is_drag_clone_ ensures that we always paint |
610 // the active representation for the dragged tab. | 640 // the active representation for the dragged tab. |
611 PaintActiveTabBackground(canvas); | 641 PaintActiveTabBackground(canvas); |
612 } else { | 642 } else { |
613 // Draw our hover state. | 643 PaintInactiveTabBackground(canvas); |
614 Animation* animation = hover_animation_.get(); | |
615 if (pulse_animation_->IsAnimating()) | |
616 animation = pulse_animation_.get(); | |
617 | 644 |
618 PaintInactiveTabBackground(canvas); | 645 double throb_value = GetThrobValue(); |
619 if (animation->GetCurrentValue() > 0) { | 646 if (throb_value > 0) { |
620 SkRect bounds; | 647 SkRect bounds; |
621 bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height())); | 648 bounds.set(0, 0, SkIntToScalar(width()), SkIntToScalar(height())); |
622 canvas->saveLayerAlpha(&bounds, | 649 canvas->saveLayerAlpha(&bounds, static_cast<int>(throb_value * 0xff), |
623 static_cast<int>(animation->GetCurrentValue() * kHoverOpacity * 0xff), | 650 SkCanvas::kARGB_ClipLayer_SaveFlag); |
624 SkCanvas::kARGB_ClipLayer_SaveFlag); | |
625 canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); | 651 canvas->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); |
626 PaintActiveTabBackground(canvas); | 652 PaintActiveTabBackground(canvas); |
627 canvas->restore(); | 653 canvas->restore(); |
628 } | 654 } |
629 } | 655 } |
630 } | 656 } |
631 | 657 |
632 void TabRenderer::PaintInactiveTabBackground(gfx::Canvas* canvas) { | 658 void TabRenderer::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
633 bool is_otr = data_.off_the_record; | 659 bool is_otr = data_.off_the_record; |
634 | 660 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 } | 817 } |
792 // Non-selected tabs clip close button before favicon. | 818 // Non-selected tabs clip close button before favicon. |
793 return IconCapacity() >= 1; | 819 return IconCapacity() >= 1; |
794 } | 820 } |
795 | 821 |
796 bool TabRenderer::ShouldShowCloseBox() const { | 822 bool TabRenderer::ShouldShowCloseBox() const { |
797 // The selected tab never clips close button. | 823 // The selected tab never clips close button. |
798 return !pinned() && (IsSelected() || IconCapacity() >= 3); | 824 return !pinned() && (IsSelected() || IconCapacity() >= 3); |
799 } | 825 } |
800 | 826 |
| 827 double TabRenderer::GetThrobValue() { |
| 828 if (pulse_animation_->IsAnimating()) |
| 829 return pulse_animation_->GetCurrentValue() * kHoverOpacity; |
| 830 |
| 831 if (pinned_title_animation_.get() && pinned_title_animation_->IsAnimating()) |
| 832 return pinned_title_animation_->GetCurrentValue() * kPinnedThrobOpacity; |
| 833 |
| 834 return hover_animation_.get() ? |
| 835 kHoverOpacity * hover_animation_->GetCurrentValue() : 0; |
| 836 } |
| 837 |
801 //////////////////////////////////////////////////////////////////////////////// | 838 //////////////////////////////////////////////////////////////////////////////// |
802 // TabRenderer, private: | 839 // TabRenderer, private: |
803 | 840 |
804 void TabRenderer::StartCrashAnimation() { | 841 void TabRenderer::StartCrashAnimation() { |
805 if (!crash_animation_) | 842 if (!crash_animation_) |
806 crash_animation_ = new FavIconCrashAnimation(this); | 843 crash_animation_ = new FavIconCrashAnimation(this); |
807 crash_animation_->Reset(); | 844 crash_animation_->Reset(); |
808 crash_animation_->Start(); | 845 crash_animation_->Start(); |
809 } | 846 } |
810 | 847 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); | 885 tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); |
849 tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); | 886 tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); |
850 tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); | 887 tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); |
851 | 888 |
852 tab_inactive.l_width = tab_inactive.image_l->width(); | 889 tab_inactive.l_width = tab_inactive.image_l->width(); |
853 tab_inactive.r_width = tab_inactive.image_r->width(); | 890 tab_inactive.r_width = tab_inactive.image_r->width(); |
854 | 891 |
855 loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER); | 892 loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER); |
856 waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING); | 893 waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING); |
857 } | 894 } |
OLD | NEW |