| 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 2b4392ccd588810ba7dd052c5d4aa19c003d030d..62d495824738977661272a96ac84efac3e44b5f6 100644
|
| --- a/chrome/browser/ui/views/tabs/tab.cc
|
| +++ b/chrome/browser/ui/views/tabs/tab.cc
|
| @@ -185,6 +185,13 @@ chrome::HostDesktopType GetHostDesktopType(views::View* view) {
|
| widget ? widget->GetNativeView() : NULL);
|
| }
|
|
|
| +// Stop()s |animation| and then deletes it. We do this rather than just deleting
|
| +// so that the delegate is notified before the destruction.
|
| +void StopAndDeleteAnimation(scoped_ptr<gfx::Animation> animation) {
|
| + if (animation)
|
| + animation->Stop();
|
| +}
|
| +
|
| } // namespace
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| @@ -481,10 +488,8 @@ void Tab::SetData(const TabRendererData& data) {
|
| }
|
|
|
| if (old.mini != data_.mini) {
|
| - if (tab_animation_.get() && tab_animation_->is_animating()) {
|
| - tab_animation_->Stop();
|
| - tab_animation_.reset(NULL);
|
| - }
|
| + StopAndDeleteAnimation(
|
| + mini_title_change_animation_.PassAs<gfx::Animation>());
|
| }
|
|
|
| DataChanged(old);
|
| @@ -507,27 +512,21 @@ void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) {
|
| }
|
|
|
| void Tab::StartPulse() {
|
| - gfx::ThrobAnimation* animation = new gfx::ThrobAnimation(this);
|
| - animation->SetSlideDuration(kPulseDurationMs);
|
| - if (animation_container_.get())
|
| - animation->SetContainer(animation_container_.get());
|
| - animation->StartThrobbing(std::numeric_limits<int>::max());
|
| - tab_animation_.reset(animation);
|
| + pulse_animation_.reset(new gfx::ThrobAnimation(this));
|
| + pulse_animation_->SetSlideDuration(kPulseDurationMs);
|
| + if (animation_container_)
|
| + pulse_animation_->SetContainer(animation_container_.get());
|
| + pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
|
| }
|
|
|
| void Tab::StopPulse() {
|
| - if (!tab_animation_.get())
|
| - return;
|
| - tab_animation_->Stop();
|
| - tab_animation_.reset(NULL);
|
| + StopAndDeleteAnimation(pulse_animation_.PassAs<gfx::Animation>());
|
| }
|
|
|
| void Tab::StartMiniTabTitleAnimation() {
|
| - // We can only do this animation if the tab is mini because we will
|
| - // upcast tab_animation back to MultiAnimation when we draw.
|
| if (!data().mini)
|
| return;
|
| - if (!tab_animation_.get()) {
|
| + if (!mini_title_change_animation_) {
|
| gfx::MultiAnimation::Parts parts;
|
| parts.push_back(
|
| gfx::MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS,
|
| @@ -544,20 +543,16 @@ void Tab::StartMiniTabTitleAnimation() {
|
| parts[2].end_time_ms = kMiniTitleChangeAnimationEnd3MS;
|
| base::TimeDelta timeout =
|
| base::TimeDelta::FromMilliseconds(kMiniTitleChangeAnimationIntervalMS);
|
| - gfx::MultiAnimation* animation = new gfx::MultiAnimation(parts, timeout);
|
| - if (animation_container_.get())
|
| - animation->SetContainer(animation_container_.get());
|
| - animation->set_delegate(this);
|
| - tab_animation_.reset(animation);
|
| + mini_title_change_animation_.reset(new gfx::MultiAnimation(parts, timeout));
|
| + if (animation_container_)
|
| + mini_title_change_animation_->SetContainer(animation_container_.get());
|
| + mini_title_change_animation_->set_delegate(this);
|
| }
|
| - tab_animation_->Start();
|
| + mini_title_change_animation_->Start();
|
| }
|
|
|
| void Tab::StopMiniTabTitleAnimation() {
|
| - if (!tab_animation_.get())
|
| - return;
|
| - tab_animation_->Stop();
|
| - tab_animation_.reset(NULL);
|
| + StopAndDeleteAnimation(mini_title_change_animation_.PassAs<gfx::Animation>());
|
| }
|
|
|
| // static
|
| @@ -613,7 +608,7 @@ int Tab::GetImmersiveHeight() {
|
| void Tab::AnimationProgressed(const gfx::Animation* animation) {
|
| // Ignore if the pulse animation is being performed on active tab because
|
| // it repaints the same image. See |Tab::PaintTabBackground()|.
|
| - if (animation == tab_animation_.get() && IsActive())
|
| + if (animation == pulse_animation_.get() && IsActive())
|
| return;
|
| SchedulePaint();
|
| }
|
| @@ -1044,10 +1039,8 @@ void Tab::PaintTab(gfx::Canvas* canvas) {
|
| void Tab::PaintImmersiveTab(gfx::Canvas* canvas) {
|
| // Use transparency for the draw-attention animation.
|
| int alpha = 255;
|
| - if (tab_animation_ &&
|
| - tab_animation_->is_animating() &&
|
| - !data().mini) {
|
| - alpha = tab_animation_->CurrentValueBetween(
|
| + if (pulse_animation_ && pulse_animation_->is_animating() && !data().mini) {
|
| + alpha = pulse_animation_->CurrentValueBetween(
|
| 255, static_cast<int>(255 * kImmersiveTabMinThrobOpacity));
|
| }
|
|
|
| @@ -1091,12 +1084,9 @@ void Tab::PaintTabBackground(gfx::Canvas* canvas) {
|
| if (IsActive()) {
|
| PaintActiveTabBackground(canvas);
|
| } else {
|
| - if (tab_animation_.get() &&
|
| - tab_animation_->is_animating() &&
|
| - data().mini) {
|
| - gfx::MultiAnimation* animation =
|
| - static_cast<gfx::MultiAnimation*>(tab_animation_.get());
|
| - PaintInactiveTabBackgroundWithTitleChange(canvas, animation);
|
| + if (mini_title_change_animation_ &&
|
| + mini_title_change_animation_->is_animating()) {
|
| + PaintInactiveTabBackgroundWithTitleChange(canvas);
|
| } else {
|
| PaintInactiveTabBackground(canvas);
|
| }
|
| @@ -1111,9 +1101,7 @@ void Tab::PaintTabBackground(gfx::Canvas* canvas) {
|
| }
|
| }
|
|
|
| -void Tab::PaintInactiveTabBackgroundWithTitleChange(
|
| - gfx::Canvas* canvas,
|
| - gfx::MultiAnimation* animation) {
|
| +void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) {
|
| // Render the inactive tab background. We'll use this for clipping.
|
| gfx::Canvas background_canvas(size(), canvas->image_scale(), false);
|
| PaintInactiveTabBackground(&background_canvas);
|
| @@ -1127,12 +1115,12 @@ void Tab::PaintInactiveTabBackgroundWithTitleChange(
|
| int x1 = radius;
|
| int x2 = -radius;
|
| int x;
|
| - if (animation->current_part_index() == 0) {
|
| - x = animation->CurrentValueBetween(x0, x1);
|
| - } else if (animation->current_part_index() == 1) {
|
| + if (mini_title_change_animation_->current_part_index() == 0) {
|
| + x = mini_title_change_animation_->CurrentValueBetween(x0, x1);
|
| + } else if (mini_title_change_animation_->current_part_index() == 1) {
|
| x = x1;
|
| } else {
|
| - x = animation->CurrentValueBetween(x1, x2);
|
| + x = mini_title_change_animation_->CurrentValueBetween(x1, x2);
|
| }
|
| SkPoint center_point;
|
| center_point.iset(x, 0);
|
| @@ -1155,8 +1143,8 @@ void Tab::PaintInactiveTabBackgroundWithTitleChange(
|
| canvas->DrawImageInt(background_image, 0, 0);
|
|
|
| // And then the gradient on top of that.
|
| - if (animation->current_part_index() == 2) {
|
| - uint8 alpha = animation->CurrentValueBetween(255, 0);
|
| + if (mini_title_change_animation_->current_part_index() == 2) {
|
| + uint8 alpha = mini_title_change_animation_->CurrentValueBetween(255, 0);
|
| canvas->DrawImageInt(hover_image, 0, 0, alpha);
|
| } else {
|
| canvas->DrawImageInt(hover_image, 0, 0);
|
| @@ -1469,13 +1457,16 @@ bool Tab::ShouldShowCloseBox() const {
|
| }
|
|
|
| double Tab::GetThrobValue() {
|
| - bool is_selected = IsSelected();
|
| - double min = is_selected ? kSelectedTabOpacity : 0;
|
| - double scale = is_selected ? kSelectedTabThrobScale : 1;
|
| -
|
| - if (!data().mini) {
|
| - if (tab_animation_.get() && tab_animation_->is_animating())
|
| - return tab_animation_->GetCurrentValue() * kHoverOpacity * scale + min;
|
| + const bool is_selected = IsSelected();
|
| + const double min = is_selected ? kSelectedTabOpacity : 0;
|
| + const double scale = is_selected ? kSelectedTabThrobScale : 1;
|
| +
|
| + // Showing both the pulse and title change animation at the same time is too
|
| + // much.
|
| + if (pulse_animation_ && pulse_animation_->is_animating() &&
|
| + (!mini_title_change_animation_ ||
|
| + !mini_title_change_animation_->is_animating())) {
|
| + return pulse_animation_->GetCurrentValue() * kHoverOpacity * scale + min;
|
| }
|
|
|
| if (hover_controller_.ShouldDraw()) {
|
|
|