1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_LAYOUT_HELPER_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_LAYOUT_HELPER_H_
#include <optional>
#include <vector>
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ref.h"
#include "chrome/browser/ui/tabs/tab_types.h"
#include "chrome/browser/ui/views/tabs/tab_layout_state.h"
#include "chrome/browser/ui/views/tabs/tab_slot_view.h"
#include "chrome/browser/ui/views/tabs/tab_strip_layout.h"
#include "chrome/browser/ui/views/tabs/tab_strip_layout_types.h"
#include "chrome/browser/ui/views/tabs/tab_width_constraints.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/view_model.h"
class Tab;
class TabGroupHeader;
class TabContainerController;
namespace tab_groups {
class TabGroupId;
}
// Helper class for TabStrip, that is responsible for calculating and assigning
// layouts for tabs and group headers. It tracks animations and changes to the
// model so that it has all necessary information for layout purposes.
class TabStripLayoutHelper {
public:
using GetTabsCallback = base::RepeatingCallback<views::ViewModelT<Tab>*()>;
TabStripLayoutHelper(const TabContainerController& controller,
GetTabsCallback get_tabs_callback);
TabStripLayoutHelper(const TabStripLayoutHelper&) = delete;
TabStripLayoutHelper& operator=(const TabStripLayoutHelper&) = delete;
~TabStripLayoutHelper();
// Returns a vector of all tabs in the strip, including both closing tabs
// and tabs still in the model.
std::vector<Tab*> GetTabs() const;
// Get all tab slot views in visual order, including all tabs from
// GetTabs() and all tab group headers.
std::vector<TabSlotView*> GetTabSlotViews() const;
LayoutDomain layout_domain() { return tab_strip_layout_domain_; }
// Returns the number of pinned tabs in the tabstrip.
size_t GetPinnedTabCount() const;
// Returns a map of all tab groups and their bounds.
const std::map<tab_groups::TabGroupId, gfx::Rect>& group_header_ideal_bounds()
const {
return group_header_ideal_bounds_;
}
// Inserts a new tab at `index`.
void InsertTabAt(int model_index, Tab* tab, TabPinned pinned);
// Marks the tab at `model_index` as closing, but does not remove it from
// `slots_`.
void MarkTabAsClosing(int model_index, Tab* tab);
// Removes `tab` from `slots_`.
void RemoveTab(Tab* tab);
// Moves the tab at `prev_index` with group `moving_tab_group` to `new_index`.
// Also updates the group header's location if necessary.
void MoveTab(std::optional<tab_groups::TabGroupId> moving_tab_group,
int prev_index,
int new_index);
// Sets the tab at `index`'s pinned state to `pinned`.
void SetTabPinned(int model_index, TabPinned pinned);
// Inserts a new group header for `group`.
void InsertGroupHeader(tab_groups::TabGroupId group, TabGroupHeader* header);
// Removes the group header for `group`.
void RemoveGroupHeader(tab_groups::TabGroupId group);
// Ensures the group header for `group` is at the correct index. Should be
// called externally when group membership changes but nothing else about the
// layout does.
void UpdateGroupHeaderIndex(tab_groups::TabGroupId group);
// Changes the active tab from `prev_active_index` to `new_active_index`.
void SetActiveTab(std::optional<size_t> prev_active_index,
std::optional<size_t> new_active_index);
// Calculates the smallest width the tabs can occupy.
int CalculateMinimumWidth();
// Calculates the width the tabs would occupy if they have enough space.
int CalculatePreferredWidth();
// Generates and sets the ideal bounds for the views in `tabs` and
// `group_headers`. Returns the total width occupied by the new ideal bounds.
int UpdateIdealBounds(int available_width);
private:
struct TabSlot;
// Calculates the bounds each tab should occupy, subject to the provided
// width constraint.
std::pair<std::vector<gfx::Rect>, LayoutDomain> CalculateIdealBounds(
std::optional<int> available_width);
// Given `model_index` for a tab already present in `slots_`, return
// the corresponding index in `slots_`.
int GetSlotIndexForExistingTab(int model_index) const;
// For a new tab at `new_model_index`, get the insertion index in
// `slots_`. `group` is the new tab's group.
int GetSlotInsertionIndexForNewTab(
int new_model_index,
std::optional<tab_groups::TabGroupId> group) const;
// Returns the slot corresponding to the first tab in a group
// in the view.
std::optional<int> GetFirstTabSlotForGroup(
tab_groups::TabGroupId group) const;
// Used internally in the above two functions. For a tabstrip with N
// tabs, this takes 0 <= `model_index` <= N and returns the first
// possible slot corresponding to this model index.
//
// This means that if `model_index` is the first tab in a group, the
// returned slot index will point to the group header. For other tabs,
// the slot index corresponding to that tab will be returned. Finally,
// if `model_index` = N, slots_.size() will be returned.
int GetFirstSlotIndexForTabModelIndex(int model_index) const;
// Given a group ID, returns the index of its header's corresponding TabSlot
// in `slots_`.
int GetSlotIndexForGroupHeader(tab_groups::TabGroupId group) const;
// If the tab at `index` is split, returns the index of the adjacent split
// tab. Otherwise returns `std::nullopt`.
std::optional<int> GetAdjacentSplitTab(int index) const;
// True iff the slot at index `i` is a tab that is in a collapsed group.
bool SlotIsCollapsedTab(int i) const;
// The owning TabContainer's controller.
const raw_ref<const TabContainerController, DanglingUntriaged> controller_;
// Callback to get the necessary View objects from the owning tabstrip.
GetTabsCallback get_tabs_callback_;
// Current collation of tabs and group headers, along with necessary data to
// run layout and animations for those Views.
std::vector<TabSlot> slots_;
// Contains the ideal bounds of tab group headers.
std::map<tab_groups::TabGroupId, gfx::Rect> group_header_ideal_bounds_;
LayoutDomain tab_strip_layout_domain_;
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_LAYOUT_HELPER_H_
|