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, ui::MultiAnimation* animation) { | |
sky
2013/01/23 22:16:31
When you warp, each param on its own line.
| |
1095 // Render the inactive tab background. We'll use this for clipping. | 1104 // Render the inactive tab background. We'll use this for clipping. |
1096 gfx::Canvas background_canvas(size(), canvas->scale_factor(), false); | 1105 gfx::Canvas background_canvas(size(), canvas->scale_factor(), false); |
1097 PaintInactiveTabBackground(&background_canvas); | 1106 PaintInactiveTabBackground(&background_canvas); |
1098 | 1107 |
1099 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); | 1108 gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
1100 | 1109 |
1101 // Draw a radial gradient to hover_canvas. | 1110 // Draw a radial gradient to hover_canvas. |
1102 gfx::Canvas hover_canvas(size(), canvas->scale_factor(), false); | 1111 gfx::Canvas hover_canvas(size(), canvas->scale_factor(), false); |
1103 int radius = kMiniTitleChangeGradientRadius; | 1112 int radius = kMiniTitleChangeGradientRadius; |
1104 int x0 = width() + radius - kMiniTitleChangeInitialXOffset; | 1113 int x0 = width() + radius - kMiniTitleChangeInitialXOffset; |
1105 int x1 = radius; | 1114 int x1 = radius; |
1106 int x2 = -radius; | 1115 int x2 = -radius; |
1107 int x; | 1116 int x; |
1108 if (mini_title_animation_->current_part_index() == 0) { | 1117 if (animation->current_part_index() == 0) { |
1109 x = mini_title_animation_->CurrentValueBetween(x0, x1); | 1118 x = animation->CurrentValueBetween(x0, x1); |
1110 } else if (mini_title_animation_->current_part_index() == 1) { | 1119 } else if (animation->current_part_index() == 1) { |
1111 x = x1; | 1120 x = x1; |
1112 } else { | 1121 } else { |
1113 x = mini_title_animation_->CurrentValueBetween(x1, x2); | 1122 x = animation->CurrentValueBetween(x1, x2); |
1114 } | 1123 } |
1115 SkPoint center_point; | 1124 SkPoint center_point; |
1116 center_point.iset(x, 0); | 1125 center_point.iset(x, 0); |
1117 SkColor colors[2] = { kMiniTitleChangeGradientColor1, | 1126 SkColor colors[2] = { kMiniTitleChangeGradientColor1, |
1118 kMiniTitleChangeGradientColor2 }; | 1127 kMiniTitleChangeGradientColor2 }; |
1119 skia::RefPtr<SkShader> shader = skia::AdoptRef( | 1128 skia::RefPtr<SkShader> shader = skia::AdoptRef( |
1120 SkGradientShader::CreateRadial( | 1129 SkGradientShader::CreateRadial( |
1121 center_point, SkIntToScalar(radius), colors, NULL, 2, | 1130 center_point, SkIntToScalar(radius), colors, NULL, 2, |
1122 SkShader::kClamp_TileMode)); | 1131 SkShader::kClamp_TileMode)); |
1123 SkPaint paint; | 1132 SkPaint paint; |
1124 paint.setShader(shader.get()); | 1133 paint.setShader(shader.get()); |
1125 hover_canvas.DrawRect(gfx::Rect(x - radius, -radius, radius * 2, radius * 2), | 1134 hover_canvas.DrawRect(gfx::Rect(x - radius, -radius, radius * 2, radius * 2), |
1126 paint); | 1135 paint); |
1127 | 1136 |
1128 // Draw the radial gradient clipped to the background into hover_image. | 1137 // Draw the radial gradient clipped to the background into hover_image. |
1129 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( | 1138 gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( |
1130 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); | 1139 gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
1131 | 1140 |
1132 // Draw the tab background to the canvas. | 1141 // Draw the tab background to the canvas. |
1133 canvas->DrawImageInt(background_image, 0, 0); | 1142 canvas->DrawImageInt(background_image, 0, 0); |
1134 | 1143 |
1135 // And then the gradient on top of that. | 1144 // And then the gradient on top of that. |
1136 if (mini_title_animation_->current_part_index() == 2) { | 1145 if (animation->current_part_index() == 2) { |
1137 uint8 alpha = mini_title_animation_->CurrentValueBetween(255, 0); | 1146 uint8 alpha = animation->CurrentValueBetween(255, 0); |
1138 canvas->DrawImageInt(hover_image, 0, 0, alpha); | 1147 canvas->DrawImageInt(hover_image, 0, 0, alpha); |
1139 } else { | 1148 } else { |
1140 canvas->DrawImageInt(hover_image, 0, 0); | 1149 canvas->DrawImageInt(hover_image, 0, 0); |
1141 } | 1150 } |
1142 } | 1151 } |
1143 | 1152 |
1144 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { | 1153 void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
1145 int tab_id; | 1154 int tab_id; |
1146 if (GetWidget() && GetWidget()->GetTopLevelWidget()->ShouldUseNativeFrame()) { | 1155 if (GetWidget() && GetWidget()->GetTopLevelWidget()->ShouldUseNativeFrame()) { |
1147 tab_id = IDR_THEME_TAB_BACKGROUND_V; | 1156 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 { | 1498 bool Tab::ShouldShowCloseBox() const { |
1490 // The active tab never clips close button. | 1499 // The active tab never clips close button. |
1491 return !data().mini && (IsActive() || IconCapacity() >= 3); | 1500 return !data().mini && (IsActive() || IconCapacity() >= 3); |
1492 } | 1501 } |
1493 | 1502 |
1494 double Tab::GetThrobValue() { | 1503 double Tab::GetThrobValue() { |
1495 bool is_selected = IsSelected(); | 1504 bool is_selected = IsSelected(); |
1496 double min = is_selected ? kSelectedTabOpacity : 0; | 1505 double min = is_selected ? kSelectedTabOpacity : 0; |
1497 double scale = is_selected ? kSelectedTabThrobScale : 1; | 1506 double scale = is_selected ? kSelectedTabThrobScale : 1; |
1498 | 1507 |
1499 if (tab_animation_.get() && tab_animation_->is_animating()) | 1508 if (!data().mini) { |
sky
2013/01/23 22:16:31
Combine into a single if.
| |
1500 return tab_animation_->GetCurrentValue() * kHoverOpacity * scale + min; | 1509 if (tab_animation_.get() && tab_animation_->is_animating()) |
1510 return tab_animation_->GetCurrentValue() * kHoverOpacity * scale + min; | |
1511 } | |
1501 | 1512 |
1502 if (hover_controller_.ShouldDraw()) { | 1513 if (hover_controller_.ShouldDraw()) { |
1503 return kHoverOpacity * hover_controller_.GetAnimationValue() * scale + | 1514 return kHoverOpacity * hover_controller_.GetAnimationValue() * scale + |
1504 min; | 1515 min; |
1505 } | 1516 } |
1506 | 1517 |
1507 return is_selected ? kSelectedTabOpacity : 0; | 1518 return is_selected ? kSelectedTabOpacity : 0; |
1508 } | 1519 } |
1509 | 1520 |
1510 void Tab::SetFaviconHidingOffset(int offset) { | 1521 void Tab::SetFaviconHidingOffset(int offset) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1625 const gfx::ImageSkia& image) { | 1636 const gfx::ImageSkia& image) { |
1626 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1637 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1627 ImageCacheEntry entry; | 1638 ImageCacheEntry entry; |
1628 entry.resource_id = resource_id; | 1639 entry.resource_id = resource_id; |
1629 entry.scale_factor = scale_factor; | 1640 entry.scale_factor = scale_factor; |
1630 entry.image = image; | 1641 entry.image = image; |
1631 image_cache_->push_front(entry); | 1642 image_cache_->push_front(entry); |
1632 if (image_cache_->size() > kMaxImageCacheSize) | 1643 if (image_cache_->size() > kMaxImageCacheSize) |
1633 image_cache_->pop_back(); | 1644 image_cache_->pop_back(); |
1634 } | 1645 } |
OLD | NEW |