Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/ui/views/tabs/tab.h" | 5 #include "chrome/browser/ui/views/tabs/tab.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 #include "ui/base/resource/resource_bundle.h" | 30 #include "ui/base/resource/resource_bundle.h" |
| 31 #include "ui/base/theme_provider.h" | 31 #include "ui/base/theme_provider.h" |
| 32 #include "ui/gfx/animation/animation_container.h" | 32 #include "ui/gfx/animation/animation_container.h" |
| 33 #include "ui/gfx/animation/multi_animation.h" | 33 #include "ui/gfx/animation/multi_animation.h" |
| 34 #include "ui/gfx/animation/throb_animation.h" | 34 #include "ui/gfx/animation/throb_animation.h" |
| 35 #include "ui/gfx/canvas.h" | 35 #include "ui/gfx/canvas.h" |
| 36 #include "ui/gfx/color_analysis.h" | 36 #include "ui/gfx/color_analysis.h" |
| 37 #include "ui/gfx/favicon_size.h" | 37 #include "ui/gfx/favicon_size.h" |
| 38 #include "ui/gfx/geometry/rect_conversions.h" | 38 #include "ui/gfx/geometry/rect_conversions.h" |
| 39 #include "ui/gfx/image/image_skia_operations.h" | 39 #include "ui/gfx/image/image_skia_operations.h" |
| 40 #include "ui/gfx/paint_vector_icon.h" | |
| 40 #include "ui/gfx/path.h" | 41 #include "ui/gfx/path.h" |
| 41 #include "ui/gfx/skia_util.h" | 42 #include "ui/gfx/skia_util.h" |
| 43 #include "ui/gfx/vector_icons_public.h" | |
| 44 #include "ui/native_theme/common_theme.h" | |
| 45 #include "ui/native_theme/native_theme.h" | |
| 42 #include "ui/resources/grit/ui_resources.h" | 46 #include "ui/resources/grit/ui_resources.h" |
| 43 #include "ui/views/border.h" | 47 #include "ui/views/border.h" |
| 44 #include "ui/views/controls/button/image_button.h" | 48 #include "ui/views/controls/button/image_button.h" |
| 45 #include "ui/views/controls/label.h" | 49 #include "ui/views/controls/label.h" |
| 46 #include "ui/views/rect_based_targeting_utils.h" | 50 #include "ui/views/rect_based_targeting_utils.h" |
| 47 #include "ui/views/view_targeter.h" | 51 #include "ui/views/view_targeter.h" |
| 48 #include "ui/views/widget/tooltip_manager.h" | 52 #include "ui/views/widget/tooltip_manager.h" |
| 49 #include "ui/views/widget/widget.h" | 53 #include "ui/views/widget/widget.h" |
| 50 #include "ui/views/window/non_client_view.h" | 54 #include "ui/views/window/non_client_view.h" |
| 51 | 55 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 68 | 72 |
| 69 // How long the pulse throb takes. | 73 // How long the pulse throb takes. |
| 70 const int kPulseDurationMs = 200; | 74 const int kPulseDurationMs = 200; |
| 71 | 75 |
| 72 // Width of touch tabs. | 76 // Width of touch tabs. |
| 73 const int kTouchWidth = 120; | 77 const int kTouchWidth = 120; |
| 74 | 78 |
| 75 const int kToolbarOverlap = 1; | 79 const int kToolbarOverlap = 1; |
| 76 const int kExtraLeftPaddingToBalanceCloseButtonPadding = 2; | 80 const int kExtraLeftPaddingToBalanceCloseButtonPadding = 2; |
| 77 const int kFaviconTitleSpacing = 4; | 81 const int kFaviconTitleSpacing = 4; |
| 78 const int kAfterTitleSpacing = 3; | 82 const int kAfterTitleSpacing = 4; |
| 79 const int kCloseButtonRightPaddingOverlap = 3; | 83 const int kCloseButtonRightPaddingOverlap = 2; |
| 80 const int kStandardTitleWidth = 175; | 84 const int kStandardTitleWidth = 175; |
| 81 | 85 |
| 82 // Width of the content inside a pinned tab. | 86 // Width of the content inside a pinned tab. |
| 83 int kPinnedTabContentWidth = 25; | 87 int kPinnedTabContentWidth = 25; |
| 84 | 88 |
| 85 // When a non-pinned tab becomes a pinned tab the width of the tab animates. If | 89 // When a non-pinned tab becomes a pinned tab the width of the tab animates. If |
| 86 // the width of a pinned tab is at least kPinnedTabExtraWidthToRenderAsNormal | 90 // the width of a pinned tab is at least kPinnedTabExtraWidthToRenderAsNormal |
| 87 // larger than the desired pinned tab width then the tab is rendered as a normal | 91 // larger than the desired pinned tab width then the tab is rendered as a normal |
| 88 // tab. This is done to avoid having the title immediately disappear when | 92 // tab. This is done to avoid having the title immediately disappear when |
| 89 // transitioning a tab from normal to pinned tab. | 93 // transitioning a tab from normal to pinned tab. |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 immersive_loading_step_(0), | 425 immersive_loading_step_(0), |
| 422 should_display_crashed_favicon_(false), | 426 should_display_crashed_favicon_(false), |
| 423 close_button_(NULL), | 427 close_button_(NULL), |
| 424 media_indicator_button_(NULL), | 428 media_indicator_button_(NULL), |
| 425 title_(new views::Label()), | 429 title_(new views::Label()), |
| 426 tab_activated_with_last_tap_down_(false), | 430 tab_activated_with_last_tap_down_(false), |
| 427 hover_controller_(this), | 431 hover_controller_(this), |
| 428 showing_icon_(false), | 432 showing_icon_(false), |
| 429 showing_media_indicator_(false), | 433 showing_media_indicator_(false), |
| 430 showing_close_button_(false), | 434 showing_close_button_(false), |
| 431 close_button_color_(0) { | 435 close_button_color_(SK_ColorTRANSPARENT) { |
| 432 DCHECK(controller); | 436 DCHECK(controller); |
| 433 InitTabResources(); | 437 InitTabResources(); |
| 434 | 438 |
| 435 // So we get don't get enter/exit on children and don't prematurely stop the | 439 // So we get don't get enter/exit on children and don't prematurely stop the |
| 436 // hover. | 440 // hover. |
| 437 set_notify_enter_exit_on_child(true); | 441 set_notify_enter_exit_on_child(true); |
| 438 | 442 |
| 439 set_id(VIEW_ID_TAB); | 443 set_id(VIEW_ID_TAB); |
| 440 | 444 |
| 441 title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); | 445 title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); |
| 442 title_->SetElideBehavior(gfx::FADE_TAIL); | 446 title_->SetElideBehavior(gfx::FADE_TAIL); |
| 443 title_->SetHandlesTooltips(false); | 447 title_->SetHandlesTooltips(false); |
| 444 title_->SetAutoColorReadabilityEnabled(false); | 448 title_->SetAutoColorReadabilityEnabled(false); |
| 445 title_->SetText(CoreTabHelper::GetDefaultTitle()); | 449 title_->SetText(CoreTabHelper::GetDefaultTitle()); |
| 446 AddChildView(title_); | 450 AddChildView(title_); |
| 447 | 451 |
| 448 SetEventTargeter( | 452 SetEventTargeter( |
| 449 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); | 453 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); |
| 450 | 454 |
| 451 // Add the Close Button. | |
| 452 close_button_ = new TabCloseButton(this); | 455 close_button_ = new TabCloseButton(this); |
| 453 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 454 close_button_->SetImage(views::CustomButton::STATE_NORMAL, | |
| 455 rb.GetImageSkiaNamed(IDR_CLOSE_1)); | |
| 456 close_button_->SetImage(views::CustomButton::STATE_HOVERED, | |
| 457 rb.GetImageSkiaNamed(IDR_CLOSE_1_H)); | |
| 458 close_button_->SetImage(views::CustomButton::STATE_PRESSED, | |
| 459 rb.GetImageSkiaNamed(IDR_CLOSE_1_P)); | |
| 460 close_button_->SetAccessibleName( | 456 close_button_->SetAccessibleName( |
| 461 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); | 457 l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); |
| 458 | |
| 459 // We need to set the close button's normal image now, even though it will | |
| 460 // have the wrong color, so that the close button gets sized and laid out | |
| 461 // correctly. (We can't get the correct color without a ThemeProvider, which | |
| 462 // we won't have until we're part of a Widget hierarchy.) We'll reset the | |
| 463 // image to the right color the first time through OnPaint(), when we're | |
| 464 // guaranteed to have the ThemeProvider available. | |
| 465 SetCloseButtonNormalImage(); | |
| 466 | |
| 467 // The hovered andpressed images won't be changing later, so we can set them | |
|
Evan Stade
2015/09/18 17:30:33
nit: "and pressed"
Peter Kasting
2015/09/18 19:48:30
Done.
| |
| 468 // correctly here. | |
| 469 const gfx::ImageSkia& hovered = gfx::CreateVectorIcon( | |
| 470 gfx::VectorIconId::TAB_CLOSE_HOVERED_PRESSED, 16, | |
| 471 SkColorSetARGB(0xFF, 0xDB, 0x44, 0x37)); | |
| 472 const gfx::ImageSkia& pressed = gfx::CreateVectorIcon( | |
| 473 gfx::VectorIconId::TAB_CLOSE_HOVERED_PRESSED, 16, | |
| 474 SkColorSetARGB(0xFF, 0xA8, 0x35, 0x2A)); | |
| 475 close_button_->SetImage(views::CustomButton::STATE_HOVERED, &hovered); | |
| 476 close_button_->SetImage(views::CustomButton::STATE_PRESSED, &pressed); | |
| 477 | |
| 462 // Disable animation so that the red danger sign shows up immediately | 478 // Disable animation so that the red danger sign shows up immediately |
| 463 // to help avoid mis-clicks. | 479 // to help avoid mis-clicks. |
| 464 close_button_->SetAnimationDuration(0); | 480 close_button_->SetAnimationDuration(0); |
| 481 | |
| 465 AddChildView(close_button_); | 482 AddChildView(close_button_); |
| 466 | 483 |
| 467 set_context_menu_controller(this); | 484 set_context_menu_controller(this); |
| 468 } | 485 } |
| 469 | 486 |
| 470 Tab::~Tab() { | 487 Tab::~Tab() { |
| 471 } | 488 } |
| 472 | 489 |
| 473 void Tab::set_animation_container(gfx::AnimationContainer* container) { | 490 void Tab::set_animation_container(gfx::AnimationContainer* container) { |
| 474 animation_container_ = container; | 491 animation_container_ = container; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 737 | 754 |
| 738 void Tab::OnPaint(gfx::Canvas* canvas) { | 755 void Tab::OnPaint(gfx::Canvas* canvas) { |
| 739 // Don't paint if we're narrower than we can render correctly. (This should | 756 // Don't paint if we're narrower than we can render correctly. (This should |
| 740 // only happen during animations). | 757 // only happen during animations). |
| 741 if (width() < GetMinimumUnselectedSize().width() && !data().pinned) | 758 if (width() < GetMinimumUnselectedSize().width() && !data().pinned) |
| 742 return; | 759 return; |
| 743 | 760 |
| 744 gfx::Rect clip; | 761 gfx::Rect clip; |
| 745 if (!controller_->ShouldPaintTab(this, &clip)) | 762 if (!controller_->ShouldPaintTab(this, &clip)) |
| 746 return; | 763 return; |
| 764 | |
| 765 // If we haven't set the correct close button normal image, we can do so now. | |
| 766 if (close_button_color_ == SK_ColorTRANSPARENT) | |
| 767 OnThemeChanged(); | |
|
Evan Stade
2015/09/18 17:30:33
why not use OnViewHierarchyChanged? I imagine that
Peter Kasting
2015/09/18 19:48:30
Done. I also needed to handle active state change
| |
| 768 | |
| 747 if (!clip.IsEmpty()) { | 769 if (!clip.IsEmpty()) { |
| 748 canvas->Save(); | 770 canvas->Save(); |
| 749 canvas->ClipRect(clip); | 771 canvas->ClipRect(clip); |
| 750 } | 772 } |
| 751 | 773 |
| 752 if (controller_->IsImmersiveStyle()) | 774 if (controller_->IsImmersiveStyle()) |
| 753 PaintImmersiveTab(canvas); | 775 PaintImmersiveTab(canvas); |
| 754 else | 776 else |
| 755 PaintTab(canvas); | 777 PaintTab(canvas); |
| 756 | 778 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 840 rect.set_y(lb.y() - (title_height - rect.height()) / 2); | 862 rect.set_y(lb.y() - (title_height - rect.height()) / 2); |
| 841 rect.set_height(title_height); | 863 rect.set_height(title_height); |
| 842 } | 864 } |
| 843 title_->SetBoundsRect(rect); | 865 title_->SetBoundsRect(rect); |
| 844 } | 866 } |
| 845 title_->SetVisible(show_title); | 867 title_->SetVisible(show_title); |
| 846 } | 868 } |
| 847 | 869 |
| 848 void Tab::OnThemeChanged() { | 870 void Tab::OnThemeChanged() { |
| 849 LoadTabImages(); | 871 LoadTabImages(); |
| 872 | |
| 873 const SkColor text_color = GetThemeProvider()->GetColor( | |
| 874 IsActive() ? ThemeProperties::COLOR_TAB_TEXT | |
| 875 : ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); | |
| 876 close_button_color_ = SkColorSetA(text_color, 0x70); | |
| 877 SetCloseButtonNormalImage(); | |
| 850 } | 878 } |
| 851 | 879 |
| 852 const char* Tab::GetClassName() const { | 880 const char* Tab::GetClassName() const { |
| 853 return kViewClassName; | 881 return kViewClassName; |
| 854 } | 882 } |
| 855 | 883 |
| 856 bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { | 884 bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { |
| 857 // Note: Anything that affects the tooltip text should be accounted for when | 885 // Note: Anything that affects the tooltip text should be accounted for when |
| 858 // calling TooltipTextChanged() from Tab::DataChanged(). | 886 // calling TooltipTextChanged() from Tab::DataChanged(). |
| 859 *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.media_state); | 887 *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.media_state); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1041 StopPulse(); | 1069 StopPulse(); |
| 1042 } | 1070 } |
| 1043 | 1071 |
| 1044 void Tab::PaintTab(gfx::Canvas* canvas) { | 1072 void Tab::PaintTab(gfx::Canvas* canvas) { |
| 1045 // See if the model changes whether the icons should be painted. | 1073 // See if the model changes whether the icons should be painted. |
| 1046 const bool show_icon = ShouldShowIcon(); | 1074 const bool show_icon = ShouldShowIcon(); |
| 1047 const bool show_media_indicator = ShouldShowMediaIndicator(); | 1075 const bool show_media_indicator = ShouldShowMediaIndicator(); |
| 1048 const bool show_close_button = ShouldShowCloseBox(); | 1076 const bool show_close_button = ShouldShowCloseBox(); |
| 1049 if (show_icon != showing_icon_ || | 1077 if (show_icon != showing_icon_ || |
| 1050 show_media_indicator != showing_media_indicator_ || | 1078 show_media_indicator != showing_media_indicator_ || |
| 1051 show_close_button != showing_close_button_) { | 1079 show_close_button != showing_close_button_) |
| 1052 Layout(); | 1080 Layout(); |
| 1053 } | |
| 1054 | 1081 |
| 1055 PaintTabBackground(canvas); | 1082 PaintTabBackground(canvas); |
| 1056 | 1083 |
| 1057 const SkColor title_color = GetThemeProvider()->GetColor(IsSelected() ? | 1084 const SkColor title_color = GetThemeProvider()->GetColor(IsSelected() ? |
| 1058 ThemeProperties::COLOR_TAB_TEXT : | 1085 ThemeProperties::COLOR_TAB_TEXT : |
| 1059 ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); | 1086 ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); |
| 1060 title_->SetVisible(ShouldRenderAsNormalTab()); | |
|
sky
2015/09/18 16:01:52
How come you removed this line?
Peter Kasting
2015/09/18 19:48:30
See comment in patch set 1 -- we do this already i
sky
2015/09/18 20:33:38
I only saw this patchset, so I missed that comment
| |
| 1061 title_->SetEnabledColor(title_color); | 1087 title_->SetEnabledColor(title_color); |
| 1062 | 1088 |
| 1063 if (show_icon) | 1089 if (show_icon) |
| 1064 PaintIcon(canvas); | 1090 PaintIcon(canvas); |
| 1065 | |
| 1066 // If the close button color has changed, generate a new one. | |
| 1067 if (!close_button_color_ || title_color != close_button_color_) { | |
| 1068 close_button_color_ = title_color; | |
| 1069 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 1070 close_button_->SetBackground(close_button_color_, | |
| 1071 rb.GetImageSkiaNamed(IDR_CLOSE_1), | |
| 1072 rb.GetImageSkiaNamed(IDR_CLOSE_1_MASK)); | |
| 1073 } | |
| 1074 } | 1091 } |
| 1075 | 1092 |
| 1076 void Tab::PaintImmersiveTab(gfx::Canvas* canvas) { | 1093 void Tab::PaintImmersiveTab(gfx::Canvas* canvas) { |
| 1077 // Use transparency for the draw-attention animation. | 1094 // Use transparency for the draw-attention animation. |
| 1078 int alpha = 255; | 1095 int alpha = 255; |
| 1079 if (pulse_animation_ && pulse_animation_->is_animating() && !data().pinned) { | 1096 if (pulse_animation_ && pulse_animation_->is_animating() && !data().pinned) { |
| 1080 alpha = pulse_animation_->CurrentValueBetween( | 1097 alpha = pulse_animation_->CurrentValueBetween( |
| 1081 255, static_cast<int>(255 * kImmersiveTabMinThrobOpacity)); | 1098 255, static_cast<int>(255 * kImmersiveTabMinThrobOpacity)); |
| 1082 } | 1099 } |
| 1083 | 1100 |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1506 | 1523 |
| 1507 void Tab::StartCrashAnimation() { | 1524 void Tab::StartCrashAnimation() { |
| 1508 crash_icon_animation_.reset(new FaviconCrashAnimation(this)); | 1525 crash_icon_animation_.reset(new FaviconCrashAnimation(this)); |
| 1509 crash_icon_animation_->Start(); | 1526 crash_icon_animation_->Start(); |
| 1510 } | 1527 } |
| 1511 | 1528 |
| 1512 bool Tab::IsPerformingCrashAnimation() const { | 1529 bool Tab::IsPerformingCrashAnimation() const { |
| 1513 return crash_icon_animation_.get() && data_.IsCrashed(); | 1530 return crash_icon_animation_.get() && data_.IsCrashed(); |
| 1514 } | 1531 } |
| 1515 | 1532 |
| 1533 void Tab::SetCloseButtonNormalImage() { | |
| 1534 const gfx::ImageSkia& normal = gfx::CreateVectorIcon( | |
| 1535 gfx::VectorIconId::TAB_CLOSE_NORMAL, 16, close_button_color_); | |
|
Evan Stade
2015/09/18 17:30:33
nit: lots of 16s hardcoded here, why not put this
Peter Kasting
2015/09/18 19:48:30
Done.
| |
| 1536 close_button_->SetImage(views::CustomButton::STATE_NORMAL, &normal); | |
| 1537 } | |
| 1538 | |
| 1516 void Tab::ScheduleIconPaint() { | 1539 void Tab::ScheduleIconPaint() { |
| 1517 gfx::Rect bounds = favicon_bounds_; | 1540 gfx::Rect bounds = favicon_bounds_; |
| 1518 if (bounds.IsEmpty()) | 1541 if (bounds.IsEmpty()) |
| 1519 return; | 1542 return; |
| 1520 | 1543 |
| 1521 // Extends the area to the bottom when sad_favicon is animating. | 1544 // Extends the area to the bottom when sad_favicon is animating. |
| 1522 if (IsPerformingCrashAnimation()) | 1545 if (IsPerformingCrashAnimation()) |
| 1523 bounds.set_height(height() - bounds.y()); | 1546 bounds.set_height(height() - bounds.y()); |
| 1524 bounds.set_x(GetMirroredXForRect(bounds)); | 1547 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1525 SchedulePaintInRect(bounds); | 1548 SchedulePaintInRect(bounds); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1669 const gfx::ImageSkia& image) { | 1692 const gfx::ImageSkia& image) { |
| 1670 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1693 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
| 1671 ImageCacheEntry entry; | 1694 ImageCacheEntry entry; |
| 1672 entry.resource_id = resource_id; | 1695 entry.resource_id = resource_id; |
| 1673 entry.scale_factor = scale_factor; | 1696 entry.scale_factor = scale_factor; |
| 1674 entry.image = image; | 1697 entry.image = image; |
| 1675 image_cache_->push_front(entry); | 1698 image_cache_->push_front(entry); |
| 1676 if (image_cache_->size() > kMaxImageCacheSize) | 1699 if (image_cache_->size() > kMaxImageCacheSize) |
| 1677 image_cache_->pop_back(); | 1700 image_cache_->pop_back(); |
| 1678 } | 1701 } |
| OLD | NEW |