| 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 19 matching lines...) Expand all Loading... |
| 30 #include "grit/theme_resources.h" | 30 #include "grit/theme_resources.h" |
| 31 #include "third_party/skia/include/effects/SkGradientShader.h" | 31 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 32 #include "third_party/skia/include/pathops/SkPathOps.h" | 32 #include "third_party/skia/include/pathops/SkPathOps.h" |
| 33 #include "ui/accessibility/ax_view_state.h" | 33 #include "ui/accessibility/ax_view_state.h" |
| 34 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
| 35 #include "ui/base/material_design/material_design_controller.h" | 35 #include "ui/base/material_design/material_design_controller.h" |
| 36 #include "ui/base/models/list_selection_model.h" | 36 #include "ui/base/models/list_selection_model.h" |
| 37 #include "ui/base/resource/resource_bundle.h" | 37 #include "ui/base/resource/resource_bundle.h" |
| 38 #include "ui/base/theme_provider.h" | 38 #include "ui/base/theme_provider.h" |
| 39 #include "ui/gfx/animation/animation_container.h" | 39 #include "ui/gfx/animation/animation_container.h" |
| 40 #include "ui/gfx/animation/multi_animation.h" | |
| 41 #include "ui/gfx/animation/throb_animation.h" | 40 #include "ui/gfx/animation/throb_animation.h" |
| 42 #include "ui/gfx/canvas.h" | 41 #include "ui/gfx/canvas.h" |
| 43 #include "ui/gfx/color_analysis.h" | 42 #include "ui/gfx/color_analysis.h" |
| 44 #include "ui/gfx/favicon_size.h" | 43 #include "ui/gfx/favicon_size.h" |
| 45 #include "ui/gfx/geometry/rect_conversions.h" | 44 #include "ui/gfx/geometry/rect_conversions.h" |
| 46 #include "ui/gfx/image/image_skia_operations.h" | 45 #include "ui/gfx/image/image_skia_operations.h" |
| 47 #include "ui/gfx/paint_vector_icon.h" | 46 #include "ui/gfx/paint_vector_icon.h" |
| 48 #include "ui/gfx/path.h" | 47 #include "ui/gfx/path.h" |
| 49 #include "ui/gfx/scoped_canvas.h" | 48 #include "ui/gfx/scoped_canvas.h" |
| 50 #include "ui/gfx/skia_util.h" | 49 #include "ui/gfx/skia_util.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 | 81 |
| 83 // How opaque to make the hover state (out of 1). | 82 // How opaque to make the hover state (out of 1). |
| 84 const double kHoverOpacity = 0.33; | 83 const double kHoverOpacity = 0.33; |
| 85 | 84 |
| 86 // Opacity of the active tab background painted over inactive selected tabs. | 85 // Opacity of the active tab background painted over inactive selected tabs. |
| 87 const double kSelectedTabOpacity = 0.3; | 86 const double kSelectedTabOpacity = 0.3; |
| 88 | 87 |
| 89 // Inactive selected tabs have their throb value scaled by this. | 88 // Inactive selected tabs have their throb value scaled by this. |
| 90 const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; | 89 const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; |
| 91 | 90 |
| 92 // Offset from the right edge for the start of the pinned title change | |
| 93 // animation. | |
| 94 const int kPinnedTitleChangeInitialXOffset = 6; | |
| 95 | |
| 96 // Max number of images to cache. This has to be at least two since rounding | 91 // 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. | 92 // errors may lead to tabs in the same tabstrip having different sizes. |
| 98 // 8 = normal/incognito, active/inactive, 2 sizes within tabstrip. | 93 // 8 = normal/incognito, active/inactive, 2 sizes within tabstrip. |
| 99 const size_t kMaxImageCacheSize = 8; | 94 const size_t kMaxImageCacheSize = 8; |
| 100 | 95 |
| 101 // Height of the miniature tab strip in immersive mode. | 96 // Height of the miniature tab strip in immersive mode. |
| 102 const int kImmersiveTabHeight = 3; | 97 const int kImmersiveTabHeight = 3; |
| 103 | 98 |
| 104 // Height of the small tab indicator rectangles in immersive mode. | 99 // Height of the small tab indicator rectangles in immersive mode. |
| 105 const int kImmersiveBarHeight = 2; | 100 const int kImmersiveBarHeight = 2; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 127 float GetUnscaledEndcapWidth() { | 122 float GetUnscaledEndcapWidth() { |
| 128 return GetLayoutInsets(TAB).left() - 0.5f; | 123 return GetLayoutInsets(TAB).left() - 0.5f; |
| 129 } | 124 } |
| 130 | 125 |
| 131 void DrawHighlight(gfx::Canvas* canvas, | 126 void DrawHighlight(gfx::Canvas* canvas, |
| 132 const SkPoint& p, | 127 const SkPoint& p, |
| 133 SkScalar radius, | 128 SkScalar radius, |
| 134 SkColor color) { | 129 SkColor color) { |
| 135 const SkColor colors[2] = { color, SkColorSetA(color, 0) }; | 130 const SkColor colors[2] = { color, SkColorSetA(color, 0) }; |
| 136 SkPaint paint; | 131 SkPaint paint; |
| 137 paint.setStyle(SkPaint::kFill_Style); | |
| 138 paint.setAntiAlias(true); | 132 paint.setAntiAlias(true); |
| 139 paint.setShader(SkGradientShader::MakeRadial(p, radius, colors, nullptr, 2, | 133 paint.setShader(SkGradientShader::MakeRadial(p, radius, colors, nullptr, 2, |
| 140 SkShader::kClamp_TileMode)); | 134 SkShader::kClamp_TileMode)); |
| 141 canvas->sk_canvas()->drawRect( | 135 canvas->sk_canvas()->drawRect( |
| 142 SkRect::MakeXYWH(p.x() - radius, p.y() - radius, radius * 2, radius * 2), | 136 SkRect::MakeXYWH(p.x() - radius, p.y() - radius, radius * 2, radius * 2), |
| 143 paint); | 137 paint); |
| 144 } | 138 } |
| 145 | 139 |
| 146 } // namespace | 140 } // namespace |
| 147 | 141 |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 // to help avoid mis-clicks. | 553 // to help avoid mis-clicks. |
| 560 close_button_->SetAnimationDuration(0); | 554 close_button_->SetAnimationDuration(0); |
| 561 AddChildView(close_button_); | 555 AddChildView(close_button_); |
| 562 | 556 |
| 563 set_context_menu_controller(this); | 557 set_context_menu_controller(this); |
| 564 | 558 |
| 565 const int kPulseDurationMs = 200; | 559 const int kPulseDurationMs = 200; |
| 566 pulse_animation_->SetSlideDuration(kPulseDurationMs); | 560 pulse_animation_->SetSlideDuration(kPulseDurationMs); |
| 567 pulse_animation_->SetContainer(animation_container_.get()); | 561 pulse_animation_->SetContainer(animation_container_.get()); |
| 568 | 562 |
| 569 const int kPinnedTitleChangeAnimationDuration1MS = 1600; | |
| 570 const int kPinnedTitleChangeAnimationStart1MS = 0; | |
| 571 const int kPinnedTitleChangeAnimationEnd1MS = 1900; | |
| 572 const int kPinnedTitleChangeAnimationDuration2MS = 0; | |
| 573 const int kPinnedTitleChangeAnimationDuration3MS = 550; | |
| 574 const int kPinnedTitleChangeAnimationStart3MS = 150; | |
| 575 const int kPinnedTitleChangeAnimationEnd3MS = 800; | |
| 576 const int kPinnedTitleChangeAnimationIntervalMS = 40; | |
| 577 gfx::MultiAnimation::Parts parts; | |
| 578 parts.push_back(gfx::MultiAnimation::Part( | |
| 579 kPinnedTitleChangeAnimationDuration1MS, | |
| 580 kPinnedTitleChangeAnimationStart1MS, | |
| 581 kPinnedTitleChangeAnimationEnd1MS, | |
| 582 gfx::Tween::EASE_OUT)); | |
| 583 parts.push_back(gfx::MultiAnimation::Part( | |
| 584 kPinnedTitleChangeAnimationDuration2MS, | |
| 585 gfx::Tween::ZERO)); | |
| 586 parts.push_back(gfx::MultiAnimation::Part( | |
| 587 kPinnedTitleChangeAnimationDuration3MS, | |
| 588 kPinnedTitleChangeAnimationStart3MS, | |
| 589 kPinnedTitleChangeAnimationEnd3MS, | |
| 590 gfx::Tween::EASE_IN)); | |
| 591 const base::TimeDelta timeout = | |
| 592 base::TimeDelta::FromMilliseconds(kPinnedTitleChangeAnimationIntervalMS); | |
| 593 pinned_title_change_animation_.reset(new gfx::MultiAnimation(parts, timeout)); | |
| 594 pinned_title_change_animation_->SetContainer(animation_container_.get()); | |
| 595 pinned_title_change_animation_->set_delegate(this); | |
| 596 | |
| 597 hover_controller_.SetAnimationContainer(animation_container_.get()); | 563 hover_controller_.SetAnimationContainer(animation_container_.get()); |
| 598 } | 564 } |
| 599 | 565 |
| 600 Tab::~Tab() { | 566 Tab::~Tab() { |
| 601 } | 567 } |
| 602 | 568 |
| 603 bool Tab::IsActive() const { | 569 bool Tab::IsActive() const { |
| 604 return controller_->IsActiveTab(this); | 570 return controller_->IsActiveTab(this); |
| 605 } | 571 } |
| 606 | 572 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 } else if (!should_display_crashed_favicon_ && | 611 } else if (!should_display_crashed_favicon_ && |
| 646 !crash_icon_animation_->is_animating()) { | 612 !crash_icon_animation_->is_animating()) { |
| 647 data_.alert_state = TabAlertState::NONE; | 613 data_.alert_state = TabAlertState::NONE; |
| 648 crash_icon_animation_->Start(); | 614 crash_icon_animation_->Start(); |
| 649 } | 615 } |
| 650 | 616 |
| 651 if (data_.alert_state != old.alert_state) | 617 if (data_.alert_state != old.alert_state) |
| 652 alert_indicator_button_->TransitionToAlertState(data_.alert_state); | 618 alert_indicator_button_->TransitionToAlertState(data_.alert_state); |
| 653 | 619 |
| 654 if (old.pinned != data_.pinned) | 620 if (old.pinned != data_.pinned) |
| 655 StopPinnedTabTitleAnimation(); | 621 showing_pinned_tab_title_changed_indicator_ = false; |
| 656 | 622 |
| 657 DataChanged(old); | 623 DataChanged(old); |
| 658 | 624 |
| 659 Layout(); | 625 Layout(); |
| 660 SchedulePaint(); | 626 SchedulePaint(); |
| 661 } | 627 } |
| 662 | 628 |
| 663 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { | 629 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { |
| 664 if (state == data_.network_state && | 630 if (state == data_.network_state && |
| 665 state == TabRendererData::NETWORK_STATE_NONE) { | 631 state == TabRendererData::NETWORK_STATE_NONE) { |
| 666 // If the network state is none and hasn't changed, do nothing. Otherwise we | 632 // If the network state is none and hasn't changed, do nothing. Otherwise we |
| 667 // need to advance the animation frame. | 633 // need to advance the animation frame. |
| 668 return; | 634 return; |
| 669 } | 635 } |
| 670 | 636 |
| 671 data_.network_state = state; | 637 data_.network_state = state; |
| 672 AdvanceLoadingAnimation(); | 638 AdvanceLoadingAnimation(); |
| 673 } | 639 } |
| 674 | 640 |
| 675 void Tab::StartPulse() { | 641 void Tab::StartPulse() { |
| 676 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); | 642 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); |
| 677 } | 643 } |
| 678 | 644 |
| 679 void Tab::StopPulse() { | 645 void Tab::StopPulse() { |
| 680 pulse_animation_->Stop(); | 646 pulse_animation_->Stop(); |
| 681 } | 647 } |
| 682 | 648 |
| 683 void Tab::StartPinnedTabTitleAnimation() { | 649 void Tab::SetPinnedTabTitleChangedIndicatorVisible(bool value) { |
| 684 if (data().pinned) | 650 if (value == showing_pinned_tab_title_changed_indicator_) |
| 685 pinned_title_change_animation_->Start(); | 651 return; |
| 686 } | |
| 687 | 652 |
| 688 void Tab::StopPinnedTabTitleAnimation() { | 653 DCHECK(!value || data().pinned); |
| 689 pinned_title_change_animation_->Stop(); | 654 |
| 655 showing_pinned_tab_title_changed_indicator_ = value; |
| 656 SchedulePaint(); |
| 690 } | 657 } |
| 691 | 658 |
| 692 int Tab::GetWidthOfLargestSelectableRegion() const { | 659 int Tab::GetWidthOfLargestSelectableRegion() const { |
| 693 // Assume the entire region to the left of the alert indicator and/or close | 660 // Assume the entire region to the left of the alert indicator and/or close |
| 694 // buttons is available for click-to-select. If neither are visible, the | 661 // buttons is available for click-to-select. If neither are visible, the |
| 695 // entire tab region is available. | 662 // entire tab region is available. |
| 696 const int indicator_left = | 663 const int indicator_left = |
| 697 showing_alert_indicator_ ? alert_indicator_button_->x() : width(); | 664 showing_alert_indicator_ ? alert_indicator_button_->x() : width(); |
| 698 const int close_button_left = showing_close_button_ ? | 665 const int close_button_left = showing_close_button_ ? |
| 699 close_button_->x() : width(); | 666 close_button_->x() : width(); |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 | 1225 |
| 1259 void Tab::PaintTabBackground(gfx::Canvas* canvas) { | 1226 void Tab::PaintTabBackground(gfx::Canvas* canvas) { |
| 1260 const int kActiveTabFillId = IDR_THEME_TOOLBAR; | 1227 const int kActiveTabFillId = IDR_THEME_TOOLBAR; |
| 1261 const bool has_custom_image = | 1228 const bool has_custom_image = |
| 1262 GetThemeProvider()->HasCustomImage(kActiveTabFillId); | 1229 GetThemeProvider()->HasCustomImage(kActiveTabFillId); |
| 1263 const int y_offset = -GetYInsetForActiveTabBackground(); | 1230 const int y_offset = -GetYInsetForActiveTabBackground(); |
| 1264 if (IsActive()) { | 1231 if (IsActive()) { |
| 1265 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, | 1232 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
| 1266 has_custom_image, y_offset); | 1233 has_custom_image, y_offset); |
| 1267 } else { | 1234 } else { |
| 1268 if (pinned_title_change_animation_->is_animating()) | 1235 PaintInactiveTabBackground(canvas); |
| 1269 PaintInactiveTabBackgroundWithTitleChange(canvas); | |
| 1270 else | |
| 1271 PaintInactiveTabBackground(canvas); | |
| 1272 | 1236 |
| 1273 const double throb_value = GetThrobValue(); | 1237 const double throb_value = GetThrobValue(); |
| 1274 if (throb_value > 0) { | 1238 if (throb_value > 0) { |
| 1275 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), | 1239 canvas->SaveLayerAlpha(gfx::ToRoundedInt(throb_value * 0xff), |
| 1276 GetLocalBounds()); | 1240 GetLocalBounds()); |
| 1277 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, | 1241 PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
| 1278 has_custom_image, y_offset); | 1242 has_custom_image, y_offset); |
| 1279 canvas->Restore(); | 1243 canvas->Restore(); |
| 1280 } | 1244 } |
| 1281 } | 1245 } |
| 1282 } | 1246 } |
| 1283 | 1247 |
| 1284 void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { | |
| 1285 const int kPinnedTitleChangeGradientRadius = 20; | |
| 1286 const float radius = kPinnedTitleChangeGradientRadius; | |
| 1287 double x = radius; | |
| 1288 SkColor hover_color = | |
| 1289 GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR); | |
| 1290 if (pinned_title_change_animation_->current_part_index() == 0) { | |
| 1291 x = pinned_title_change_animation_->CurrentValueBetween( | |
| 1292 width() + radius - kPinnedTitleChangeInitialXOffset, radius); | |
| 1293 } else if (pinned_title_change_animation_->current_part_index() == 2) { | |
| 1294 x = pinned_title_change_animation_->CurrentValueBetween(radius, -radius); | |
| 1295 const int alpha = | |
| 1296 pinned_title_change_animation_->CurrentValueBetween(255, 0); | |
| 1297 hover_color = SkColorSetA(hover_color, static_cast<SkAlpha>(alpha)); | |
| 1298 } | |
| 1299 SkPoint p; | |
| 1300 p.set(SkDoubleToScalar(x), 0); | |
| 1301 if (ui::MaterialDesignController::IsModeMaterial()) { | |
| 1302 PaintInactiveTabBackground(canvas); | |
| 1303 gfx::ScopedCanvas scoped_canvas(canvas); | |
| 1304 const float scale = canvas->UndoDeviceScaleFactor(); | |
| 1305 SkPath fill; | |
| 1306 GetFillPath(scale, &fill); | |
| 1307 canvas->ClipPath(fill, true); | |
| 1308 p.scale(SkFloatToScalar(scale)); | |
| 1309 DrawHighlight(canvas, p, SkFloatToScalar(radius * scale), hover_color); | |
| 1310 } else { | |
| 1311 gfx::Canvas background_canvas(size(), canvas->image_scale(), false); | |
| 1312 PaintInactiveTabBackground(&background_canvas); | |
| 1313 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | |
| 1314 canvas->DrawImageInt(background_image, 0, 0); | |
| 1315 gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); | |
| 1316 DrawHighlight(&hover_canvas, p, SkFloatToScalar(radius), hover_color); | |
| 1317 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( | |
| 1318 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | |
| 1319 canvas->DrawImageInt(hover_image, 0, 0); | |
| 1320 } | |
| 1321 } | |
| 1322 | |
| 1323 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { | 1248 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
| 1324 bool has_custom_image; | 1249 bool has_custom_image; |
| 1325 int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); | 1250 int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); |
| 1326 | 1251 |
| 1327 // If the theme is providing a custom background image, then its top edge | 1252 // If the theme is providing a custom background image, then its top edge |
| 1328 // should be at the top of the tab. Otherwise, we assume that the background | 1253 // should be at the top of the tab. Otherwise, we assume that the background |
| 1329 // image is a composited foreground + frame image. Note that if the theme is | 1254 // image is a composited foreground + frame image. Note that if the theme is |
| 1330 // only providing a custom frame image, |has_custom_image| will be true, but | 1255 // only providing a custom frame image, |has_custom_image| will be true, but |
| 1331 // we should use the |background_offset_| here. | 1256 // we should use the |background_offset_| here. |
| 1332 const ui::ThemeProvider* tp = GetThemeProvider(); | 1257 const ui::ThemeProvider* tp = GetThemeProvider(); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 | 1410 |
| 1486 // Draw center. Instead of masking out the top portion we simply skip over it | 1411 // Draw center. Instead of masking out the top portion we simply skip over it |
| 1487 // by incrementing by the top padding, since it's a simple rectangle. | 1412 // by incrementing by the top padding, since it's a simple rectangle. |
| 1488 canvas->TileImageInt(*fill_image, x_offset + mask_images_.l_width, | 1413 canvas->TileImageInt(*fill_image, x_offset + mask_images_.l_width, |
| 1489 y_offset + tab_insets.top(), mask_images_.l_width, | 1414 y_offset + tab_insets.top(), mask_images_.l_width, |
| 1490 tab_insets.top(), | 1415 tab_insets.top(), |
| 1491 width() - mask_images_.l_width - mask_images_.r_width, | 1416 width() - mask_images_.l_width - mask_images_.r_width, |
| 1492 height() - tab_insets.top() - toolbar_overlap); | 1417 height() - tab_insets.top() - toolbar_overlap); |
| 1493 } | 1418 } |
| 1494 | 1419 |
| 1420 void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
| 1421 gfx::Canvas* canvas, |
| 1422 const gfx::ImageSkia& favicon, |
| 1423 const gfx::Rect& favicon_draw_bounds) { |
| 1424 // The pinned tab title changed indicator consists of two parts: |
| 1425 // . a clear (totally transparent) part over the bottom right (or left in rtl) |
| 1426 // of the favicon. This is done by drawing the favicon to a canvas, then |
| 1427 // drawing the clear part on top of the favicon. |
| 1428 // . a circle in the bottom right (or left in rtl) of the favicon. |
| 1429 if (!favicon.isNull()) { |
| 1430 const float kIndicatorCropRadius = 4.5; |
| 1431 gfx::Canvas icon_canvas(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize), |
| 1432 canvas->image_scale(), false); |
| 1433 icon_canvas.DrawImageInt(favicon, 0, 0); |
| 1434 SkPaint clear_paint; |
| 1435 clear_paint.setAntiAlias(true); |
| 1436 clear_paint.setXfermodeMode(SkXfermode::kClear_Mode); |
| 1437 const int circle_x = base::i18n::IsRTL() ? 0 : gfx::kFaviconSize; |
| 1438 icon_canvas.DrawCircle(gfx::PointF(circle_x, gfx::kFaviconSize), |
| 1439 kIndicatorCropRadius, clear_paint); |
| 1440 canvas->DrawImageInt(gfx::ImageSkia(icon_canvas.ExtractImageRep()), 0, 0, |
| 1441 favicon_draw_bounds.width(), |
| 1442 favicon_draw_bounds.height(), favicon_draw_bounds.x(), |
| 1443 favicon_draw_bounds.y(), favicon_draw_bounds.width(), |
| 1444 favicon_draw_bounds.height(), false); |
| 1445 } |
| 1446 |
| 1447 // Draws the actual pinned tab title changed indicator. |
| 1448 const int kIndicatorRadius = 3; |
| 1449 SkPaint indicator_paint; |
| 1450 indicator_paint.setColor(GetNativeTheme()->GetSystemColor( |
| 1451 ui::NativeTheme::kColorId_CallToActionColor)); |
| 1452 indicator_paint.setAntiAlias(true); |
| 1453 const int indicator_x = GetMirroredXWithWidthInView( |
| 1454 favicon_bounds_.right() - kIndicatorRadius, kIndicatorRadius * 2); |
| 1455 const int indicator_y = favicon_bounds_.bottom() - kIndicatorRadius; |
| 1456 canvas->DrawCircle(gfx::Point(indicator_x + kIndicatorRadius, |
| 1457 indicator_y + kIndicatorRadius), |
| 1458 kIndicatorRadius, indicator_paint); |
| 1459 } |
| 1460 |
| 1495 void Tab::PaintIcon(gfx::Canvas* canvas) { | 1461 void Tab::PaintIcon(gfx::Canvas* canvas) { |
| 1496 gfx::Rect bounds = favicon_bounds_; | 1462 gfx::Rect bounds = favicon_bounds_; |
| 1497 bounds.set_x(GetMirroredXForRect(bounds)); | 1463 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1498 bounds.Offset(0, favicon_hiding_offset_); | 1464 bounds.Offset(0, favicon_hiding_offset_); |
| 1499 bounds.Intersect(GetContentsBounds()); | 1465 bounds.Intersect(GetContentsBounds()); |
| 1500 if (bounds.IsEmpty()) | 1466 if (bounds.IsEmpty()) |
| 1501 return; | 1467 return; |
| 1502 | 1468 |
| 1503 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { | 1469 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { |
| 1504 // Throbber will do its own painting. | 1470 // Throbber will do its own painting. |
| 1505 } else { | 1471 return; |
| 1506 const gfx::ImageSkia& favicon = should_display_crashed_favicon_ ? | 1472 } |
| 1507 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | 1473 const gfx::ImageSkia& favicon = |
| 1508 IDR_CRASH_SAD_FAVICON) : | 1474 should_display_crashed_favicon_ |
| 1509 data().favicon; | 1475 ? *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| 1510 if (!favicon.isNull()) { | 1476 IDR_CRASH_SAD_FAVICON) |
| 1511 canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(), | 1477 : data().favicon; |
| 1512 bounds.x(), bounds.y(), bounds.width(), | 1478 |
| 1513 bounds.height(), false); | 1479 if (showing_pinned_tab_title_changed_indicator_ && |
| 1514 } | 1480 !should_display_crashed_favicon_) { |
| 1481 PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, favicon, bounds); |
| 1482 } else if (!favicon.isNull()) { |
| 1483 canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(), |
| 1484 bounds.x(), bounds.y(), bounds.width(), |
| 1485 bounds.height(), false); |
| 1515 } | 1486 } |
| 1516 } | 1487 } |
| 1517 | 1488 |
| 1518 void Tab::AdvanceLoadingAnimation() { | 1489 void Tab::AdvanceLoadingAnimation() { |
| 1519 const TabRendererData::NetworkState state = data().network_state; | 1490 const TabRendererData::NetworkState state = data().network_state; |
| 1520 if (controller_->IsImmersiveStyle()) { | 1491 if (controller_->IsImmersiveStyle()) { |
| 1521 throbber_->SetVisible(false); | 1492 throbber_->SetVisible(false); |
| 1522 if (state == TabRendererData::NETWORK_STATE_WAITING) { | 1493 if (state == TabRendererData::NETWORK_STATE_WAITING) { |
| 1523 // Waiting steps backwards. | 1494 // Waiting steps backwards. |
| 1524 immersive_loading_step_ = | 1495 immersive_loading_step_ = |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1609 return !data().pinned || | 1580 return !data().pinned || |
| 1610 (width() >= (GetPinnedWidth() + kPinnedTabExtraWidthToRenderAsNormal)); | 1581 (width() >= (GetPinnedWidth() + kPinnedTabExtraWidthToRenderAsNormal)); |
| 1611 } | 1582 } |
| 1612 | 1583 |
| 1613 double Tab::GetThrobValue() { | 1584 double Tab::GetThrobValue() { |
| 1614 const bool is_selected = IsSelected(); | 1585 const bool is_selected = IsSelected(); |
| 1615 double val = is_selected ? kSelectedTabOpacity : 0; | 1586 double val = is_selected ? kSelectedTabOpacity : 0; |
| 1616 const double offset = | 1587 const double offset = |
| 1617 is_selected ? (kSelectedTabThrobScale * kHoverOpacity) : kHoverOpacity; | 1588 is_selected ? (kSelectedTabThrobScale * kHoverOpacity) : kHoverOpacity; |
| 1618 | 1589 |
| 1619 // Showing both the pulse and title change animation at the same time is too | 1590 if (pulse_animation_->is_animating()) |
| 1620 // much. | |
| 1621 if (pulse_animation_->is_animating() && | |
| 1622 !pinned_title_change_animation_->is_animating()) { | |
| 1623 val += pulse_animation_->GetCurrentValue() * offset; | 1591 val += pulse_animation_->GetCurrentValue() * offset; |
| 1624 } else if (hover_controller_.ShouldDraw()) { | 1592 else if (hover_controller_.ShouldDraw()) |
| 1625 val += hover_controller_.GetAnimationValue() * offset; | 1593 val += hover_controller_.GetAnimationValue() * offset; |
| 1626 } | |
| 1627 return val; | 1594 return val; |
| 1628 } | 1595 } |
| 1629 | 1596 |
| 1630 void Tab::SetFaviconHidingOffset(int offset) { | 1597 void Tab::SetFaviconHidingOffset(int offset) { |
| 1631 favicon_hiding_offset_ = offset; | 1598 favicon_hiding_offset_ = offset; |
| 1632 ScheduleIconPaint(); | 1599 ScheduleIconPaint(); |
| 1633 } | 1600 } |
| 1634 | 1601 |
| 1635 void Tab::OnButtonColorMaybeChanged() { | 1602 void Tab::OnButtonColorMaybeChanged() { |
| 1636 // The theme provider may be null if we're not currently in a widget | 1603 // The theme provider may be null if we're not currently in a widget |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); | 1741 inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); |
| 1775 inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); | 1742 inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); |
| 1776 inactive_images_.l_width = inactive_images_.image_l->width(); | 1743 inactive_images_.l_width = inactive_images_.image_l->width(); |
| 1777 inactive_images_.r_width = inactive_images_.image_r->width(); | 1744 inactive_images_.r_width = inactive_images_.image_r->width(); |
| 1778 | 1745 |
| 1779 mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); | 1746 mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); |
| 1780 mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); | 1747 mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); |
| 1781 mask_images_.l_width = mask_images_.image_l->width(); | 1748 mask_images_.l_width = mask_images_.image_l->width(); |
| 1782 mask_images_.r_width = mask_images_.image_r->width(); | 1749 mask_images_.r_width = mask_images_.image_r->width(); |
| 1783 } | 1750 } |
| OLD | NEW |