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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 #include "ui/views/window/non_client_view.h" | 54 #include "ui/views/window/non_client_view.h" |
55 | 55 |
56 #if defined(USE_AURA) | 56 #if defined(USE_AURA) |
57 #include "ui/aura/env.h" | 57 #include "ui/aura/env.h" |
58 #endif | 58 #endif |
59 | 59 |
60 using base::UserMetricsAction; | 60 using base::UserMetricsAction; |
61 | 61 |
62 namespace { | 62 namespace { |
63 | 63 |
64 // Height of the shadow at the top of the tab image assets. | |
65 const int kDropShadowHeight = 4; | |
66 | |
67 // How long the pulse throb takes. | 64 // How long the pulse throb takes. |
68 const int kPulseDurationMs = 200; | 65 const int kPulseDurationMs = 200; |
69 | 66 |
70 // Width of touch tabs. | 67 // Width of touch tabs. |
71 const int kTouchWidth = 120; | 68 const int kTouchWidth = 120; |
72 | 69 |
73 const int kToolbarOverlap = 1; | |
74 const int kExtraLeftPaddingToBalanceCloseButtonPadding = 2; | 70 const int kExtraLeftPaddingToBalanceCloseButtonPadding = 2; |
75 const int kAfterTitleSpacing = 4; | 71 const int kAfterTitleSpacing = 4; |
76 | 72 |
77 // When a non-pinned tab becomes a pinned tab the width of the tab animates. If | 73 // When a non-pinned tab becomes a pinned tab the width of the tab animates. If |
78 // the width of a pinned tab is at least kPinnedTabExtraWidthToRenderAsNormal | 74 // the width of a pinned tab is at least kPinnedTabExtraWidthToRenderAsNormal |
79 // larger than the desired pinned tab width then the tab is rendered as a normal | 75 // larger than the desired pinned tab width then the tab is rendered as a normal |
80 // tab. This is done to avoid having the title immediately disappear when | 76 // tab. This is done to avoid having the title immediately disappear when |
81 // transitioning a tab from normal to pinned tab. | 77 // transitioning a tab from normal to pinned tab. |
82 const int kPinnedTabExtraWidthToRenderAsNormal = 30; | 78 const int kPinnedTabExtraWidthToRenderAsNormal = 30; |
83 | 79 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 // The minimum opacity (out of 1) when a tab (either active or inactive) is | 127 // The minimum opacity (out of 1) when a tab (either active or inactive) is |
132 // throbbing in the immersive mode light strip. | 128 // throbbing in the immersive mode light strip. |
133 const double kImmersiveTabMinThrobOpacity = 0.66; | 129 const double kImmersiveTabMinThrobOpacity = 0.66; |
134 | 130 |
135 // Number of steps in the immersive mode loading animation. | 131 // Number of steps in the immersive mode loading animation. |
136 const int kImmersiveLoadingStepCount = 32; | 132 const int kImmersiveLoadingStepCount = 32; |
137 | 133 |
138 const char kTabCloseButtonName[] = "TabCloseButton"; | 134 const char kTabCloseButtonName[] = "TabCloseButton"; |
139 const int kTabCloseButtonSize = 16; | 135 const int kTabCloseButtonSize = 16; |
140 | 136 |
141 void DrawIconAtLocation(gfx::Canvas* canvas, | |
142 const gfx::ImageSkia& image, | |
143 int image_offset, | |
144 int dst_x, | |
145 int dst_y, | |
146 int icon_width, | |
147 int icon_height, | |
148 bool filter, | |
149 const SkPaint& paint) { | |
150 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. | |
151 canvas->Save(); | |
152 canvas->ClipRect(gfx::Rect(dst_x, dst_y, icon_width, icon_height)); | |
153 canvas->DrawImageInt(image, | |
154 image_offset, 0, icon_width, icon_height, | |
155 dst_x, dst_y, icon_width, icon_height, | |
156 filter, paint); | |
157 canvas->Restore(); | |
158 } | |
159 | |
160 // Draws the icon image at the center of |bounds|. | |
161 void DrawIconCenter(gfx::Canvas* canvas, | |
162 const gfx::ImageSkia& image, | |
163 int image_offset, | |
164 int icon_width, | |
165 int icon_height, | |
166 const gfx::Rect& bounds, | |
167 bool filter, | |
168 const SkPaint& paint) { | |
169 // Center the image within bounds. | |
170 int dst_x = bounds.x() - (icon_width - bounds.width()) / 2; | |
171 int dst_y = bounds.y() - (icon_height - bounds.height()) / 2; | |
172 DrawIconAtLocation(canvas, image, image_offset, dst_x, dst_y, icon_width, | |
173 icon_height, filter, paint); | |
174 } | |
175 | |
176 chrome::HostDesktopType GetHostDesktopType(views::View* view) { | 137 chrome::HostDesktopType GetHostDesktopType(views::View* view) { |
177 // Widget is NULL when tabs are detached. | 138 // Widget is NULL when tabs are detached. |
178 views::Widget* widget = view->GetWidget(); | 139 views::Widget* widget = view->GetWidget(); |
179 return chrome::GetHostDesktopTypeForNativeView( | 140 return chrome::GetHostDesktopTypeForNativeView( |
180 widget ? widget->GetNativeView() : NULL); | 141 widget ? widget->GetNativeView() : NULL); |
181 } | 142 } |
182 | 143 |
183 // Stop()s |animation| and then deletes it. We do this rather than just deleting | 144 // Stop()s |animation| and then deletes it. We do this rather than just deleting |
184 // so that the delegate is notified before the destruction. | 145 // so that the delegate is notified before the destruction. |
185 void StopAndDeleteAnimation(scoped_ptr<gfx::Animation> animation) { | 146 void StopAndDeleteAnimation(scoped_ptr<gfx::Animation> animation) { |
(...skipping 14 matching lines...) Expand all Loading... | |
200 : gfx::LinearAnimation(1000, 25, this), | 161 : gfx::LinearAnimation(1000, 25, this), |
201 target_(target) { | 162 target_(target) { |
202 } | 163 } |
203 ~FaviconCrashAnimation() override {} | 164 ~FaviconCrashAnimation() override {} |
204 | 165 |
205 // gfx::Animation overrides: | 166 // gfx::Animation overrides: |
206 void AnimateToState(double state) override { | 167 void AnimateToState(double state) override { |
207 const double kHidingOffset = 27; | 168 const double kHidingOffset = 27; |
208 | 169 |
209 if (state < .5) { | 170 if (state < .5) { |
171 // Animate the normal icon down. | |
210 target_->SetFaviconHidingOffset( | 172 target_->SetFaviconHidingOffset( |
211 static_cast<int>(floor(kHidingOffset * 2.0 * state))); | 173 static_cast<int>(floor(kHidingOffset * 2.0 * state))); |
212 } else { | 174 } else { |
175 // Animate the crashed icon up. | |
213 target_->DisplayCrashedFavicon(); | 176 target_->DisplayCrashedFavicon(); |
214 target_->SetFaviconHidingOffset( | 177 target_->SetFaviconHidingOffset( |
215 static_cast<int>( | 178 static_cast<int>( |
216 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); | 179 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); |
217 } | 180 } |
218 } | 181 } |
219 | 182 |
220 // gfx::AnimationDelegate overrides: | 183 // gfx::AnimationDelegate overrides: |
221 void AnimationCanceled(const gfx::Animation* animation) override { | 184 void AnimationCanceled(const gfx::Animation* animation) override { |
222 target_->SetFaviconHidingOffset(0); | 185 target_->SetFaviconHidingOffset(0); |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
711 //////////////////////////////////////////////////////////////////////////////// | 674 //////////////////////////////////////////////////////////////////////////////// |
712 // Tab, views::MaskedTargeterDelegate overrides: | 675 // Tab, views::MaskedTargeterDelegate overrides: |
713 | 676 |
714 bool Tab::GetHitTestMask(gfx::Path* mask) const { | 677 bool Tab::GetHitTestMask(gfx::Path* mask) const { |
715 DCHECK(mask); | 678 DCHECK(mask); |
716 | 679 |
717 // When the window is maximized we don't want to shave off the edges or top | 680 // When the window is maximized we don't want to shave off the edges or top |
718 // shadow of the tab, such that the user can click anywhere along the top | 681 // shadow of the tab, such that the user can click anywhere along the top |
719 // edge of the screen to select a tab. Ditto for immersive fullscreen. | 682 // edge of the screen to select a tab. Ditto for immersive fullscreen. |
720 const views::Widget* widget = GetWidget(); | 683 const views::Widget* widget = GetWidget(); |
721 GetHitTestMaskHelper( | 684 const bool extend_to_top = |
722 widget && (widget->IsMaximized() || widget->IsFullscreen()), mask); | 685 widget && (widget->IsMaximized() || widget->IsFullscreen()); |
686 | |
687 // Hit mask constants. | |
688 const SkScalar kTabCapWidth = 15; | |
689 const SkScalar kTabTopCurveWidth = 4; | |
690 const SkScalar kTabBottomCurveWidth = 3; | |
691 #if defined(OS_MACOSX) | |
692 // Mac's Cocoa UI doesn't have shadows. | |
693 const SkScalar kTabInset = 0; | |
694 const SkScalar kTabTop = 0; | |
695 #elif defined(TOOLKIT_VIEWS) | |
696 // The views browser UI has shadows in the left, right and top parts of the | |
697 // tab. | |
698 const SkScalar kTabInset = 6; | |
699 const SkScalar kTabTop = 2; | |
700 #endif | |
701 | |
702 SkScalar left = kTabInset; | |
703 SkScalar top = kTabTop; | |
704 SkScalar right = SkIntToScalar(width()) - kTabInset; | |
705 SkScalar bottom = SkIntToScalar(height()); | |
706 | |
707 // Start in the lower-left corner. | |
708 mask->moveTo(left, bottom); | |
709 | |
710 // Left end cap. | |
711 mask->lineTo(left + kTabBottomCurveWidth, bottom - kTabBottomCurveWidth); | |
712 mask->lineTo(left + kTabCapWidth - kTabTopCurveWidth, | |
713 top + kTabTopCurveWidth); | |
714 mask->lineTo(left + kTabCapWidth, top); | |
715 | |
716 // Extend over the top shadow area if we have one and the caller wants it. | |
717 if (kTabTop > 0 && extend_to_top) { | |
718 mask->lineTo(left + kTabCapWidth, 0); | |
719 mask->lineTo(right - kTabCapWidth, 0); | |
720 } | |
721 | |
722 // Connect to the right cap. | |
723 mask->lineTo(right - kTabCapWidth, top); | |
724 | |
725 // Right end cap. | |
726 mask->lineTo(right - kTabCapWidth + kTabTopCurveWidth, | |
727 top + kTabTopCurveWidth); | |
728 mask->lineTo(right - kTabBottomCurveWidth, bottom - kTabBottomCurveWidth); | |
729 mask->lineTo(right, bottom); | |
730 | |
731 // Close out the path. | |
732 mask->lineTo(left, bottom); | |
733 mask->close(); | |
723 | 734 |
724 // It is possible for a portion of the tab to be occluded if tabs are | 735 // It is possible for a portion of the tab to be occluded if tabs are |
725 // stacked, so modify the hit test mask to only include the visible | 736 // stacked, so modify the hit test mask to only include the visible |
726 // region of the tab. | 737 // region of the tab. |
727 gfx::Rect clip; | 738 gfx::Rect clip; |
728 controller_->ShouldPaintTab(this, &clip); | 739 controller_->ShouldPaintTab(this, &clip); |
729 if (clip.size().GetArea()) { | 740 if (clip.size().GetArea()) { |
730 SkRect intersection(mask->getBounds()); | 741 SkRect intersection(mask->getBounds()); |
731 mask->reset(); | 742 mask->reset(); |
732 if (!intersection.intersect(RectToSkRect(clip))) | 743 if (!intersection.intersect(RectToSkRect(clip))) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
764 if (controller_->IsImmersiveStyle()) | 775 if (controller_->IsImmersiveStyle()) |
765 PaintImmersiveTab(canvas); | 776 PaintImmersiveTab(canvas); |
766 else | 777 else |
767 PaintTab(canvas); | 778 PaintTab(canvas); |
768 | 779 |
769 if (!clip.IsEmpty()) | 780 if (!clip.IsEmpty()) |
770 canvas->Restore(); | 781 canvas->Restore(); |
771 } | 782 } |
772 | 783 |
773 void Tab::Layout() { | 784 void Tab::Layout() { |
774 gfx::Rect lb = GetContentsBounds(); | 785 gfx::Rect lb = GetInteriorBounds(); |
775 if (lb.IsEmpty()) | 786 if (lb.IsEmpty()) |
776 return; | 787 return; |
777 | 788 |
778 lb.Inset(GetLayoutInsets(TAB)); | |
779 showing_icon_ = ShouldShowIcon(); | 789 showing_icon_ = ShouldShowIcon(); |
780 // See comments in IconCapacity(). | 790 // See comments in IconCapacity(). |
781 const int extra_padding = | 791 const int extra_padding = |
782 (controller_->ShouldHideCloseButtonForInactiveTabs() || | 792 (controller_->ShouldHideCloseButtonForInactiveTabs() || |
783 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; | 793 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; |
784 const int start = lb.x() + extra_padding; | 794 const int start = lb.x() + extra_padding; |
785 favicon_bounds_.SetRect(start, lb.y(), 0, 0); | 795 favicon_bounds_.SetRect(start, lb.y(), 0, 0); |
786 if (showing_icon_) { | 796 if (showing_icon_) { |
787 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); | 797 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); |
788 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); | 798 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
838 (favicon_bounds_.right() + title_spacing) : start; | 848 (favicon_bounds_.right() + title_spacing) : start; |
839 int title_width = lb.right() - title_left; | 849 int title_width = lb.right() - title_left; |
840 if (showing_media_indicator_) { | 850 if (showing_media_indicator_) { |
841 title_width = | 851 title_width = |
842 media_indicator_button_->x() - kAfterTitleSpacing - title_left; | 852 media_indicator_button_->x() - kAfterTitleSpacing - title_left; |
843 } else if (close_button_->visible()) { | 853 } else if (close_button_->visible()) { |
844 // Allow the title to overlay the close button's empty border padding. | 854 // Allow the title to overlay the close button's empty border padding. |
845 title_width = close_button_->x() + close_button_->GetInsets().left() - | 855 title_width = close_button_->x() + close_button_->GetInsets().left() - |
846 kAfterTitleSpacing - title_left; | 856 kAfterTitleSpacing - title_left; |
847 } | 857 } |
848 gfx::Rect rect(title_left, lb.y(), std::max(title_width, 0), lb.height()); | 858 // The Label will automatically center the font's cap height within the |
849 const int title_height = title_->GetPreferredSize().height(); | 859 // provided vertical space. |
850 if (title_height > rect.height()) { | 860 title_->SetBoundsRect( |
851 rect.set_y(lb.y() - (title_height - rect.height()) / 2); | 861 gfx::Rect(title_left, lb.y(), std::max(title_width, 0), lb.height())); |
852 rect.set_height(title_height); | |
853 } | |
854 title_->SetBoundsRect(rect); | |
855 } | 862 } |
856 title_->SetVisible(show_title); | 863 title_->SetVisible(show_title); |
857 } | 864 } |
858 | 865 |
859 void Tab::OnThemeChanged() { | 866 void Tab::OnThemeChanged() { |
860 LoadTabImages(); | 867 LoadTabImages(); |
861 OnButtonColorMaybeChanged(); | 868 OnButtonColorMaybeChanged(); |
862 } | 869 } |
863 | 870 |
864 const char* Tab::GetClassName() const { | 871 const char* Tab::GetClassName() const { |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1241 // image is a composited foreground + frame image. | 1248 // image is a composited foreground + frame image. |
1242 int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? | 1249 int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? |
1243 0 : background_offset_.y(); | 1250 0 : background_offset_.y(); |
1244 | 1251 |
1245 // We need a gfx::Canvas object to be able to extract the image from. | 1252 // We need a gfx::Canvas object to be able to extract the image from. |
1246 // We draw everything to this canvas and then output it to the canvas | 1253 // We draw everything to this canvas and then output it to the canvas |
1247 // parameter in addition to using it to mask the hover glow if needed. | 1254 // parameter in addition to using it to mask the hover glow if needed. |
1248 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); | 1255 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); |
1249 | 1256 |
1250 // Draw left edge. Don't draw over the toolbar, as we're not the foreground | 1257 // Draw left edge. Don't draw over the toolbar, as we're not the foreground |
1251 // tab. | 1258 // tab, but do include the 1 px divider stroke at the bottom. |
1259 const gfx::Insets tab_insets(GetLayoutInsets(TAB)); | |
1260 const int toolbar_overlap = tab_insets.bottom() - 1; | |
1252 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( | 1261 gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( |
1253 *tab_bg, offset, bg_offset_y, tab_image->l_width, height()); | 1262 *tab_bg, offset, bg_offset_y, tab_image->l_width, height()); |
1254 gfx::ImageSkia theme_l = | 1263 gfx::ImageSkia theme_l = |
1255 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *alpha->image_l); | 1264 gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *alpha->image_l); |
1256 background_canvas.DrawImageInt(theme_l, | 1265 background_canvas.DrawImageInt(theme_l, |
1257 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, | 1266 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, |
1258 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, | 1267 0, 0, theme_l.width(), theme_l.height() - toolbar_overlap, |
1259 false); | 1268 false); |
1260 | 1269 |
1261 // Draw right edge. Again, don't draw over the toolbar. | 1270 // Draw right edge. Again, don't draw over the toolbar. |
1262 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage(*tab_bg, | 1271 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage(*tab_bg, |
1263 offset + width() - tab_image->r_width, bg_offset_y, | 1272 offset + width() - tab_image->r_width, bg_offset_y, |
1264 tab_image->r_width, height()); | 1273 tab_image->r_width, height()); |
1265 gfx::ImageSkia theme_r = | 1274 gfx::ImageSkia theme_r = |
1266 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); | 1275 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); |
1267 background_canvas.DrawImageInt(theme_r, | 1276 background_canvas.DrawImageInt(theme_r, |
1268 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap, | 1277 0, 0, theme_r.width(), theme_r.height() - toolbar_overlap, |
1269 width() - theme_r.width(), 0, theme_r.width(), | 1278 width() - theme_r.width(), 0, theme_r.width(), |
1270 theme_r.height() - kToolbarOverlap, false); | 1279 theme_r.height() - toolbar_overlap, false); |
1271 | 1280 |
1272 // Draw center. Instead of masking out the top portion we simply skip over | 1281 // Draw center. Instead of masking out the top portion we simply skip over |
1273 // it by incrementing by GetDropShadowHeight(), since it's a simple | 1282 // it by incrementing by the top padding, since it's a simple rectangle. And |
1274 // rectangle. And again, don't draw over the toolbar. | 1283 // again, don't draw over the toolbar. |
1275 background_canvas.TileImageInt(*tab_bg, | 1284 background_canvas.TileImageInt( |
1276 offset + tab_image->l_width, | 1285 *tab_bg, offset + tab_image->l_width, bg_offset_y + tab_insets.top(), |
1277 bg_offset_y + kDropShadowHeight, | 1286 tab_image->l_width, tab_insets.top(), |
1278 tab_image->l_width, | |
1279 kDropShadowHeight, | |
1280 width() - tab_image->l_width - tab_image->r_width, | 1287 width() - tab_image->l_width - tab_image->r_width, |
1281 height() - kDropShadowHeight - kToolbarOverlap); | 1288 height() - tab_insets.top() - toolbar_overlap); |
1282 | 1289 |
1283 canvas->DrawImageInt( | 1290 canvas->DrawImageInt( |
1284 gfx::ImageSkia(background_canvas.ExtractImageRep()), 0, 0); | 1291 gfx::ImageSkia(background_canvas.ExtractImageRep()), 0, 0); |
1285 | 1292 |
1286 if (!GetThemeProvider()->HasCustomImage(tab_id) && | 1293 if (!GetThemeProvider()->HasCustomImage(tab_id) && |
1287 hover_controller_.ShouldDraw()) { | 1294 hover_controller_.ShouldDraw()) { |
1288 hover_controller_.Draw(canvas, gfx::ImageSkia( | 1295 hover_controller_.Draw(canvas, gfx::ImageSkia( |
1289 background_canvas.ExtractImageRep())); | 1296 background_canvas.ExtractImageRep())); |
1290 } | 1297 } |
1291 | 1298 |
(...skipping 25 matching lines...) Expand all Loading... | |
1317 | 1324 |
1318 // Draw right edge. | 1325 // Draw right edge. |
1319 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( | 1326 gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( |
1320 *tab_background, | 1327 *tab_background, |
1321 offset + width() - tab_image->r_width, 0, tab_image->r_width, height()); | 1328 offset + width() - tab_image->r_width, 0, tab_image->r_width, height()); |
1322 gfx::ImageSkia theme_r = | 1329 gfx::ImageSkia theme_r = |
1323 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); | 1330 gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); |
1324 canvas->DrawImageInt(theme_r, width() - tab_image->r_width, 0); | 1331 canvas->DrawImageInt(theme_r, width() - tab_image->r_width, 0); |
1325 | 1332 |
1326 // Draw center. Instead of masking out the top portion we simply skip over it | 1333 // Draw center. Instead of masking out the top portion we simply skip over it |
1327 // by incrementing by GetDropShadowHeight(), since it's a simple rectangle. | 1334 // by incrementing by the top padding, since it's a simple rectangle. |
1328 canvas->TileImageInt(*tab_background, | 1335 const int top_padding = GetLayoutInsets(TAB).top(); |
1329 offset + tab_image->l_width, | 1336 canvas->TileImageInt(*tab_background, offset + tab_image->l_width, |
1330 kDropShadowHeight, | 1337 top_padding, tab_image->l_width, top_padding, |
1331 tab_image->l_width, | 1338 width() - tab_image->l_width - tab_image->r_width, |
1332 kDropShadowHeight, | 1339 height() - top_padding); |
1333 width() - tab_image->l_width - tab_image->r_width, | |
1334 height() - kDropShadowHeight); | |
1335 | 1340 |
1336 // Now draw the highlights/shadows around the tab edge. | 1341 // Now draw the highlights/shadows around the tab edge. |
1337 canvas->DrawImageInt(*tab_image->image_l, 0, 0); | 1342 canvas->DrawImageInt(*tab_image->image_l, 0, 0); |
1338 canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, | 1343 canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, |
1339 width() - tab_image->l_width - tab_image->r_width, height()); | 1344 width() - tab_image->l_width - tab_image->r_width, height()); |
1340 canvas->DrawImageInt(*tab_image->image_r, width() - tab_image->r_width, 0); | 1345 canvas->DrawImageInt(*tab_image->image_r, width() - tab_image->r_width, 0); |
1341 } | 1346 } |
1342 | 1347 |
1343 void Tab::PaintIcon(gfx::Canvas* canvas) { | 1348 void Tab::PaintIcon(gfx::Canvas* canvas) { |
1344 gfx::Rect bounds = favicon_bounds_; | 1349 gfx::Rect bounds = favicon_bounds_; |
(...skipping 18 matching lines...) Expand all Loading... | |
1363 if (loading_start_time_ == base::TimeTicks()) | 1368 if (loading_start_time_ == base::TimeTicks()) |
1364 loading_start_time_ = base::TimeTicks::Now(); | 1369 loading_start_time_ = base::TimeTicks::Now(); |
1365 | 1370 |
1366 waiting_state_.color = | 1371 waiting_state_.color = |
1367 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING); | 1372 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING); |
1368 gfx::PaintThrobberSpinningAfterWaiting( | 1373 gfx::PaintThrobberSpinningAfterWaiting( |
1369 canvas, bounds, | 1374 canvas, bounds, |
1370 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING), | 1375 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING), |
1371 base::TimeTicks::Now() - loading_start_time_, &waiting_state_); | 1376 base::TimeTicks::Now() - loading_start_time_, &waiting_state_); |
1372 } | 1377 } |
1373 } else if (should_display_crashed_favicon_) { | 1378 } else { |
1374 // Paint crash favicon. | 1379 const gfx::ImageSkia& favicon = should_display_crashed_favicon_ ? |
1375 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 1380 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
1376 gfx::ImageSkia crashed_favicon( | 1381 IDR_CRASH_SAD_FAVICON) : |
1377 *rb.GetImageSkiaNamed(IDR_CRASH_SAD_FAVICON)); | 1382 data().favicon; |
1378 bounds.set_y(bounds.y() + favicon_hiding_offset_); | 1383 if (!favicon.isNull()) { |
1379 DrawIconCenter(canvas, crashed_favicon, 0, | 1384 canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(), |
1380 crashed_favicon.width(), | 1385 bounds.x(), bounds.y(), bounds.width(), |
1381 crashed_favicon.height(), | 1386 bounds.height(), false); |
1382 bounds, true, SkPaint()); | 1387 } |
1383 } else if (!data().favicon.isNull()) { | |
1384 // Paint the normal favicon. | |
1385 DrawIconCenter(canvas, data().favicon, 0, | |
1386 data().favicon.width(), | |
1387 data().favicon.height(), | |
1388 bounds, true, SkPaint()); | |
1389 } | 1388 } |
1390 } | 1389 } |
1391 | 1390 |
1392 void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, | 1391 void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, |
1393 TabRendererData::NetworkState state) { | 1392 TabRendererData::NetworkState state) { |
1394 if (state == TabRendererData::NETWORK_STATE_WAITING) { | 1393 if (state == TabRendererData::NETWORK_STATE_WAITING) { |
1395 // Waiting steps backwards. | 1394 // Waiting steps backwards. |
1396 immersive_loading_step_ = | 1395 immersive_loading_step_ = |
1397 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % | 1396 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % |
1398 kImmersiveLoadingStepCount; | 1397 kImmersiveLoadingStepCount; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1538 if (bounds.IsEmpty()) | 1537 if (bounds.IsEmpty()) |
1539 return; | 1538 return; |
1540 | 1539 |
1541 // Extends the area to the bottom when sad_favicon is animating. | 1540 // Extends the area to the bottom when sad_favicon is animating. |
1542 if (IsPerformingCrashAnimation()) | 1541 if (IsPerformingCrashAnimation()) |
1543 bounds.set_height(height() - bounds.y()); | 1542 bounds.set_height(height() - bounds.y()); |
1544 bounds.set_x(GetMirroredXForRect(bounds)); | 1543 bounds.set_x(GetMirroredXForRect(bounds)); |
1545 SchedulePaintInRect(bounds); | 1544 SchedulePaintInRect(bounds); |
1546 } | 1545 } |
1547 | 1546 |
1548 void Tab::GetHitTestMaskHelper(bool include_top_shadow, gfx::Path* path) const { | 1547 gfx::Rect Tab::GetInteriorBounds() const { |
1549 DCHECK(path); | 1548 gfx::Rect bounds(GetContentsBounds()); |
1550 | 1549 bounds.Inset(GetLayoutInsets(TAB)); |
sky
2015/10/09 16:31:38
Did you consider: SetBorder(Border::CreateEmptyBor
| |
1551 // Hit mask constants. | 1550 return bounds; |
1552 const SkScalar kTabCapWidth = 15; | |
1553 const SkScalar kTabTopCurveWidth = 4; | |
1554 const SkScalar kTabBottomCurveWidth = 3; | |
1555 #if defined(OS_MACOSX) | |
1556 // Mac's Cocoa UI doesn't have shadows. | |
1557 const SkScalar kTabInset = 0; | |
1558 const SkScalar kTabTop = 0; | |
1559 #elif defined(TOOLKIT_VIEWS) | |
1560 // The views browser UI has shadows in the left, right and top parts of the | |
1561 // tab. | |
1562 const SkScalar kTabInset = 6; | |
1563 const SkScalar kTabTop = 2; | |
1564 #endif | |
1565 | |
1566 SkScalar left = kTabInset; | |
1567 SkScalar top = kTabTop; | |
1568 SkScalar right = SkIntToScalar(width()) - kTabInset; | |
1569 SkScalar bottom = SkIntToScalar(height()); | |
1570 | |
1571 // Start in the lower-left corner. | |
1572 path->moveTo(left, bottom); | |
1573 | |
1574 // Left end cap. | |
1575 path->lineTo(left + kTabBottomCurveWidth, bottom - kTabBottomCurveWidth); | |
1576 path->lineTo(left + kTabCapWidth - kTabTopCurveWidth, | |
1577 top + kTabTopCurveWidth); | |
1578 path->lineTo(left + kTabCapWidth, top); | |
1579 | |
1580 // Extend over the top shadow area if we have one and the caller wants it. | |
1581 if (kTabTop > 0 && include_top_shadow) { | |
1582 path->lineTo(left + kTabCapWidth, 0); | |
1583 path->lineTo(right - kTabCapWidth, 0); | |
1584 } | |
1585 | |
1586 // Connect to the right cap. | |
1587 path->lineTo(right - kTabCapWidth, top); | |
1588 | |
1589 // Right end cap. | |
1590 path->lineTo(right - kTabCapWidth + kTabTopCurveWidth, | |
1591 top + kTabTopCurveWidth); | |
1592 path->lineTo(right - kTabBottomCurveWidth, bottom - kTabBottomCurveWidth); | |
1593 path->lineTo(right, bottom); | |
1594 | |
1595 // Close out the path. | |
1596 path->lineTo(left, bottom); | |
1597 path->close(); | |
1598 } | 1551 } |
1599 | 1552 |
1600 gfx::Rect Tab::GetImmersiveBarRect() const { | 1553 gfx::Rect Tab::GetImmersiveBarRect() const { |
1601 // The main bar is as wide as the normal tab's horizontal top line. | 1554 // The main bar is as wide as the normal tab's horizontal top line. |
1602 // This top line of the tab extends a few pixels left and right of the | 1555 // This top line of the tab extends a few pixels left and right of the |
1603 // center image due to pixels in the rounded corner images. | 1556 // center image due to pixels in the rounded corner images. |
1604 const int kBarPadding = 1; | 1557 const int kBarPadding = 1; |
1605 int main_bar_left = tab_active_.l_width - kBarPadding; | 1558 int main_bar_left = tab_active_.l_width - kBarPadding; |
1606 int main_bar_right = width() - tab_active_.r_width + kBarPadding; | 1559 int main_bar_right = width() - tab_active_.r_width + kBarPadding; |
1607 return gfx::Rect( | 1560 return gfx::Rect( |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1681 const gfx::ImageSkia& image) { | 1634 const gfx::ImageSkia& image) { |
1682 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1635 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1683 ImageCacheEntry entry; | 1636 ImageCacheEntry entry; |
1684 entry.resource_id = resource_id; | 1637 entry.resource_id = resource_id; |
1685 entry.scale_factor = scale_factor; | 1638 entry.scale_factor = scale_factor; |
1686 entry.image = image; | 1639 entry.image = image; |
1687 image_cache_->push_front(entry); | 1640 image_cache_->push_front(entry); |
1688 if (image_cache_->size() > kMaxImageCacheSize) | 1641 if (image_cache_->size() > kMaxImageCacheSize) |
1689 image_cache_->pop_back(); | 1642 image_cache_->pop_back(); |
1690 } | 1643 } |
OLD | NEW |