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" |
11 #include "base/profiler/scoped_tracker.h" | 11 #include "base/profiler/scoped_tracker.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "chrome/browser/themes/theme_properties.h" | 13 #include "chrome/browser/themes/theme_properties.h" |
14 #include "chrome/browser/ui/browser.h" | 14 #include "chrome/browser/ui/browser.h" |
15 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | 15 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" |
16 #include "chrome/browser/ui/tabs/tab_utils.h" | 16 #include "chrome/browser/ui/tabs/tab_utils.h" |
17 #include "chrome/browser/ui/view_ids.h" | 17 #include "chrome/browser/ui/view_ids.h" |
| 18 #include "chrome/browser/ui/views/layout_constants.h" |
18 #include "chrome/browser/ui/views/tabs/media_indicator_button.h" | 19 #include "chrome/browser/ui/views/tabs/media_indicator_button.h" |
19 #include "chrome/browser/ui/views/tabs/tab_controller.h" | 20 #include "chrome/browser/ui/views/tabs/tab_controller.h" |
20 #include "chrome/browser/ui/views/theme_image_mapper.h" | 21 #include "chrome/browser/ui/views/theme_image_mapper.h" |
21 #include "chrome/browser/ui/views/touch_uma/touch_uma.h" | 22 #include "chrome/browser/ui/views/touch_uma/touch_uma.h" |
22 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
23 #include "chrome/grit/generated_resources.h" | 24 #include "chrome/grit/generated_resources.h" |
24 #include "content/public/browser/user_metrics.h" | 25 #include "content/public/browser/user_metrics.h" |
25 #include "grit/theme_resources.h" | 26 #include "grit/theme_resources.h" |
26 #include "third_party/skia/include/effects/SkGradientShader.h" | 27 #include "third_party/skia/include/effects/SkGradientShader.h" |
27 #include "ui/accessibility/ax_view_state.h" | 28 #include "ui/accessibility/ax_view_state.h" |
(...skipping 22 matching lines...) Expand all Loading... |
50 #include "ui/views/window/non_client_view.h" | 51 #include "ui/views/window/non_client_view.h" |
51 | 52 |
52 #if defined(USE_AURA) | 53 #if defined(USE_AURA) |
53 #include "ui/aura/env.h" | 54 #include "ui/aura/env.h" |
54 #endif | 55 #endif |
55 | 56 |
56 using base::UserMetricsAction; | 57 using base::UserMetricsAction; |
57 | 58 |
58 namespace { | 59 namespace { |
59 | 60 |
60 // Padding around the "content" of a tab, occupied by the tab border graphics. | |
61 const int kLeftPadding = 20; | |
62 const int kTopPadding = 4; | |
63 const int kRightPadding = 20; | |
64 const int kBottomPadding = 2; | |
65 | |
66 // Height of the shadow at the top of the tab image assets. | 61 // Height of the shadow at the top of the tab image assets. |
67 const int kDropShadowHeight = 4; | 62 const int kDropShadowHeight = 4; |
68 | 63 |
69 // How long the pulse throb takes. | 64 // How long the pulse throb takes. |
70 const int kPulseDurationMs = 200; | 65 const int kPulseDurationMs = 200; |
71 | 66 |
72 // Width of touch tabs. | 67 // Width of touch tabs. |
73 const int kTouchWidth = 120; | 68 const int kTouchWidth = 120; |
74 | 69 |
75 const int kToolbarOverlap = 1; | 70 const int kToolbarOverlap = 1; |
76 const int kExtraLeftPaddingToBalanceCloseButtonPadding = 2; | 71 const int kExtraLeftPaddingToBalanceCloseButtonPadding = 2; |
77 const int kFaviconTitleSpacing = 4; | |
78 const int kAfterTitleSpacing = 3; | 72 const int kAfterTitleSpacing = 3; |
79 const int kCloseButtonRightPaddingOverlap = 3; | |
80 const int kStandardTitleWidth = 175; | |
81 | |
82 // Width of the content inside a pinned tab. | |
83 int kPinnedTabContentWidth = 25; | |
84 | 73 |
85 // When a non-pinned tab becomes a pinned tab the width of the tab animates. If | 74 // 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 | 75 // 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 | 76 // 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 | 77 // tab. This is done to avoid having the title immediately disappear when |
89 // transitioning a tab from normal to pinned tab. | 78 // transitioning a tab from normal to pinned tab. |
90 const int kPinnedTabExtraWidthToRenderAsNormal = 30; | 79 const int kPinnedTabExtraWidthToRenderAsNormal = 30; |
91 | 80 |
92 // How opaque to make the hover state (out of 1). | 81 // How opaque to make the hover state (out of 1). |
93 const double kHoverOpacity = 0.33; | 82 const double kHoverOpacity = 0.33; |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 const int close_button_left = showing_close_button_ ? | 600 const int close_button_left = showing_close_button_ ? |
612 close_button_->x() : width(); | 601 close_button_->x() : width(); |
613 return std::min(indicator_left, close_button_left); | 602 return std::min(indicator_left, close_button_left); |
614 } | 603 } |
615 | 604 |
616 gfx::Size Tab::GetMinimumUnselectedSize() { | 605 gfx::Size Tab::GetMinimumUnselectedSize() { |
617 // Since we use images, the real minimum height of the image is | 606 // Since we use images, the real minimum height of the image is |
618 // defined most accurately by the height of the end cap images. | 607 // defined most accurately by the height of the end cap images. |
619 InitTabResources(); | 608 InitTabResources(); |
620 int height = tab_active_.image_l->height(); | 609 int height = tab_active_.image_l->height(); |
621 return gfx::Size(kLeftPadding + kRightPadding, height); | 610 return gfx::Size(GetLayoutInsets(TAB).width(), height); |
622 } | 611 } |
623 | 612 |
624 // static | 613 // static |
625 gfx::Size Tab::GetMinimumSelectedSize() { | 614 gfx::Size Tab::GetMinimumSelectedSize() { |
626 gfx::Size minimum_size = GetMinimumUnselectedSize(); | 615 gfx::Size minimum_size = GetMinimumUnselectedSize(); |
627 minimum_size.Enlarge(gfx::kFaviconSize, 0); | 616 minimum_size.Enlarge(gfx::kFaviconSize, 0); |
628 return minimum_size; | 617 return minimum_size; |
629 } | 618 } |
630 | 619 |
631 // static | 620 // static |
632 gfx::Size Tab::GetStandardSize() { | 621 gfx::Size Tab::GetStandardSize() { |
633 gfx::Size standard_size = GetMinimumUnselectedSize(); | 622 gfx::Size standard_size = GetMinimumUnselectedSize(); |
634 standard_size.Enlarge(kFaviconTitleSpacing + kStandardTitleWidth, 0); | 623 const int title_spacing = GetLayoutConstant(TAB_FAVICON_TITLE_SPACING); |
| 624 const int title_width = GetLayoutConstant(TAB_MAXIMUM_TITLE_WIDTH); |
| 625 standard_size.Enlarge(title_spacing + title_width, 0); |
635 return standard_size; | 626 return standard_size; |
636 } | 627 } |
637 | 628 |
638 // static | 629 // static |
639 int Tab::GetTouchWidth() { | 630 int Tab::GetTouchWidth() { |
640 return kTouchWidth; | 631 return kTouchWidth; |
641 } | 632 } |
642 | 633 |
643 // static | 634 // static |
644 int Tab::GetPinnedWidth() { | 635 int Tab::GetPinnedWidth() { |
645 return GetMinimumUnselectedSize().width() + kPinnedTabContentWidth; | 636 return GetMinimumUnselectedSize().width() + |
| 637 GetLayoutConstant(TAB_PINNED_CONTENT_WIDTH); |
646 } | 638 } |
647 | 639 |
648 // static | 640 // static |
649 int Tab::GetImmersiveHeight() { | 641 int Tab::GetImmersiveHeight() { |
650 return kImmersiveTabHeight; | 642 return kImmersiveTabHeight; |
651 } | 643 } |
652 | 644 |
653 //////////////////////////////////////////////////////////////////////////////// | 645 //////////////////////////////////////////////////////////////////////////////// |
654 // Tab, AnimationDelegate overrides: | 646 // Tab, AnimationDelegate overrides: |
655 | 647 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 | 748 |
757 if (!clip.IsEmpty()) | 749 if (!clip.IsEmpty()) |
758 canvas->Restore(); | 750 canvas->Restore(); |
759 } | 751 } |
760 | 752 |
761 void Tab::Layout() { | 753 void Tab::Layout() { |
762 gfx::Rect lb = GetContentsBounds(); | 754 gfx::Rect lb = GetContentsBounds(); |
763 if (lb.IsEmpty()) | 755 if (lb.IsEmpty()) |
764 return; | 756 return; |
765 | 757 |
766 lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding); | 758 lb.Inset(GetLayoutInsets(TAB)); |
767 showing_icon_ = ShouldShowIcon(); | 759 showing_icon_ = ShouldShowIcon(); |
768 // See comments in IconCapacity(). | 760 // See comments in IconCapacity(). |
769 const int extra_padding = | 761 const int extra_padding = |
770 (controller_->ShouldHideCloseButtonForInactiveTabs() || | 762 (controller_->ShouldHideCloseButtonForInactiveTabs() || |
771 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; | 763 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; |
772 const int start = lb.x() + extra_padding; | 764 const int start = lb.x() + extra_padding; |
773 favicon_bounds_.SetRect(start, lb.y(), 0, 0); | 765 favicon_bounds_.SetRect(start, lb.y(), 0, 0); |
774 if (showing_icon_) { | 766 if (showing_icon_) { |
775 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); | 767 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); |
776 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); | 768 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); |
777 MaybeAdjustLeftForPinnedTab(&favicon_bounds_); | 769 MaybeAdjustLeftForPinnedTab(&favicon_bounds_); |
778 } | 770 } |
779 | 771 |
780 showing_close_button_ = ShouldShowCloseBox(); | 772 showing_close_button_ = ShouldShowCloseBox(); |
781 if (showing_close_button_) { | 773 if (showing_close_button_) { |
782 // If the ratio of the close button size to tab width exceeds the maximum. | 774 // If the ratio of the close button size to tab width exceeds the maximum. |
783 // The close button should be as large as possible so that there is a larger | 775 // The close button should be as large as possible so that there is a larger |
784 // hit-target for touch events. So the close button bounds extends to the | 776 // hit-target for touch events. So the close button bounds extends to the |
785 // edges of the tab. However, the larger hit-target should be active only | 777 // edges of the tab. However, the larger hit-target should be active only |
786 // for mouse events, and the close-image should show up in the right place. | 778 // for mouse events, and the close-image should show up in the right place. |
787 // So a border is added to the button with necessary padding. The close | 779 // So a border is added to the button with necessary padding. The close |
788 // button (BaseTab::TabCloseButton) makes sure the padding is a hit-target | 780 // button (BaseTab::TabCloseButton) makes sure the padding is a hit-target |
789 // only for touch events. | 781 // only for touch events. |
790 close_button_->SetBorder(views::Border::NullBorder()); | 782 close_button_->SetBorder(views::Border::NullBorder()); |
791 const gfx::Size close_button_size(close_button_->GetPreferredSize()); | 783 const gfx::Size close_button_size(close_button_->GetPreferredSize()); |
792 const int top = lb.y() + (lb.height() - close_button_size.height() + 1) / 2; | 784 const int top = lb.y() + (lb.height() - close_button_size.height() + 1) / 2; |
793 const int left = kAfterTitleSpacing; | 785 const int left = kAfterTitleSpacing; |
794 const int close_button_end = lb.right() + kCloseButtonRightPaddingOverlap; | 786 const int close_button_end = lb.right() + |
| 787 GetLayoutConstant(TAB_CLOSE_BUTTON_TRAILING_PADDING_OVERLAP); |
795 close_button_->SetPosition( | 788 close_button_->SetPosition( |
796 gfx::Point(close_button_end - close_button_size.width() - left, 0)); | 789 gfx::Point(close_button_end - close_button_size.width() - left, 0)); |
797 const int bottom = height() - close_button_size.height() - top; | 790 const int bottom = height() - close_button_size.height() - top; |
798 const int right = width() - close_button_end; | 791 const int right = width() - close_button_end; |
799 close_button_->SetBorder( | 792 close_button_->SetBorder( |
800 views::Border::CreateEmptyBorder(top, left, bottom, right)); | 793 views::Border::CreateEmptyBorder(top, left, bottom, right)); |
801 close_button_->SizeToPreferredSize(); | 794 close_button_->SizeToPreferredSize(); |
802 } | 795 } |
803 close_button_->SetVisible(showing_close_button_); | 796 close_button_->SetVisible(showing_close_button_); |
804 | 797 |
(...skipping 11 matching lines...) Expand all Loading... |
816 MaybeAdjustLeftForPinnedTab(&bounds); | 809 MaybeAdjustLeftForPinnedTab(&bounds); |
817 button->SetBoundsRect(bounds); | 810 button->SetBoundsRect(bounds); |
818 button->SetVisible(true); | 811 button->SetVisible(true); |
819 } else if (media_indicator_button_) { | 812 } else if (media_indicator_button_) { |
820 media_indicator_button_->SetVisible(false); | 813 media_indicator_button_->SetVisible(false); |
821 } | 814 } |
822 | 815 |
823 // Size the title to fill the remaining width and use all available height. | 816 // Size the title to fill the remaining width and use all available height. |
824 const bool show_title = ShouldRenderAsNormalTab(); | 817 const bool show_title = ShouldRenderAsNormalTab(); |
825 if (show_title) { | 818 if (show_title) { |
| 819 const int title_spacing = GetLayoutConstant(TAB_FAVICON_TITLE_SPACING); |
826 int title_left = showing_icon_ ? | 820 int title_left = showing_icon_ ? |
827 (favicon_bounds_.right() + kFaviconTitleSpacing) : start; | 821 (favicon_bounds_.right() + title_spacing) : start; |
828 int title_width = lb.right() - title_left; | 822 int title_width = lb.right() - title_left; |
829 if (showing_media_indicator_) { | 823 if (showing_media_indicator_) { |
830 title_width = | 824 title_width = |
831 media_indicator_button_->x() - kAfterTitleSpacing - title_left; | 825 media_indicator_button_->x() - kAfterTitleSpacing - title_left; |
832 } else if (close_button_->visible()) { | 826 } else if (close_button_->visible()) { |
833 // Allow the title to overlay the close button's empty border padding. | 827 // Allow the title to overlay the close button's empty border padding. |
834 title_width = close_button_->x() + close_button_->GetInsets().left() - | 828 title_width = close_button_->x() + close_button_->GetInsets().left() - |
835 kAfterTitleSpacing - title_left; | 829 kAfterTitleSpacing - title_left; |
836 } | 830 } |
837 gfx::Rect rect(title_left, lb.y(), std::max(title_width, 0), lb.height()); | 831 gfx::Rect rect(title_left, lb.y(), std::max(title_width, 0), lb.height()); |
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1669 const gfx::ImageSkia& image) { | 1663 const gfx::ImageSkia& image) { |
1670 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1664 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1671 ImageCacheEntry entry; | 1665 ImageCacheEntry entry; |
1672 entry.resource_id = resource_id; | 1666 entry.resource_id = resource_id; |
1673 entry.scale_factor = scale_factor; | 1667 entry.scale_factor = scale_factor; |
1674 entry.image = image; | 1668 entry.image = image; |
1675 image_cache_->push_front(entry); | 1669 image_cache_->push_front(entry); |
1676 if (image_cache_->size() > kMaxImageCacheSize) | 1670 if (image_cache_->size() > kMaxImageCacheSize) |
1677 image_cache_->pop_back(); | 1671 image_cache_->pop_back(); |
1678 } | 1672 } |
OLD | NEW |