Chromium Code Reviews| Index: chrome/browser/ui/views/tabs/tab.cc |
| diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc |
| index ba54c9f8529263a58a8373d7abfd567659e641e9..d64ab5fc263a3d9193fcca460325fb05e07c35c6 100644 |
| --- a/chrome/browser/ui/views/tabs/tab.cc |
| +++ b/chrome/browser/ui/views/tabs/tab.cc |
| @@ -37,7 +37,6 @@ |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/base/theme_provider.h" |
| #include "ui/gfx/animation/animation_container.h" |
| -#include "ui/gfx/animation/multi_animation.h" |
| #include "ui/gfx/animation/throb_animation.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/color_analysis.h" |
| @@ -89,10 +88,6 @@ const double kSelectedTabOpacity = 0.3; |
| // Inactive selected tabs have their throb value scaled by this. |
| const double kSelectedTabThrobScale = 0.95 - kSelectedTabOpacity; |
| -// Offset from the right edge for the start of the pinned title change |
| -// animation. |
| -const int kPinnedTitleChangeInitialXOffset = 6; |
| - |
| // Max number of images to cache. This has to be at least two since rounding |
| // errors may lead to tabs in the same tabstrip having different sizes. |
| // 8 = normal/incognito, active/inactive, 2 sizes within tabstrip. |
| @@ -566,34 +561,6 @@ Tab::Tab(TabController* controller, gfx::AnimationContainer* container) |
| pulse_animation_->SetSlideDuration(kPulseDurationMs); |
| pulse_animation_->SetContainer(animation_container_.get()); |
| - const int kPinnedTitleChangeAnimationDuration1MS = 1600; |
| - const int kPinnedTitleChangeAnimationStart1MS = 0; |
| - const int kPinnedTitleChangeAnimationEnd1MS = 1900; |
| - const int kPinnedTitleChangeAnimationDuration2MS = 0; |
| - const int kPinnedTitleChangeAnimationDuration3MS = 550; |
| - const int kPinnedTitleChangeAnimationStart3MS = 150; |
| - const int kPinnedTitleChangeAnimationEnd3MS = 800; |
| - const int kPinnedTitleChangeAnimationIntervalMS = 40; |
| - gfx::MultiAnimation::Parts parts; |
| - parts.push_back(gfx::MultiAnimation::Part( |
| - kPinnedTitleChangeAnimationDuration1MS, |
| - kPinnedTitleChangeAnimationStart1MS, |
| - kPinnedTitleChangeAnimationEnd1MS, |
| - gfx::Tween::EASE_OUT)); |
| - parts.push_back(gfx::MultiAnimation::Part( |
| - kPinnedTitleChangeAnimationDuration2MS, |
| - gfx::Tween::ZERO)); |
| - parts.push_back(gfx::MultiAnimation::Part( |
| - kPinnedTitleChangeAnimationDuration3MS, |
| - kPinnedTitleChangeAnimationStart3MS, |
| - kPinnedTitleChangeAnimationEnd3MS, |
| - gfx::Tween::EASE_IN)); |
| - const base::TimeDelta timeout = |
| - base::TimeDelta::FromMilliseconds(kPinnedTitleChangeAnimationIntervalMS); |
| - pinned_title_change_animation_.reset(new gfx::MultiAnimation(parts, timeout)); |
| - pinned_title_change_animation_->SetContainer(animation_container_.get()); |
| - pinned_title_change_animation_->set_delegate(this); |
| - |
| hover_controller_.SetAnimationContainer(animation_container_.get()); |
| } |
| @@ -652,7 +619,7 @@ void Tab::SetData(const TabRendererData& data) { |
| alert_indicator_button_->TransitionToAlertState(data_.alert_state); |
| if (old.pinned != data_.pinned) |
| - StopPinnedTabTitleAnimation(); |
| + showing_pinned_tab_title_changed_indicator_ = false; |
| DataChanged(old); |
| @@ -680,13 +647,14 @@ void Tab::StopPulse() { |
| pulse_animation_->Stop(); |
| } |
| -void Tab::StartPinnedTabTitleAnimation() { |
| - if (data().pinned) |
| - pinned_title_change_animation_->Start(); |
| -} |
| +void Tab::SetPinnedTabTitleChangedIndicatorVisible(bool value) { |
| + if (value == showing_pinned_tab_title_changed_indicator_) |
| + return; |
| -void Tab::StopPinnedTabTitleAnimation() { |
| - pinned_title_change_animation_->Stop(); |
| + DCHECK(!value || data().pinned); |
| + |
| + showing_pinned_tab_title_changed_indicator_ = value; |
| + SchedulePaint(); |
| } |
| int Tab::GetWidthOfLargestSelectableRegion() const { |
| @@ -1265,10 +1233,7 @@ void Tab::PaintTabBackground(gfx::Canvas* canvas) { |
| PaintTabBackgroundUsingFillId(canvas, true, kActiveTabFillId, |
| has_custom_image, y_offset); |
| } else { |
| - if (pinned_title_change_animation_->is_animating()) |
| - PaintInactiveTabBackgroundWithTitleChange(canvas); |
| - else |
| - PaintInactiveTabBackground(canvas); |
| + PaintInactiveTabBackground(canvas); |
| const double throb_value = GetThrobValue(); |
| if (throb_value > 0) { |
| @@ -1281,45 +1246,6 @@ void Tab::PaintTabBackground(gfx::Canvas* canvas) { |
| } |
| } |
| -void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { |
| - const int kPinnedTitleChangeGradientRadius = 20; |
| - const float radius = kPinnedTitleChangeGradientRadius; |
| - double x = radius; |
| - SkColor hover_color = |
| - GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR); |
| - if (pinned_title_change_animation_->current_part_index() == 0) { |
| - x = pinned_title_change_animation_->CurrentValueBetween( |
| - width() + radius - kPinnedTitleChangeInitialXOffset, radius); |
| - } else if (pinned_title_change_animation_->current_part_index() == 2) { |
| - x = pinned_title_change_animation_->CurrentValueBetween(radius, -radius); |
| - const int alpha = |
| - pinned_title_change_animation_->CurrentValueBetween(255, 0); |
| - hover_color = SkColorSetA(hover_color, static_cast<SkAlpha>(alpha)); |
| - } |
| - SkPoint p; |
| - p.set(SkDoubleToScalar(x), 0); |
| - if (ui::MaterialDesignController::IsModeMaterial()) { |
| - PaintInactiveTabBackground(canvas); |
| - gfx::ScopedCanvas scoped_canvas(canvas); |
| - const float scale = canvas->UndoDeviceScaleFactor(); |
| - SkPath fill; |
| - GetFillPath(scale, &fill); |
| - canvas->ClipPath(fill, true); |
| - p.scale(SkFloatToScalar(scale)); |
| - DrawHighlight(canvas, p, SkFloatToScalar(radius * scale), hover_color); |
| - } else { |
| - gfx::Canvas background_canvas(size(), canvas->image_scale(), false); |
| - PaintInactiveTabBackground(&background_canvas); |
| - gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); |
| - canvas->DrawImageInt(background_image, 0, 0); |
| - gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); |
| - DrawHighlight(&hover_canvas, p, SkFloatToScalar(radius), hover_color); |
| - gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( |
| - gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); |
| - canvas->DrawImageInt(hover_image, 0, 0); |
| - } |
| -} |
| - |
| void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { |
| bool has_custom_image; |
| int fill_id = controller_->GetBackgroundResourceId(&has_custom_image); |
| @@ -1492,6 +1418,50 @@ void Tab::PaintTabFill(gfx::Canvas* canvas, |
| height() - tab_insets.top() - toolbar_overlap); |
| } |
| +void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon( |
| + gfx::Canvas* canvas, |
| + const gfx::ImageSkia& favicon, |
| + const gfx::Rect& favicon_bounds) { |
| + // The pinned tab title changed indicator consists of two parts: |
| + // . a clear (totally transparent) part over the bottom right (or left in rtl) |
| + // of the favicon. This is done by drawing the favicon to a canvas, then |
| + // drawing the clear part on top of the favicon. |
| + // . a circle in the bottom right (or left in rtl) of the favicon. |
| + if (!favicon.isNull()) { |
| + const float kIndicatorCropRadius = 4.5; |
| + gfx::Canvas icon_canvas(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize), |
| + canvas->image_scale(), false); |
| + icon_canvas.DrawImageInt(favicon, 0, 0); |
| + SkPaint clear_paint; |
| + clear_paint.setAntiAlias(true); |
| + clear_paint.setStyle(SkPaint::kFill_Style); |
| + clear_paint.setXfermodeMode(SkXfermode::kClear_Mode); |
| + const int circle_x = base::i18n::IsRTL() ? 0 : gfx::kFaviconSize; |
| + icon_canvas.DrawCircle(gfx::PointF(circle_x, gfx::kFaviconSize), |
| + kIndicatorCropRadius, clear_paint); |
| + canvas->DrawImageInt(gfx::ImageSkia(icon_canvas.ExtractImageRep()), 0, 0, |
| + favicon_bounds.width(), favicon_bounds.height(), |
| + favicon_bounds.x(), favicon_bounds.y(), |
| + favicon_bounds.width(), favicon_bounds.height(), |
| + false); |
| + } |
| + |
| + // Draws the actual pinned tab title changed indicator. |
| + const int kIndicatorRadius = 3; |
| + SkPaint indicator_paint; |
| + indicator_paint.setColor(GetNativeTheme()->GetSystemColor( |
| + ui::NativeTheme::kColorId_CallToActionColor)); |
| + indicator_paint.setAntiAlias(true); |
| + indicator_paint.setStyle(SkPaint::kFill_Style); |
| + indicator_paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
|
Evan Stade
2016/06/24 17:58:13
Fill and SrcOver are the defaults I believe. Did y
sky
2016/06/24 18:16:31
Mostly because knowing the defaults requires looki
|
| + const int indicator_x = GetMirroredXWithWidthInView( |
|
Evan Stade
2016/06/24 17:58:13
I'm unclear why this x/y calculation isn't the sam
sky
2016/06/24 18:16:31
They are centered on the same absolute point, but
Evan Stade
2016/06/24 18:32:31
ah, I missed that you're still using ExtractImageR
|
| + favicon_bounds_.right() - kIndicatorRadius, kIndicatorRadius * 2); |
|
Evan Stade
2016/06/24 17:58:13
confusing that favicon_bounds != favicon_bounds_
sky
2016/06/24 18:16:31
Ya, that is confusing. Renamed to favicon_draw_bou
|
| + const int indicator_y = favicon_bounds_.bottom() - kIndicatorRadius; |
| + canvas->DrawCircle(gfx::Point(indicator_x + kIndicatorRadius, |
| + indicator_y + kIndicatorRadius), |
| + kIndicatorRadius, indicator_paint); |
| +} |
| + |
| void Tab::PaintIcon(gfx::Canvas* canvas) { |
| gfx::Rect bounds = favicon_bounds_; |
| bounds.set_x(GetMirroredXForRect(bounds)); |
| @@ -1502,16 +1472,21 @@ void Tab::PaintIcon(gfx::Canvas* canvas) { |
| if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { |
| // Throbber will do its own painting. |
| - } else { |
| - const gfx::ImageSkia& favicon = should_display_crashed_favicon_ ? |
| - *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| - IDR_CRASH_SAD_FAVICON) : |
| - data().favicon; |
| - if (!favicon.isNull()) { |
| - canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(), |
| - bounds.x(), bounds.y(), bounds.width(), |
| - bounds.height(), false); |
| - } |
| + return; |
| + } |
| + const gfx::ImageSkia& favicon = |
| + should_display_crashed_favicon_ |
| + ? *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| + IDR_CRASH_SAD_FAVICON) |
| + : data().favicon; |
| + |
| + if (showing_pinned_tab_title_changed_indicator_ && |
| + !should_display_crashed_favicon_) { |
| + PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, favicon, bounds); |
| + } else if (!favicon.isNull()) { |
| + canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(), |
| + bounds.x(), bounds.y(), bounds.width(), |
| + bounds.height(), false); |
| } |
| } |
| @@ -1616,14 +1591,10 @@ double Tab::GetThrobValue() { |
| const double offset = |
| is_selected ? (kSelectedTabThrobScale * kHoverOpacity) : kHoverOpacity; |
| - // Showing both the pulse and title change animation at the same time is too |
| - // much. |
| - if (pulse_animation_->is_animating() && |
| - !pinned_title_change_animation_->is_animating()) { |
| + if (pulse_animation_->is_animating()) |
| val += pulse_animation_->GetCurrentValue() * offset; |
| - } else if (hover_controller_.ShouldDraw()) { |
| + else if (hover_controller_.ShouldDraw()) |
| val += hover_controller_.GetAnimationValue() * offset; |
| - } |
| return val; |
| } |