blob: 9f9f6c4fe5681bb2e832517c0d43358c8b5d04e2 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/tabs/tab_strip_animator.h"
#include "base/time/time.h"
// TODO(965227): align animation ticks to compositor events.
constexpr base::TimeDelta kTickInterval =
base::TimeDelta::FromMilliseconds(1000 / 60.0);
TabStripAnimator::TabStripAnimator(
base::RepeatingClosure on_animation_progressed_callback)
: on_animation_progressed_callback_(on_animation_progressed_callback) {}
TabStripAnimator::~TabStripAnimator() = default;
std::vector<TabAnimationState> TabStripAnimator::GetCurrentTabStates() const {
std::vector<TabAnimationState> result;
for (const TabAnimation& animation : animations_) {
result.push_back(animation.GetCurrentState());
}
return result;
}
bool TabStripAnimator::IsAnimating() const {
return timer_.IsRunning();
}
void TabStripAnimator::InsertTabAtNoAnimation(
int index,
base::OnceClosure tab_removed_callback,
TabAnimationState::TabActiveness active,
TabAnimationState::TabPinnedness pinned) {
animations_.insert(
animations_.begin() + index,
TabAnimation::ForStaticState(
TabAnimationState::ForIdealTabState(
TabAnimationState::TabOpenness::kOpen, pinned, active, 0),
std::move(tab_removed_callback)));
}
void TabStripAnimator::MoveTabNoAnimation(int prev_index, int new_index) {
TabAnimation moved_animation = std::move(animations_[prev_index]);
animations_.erase(animations_.begin() + prev_index);
animations_.insert(animations_.begin() + new_index,
std::move(moved_animation));
}
void TabStripAnimator::RemoveTabNoAnimation(int index) {
animations_.erase(animations_.begin() + index);
}
void TabStripAnimator::SetPinnednessNoAnimation(
int index,
TabAnimationState::TabPinnedness pinned) {
animations_[index].AnimateTo(
animations_[index].target_state().WithPinnedness(pinned));
animations_[index].CompleteAnimation();
}
void TabStripAnimator::InsertTabAt(int index,
base::OnceClosure tab_removed_callback,
TabAnimationState::TabActiveness active,
TabAnimationState::TabPinnedness pinned) {
animations_.insert(
animations_.begin() + index,
TabAnimation::ForStaticState(
TabAnimationState::ForIdealTabState(
TabAnimationState::TabOpenness::kClosed, pinned, active, 0),
std::move(tab_removed_callback)));
AnimateTabTo(index, animations_[index].target_state().WithOpenness(
TabAnimationState::TabOpenness::kOpen));
}
void TabStripAnimator::RemoveTab(int index) {
AnimateTabTo(index, animations_[index].target_state().WithOpenness(
TabAnimationState::TabOpenness::kClosed));
}
void TabStripAnimator::SetActiveTab(int prev_active_index,
int new_active_index) {
// Set activeness without animating by immediately completing animations.
if (prev_active_index >= 0) {
animations_[prev_active_index].AnimateTo(
animations_[prev_active_index].target_state().WithActiveness(
TabAnimationState::TabActiveness::kInactive));
animations_[prev_active_index].CompleteAnimation();
}
if (new_active_index >= 0) {
animations_[new_active_index].AnimateTo(
animations_[new_active_index].target_state().WithActiveness(
TabAnimationState::TabActiveness::kActive));
animations_[new_active_index].CompleteAnimation();
}
}
void TabStripAnimator::CompleteAnimations() {
for (size_t i = 0; i < animations_.size(); i++) {
animations_[i].CompleteAnimation();
}
RemoveClosedTabs();
timer_.Stop();
}
void TabStripAnimator::CancelAnimations() {
for (TabAnimation& animation : animations_) {
animation.CancelAnimation();
}
timer_.Stop();
}
void TabStripAnimator::AnimateTabTo(int index, TabAnimationState target_state) {
animations_[index].AnimateTo(target_state);
if (!timer_.IsRunning()) {
timer_.Start(FROM_HERE, kTickInterval, this,
&TabStripAnimator::TickAnimations);
}
}
void TabStripAnimator::TickAnimations() {
bool all_animations_completed = true;
for (TabAnimation& animation : animations_) {
all_animations_completed &= animation.GetTimeRemaining().is_zero();
}
RemoveClosedTabs();
if (all_animations_completed) {
timer_.Stop();
}
on_animation_progressed_callback_.Run();
}
void TabStripAnimator::RemoveClosedTabs() {
for (auto it = animations_.begin(); it != animations_.end();) {
if (it->GetTimeRemaining().is_zero() &&
it->GetCurrentState().IsFullyClosed()) {
it->NotifyCloseCompleted();
it = animations_.erase(it);
} else {
it++;
}
}
}