Commit d22ae8d8 authored by Taylor Bergquist's avatar Taylor Bergquist Committed by Commit Bot

Track closing tabs in layout_helper_ instead of tabs_closing_map_.

This requires notifying layout_helper_ when a tab is being destroyed,
and TabStripLayoutHelper to step carefully around closing tabs in a few
places, but saves more complexity by not duplicating state between
TabStrip and TabStripLayoutHelper.

Bug: 958173
Change-Id: Iaeafc2391ecac0397947ccc34ddaecf853feb787
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1725271
Commit-Queue: Taylor Bergquist <tbergquist@chromium.org>
Reviewed-by: default avatarBret Sepulveda <bsep@chromium.org>
Cr-Commit-Position: refs/heads/master@{#683380}
parent af7c83f8
......@@ -328,7 +328,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext {
int model_index,
const ui::LocatedEvent& event,
const ui::ListSelectionModel& original_selection) {
Tabs tabs;
std::vector<Tab*> tabs;
int x = tab->GetMirroredXInView(event.x());
int y = event.y();
// Build the set of selected tabs to drag and calculate the offset from the
......@@ -586,7 +586,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext {
}
std::vector<gfx::Rect> CalculateBoundsForDraggedTabs(
const Tabs& tabs) override {
const std::vector<Tab*>& tabs) override {
DCHECK(!tabs.empty());
std::vector<gfx::Rect> bounds;
......@@ -611,7 +611,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext {
tab_strip_->last_layout_size_ = gfx::Size();
}
void StartedDraggingTabs(const Tabs& tabs) override {
void StartedDraggingTabs(const std::vector<Tab*>& tabs) override {
// Let the controller know that the user started dragging tabs.
tab_strip_->controller_->OnStartedDraggingTabs();
......@@ -648,7 +648,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext {
SetNewTabButtonVisible(true);
}
void StoppedDraggingTabs(const Tabs& tabs,
void StoppedDraggingTabs(const std::vector<Tab*>& tabs,
const std::vector<int>& initial_positions,
bool move_only,
bool completed) override {
......@@ -667,7 +667,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext {
tab_strip_->StoppedDraggingTab(tabs[i], &is_first_tab);
}
void LayoutDraggedTabsAt(const Tabs& tabs,
void LayoutDraggedTabsAt(const std::vector<Tab*>& tabs,
Tab* active_tab,
const gfx::Point& location,
bool initial_drag) override {
......@@ -979,7 +979,6 @@ void TabStrip::AddTabAt(int model_index, TabRendererData data, bool is_active) {
Tab* tab = new Tab(this);
AddChildViewAt(tab, view_index);
const bool pinned = data.pinned;
UpdateTabsClosingMap(model_index, 1);
tabs_.Add(tab, model_index);
selected_tabs_.IncrementFrom(model_index);
......@@ -1010,7 +1009,7 @@ void TabStrip::AddTabAt(int model_index, TabRendererData data, bool is_active) {
StartInsertTabAnimation(model_index, activeness, pinnedness);
} else {
layout_helper_->InsertTabAtNoAnimation(
model_index,
model_index, tab,
base::BindOnce(&TabStrip::OnTabCloseAnimationCompleted,
base::Unretained(this), base::Unretained(tab)),
activeness, pinnedness);
......@@ -1139,7 +1138,7 @@ void TabStrip::RemoveTabAt(content::WebContents* contents,
UpdateIdealBoundsForPinnedTabs(nullptr), old_x);
}
layout_helper_->RemoveTabAt(model_index);
layout_helper_->CloseTabAt(model_index);
UpdateIdealBounds();
AnimateToIdealBounds();
......@@ -1506,7 +1505,14 @@ void TabStrip::CloseTab(Tab* tab, CloseTabSource source) {
// If the tab is already closing, close the next tab. We do this so that the
// user can rapidly close tabs by clicking the close button and not have
// the animations interfere with that.
model_index = FindClosingTab(tab).first->first;
std::vector<Tab*> all_tabs = layout_helper_->GetTabs();
auto it = std::find(all_tabs.begin(), all_tabs.end(), tab);
while (it < all_tabs.end() && (*it)->closing()) {
it++;
}
model_index =
it != all_tabs.end() ? GetModelIndexOfTab(*it) : TabStripModel::kNoTab;
}
if (!IsValidModelIndex(model_index))
......@@ -1875,13 +1881,12 @@ void TabStrip::PaintChildren(const views::PaintInfo& paint_info) {
// This is used to log to UMA. NO EARLY RETURNS!
base::ElapsedTimer paint_timer;
// The view order doesn't match the paint order (tabs_ contains the tab
// ordering). Additionally we need to paint the tabs that are closing in
// |tabs_closing_map_|.
// The view order doesn't match the paint order (layout_helper_ contains the
// view ordering).
bool is_dragging = false;
Tab* active_tab = nullptr;
Tabs tabs_dragging;
Tabs selected_and_hovered_tabs;
std::vector<Tab*> tabs_dragging;
std::vector<Tab*> selected_and_hovered_tabs;
// When background tab shapes are visible, as for hovered or selected tabs,
// the paint order must be handled carefully to avoid Z-order errors, so
......@@ -1895,18 +1900,11 @@ void TabStrip::PaintChildren(const views::PaintInfo& paint_info) {
}
};
const auto paint_closing_tabs = [=](int index) {
if (tabs_closing_map_.find(index) == tabs_closing_map_.end())
return;
for (Tab* tab : base::Reversed(tabs_closing_map_[index]))
paint_or_add_to_tabs(tab);
};
paint_closing_tabs(tab_count());
std::vector<Tab*> all_tabs = layout_helper_->GetTabs();
int active_tab_index = -1;
for (int i = tab_count() - 1; i >= 0; --i) {
Tab* tab = tab_at(i);
for (int i = all_tabs.size() - 1; i >= 0; --i) {
Tab* tab = all_tabs[i];
if (tab->dragging() && !stacked_layout_) {
is_dragging = true;
if (tab->IsActive()) {
......@@ -1921,18 +1919,17 @@ void TabStrip::PaintChildren(const views::PaintInfo& paint_info) {
} else if (!stacked_layout_) {
paint_or_add_to_tabs(tab);
}
paint_closing_tabs(i);
}
// Draw from the left and then the right if we're in touch mode.
if (stacked_layout_ && active_tab_index >= 0) {
for (int i = 0; i < active_tab_index; ++i) {
Tab* tab = tab_at(i);
Tab* tab = all_tabs[i];
tab->Paint(paint_info);
}
for (int i = tab_count() - 1; i > active_tab_index; --i) {
Tab* tab = tab_at(i);
for (int i = all_tabs.size() - 1; i > active_tab_index; --i) {
Tab* tab = all_tabs[i];
tab->Paint(paint_info);
}
}
......@@ -2139,7 +2136,7 @@ void TabStrip::StartInsertTabAnimation(
TabAnimationState::TabPinnedness pinnedness) {
if (!bounds_animator_.IsAnimating() && !in_tab_close_) {
layout_helper_->InsertTabAt(
model_index,
model_index, tab_at(model_index),
base::BindOnce(&TabStrip::OnTabCloseAnimationCompleted,
base::Unretained(this),
base::Unretained(tab_at(model_index))),
......@@ -2148,7 +2145,7 @@ void TabStrip::StartInsertTabAnimation(
// TODO(958173): Delete this branch once |TabStripLayoutHelper::animator_|
// has taken over all animation responsibilities.
layout_helper_->InsertTabAtNoAnimation(
model_index,
model_index, tab_at(model_index),
base::BindOnce(&TabStrip::OnTabCloseAnimationCompleted,
base::Unretained(this),
base::Unretained(tab_at(model_index))),
......@@ -2257,7 +2254,13 @@ bool TabStrip::TitlebarBackgroundIsTransparent() const {
}
void TabStrip::CompleteAnimationAndLayout() {
// If |bounds_animator_| is running, it owns destroying tabs when close
// animations complete. Otherwise, |layout_helper_| does.
if (bounds_animator_.IsAnimating()) {
layout_helper_->CompleteAnimationsWithoutDestroyingTabs();
} else {
layout_helper_->CompleteAnimations();
}
LayoutToCurrentBounds();
UpdateIdealBounds();
......@@ -2299,14 +2302,8 @@ void TabStrip::SetTabVisibility() {
// we could e.g. binary-search for the changeover point. But since we have to
// iterate through all the tabs to call SetVisible() anyway, it doesn't seem
// worth it.
for (int i = 0; i < tab_count(); ++i) {
Tab* tab = tab_at(i);
tab->SetVisible(ShouldTabBeVisible(tab));
}
for (const auto& closing_tab : tabs_closing_map_) {
for (Tab* tab : closing_tab.second)
for (Tab* tab : layout_helper_->GetTabs())
tab->SetVisible(ShouldTabBeVisible(tab));
}
}
void TabStrip::UpdateAccessibleTabIndices() {
......@@ -2353,10 +2350,8 @@ void TabStrip::RemoveTabFromViewModel(int index) {
UpdateHoverCard(nullptr);
// We still need to paint the tab until we actually remove it. Put it
// in tabs_closing_map_ so we can find it.
tabs_closing_map_[index].push_back(closing_tab);
UpdateTabsClosingMap(index + 1, -1);
// We still need to keep the tab alive until the remove tab animation
// completes. Defer destroying it until then.
tabs_.Remove(index);
selected_tabs_.DecrementFrom(index);
......@@ -2368,10 +2363,7 @@ void TabStrip::OnTabCloseAnimationCompleted(Tab* tab) {
DCHECK(tab->closing());
std::unique_ptr<Tab> deleter(tab);
FindClosingTabResult res(FindClosingTab(tab));
res.first->second.erase(res.second);
if (res.first->second.empty())
tabs_closing_map_.erase(res.first);
layout_helper_->OnTabDestroyed(tab);
// Send the Container a message to simulate a mouse moved event at the current
// mouse position. This tickles the Tab the mouse is currently over to show
......@@ -2393,29 +2385,6 @@ void TabStrip::OnGroupCloseAnimationCompleted(TabGroupId group) {
// we do in OnTabCloseAnimationCompleted.
}
void TabStrip::UpdateTabsClosingMap(int index, int delta) {
if (tabs_closing_map_.empty())
return;
if (delta == -1 &&
tabs_closing_map_.find(index - 1) != tabs_closing_map_.end() &&
tabs_closing_map_.find(index) != tabs_closing_map_.end()) {
const Tabs& tabs(tabs_closing_map_[index]);
tabs_closing_map_[index - 1].insert(tabs_closing_map_[index - 1].end(),
tabs.begin(), tabs.end());
}
TabsClosingMap updated_map;
for (auto& i : tabs_closing_map_) {
if (i.first > index)
updated_map[i.first + delta] = i.second;
else if (i.first < index)
updated_map[i.first] = i.second;
}
if (delta > 0 && tabs_closing_map_.find(index) != tabs_closing_map_.end())
updated_map[index + delta] = tabs_closing_map_[index];
tabs_closing_map_.swap(updated_map);
}
void TabStrip::StoppedDraggingTab(Tab* tab, bool* is_first_tab) {
int tab_data_index = GetModelIndexOfTab(tab);
if (tab_data_index == -1) {
......@@ -2439,17 +2408,6 @@ void TabStrip::StoppedDraggingTab(Tab* tab, bool* is_first_tab) {
std::make_unique<ResetDraggingStateDelegate>(this, tab));
}
TabStrip::FindClosingTabResult TabStrip::FindClosingTab(const Tab* tab) {
DCHECK(tab->closing());
for (auto i = tabs_closing_map_.begin(); i != tabs_closing_map_.end(); ++i) {
auto j = std::find(i->second.begin(), i->second.end(), tab);
if (j != i->second.end())
return FindClosingTabResult(i, j);
}
NOTREACHED();
return FindClosingTabResult(tabs_closing_map_.end(), Tabs::iterator());
}
void TabStrip::UpdateStackedLayoutFromMouseEvent(views::View* source,
const ui::MouseEvent& event) {
if (!adjust_layout_)
......@@ -2806,20 +2764,24 @@ Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point,
}
Tab* TabStrip::FindTabHitByPoint(const gfx::Point& point) {
// Check all tabs, even closing tabs. Mouse events need to reach closing tabs
// for users to be able to rapidly middle-click close several tabs.
std::vector<Tab*> all_tabs = layout_helper_->GetTabs();
// The display order doesn't necessarily match the child order, so we iterate
// in display order.
for (int i = 0; i < tab_count(); ++i) {
for (size_t i = 0; i < all_tabs.size(); ++i) {
// If we don't first exclude points outside the current tab, the code below
// will return the wrong tab if the next tab is selected, the following tab
// is active, and |point| is in the overlap region between the two.
Tab* tab = tab_at(i);
Tab* tab = all_tabs[i];
if (!IsPointInTab(tab, point))
continue;
// Selected tabs render atop unselected ones, and active tabs render atop
// everything. Check whether the next tab renders atop this one and |point|
// is in the overlap region.
Tab* next_tab = i < (tab_count() - 1) ? tab_at(i + 1) : nullptr;
Tab* next_tab = i < (all_tabs.size() - 1) ? all_tabs[i + 1] : nullptr;
if (next_tab &&
(next_tab->IsActive() ||
(next_tab->IsSelected() && !tab->IsSelected())) &&
......@@ -2830,17 +2792,6 @@ Tab* TabStrip::FindTabHitByPoint(const gfx::Point& point) {
return tab;
}
// Also check closing tabs. Mouse events need to reach closing tabs for users
// to be able to rapidly middle-click close several tabs. Since closing tabs
// are never selected or active, the check here can be simpler than the one
// above.
for (const auto& index_and_tabs : tabs_closing_map_) {
for (Tab* tab : index_and_tabs.second) {
if (IsPointInTab(tab, point))
return tab;
}
}
return nullptr;
}
......
......@@ -298,11 +298,6 @@ class TabStrip : public views::AccessiblePaneView,
void HandleDragExited() override;
private:
using Tabs = std::vector<Tab*>;
using TabsClosingMap = std::map<int, Tabs>;
using FindClosingTabResult =
std::pair<TabsClosingMap::iterator, Tabs::iterator>;
class RemoveTabDelegate;
class TabDragContextImpl;
......@@ -403,8 +398,7 @@ class TabStrip : public views::AccessiblePaneView,
// the actual last tab unless the strip is in the overflow node_data.
const Tab* GetLastVisibleTab() const;
// Adds the tab at |index| to |tabs_closing_map_| and removes the tab from
// |tabs_|.
// Removes the tab at |index| from |tabs_|.
void RemoveTabFromViewModel(int index);
// Cleans up the Tab from the TabStrip. This is called from the tab animation
......@@ -415,18 +409,10 @@ class TabStrip : public views::AccessiblePaneView,
// from the tab animation code and is not a general-purpose method.
void OnGroupCloseAnimationCompleted(TabGroupId group);
// Adjusts the indices of all tabs in |tabs_closing_map_| whose index is
// >= |index| to have a new index of |index + delta|.
void UpdateTabsClosingMap(int index, int delta);
// Invoked from StoppedDraggingTabs to cleanup |tab|. If |tab| is known
// |is_first_tab| is set to true.
void StoppedDraggingTab(Tab* tab, bool* is_first_tab);
// Finds |tab| in the |tab_closing_map_| and returns a pair of iterators
// indicating precisely where it is.
FindClosingTabResult FindClosingTab(const Tab* tab);
// Invoked when a mouse event occurs over |source|. Potentially switches the
// |stacked_layout_|.
void UpdateStackedLayoutFromMouseEvent(views::View* source,
......@@ -563,12 +549,9 @@ class TabStrip : public views::AccessiblePaneView,
// There is a one-to-one mapping between each of the tabs in the
// TabStripController (TabStripModel) and |tabs_|. Because we animate tab
// removal there exists a period of time where a tab is displayed but not in
// the model. When this occurs the tab is removed from |tabs_| and placed in
// |tabs_closing_map_|. When the animation completes the tab is removed from
// |tabs_closing_map_|. The painting code ensures both sets of tabs are
// painted, and the event handling code ensures only tabs in |tabs_| are used.
// the model. When this occurs the tab is removed from |tabs_|, but remains
// in |layout_helper_| until the remove animation completes.
views::ViewModelT<Tab> tabs_;
TabsClosingMap tabs_closing_map_;
// Map associating each group to its TabGroupHeader instance.
std::map<TabGroupId, std::unique_ptr<TabGroupHeader>> group_headers_;
......
......@@ -54,11 +54,13 @@ enum class ViewType {
struct TabStripLayoutHelper::TabSlot {
static TabStripLayoutHelper::TabSlot CreateForTab(
Tab* tab,
TabAnimationState::TabOpenness openness,
TabAnimationState::TabPinnedness pinned,
base::OnceClosure removed_callback) {
TabStripLayoutHelper::TabSlot slot;
slot.type = ViewType::kTab;
slot.tab = tab;
TabAnimationState initial_state = TabAnimationState::ForIdealTabState(
openness, pinned, TabAnimationState::TabActiveness::kInactive, 0);
slot.animation = std::make_unique<TabAnimation>(
......@@ -86,9 +88,15 @@ struct TabStripLayoutHelper::TabSlot {
return group.value();
}
Tab* GetTab() const {
DCHECK(tab.has_value());
return tab.value();
}
ViewType type;
std::unique_ptr<TabAnimation> animation;
base::Optional<TabGroupId> group;
base::Optional<Tab*> tab;
};
TabStripLayoutHelper::TabStripLayoutHelper(
......@@ -107,6 +115,17 @@ TabStripLayoutHelper::TabStripLayoutHelper(
TabStripLayoutHelper::~TabStripLayoutHelper() = default;
std::vector<Tab*> TabStripLayoutHelper::GetTabs() {
std::vector<Tab*> tabs;
for (const TabSlot& slot : slots_) {
if (slot.type == ViewType::kTab) {
tabs.push_back(slot.GetTab());
}
}
return tabs;
}
bool TabStripLayoutHelper::IsAnimating() const {
return animation_timer_.IsRunning();
}
......@@ -123,32 +142,48 @@ int TabStripLayoutHelper::GetPinnedTabCount() const {
void TabStripLayoutHelper::InsertTabAtNoAnimation(
int model_index,
Tab* tab,
base::OnceClosure tab_removed_callback,
TabAnimationState::TabActiveness active,
TabAnimationState::TabPinnedness pinned) {
const int slot_index = GetSlotIndexForTabModelIndex(model_index);
slots_.insert(slots_.begin() + slot_index,
TabSlot::CreateForTab(TabAnimationState::TabOpenness::kOpen,
pinned, std::move(tab_removed_callback)));
slots_.insert(
slots_.begin() + slot_index,
TabSlot::CreateForTab(tab, TabAnimationState::TabOpenness::kOpen, pinned,
std::move(tab_removed_callback)));
}
void TabStripLayoutHelper::InsertTabAt(
int model_index,
Tab* tab,
base::OnceClosure tab_removed_callback,
TabAnimationState::TabActiveness active,
TabAnimationState::TabPinnedness pinned) {
const int slot_index = GetSlotIndexForTabModelIndex(model_index);
slots_.insert(slots_.begin() + slot_index,
TabSlot::CreateForTab(TabAnimationState::TabOpenness::kClosed,
slots_.insert(
slots_.begin() + slot_index,
TabSlot::CreateForTab(tab, TabAnimationState::TabOpenness::kClosed,
pinned, std::move(tab_removed_callback)));
AnimateSlot(slot_index,
slots_[slot_index].animation->target_state().WithOpenness(
TabAnimationState::TabOpenness::kOpen));
}
void TabStripLayoutHelper::RemoveTabAt(int model_index) {
void TabStripLayoutHelper::CloseTabAt(int model_index) {
// TODO(958173): Animate closed.
slots_.erase(slots_.begin() + GetSlotIndexForTabModelIndex(model_index));
TabAnimation* animation =
slots_[GetSlotIndexForTabModelIndex(model_index)].animation.get();
animation->AnimateTo(animation->target_state().WithOpenness(
TabAnimationState::TabOpenness::kClosed));
}
void TabStripLayoutHelper::OnTabDestroyed(Tab* tab) {
auto it =
std::find_if(slots_.begin(), slots_.end(), [tab](const TabSlot& slot) {
return slot.type == ViewType::kTab && slot.GetTab() == tab;
});
DCHECK(it != slots_.end());
slots_.erase(it);
}
void TabStripLayoutHelper::MoveTab(
......@@ -254,8 +289,11 @@ void TabStripLayoutHelper::UpdateIdealBounds(int available_width) {
auto pinned = i <= last_pinned_tab_slot_index
? TabAnimationState::TabPinnedness::kPinned
: TabAnimationState::TabPinnedness::kUnpinned;
ideal_animation_states.push_back(TabAnimationState::ForIdealTabState(
TabAnimationState::TabOpenness::kOpen, pinned, active, 0));
auto open = slots_[i].animation->target_state().IsFullyClosed()
? TabAnimationState::TabOpenness::kClosed
: TabAnimationState::TabOpenness::kOpen;
ideal_animation_states.push_back(
TabAnimationState::ForIdealTabState(open, pinned, active, 0));
}
const std::vector<gfx::Rect> bounds = CalculateTabBounds(
......@@ -271,9 +309,12 @@ void TabStripLayoutHelper::UpdateIdealBounds(int available_width) {
const TabSlot& slot = slots_[i];
switch (slot.type) {
case ViewType::kTab:
if (!slot.animation->target_state().IsFullyClosed()) {
tabs->set_ideal_bounds(current_tab_model_index, bounds[i]);
UpdateCachedTabWidth(i, bounds[i].width(), i == active_tab_slot_index);
UpdateCachedTabWidth(i, bounds[i].width(),
i == active_tab_slot_index);
++current_tab_model_index;
}
break;
case ViewType::kGroupHeader:
group_headers[slot.GetGroup()]->SetBoundsRect(bounds[i]);
......@@ -314,8 +355,15 @@ int TabStripLayoutHelper::LayoutTabs(int available_width) {
std::vector<gfx::Rect> bounds = CalculateTabBounds(
GetTabSizeInfo(), GetCurrentTabStates(), available_width);
// TODO(958173): Assume for now that there are no closing tabs or headers.
DCHECK_EQ(bounds.size(), tabs->view_size() + group_headers.size());
if (DCHECK_IS_ON()) {
int num_closing_tabs = 0;
for (Tab* tab : GetTabs()) {
if (tab->closing())
++num_closing_tabs;
}
DCHECK_EQ(bounds.size(),
tabs->view_size() + num_closing_tabs + group_headers.size());
}
int trailing_x = 0;
......@@ -325,8 +373,9 @@ int TabStripLayoutHelper::LayoutTabs(int available_width) {
for (size_t i = 0; i < bounds.size(); i++) {
switch (slots_[i].type) {
case ViewType::kTab: {
if (!tabs->view_at(current_tab_model_index)->dragging()) {
tabs->view_at(current_tab_model_index)->SetBoundsRect(bounds[i]);
Tab* tab = slots_[i].GetTab();
if (!tab->dragging()) {
tab->SetBoundsRect(bounds[i]);
trailing_x = std::max(trailing_x, bounds[i].right());
// TODO(958173): We shouldn't need to update the cached widths here,
// since they're also updated in UpdateIdealBounds. However, tests
......@@ -335,6 +384,7 @@ int TabStripLayoutHelper::LayoutTabs(int available_width) {
current_tab_model_index, bounds[i].width(),
current_tab_model_index == active_tab_model_index);
}
if (!slots_[i].animation->target_state().IsFullyClosed())
++current_tab_model_index;
break;
}
......@@ -353,7 +403,8 @@ int TabStripLayoutHelper::LayoutTabs(int available_width) {
int TabStripLayoutHelper::GetSlotIndexForTabModelIndex(int model_index) const {
int current_model_index = 0;
for (size_t i = 0; i < slots_.size(); i++) {
if (slots_[i].type == ViewType::kTab) {
if (slots_[i].type == ViewType::kTab &&
!slots_[i].animation->target_state().IsFullyClosed()) {
if (current_model_index == model_index)
return i;
++current_model_index;
......
......@@ -36,6 +36,10 @@ class TabStripLayoutHelper {
base::RepeatingClosure on_animation_progressed);
~TabStripLayoutHelper();
// Returns a vector of all tabs in the strip, including both closing tabs
// and tabs still in the model.
std::vector<Tab*> GetTabs();
// Returns whether any animations for tabs or group headers are in progress.
bool IsAnimating() const;
......@@ -50,6 +54,7 @@ class TabStripLayoutHelper {
// Inserts a new tab at |index|, without animation. |tab_removed_callback|
// will be invoked if the tab is removed at the end of a remove animation.
void InsertTabAtNoAnimation(int model_index,
Tab* tab,
base::OnceClosure tab_removed_callback,
TabAnimationState::TabActiveness active,
TabAnimationState::TabPinnedness pinned);
......@@ -57,14 +62,18 @@ class TabStripLayoutHelper {
// Inserts a new tab at |index|, with animation. |tab_removed_callback| will
// be invoked if the tab is removed at the end of a remove animation.
void InsertTabAt(int model_index,
Tab* tab,
base::OnceClosure tab_removed_callback,
TabAnimationState::TabActiveness active,
TabAnimationState::TabPinnedness pinned);
// Removes the tab at |index|. TODO(958173): This should invoke the associated
// |tab_removed_callback| but currently does not, as it would duplicate
// TabStrip::RemoveTabDelegate::AnimationEnded.
void RemoveTabAt(int model_index);
// Marks the tab at |model_index| as closing. Invoked when the remove
// animation begins and the tab is removed from the model.
void CloseTabAt(int model_index);
// Invoked when |tab| has been destroyed by TabStrip (i.e. the remove
// animation has completed).
void OnTabDestroyed(Tab* tab);
// Moves the tab at |prev_index| with group |group_at_prev_index| to
// |new_index|. Also updates the group header's location if necessary.
......@@ -90,9 +99,11 @@ class TabStripLayoutHelper {
// Finishes all in-progress animations.
void CompleteAnimations();
// TODO(958173): Temporary method. Like CompleteAnimations, but does not call
// any associated |tab_removed_callback| or |header_removed_callback|. See
// comment on TabStripAnimator::CompleteAnimationsWithoutDestroyingTabs.
// TODO(958173): Temporary method that completes running animations
// without invoking the callback to destroy removed tabs. Use to hand
// off animation (and removed tab destruction) responsibilities from
// this animator to elsewhere without teleporting tabs or destroying
// the same tab more than once.
void CompleteAnimationsWithoutDestroyingTabs();
// Generates and sets the ideal bounds for the views in |tabs| and
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment