File: tab_strip_layout_helper.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (167 lines) | stat: -rw-r--r-- 6,472 bytes parent folder | download | duplicates (4)
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_