| 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 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 //////////////////////////////////////////////////////////////////////////////// | 410 //////////////////////////////////////////////////////////////////////////////// |
| 411 // Tab, public: | 411 // Tab, public: |
| 412 | 412 |
| 413 Tab::Tab(TabController* controller) | 413 Tab::Tab(TabController* controller) |
| 414 : controller_(controller), | 414 : controller_(controller), |
| 415 closing_(false), | 415 closing_(false), |
| 416 dragging_(false), | 416 dragging_(false), |
| 417 favicon_hiding_offset_(0), | 417 favicon_hiding_offset_(0), |
| 418 loading_animation_frame_(0), | 418 loading_animation_frame_(0), |
| 419 should_display_crashed_favicon_(false), | 419 should_display_crashed_favicon_(false), |
| 420 throbber_disabled_(false), | |
| 421 theme_provider_(NULL), | 420 theme_provider_(NULL), |
| 422 ALLOW_THIS_IN_INITIALIZER_LIST(hover_controller_(this)), | 421 ALLOW_THIS_IN_INITIALIZER_LIST(hover_controller_(this)), |
| 423 showing_icon_(false), | 422 showing_icon_(false), |
| 424 showing_close_button_(false), | 423 showing_close_button_(false), |
| 425 close_button_color_(0), | 424 close_button_color_(0), |
| 426 icon_dominant_color_(SK_ColorWHITE) { | 425 icon_dominant_color_(SK_ColorWHITE) { |
| 427 InitTabResources(); | 426 InitTabResources(); |
| 428 | 427 |
| 429 // So we get don't get enter/exit on children and don't prematurely stop the | 428 // So we get don't get enter/exit on children and don't prematurely stop the |
| 430 // hover. | 429 // hover. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 #endif | 488 #endif |
| 490 } | 489 } |
| 491 | 490 |
| 492 } else if ((data_.capture_state == TabRendererData::CAPTURE_STATE_NONE) && | 491 } else if ((data_.capture_state == TabRendererData::CAPTURE_STATE_NONE) && |
| 493 (old.capture_state != TabRendererData::CAPTURE_STATE_NONE)) { | 492 (old.capture_state != TabRendererData::CAPTURE_STATE_NONE)) { |
| 494 StopRecordingAnimation(); | 493 StopRecordingAnimation(); |
| 495 | 494 |
| 496 } else if ((data_.capture_state != TabRendererData::CAPTURE_STATE_NONE) && | 495 } else if ((data_.capture_state != TabRendererData::CAPTURE_STATE_NONE) && |
| 497 (old.capture_state == TabRendererData::CAPTURE_STATE_NONE)) { | 496 (old.capture_state == TabRendererData::CAPTURE_STATE_NONE)) { |
| 498 StartRecordingAnimation(); | 497 StartRecordingAnimation(); |
| 498 |
| 499 } else { | 499 } else { |
| 500 if (IsPerformingCrashAnimation()) | 500 if (IsPerformingCrashAnimation()) |
| 501 StopCrashAnimation(); | 501 StopCrashAnimation(); |
| 502 ResetCrashedFavicon(); | 502 ResetCrashedFavicon(); |
| 503 } | 503 } |
| 504 | 504 |
| 505 if (old.mini != data_.mini) { |
| 506 if (tab_animation_.get() && tab_animation_->is_animating()) { |
| 507 tab_animation_->Stop(); |
| 508 tab_animation_.reset(NULL); |
| 509 } |
| 510 } |
| 511 |
| 505 // If the favicon changed, re-compute its dominant color. | 512 // If the favicon changed, re-compute its dominant color. |
| 506 if (controller() && | 513 if (controller() && |
| 507 controller()->IsImmersiveStyle() && | 514 controller()->IsImmersiveStyle() && |
| 508 !data_.favicon.isNull() && | 515 !data_.favicon.isNull() && |
| 509 !data_.favicon.BackedBySameObjectAs(old.favicon)) | 516 !data_.favicon.BackedBySameObjectAs(old.favicon)) |
| 510 UpdateIconDominantColor(); | 517 UpdateIconDominantColor(); |
| 511 | 518 |
| 512 DataChanged(old); | 519 DataChanged(old); |
| 513 | 520 |
| 514 Layout(); | 521 Layout(); |
| 515 SchedulePaint(); | 522 SchedulePaint(); |
| 516 } | 523 } |
| 517 | 524 |
| 518 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { | 525 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { |
| 519 // If this is an extension app and a command line flag is set, | |
| 520 // then disable the throbber. | |
| 521 throbber_disabled_ = data().app && | |
| 522 CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppsNoThrob); | |
| 523 | |
| 524 if (throbber_disabled_) | |
| 525 return; | |
| 526 | |
| 527 if (state == data_.network_state && | 526 if (state == data_.network_state && |
| 528 state == TabRendererData::NETWORK_STATE_NONE) { | 527 state == TabRendererData::NETWORK_STATE_NONE) { |
| 529 // If the network state is none and hasn't changed, do nothing. Otherwise we | 528 // If the network state is none and hasn't changed, do nothing. Otherwise we |
| 530 // need to advance the animation frame. | 529 // need to advance the animation frame. |
| 531 return; | 530 return; |
| 532 } | 531 } |
| 533 | 532 |
| 534 TabRendererData::NetworkState old_state = data_.network_state; | 533 TabRendererData::NetworkState old_state = data_.network_state; |
| 535 data_.network_state = state; | 534 data_.network_state = state; |
| 536 AdvanceLoadingAnimation(old_state, state); | 535 AdvanceLoadingAnimation(old_state, state); |
| 537 } | 536 } |
| 538 | 537 |
| 539 void Tab::StartPulse() { | 538 void Tab::StartPulse() { |
| 540 if (!tab_animation_.get()) { | 539 ui::ThrobAnimation* animation = new ui::ThrobAnimation(this); |
| 541 tab_animation_.reset(new ui::ThrobAnimation(this)); | 540 animation->SetSlideDuration(kPulseDurationMs); |
| 542 tab_animation_->SetSlideDuration(kPulseDurationMs); | 541 if (animation_container_.get()) |
| 543 if (animation_container_.get()) | 542 animation->SetContainer(animation_container_.get()); |
| 544 tab_animation_->SetContainer(animation_container_.get()); | 543 animation->StartThrobbing(std::numeric_limits<int>::max()); |
| 545 } | 544 tab_animation_.reset(animation); |
| 546 tab_animation_->Reset(); | |
| 547 tab_animation_->StartThrobbing(std::numeric_limits<int>::max()); | |
| 548 } | 545 } |
| 549 | 546 |
| 550 void Tab::StopPulse() { | 547 void Tab::StopPulse() { |
| 551 if (!tab_animation_.get()) | 548 if (!tab_animation_.get()) |
| 552 return; | 549 return; |
| 553 | 550 tab_animation_->Stop(); |
| 554 tab_animation_->Stop(); // Do stop so we get notified. | |
| 555 tab_animation_.reset(NULL); | 551 tab_animation_.reset(NULL); |
| 556 } | 552 } |
| 557 | 553 |
| 558 void Tab::StartMiniTabTitleAnimation() { | 554 void Tab::StartMiniTabTitleAnimation() { |
| 559 if (!mini_title_animation_.get()) { | 555 // We can only do this animation if the tab is mini because we will |
| 556 // upcast tab_animation back to MultiAnimation when we draw. |
| 557 if (!data().mini) |
| 558 return; |
| 559 if (!tab_animation_.get()) { |
| 560 ui::MultiAnimation::Parts parts; | 560 ui::MultiAnimation::Parts parts; |
| 561 parts.push_back( | 561 parts.push_back( |
| 562 ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS, | 562 ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS, |
| 563 ui::Tween::EASE_OUT)); | 563 ui::Tween::EASE_OUT)); |
| 564 parts.push_back( | 564 parts.push_back( |
| 565 ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS, | 565 ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS, |
| 566 ui::Tween::ZERO)); | 566 ui::Tween::ZERO)); |
| 567 parts.push_back( | 567 parts.push_back( |
| 568 ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS, | 568 ui::MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS, |
| 569 ui::Tween::EASE_IN)); | 569 ui::Tween::EASE_IN)); |
| 570 parts[0].start_time_ms = kMiniTitleChangeAnimationStart1MS; | 570 parts[0].start_time_ms = kMiniTitleChangeAnimationStart1MS; |
| 571 parts[0].end_time_ms = kMiniTitleChangeAnimationEnd1MS; | 571 parts[0].end_time_ms = kMiniTitleChangeAnimationEnd1MS; |
| 572 parts[2].start_time_ms = kMiniTitleChangeAnimationStart3MS; | 572 parts[2].start_time_ms = kMiniTitleChangeAnimationStart3MS; |
| 573 parts[2].end_time_ms = kMiniTitleChangeAnimationEnd3MS; | 573 parts[2].end_time_ms = kMiniTitleChangeAnimationEnd3MS; |
| 574 mini_title_animation_.reset(new ui::MultiAnimation( | 574 base::TimeDelta timeout = |
| 575 parts, | 575 base::TimeDelta::FromMilliseconds(kMiniTitleChangeAnimationIntervalMS); |
| 576 base::TimeDelta::FromMilliseconds( | 576 ui::MultiAnimation* animation = new ui::MultiAnimation(parts, timeout); |
| 577 kMiniTitleChangeAnimationIntervalMS))); | 577 if (animation_container_.get()) |
| 578 mini_title_animation_->SetContainer(animation_container()); | 578 animation->SetContainer(animation_container_.get()); |
| 579 mini_title_animation_->set_delegate(this); | 579 animation->set_delegate(this); |
| 580 tab_animation_.reset(animation); |
| 580 } | 581 } |
| 581 mini_title_animation_->Start(); | 582 tab_animation_->Start(); |
| 582 } | 583 } |
| 583 | 584 |
| 584 void Tab::StopMiniTabTitleAnimation() { | 585 void Tab::StopMiniTabTitleAnimation() { |
| 585 if (mini_title_animation_.get()) | 586 if (!tab_animation_.get()) |
| 586 mini_title_animation_->Stop(); | 587 return; |
| 588 tab_animation_->Stop(); |
| 589 tab_animation_.reset(NULL); |
| 587 } | 590 } |
| 588 | 591 |
| 589 void Tab::UpdateIconDominantColor() { | 592 void Tab::UpdateIconDominantColor() { |
| 590 icon_dominant_color_ = | 593 icon_dominant_color_ = |
| 591 color_utils::CalculateKMeanColorOfBitmap(*data_.favicon.bitmap()); | 594 color_utils::CalculateKMeanColorOfBitmap(*data_.favicon.bitmap()); |
| 592 } | 595 } |
| 593 | 596 |
| 594 // static | 597 // static |
| 595 gfx::Size Tab::GetBasicMinimumUnselectedSize() { | 598 gfx::Size Tab::GetBasicMinimumUnselectedSize() { |
| 596 InitTabResources(); | 599 InitTabResources(); |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 IsActive() ? kImmersiveActiveTabColor : kImmersiveInactiveTabColor; | 1072 IsActive() ? kImmersiveActiveTabColor : kImmersiveInactiveTabColor; |
| 1070 gfx::Rect main_bar_rect( | 1073 gfx::Rect main_bar_rect( |
| 1071 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); | 1074 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); |
| 1072 canvas->FillRect(main_bar_rect, color); | 1075 canvas->FillRect(main_bar_rect, color); |
| 1073 } | 1076 } |
| 1074 | 1077 |
| 1075 void Tab::PaintTabBackground(gfx::Canvas* canvas) { | 1078 void Tab::PaintTabBackground(gfx::Canvas* canvas) { |
| 1076 if (IsActive()) { | 1079 if (IsActive()) { |
| 1077 PaintActiveTabBackground(canvas); | 1080 PaintActiveTabBackground(canvas); |
| 1078 } else { | 1081 } else { |
| 1079 if (mini_title_animation_.get() && mini_title_animation_->is_animating()) | 1082 if (tab_animation_.get() && |
| 1080 PaintInactiveTabBackgroundWithTitleChange(canvas); | 1083 tab_animation_->is_animating() && |
| 1081 else | 1084 data().mini) { |
| 1085 ui::MultiAnimation* animation = |
| 1086 static_cast<ui::MultiAnimation*>(tab_animation_.get()); |
| 1087 PaintInactiveTabBackgroundWithTitleChange(canvas, animation); |
| 1088 } else { |
| 1082 PaintInactiveTabBackground(canvas); | 1089 PaintInactiveTabBackground(canvas); |
| 1090 } |
| 1083 | 1091 |
| 1084 double throb_value = GetThrobValue(); | 1092 double throb_value = GetThrobValue(); |
| 1085 if (throb_value > 0) { | 1093 if (throb_value > 0) { |
| 1086 canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff), | 1094 canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff), |
| 1087 GetLocalBounds()); | 1095 GetLocalBounds()); |
| 1088 PaintActiveTabBackground(canvas); | 1096 PaintActiveTabBackground(canvas); |
| 1089 canvas->Restore(); | 1097 canvas->Restore(); |
| 1090 } | 1098 } |
| 1091 } | 1099 } |
| 1092 } | 1100 } |
| 1093 | 1101 |
| 1094 void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { | 1102 void Tab::PaintInactiveTabBackgroundWithTitleChange( |
| 1103 gfx::Canvas* canvas, |
| 1104 ui::MultiAnimation* animation) { |
| 1095 // Render the inactive tab background. We'll use this for clipping. | 1105 // Render the inactive tab background. We'll use this for clipping. |
| 1096 gfx::Canvas background_canvas(size(), canvas->scale_factor(), false); | 1106 gfx::Canvas background_canvas(size(), canvas->scale_factor(), false); |
| 1097 PaintInactiveTabBackground(&background_canvas); | 1107 PaintInactiveTabBackground(&background_canvas); |
| 1098 | 1108 |
| 1099 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | 1109 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
| 1100 | 1110 |
| 1101 // Draw a radial gradient to hover_canvas. | 1111 // Draw a radial gradient to hover_canvas. |
| 1102 gfx::Canvas hover_canvas(size(), canvas->scale_factor(), false); | 1112 gfx::Canvas hover_canvas(size(), canvas->scale_factor(), false); |
| 1103 int radius = kMiniTitleChangeGradientRadius; | 1113 int radius = kMiniTitleChangeGradientRadius; |
| 1104 int x0 = width() + radius - kMiniTitleChangeInitialXOffset; | 1114 int x0 = width() + radius - kMiniTitleChangeInitialXOffset; |
| 1105 int x1 = radius; | 1115 int x1 = radius; |
| 1106 int x2 = -radius; | 1116 int x2 = -radius; |
| 1107 int x; | 1117 int x; |
| 1108 if (mini_title_animation_->current_part_index() == 0) { | 1118 if (animation->current_part_index() == 0) { |
| 1109 x = mini_title_animation_->CurrentValueBetween(x0, x1); | 1119 x = animation->CurrentValueBetween(x0, x1); |
| 1110 } else if (mini_title_animation_->current_part_index() == 1) { | 1120 } else if (animation->current_part_index() == 1) { |
| 1111 x = x1; | 1121 x = x1; |
| 1112 } else { | 1122 } else { |
| 1113 x = mini_title_animation_->CurrentValueBetween(x1, x2); | 1123 x = animation->CurrentValueBetween(x1, x2); |
| 1114 } | 1124 } |
| 1115 SkPoint center_point; | 1125 SkPoint center_point; |
| 1116 center_point.iset(x, 0); | 1126 center_point.iset(x, 0); |
| 1117 SkColor colors[2] = { kMiniTitleChangeGradientColor1, | 1127 SkColor colors[2] = { kMiniTitleChangeGradientColor1, |
| 1118 kMiniTitleChangeGradientColor2 }; | 1128 kMiniTitleChangeGradientColor2 }; |
| 1119 skia::RefPtr<SkShader> shader = skia::AdoptRef( | 1129 skia::RefPtr<SkShader> shader = skia::AdoptRef( |
| 1120 SkGradientShader::CreateRadial( | 1130 SkGradientShader::CreateRadial( |
| 1121 center_point, SkIntToScalar(radius), colors, NULL, 2, | 1131 center_point, SkIntToScalar(radius), colors, NULL, 2, |
| 1122 SkShader::kClamp_TileMode)); | 1132 SkShader::kClamp_TileMode)); |
| 1123 SkPaint paint; | 1133 SkPaint paint; |
| 1124 paint.setShader(shader.get()); | 1134 paint.setShader(shader.get()); |
| 1125 hover_canvas.DrawRect(gfx::Rect(x - radius, -radius, radius * 2, radius * 2), | 1135 hover_canvas.DrawRect(gfx::Rect(x - radius, -radius, radius * 2, radius * 2), |
| 1126 paint); | 1136 paint); |
| 1127 | 1137 |
| 1128 // Draw the radial gradient clipped to the background into hover_image. | 1138 // Draw the radial gradient clipped to the background into hover_image. |
| 1129 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( | 1139 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( |
| 1130 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | 1140 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
| 1131 | 1141 |
| 1132 // Draw the tab background to the canvas. | 1142 // Draw the tab background to the canvas. |
| 1133 canvas->DrawImageInt(background_image, 0, 0); | 1143 canvas->DrawImageInt(background_image, 0, 0); |
| 1134 | 1144 |
| 1135 // And then the gradient on top of that. | 1145 // And then the gradient on top of that. |
| 1136 if (mini_title_animation_->current_part_index() == 2) { | 1146 if (animation->current_part_index() == 2) { |
| 1137 uint8 alpha = mini_title_animation_->CurrentValueBetween(255, 0); | 1147 uint8 alpha = animation->CurrentValueBetween(255, 0); |
| 1138 canvas->DrawImageInt(hover_image, 0, 0, alpha); | 1148 canvas->DrawImageInt(hover_image, 0, 0, alpha); |
| 1139 } else { | 1149 } else { |
| 1140 canvas->DrawImageInt(hover_image, 0, 0); | 1150 canvas->DrawImageInt(hover_image, 0, 0); |
| 1141 } | 1151 } |
| 1142 } | 1152 } |
| 1143 | 1153 |
| 1144 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { | 1154 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
| 1145 int tab_id; | 1155 int tab_id; |
| 1146 if (GetWidget() && GetWidget()->GetTopLevelWidget()->ShouldUseNativeFrame()) { | 1156 if (GetWidget() && GetWidget()->GetTopLevelWidget()->ShouldUseNativeFrame()) { |
| 1147 tab_id = IDR_THEME_TAB_BACKGROUND_V; | 1157 tab_id = IDR_THEME_TAB_BACKGROUND_V; |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 bool Tab::ShouldShowCloseBox() const { | 1499 bool Tab::ShouldShowCloseBox() const { |
| 1490 // The active tab never clips close button. | 1500 // The active tab never clips close button. |
| 1491 return !data().mini && (IsActive() || IconCapacity() >= 3); | 1501 return !data().mini && (IsActive() || IconCapacity() >= 3); |
| 1492 } | 1502 } |
| 1493 | 1503 |
| 1494 double Tab::GetThrobValue() { | 1504 double Tab::GetThrobValue() { |
| 1495 bool is_selected = IsSelected(); | 1505 bool is_selected = IsSelected(); |
| 1496 double min = is_selected ? kSelectedTabOpacity : 0; | 1506 double min = is_selected ? kSelectedTabOpacity : 0; |
| 1497 double scale = is_selected ? kSelectedTabThrobScale : 1; | 1507 double scale = is_selected ? kSelectedTabThrobScale : 1; |
| 1498 | 1508 |
| 1499 if (tab_animation_.get() && tab_animation_->is_animating()) | 1509 if (!data().mini) { |
| 1500 return tab_animation_->GetCurrentValue() * kHoverOpacity * scale + min; | 1510 if (tab_animation_.get() && tab_animation_->is_animating()) |
| 1511 return tab_animation_->GetCurrentValue() * kHoverOpacity * scale + min; |
| 1512 } |
| 1501 | 1513 |
| 1502 if (hover_controller_.ShouldDraw()) { | 1514 if (hover_controller_.ShouldDraw()) { |
| 1503 return kHoverOpacity * hover_controller_.GetAnimationValue() * scale + | 1515 return kHoverOpacity * hover_controller_.GetAnimationValue() * scale + |
| 1504 min; | 1516 min; |
| 1505 } | 1517 } |
| 1506 | 1518 |
| 1507 return is_selected ? kSelectedTabOpacity : 0; | 1519 return is_selected ? kSelectedTabOpacity : 0; |
| 1508 } | 1520 } |
| 1509 | 1521 |
| 1510 void Tab::SetFaviconHidingOffset(int offset) { | 1522 void Tab::SetFaviconHidingOffset(int offset) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 const gfx::ImageSkia& image) { | 1637 const gfx::ImageSkia& image) { |
| 1626 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1638 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
| 1627 ImageCacheEntry entry; | 1639 ImageCacheEntry entry; |
| 1628 entry.resource_id = resource_id; | 1640 entry.resource_id = resource_id; |
| 1629 entry.scale_factor = scale_factor; | 1641 entry.scale_factor = scale_factor; |
| 1630 entry.image = image; | 1642 entry.image = image; |
| 1631 image_cache_->push_front(entry); | 1643 image_cache_->push_front(entry); |
| 1632 if (image_cache_->size() > kMaxImageCacheSize) | 1644 if (image_cache_->size() > kMaxImageCacheSize) |
| 1633 image_cache_->pop_back(); | 1645 image_cache_->pop_back(); |
| 1634 } | 1646 } |
| OLD | NEW |