| 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 <stddef.h> | 7 #include <stddef.h> | 
| 8 #include <limits> | 8 #include <limits> | 
| 9 #include <utility> | 9 #include <utility> | 
| 10 | 10 | 
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 91 const double kSelectedTabOpacity = 0.3; | 91 const double kSelectedTabOpacity = 0.3; | 
| 92 | 92 | 
| 93 // Inactive selected tabs have their throb value scaled by this. | 93 // Inactive selected tabs have their throb value scaled by this. | 
| 94 const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; | 94 const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; | 
| 95 | 95 | 
| 96 // Max number of images to cache. This has to be at least two since rounding | 96 // Max number of images to cache. This has to be at least two since rounding | 
| 97 // errors may lead to tabs in the same tabstrip having different sizes. | 97 // errors may lead to tabs in the same tabstrip having different sizes. | 
| 98 // 8 = normal/incognito, active/inactive, 2 sizes within tabstrip. | 98 // 8 = normal/incognito, active/inactive, 2 sizes within tabstrip. | 
| 99 const size_t kMaxImageCacheSize = 8; | 99 const size_t kMaxImageCacheSize = 8; | 
| 100 | 100 | 
| 101 // Height of the miniature tab strip in immersive mode. |  | 
| 102 const int kImmersiveTabHeight = 3; |  | 
| 103 |  | 
| 104 // Height of the small tab indicator rectangles in immersive mode. |  | 
| 105 const int kImmersiveBarHeight = 2; |  | 
| 106 |  | 
| 107 // Color for active and inactive tabs in the immersive mode light strip. These |  | 
| 108 // should be a little brighter than the color of the normal art assets for tabs, |  | 
| 109 // which for active tabs is 230, 230, 230 and for inactive is 184, 184, 184. |  | 
| 110 const SkColor kImmersiveActiveTabColor = SkColorSetRGB(235, 235, 235); |  | 
| 111 const SkColor kImmersiveInactiveTabColor = SkColorSetRGB(190, 190, 190); |  | 
| 112 |  | 
| 113 // The minimum opacity (out of 1) when a tab (either active or inactive) is |  | 
| 114 // throbbing in the immersive mode light strip. |  | 
| 115 const double kImmersiveTabMinThrobOpacity = 0.66; |  | 
| 116 |  | 
| 117 // Number of steps in the immersive mode loading animation. |  | 
| 118 const int kImmersiveLoadingStepCount = 32; |  | 
| 119 |  | 
| 120 const char kTabCloseButtonName[] = "TabCloseButton"; | 101 const char kTabCloseButtonName[] = "TabCloseButton"; | 
| 121 | 102 | 
| 122 //////////////////////////////////////////////////////////////////////////////// | 103 //////////////////////////////////////////////////////////////////////////////// | 
| 123 // ImageCacheEntryMetadata | 104 // ImageCacheEntryMetadata | 
| 124 // | 105 // | 
| 125 // All metadata necessary to uniquely identify a cached image. | 106 // All metadata necessary to uniquely identify a cached image. | 
| 126 struct ImageCacheEntryMetadata { | 107 struct ImageCacheEntryMetadata { | 
| 127   ImageCacheEntryMetadata(SkColor fill_color, | 108   ImageCacheEntryMetadata(SkColor fill_color, | 
| 128                           SkColor stroke_color, | 109                           SkColor stroke_color, | 
| 129                           bool use_fill_and_stroke_images, | 110                           bool use_fill_and_stroke_images, | 
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 531 | 512 | 
| 532 // static | 513 // static | 
| 533 const char Tab::kViewClassName[] = "Tab"; | 514 const char Tab::kViewClassName[] = "Tab"; | 
| 534 | 515 | 
| 535 Tab::Tab(TabController* controller, gfx::AnimationContainer* container) | 516 Tab::Tab(TabController* controller, gfx::AnimationContainer* container) | 
| 536     : controller_(controller), | 517     : controller_(controller), | 
| 537       closing_(false), | 518       closing_(false), | 
| 538       dragging_(false), | 519       dragging_(false), | 
| 539       detached_(false), | 520       detached_(false), | 
| 540       favicon_hiding_offset_(0), | 521       favicon_hiding_offset_(0), | 
| 541       immersive_loading_step_(0), |  | 
| 542       should_display_crashed_favicon_(false), | 522       should_display_crashed_favicon_(false), | 
| 543       pulse_animation_(new gfx::ThrobAnimation(this)), | 523       pulse_animation_(new gfx::ThrobAnimation(this)), | 
| 544       crash_icon_animation_(new FaviconCrashAnimation(this)), | 524       crash_icon_animation_(new FaviconCrashAnimation(this)), | 
| 545       animation_container_(container), | 525       animation_container_(container), | 
| 546       throbber_(nullptr), | 526       throbber_(nullptr), | 
| 547       alert_indicator_button_(nullptr), | 527       alert_indicator_button_(nullptr), | 
| 548       close_button_(nullptr), | 528       close_button_(nullptr), | 
| 549       title_(new views::Label()), | 529       title_(new views::Label()), | 
| 550       tab_activated_with_last_tap_down_(false), | 530       tab_activated_with_last_tap_down_(false), | 
| 551       hover_controller_(this), | 531       hover_controller_(this), | 
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 740   return kTouchWidth; | 720   return kTouchWidth; | 
| 741 } | 721 } | 
| 742 | 722 | 
| 743 // static | 723 // static | 
| 744 int Tab::GetPinnedWidth() { | 724 int Tab::GetPinnedWidth() { | 
| 745   constexpr int kTabPinnedContentWidth = 23; | 725   constexpr int kTabPinnedContentWidth = 23; | 
| 746   return GetMinimumInactiveSize().width() + kTabPinnedContentWidth; | 726   return GetMinimumInactiveSize().width() + kTabPinnedContentWidth; | 
| 747 } | 727 } | 
| 748 | 728 | 
| 749 // static | 729 // static | 
| 750 int Tab::GetImmersiveHeight() { |  | 
| 751   return kImmersiveTabHeight; |  | 
| 752 } |  | 
| 753 |  | 
| 754 // static |  | 
| 755 float Tab::GetInverseDiagonalSlope() { | 730 float Tab::GetInverseDiagonalSlope() { | 
| 756   // This is computed from the border path as follows: | 731   // This is computed from the border path as follows: | 
| 757   // * The unscaled endcap width is enough for the whole stroke outer curve, | 732   // * The unscaled endcap width is enough for the whole stroke outer curve, | 
| 758   //   i.e. the side diagonal plus the curves on both its ends. | 733   //   i.e. the side diagonal plus the curves on both its ends. | 
| 759   // * The bottom and top curve are each (2 * scale) px wide, so the diagonal is | 734   // * The bottom and top curve are each (2 * scale) px wide, so the diagonal is | 
| 760   //   (unscaled endcap width - 2 - 2) * scale px wide. | 735   //   (unscaled endcap width - 2 - 2) * scale px wide. | 
| 761   // * The bottom and top curve are each 1.5 px high.  Additionally, there is an | 736   // * The bottom and top curve are each 1.5 px high.  Additionally, there is an | 
| 762   //   extra 1 px below the bottom curve and (scale - 1) px above the top curve, | 737   //   extra 1 px below the bottom curve and (scale - 1) px above the top curve, | 
| 763   //   so the diagonal is ((height - 1.5 - 1.5) * scale - 1 - (scale - 1)) px | 738   //   so the diagonal is ((height - 1.5 - 1.5) * scale - 1 - (scale - 1)) px | 
| 764   //   high. | 739   //   high. | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 848   // only happen during animations). | 823   // only happen during animations). | 
| 849   if (width() < GetMinimumInactiveSize().width() && !data().pinned) | 824   if (width() < GetMinimumInactiveSize().width() && !data().pinned) | 
| 850     return; | 825     return; | 
| 851 | 826 | 
| 852   gfx::Path clip; | 827   gfx::Path clip; | 
| 853   if (!controller_->ShouldPaintTab( | 828   if (!controller_->ShouldPaintTab( | 
| 854           this, base::Bind(&GetBorderPath, canvas->image_scale(), true, false), | 829           this, base::Bind(&GetBorderPath, canvas->image_scale(), true, false), | 
| 855           &clip)) | 830           &clip)) | 
| 856     return; | 831     return; | 
| 857 | 832 | 
| 858   if (controller_->IsImmersiveStyle()) | 833   PaintTab(canvas, clip); | 
| 859     PaintImmersiveTab(canvas); |  | 
| 860   else |  | 
| 861     PaintTab(canvas, clip); |  | 
| 862 } | 834 } | 
| 863 | 835 | 
| 864 void Tab::Layout() { | 836 void Tab::Layout() { | 
| 865   const gfx::Rect lb = GetContentsBounds(); | 837   const gfx::Rect lb = GetContentsBounds(); | 
| 866   showing_icon_ = ShouldShowIcon(); | 838   showing_icon_ = ShouldShowIcon(); | 
| 867   // See comments in IconCapacity(). | 839   // See comments in IconCapacity(). | 
| 868   const int extra_padding = | 840   const int extra_padding = | 
| 869       (controller_->ShouldHideCloseButtonForInactiveTabs() || | 841       (controller_->ShouldHideCloseButtonForInactiveTabs() || | 
| 870        (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; | 842        (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; | 
| 871   const int start = lb.x() + extra_padding; | 843   const int start = lb.x() + extra_padding; | 
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1163       PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, | 1135       PaintTabBackgroundUsingFillId(canvas, canvas, true, kActiveTabFillId, | 
| 1164                                     y_offset); | 1136                                     y_offset); | 
| 1165       canvas->Restore(); | 1137       canvas->Restore(); | 
| 1166     } | 1138     } | 
| 1167   } | 1139   } | 
| 1168 | 1140 | 
| 1169   if (showing_icon_) | 1141   if (showing_icon_) | 
| 1170     PaintIcon(canvas); | 1142     PaintIcon(canvas); | 
| 1171 } | 1143 } | 
| 1172 | 1144 | 
| 1173 void Tab::PaintImmersiveTab(gfx::Canvas* canvas) { |  | 
| 1174   // Use transparency for the draw-attention animation. |  | 
| 1175   int alpha = 255; |  | 
| 1176   if (pulse_animation_->is_animating() && !data().pinned) { |  | 
| 1177     alpha = pulse_animation_->CurrentValueBetween( |  | 
| 1178         255, gfx::ToRoundedInt(255 * kImmersiveTabMinThrobOpacity)); |  | 
| 1179   } |  | 
| 1180 |  | 
| 1181   // Draw a gray rectangle to represent the tab. This works for pinned tabs as |  | 
| 1182   // well as regular ones. The active tab has a brigher bar. |  | 
| 1183   SkColor color = |  | 
| 1184       IsActive() ? kImmersiveActiveTabColor : kImmersiveInactiveTabColor; |  | 
| 1185   gfx::Rect bar_rect = GetImmersiveBarRect(); |  | 
| 1186   canvas->FillRect(bar_rect, SkColorSetA(color, alpha)); |  | 
| 1187 |  | 
| 1188   // Paint network activity indicator. |  | 
| 1189   // TODO(jamescook): Replace this placeholder animation with a real one. |  | 
| 1190   // For now, let's go with a Cylon eye effect, but in blue. |  | 
| 1191   if (data().network_state != TabRendererData::NETWORK_STATE_NONE && |  | 
| 1192       data().network_state != TabRendererData::NETWORK_STATE_ERROR) { |  | 
| 1193     const SkColor kEyeColor = SkColorSetARGB(alpha, 71, 138, 217); |  | 
| 1194     int eye_width = bar_rect.width() / 3; |  | 
| 1195     int eye_offset = bar_rect.width() * immersive_loading_step_ / |  | 
| 1196         kImmersiveLoadingStepCount; |  | 
| 1197     if (eye_offset + eye_width < bar_rect.width()) { |  | 
| 1198       // Draw a single indicator strip because it fits inside |bar_rect|. |  | 
| 1199       gfx::Rect eye_rect( |  | 
| 1200           bar_rect.x() + eye_offset, 0, eye_width, kImmersiveBarHeight); |  | 
| 1201       canvas->FillRect(eye_rect, kEyeColor); |  | 
| 1202     } else { |  | 
| 1203       // Draw two indicators to simulate the eye "wrapping around" to the left |  | 
| 1204       // side. The first part fills the remainder of the bar. |  | 
| 1205       int right_eye_width = bar_rect.width() - eye_offset; |  | 
| 1206       gfx::Rect right_eye_rect( |  | 
| 1207           bar_rect.x() + eye_offset, 0, right_eye_width, kImmersiveBarHeight); |  | 
| 1208       canvas->FillRect(right_eye_rect, kEyeColor); |  | 
| 1209       // The second part parts the remaining |eye_width| on the left. |  | 
| 1210       int left_eye_width = eye_offset + eye_width - bar_rect.width(); |  | 
| 1211       gfx::Rect left_eye_rect( |  | 
| 1212           bar_rect.x(), 0, left_eye_width, kImmersiveBarHeight); |  | 
| 1213       canvas->FillRect(left_eye_rect, kEyeColor); |  | 
| 1214     } |  | 
| 1215   } |  | 
| 1216 } |  | 
| 1217 |  | 
| 1218 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas, | 1145 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas, | 
| 1219                                      const gfx::Path& clip) { | 1146                                      const gfx::Path& clip) { | 
| 1220   bool has_custom_image; | 1147   bool has_custom_image; | 
| 1221   int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); | 1148   int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); | 
| 1222   const ui::ThemeProvider* tp = GetThemeProvider(); | 1149   const ui::ThemeProvider* tp = GetThemeProvider(); | 
| 1223 | 1150 | 
| 1224   // We only cache the image when it's the default image and we're not hovered, | 1151   // We only cache the image when it's the default image and we're not hovered, | 
| 1225   // to avoid caching a background image that isn't the same for all tabs. | 1152   // to avoid caching a background image that isn't the same for all tabs. | 
| 1226   if (has_custom_image) { | 1153   if (has_custom_image) { | 
| 1227     // If the theme is providing a custom background image, then its top edge | 1154     // If the theme is providing a custom background image, then its top edge | 
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1422     PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, bounds); | 1349     PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, bounds); | 
| 1423   } else if (!favicon_.isNull()) { | 1350   } else if (!favicon_.isNull()) { | 
| 1424     canvas->DrawImageInt(favicon_, 0, 0, bounds.width(), bounds.height(), | 1351     canvas->DrawImageInt(favicon_, 0, 0, bounds.width(), bounds.height(), | 
| 1425                          bounds.x(), bounds.y(), bounds.width(), | 1352                          bounds.x(), bounds.y(), bounds.width(), | 
| 1426                          bounds.height(), false); | 1353                          bounds.height(), false); | 
| 1427   } | 1354   } | 
| 1428 } | 1355 } | 
| 1429 | 1356 | 
| 1430 void Tab::AdvanceLoadingAnimation() { | 1357 void Tab::AdvanceLoadingAnimation() { | 
| 1431   const TabRendererData::NetworkState state = data().network_state; | 1358   const TabRendererData::NetworkState state = data().network_state; | 
| 1432   if (controller_->IsImmersiveStyle()) { |  | 
| 1433     throbber_->SetVisible(false); |  | 
| 1434     if (state == TabRendererData::NETWORK_STATE_WAITING) { |  | 
| 1435       // Waiting steps backwards. |  | 
| 1436       immersive_loading_step_ = |  | 
| 1437           (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % |  | 
| 1438           kImmersiveLoadingStepCount; |  | 
| 1439     } else if (state == TabRendererData::NETWORK_STATE_LOADING) { |  | 
| 1440       immersive_loading_step_ = |  | 
| 1441           (immersive_loading_step_ + 1) % kImmersiveLoadingStepCount; |  | 
| 1442     } else { |  | 
| 1443       immersive_loading_step_ = 0; |  | 
| 1444     } |  | 
| 1445 |  | 
| 1446     SchedulePaintInRect(GetImmersiveBarRect()); |  | 
| 1447     return; |  | 
| 1448   } |  | 
| 1449 |  | 
| 1450   if (state == TabRendererData::NETWORK_STATE_NONE || | 1359   if (state == TabRendererData::NETWORK_STATE_NONE || | 
| 1451       state == TabRendererData::NETWORK_STATE_ERROR) { | 1360       state == TabRendererData::NETWORK_STATE_ERROR) { | 
| 1452     throbber_->ResetStartTimes(); | 1361     throbber_->ResetStartTimes(); | 
| 1453     throbber_->SetVisible(false); | 1362     throbber_->SetVisible(false); | 
| 1454     ScheduleIconPaint(); | 1363     ScheduleIconPaint(); | 
| 1455     return; | 1364     return; | 
| 1456   } | 1365   } | 
| 1457 | 1366 | 
| 1458   // Since the throbber can animate for a long time, paint to a separate layer | 1367   // Since the throbber can animate for a long time, paint to a separate layer | 
| 1459   // when possible to reduce repaint overhead. | 1368   // when possible to reduce repaint overhead. | 
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1577   gfx::Rect bounds = favicon_bounds_; | 1486   gfx::Rect bounds = favicon_bounds_; | 
| 1578   if (bounds.IsEmpty()) | 1487   if (bounds.IsEmpty()) | 
| 1579     return; | 1488     return; | 
| 1580 | 1489 | 
| 1581   // Extends the area to the bottom when the crash animation is in progress. | 1490   // Extends the area to the bottom when the crash animation is in progress. | 
| 1582   if (crash_icon_animation_->is_animating()) | 1491   if (crash_icon_animation_->is_animating()) | 
| 1583     bounds.set_height(height() - bounds.y()); | 1492     bounds.set_height(height() - bounds.y()); | 
| 1584   bounds.set_x(GetMirroredXForRect(bounds)); | 1493   bounds.set_x(GetMirroredXForRect(bounds)); | 
| 1585   SchedulePaintInRect(bounds); | 1494   SchedulePaintInRect(bounds); | 
| 1586 } | 1495 } | 
| 1587 |  | 
| 1588 gfx::Rect Tab::GetImmersiveBarRect() const { |  | 
| 1589   // The main bar is as wide as the normal tab's horizontal top line. |  | 
| 1590   gfx::Rect contents = GetContentsBounds(); |  | 
| 1591   contents.set_y(0); |  | 
| 1592   contents.set_height(kImmersiveBarHeight); |  | 
| 1593   return contents; |  | 
| 1594 } |  | 
| OLD | NEW | 
|---|