File: compound_tab_container.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (226 lines) | stat: -rw-r--r-- 10,750 bytes parent folder | download | duplicates (5)
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Copyright 2022 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_COMPOUND_TAB_CONTAINER_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_COMPOUND_TAB_CONTAINER_H_

#include <memory>

#include "base/memory/raw_ptr.h"
#include "chrome/browser/ui/views/tabs/tab_container.h"
#include "chrome/browser/ui/views/tabs/tab_container_controller.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/view_targeter_delegate.h"

class TabHoverCardController;
class TabDragContextBase;

// Composes two TabContainers into one, keeping the pinned tabs in one container
// and the unpinned tabs in the other.
// Indices in the public and private API are all in overall indices, unless
// specifically noted otherwise as being relative to a specific container.
class CompoundTabContainer : public TabContainer,
                             public views::ViewTargeterDelegate {
  METADATA_HEADER(CompoundTabContainer, TabContainer)

 public:
  CompoundTabContainer(TabContainerController& controller,
                       TabHoverCardController* hover_card_controller,
                       TabDragContextBase* drag_context,
                       TabSlotController& tab_slot_controller,
                       views::View* scroll_contents_view);
  ~CompoundTabContainer() override;

  // TabContainer:
  void SetAvailableWidthCallback(
      base::RepeatingCallback<int()> available_width_callback) override;
  std::vector<Tab*> AddTabs(
      std::vector<TabInsertionParams> tabs_params) override;
  void MoveTab(int from_model_index, int to_model_index) override;
  void RemoveTab(int index, bool was_active) override;
  void SetTabPinned(int model_index, TabPinned pinned) override;
  void SetActiveTab(std::optional<size_t> prev_active_index,
                    std::optional<size_t> new_active_index) override;
  Tab* RemoveTabFromViewModel(int model_index) override;
  Tab* AddTabToViewModel(Tab* tab, int model_index, TabPinned pinned) override;
  void ReturnTabSlotView(TabSlotView* view) override;
  void ScrollTabToVisible(int model_index) override;
  void ScrollTabContainerByOffset(int offset) override;
  void OnGroupCreated(const tab_groups::TabGroupId& group) override;
  void OnGroupEditorOpened(const tab_groups::TabGroupId& group) override;
  void OnGroupMoved(const tab_groups::TabGroupId& group) override;
  void OnGroupContentsChanged(const tab_groups::TabGroupId& group) override;
  void OnGroupVisualsChanged(
      const tab_groups::TabGroupId& group,
      const tab_groups::TabGroupVisualData* old_visuals,
      const tab_groups::TabGroupVisualData* new_visuals) override;
  void OnGroupClosed(const tab_groups::TabGroupId& group) override;
  void ToggleTabGroup(const tab_groups::TabGroupId& group,
                      bool is_collapsing,
                      ToggleTabGroupCollapsedStateOrigin origin) override;
  void UpdateTabGroupVisuals(tab_groups::TabGroupId group_id) override;
  void NotifyTabstripBubbleOpened() override;
  void NotifyTabstripBubbleClosed() override;
  void OnSplitCreated(const std::vector<int>& indices) override;
  void OnSplitRemoved(const std::vector<int>& indices) override;
  void OnSplitContentsChanged(const std::vector<int>& indices) override;
  std::optional<int> GetModelIndexOf(
      const TabSlotView* slot_view) const override;
  Tab* GetTabAtModelIndex(int index) const override;
  int GetTabCount() const override;
  std::optional<int> GetModelIndexOfFirstNonClosingTab(Tab* tab) const override;
  void UpdateHoverCard(
      Tab* tab,
      TabSlotController::HoverCardUpdateType update_type) override;
  void HandleLongTap(ui::GestureEvent* event) override;
  bool IsRectInContentArea(const gfx::Rect& rect) override;
  std::optional<ZOrderableTabContainerElement> GetLeadingElementForZOrdering()
      const override;
  std::optional<ZOrderableTabContainerElement> GetTrailingElementForZOrdering()
      const override;
  void OnTabSlotAnimationProgressed(TabSlotView* view) override;
  void OnTabCloseAnimationCompleted(Tab* tab) override;
  void InvalidateIdealBounds() override;
  void AnimateToIdealBounds() override;
  bool IsAnimating() const override;
  void CancelAnimation() override;
  void CompleteAnimationAndLayout() override;
  int GetAvailableWidthForTabContainer() const override;
  void EnterTabClosingMode(std::optional<int> override_width,
                           CloseTabSource source) override;
  void ExitTabClosingMode() override;
  void SetTabSlotVisibility() override;
  bool InTabClose() override;
  TabGroupViews* GetGroupViews(tab_groups::TabGroupId group_id) const override;
  const std::map<tab_groups::TabGroupId, std::unique_ptr<TabGroupViews>>&
  get_group_views_for_testing() const override;
  gfx::Rect GetIdealBounds(int model_index) const override;
  gfx::Rect GetIdealBounds(tab_groups::TabGroupId group) const override;

  // views::View
  gfx::Size GetMinimumSize() const override;
  views::SizeBounds GetAvailableSize(const View* child) const override;
  gfx::Size CalculatePreferredSize(
      const views::SizeBounds& available_size) const override;
  views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
  void Layout(PassKey) override;
  void PaintChildren(const views::PaintInfo& paint_info) override;
  void ChildPreferredSizeChanged(views::View* child) override;

  // BrowserRootView::DropTarget:
  std::optional<BrowserRootView::DropIndex> GetDropIndex(
      const ui::DropTargetEvent& event) override;
  BrowserRootView::DropTarget* GetDropTarget(
      gfx::Point loc_in_local_coords) override;
  views::View* GetViewForDrop() override;
  void HandleDragUpdate(
      const std::optional<BrowserRootView::DropIndex>& index) override;
  void HandleDragExited() override;

  // views::ViewTargeterDelegate:
  views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override;

  // Notifies this CompoundTabContainer that `tab_slot_view` must be animated to
  // `target_bounds`. `pinned` indicates whether these bounds are relative to
  // `pinned_tab_container_` or `unpinned_tab_container_`.
  void UpdateAnimationTarget(TabSlotView* tab_slot_view,
                             gfx::Rect target_bounds,
                             TabPinned pinned);

 private:
  int NumPinnedTabs() const;

  // Returns true iff `index` is a valid index in the joint viewmodel index
  // space of the two TabContainers, i.e. if there's a Tab view that corresponds
  // to `index`. These index spaces are different when the model has added or
  // removed a tab but we haven't finished processing that change ourselves.
  bool IsValidViewModelIndex(int index) const;

  // Moves the tab at `from_model_index` from whichever TabContainer currently
  // holds it into the other TabContainer, inserting it into that container at
  // the index that corresponds to `to_model_index`.
  void TransferTabBetweenContainers(int from_model_index, int to_model_index);

  // Converts `ideal_bounds` from `unpinned_tab_container_`'s coordinate space
  // into local coordinate space. References ideal bounds instead of current
  // bounds to correctly account for any ongoing animations in the pinned tab
  // container.
  gfx::Rect ConvertUnpinnedContainerIdealBoundsToLocal(
      gfx::Rect ideal_bounds) const;

  // Animates `tab` to `ideal_bounds` using `bounds_animator_`. Retargets an
  // existing animation if one is already running.
  void AnimateTabTo(Tab* tab, gfx::Rect ideal_bounds);

  // Returns the child TabContainer that should contain `view`. NB this can be
  // different from `view->parent()` e.g. while `view` is being dragged.
  TabContainer& GetTabContainerFor(TabSlotView* view) const;

  // Returns the child TabContainer that should handle text drag and drop events
  // at `point_in_local_coords`.
  TabContainer* GetTabContainerForDrop(gfx::Point point_in_local_coords) const;

  // Returns the child TabContainer that contains `point_in_local_coords`, or
  // nullptr if neither contain it. If both contain it, chooses based on where
  // `point_in_local_coords` is within the overlap area.
  TabContainer* GetTabContainerAt(gfx::Point point_in_local_coords) const;

  // Returns the x position that `unpinned_tab_container_` should be at after
  // any running animations finish.
  int GetUnpinnedContainerIdealLeadingX() const;

  int GetAvailableWidthForUnpinnedTabContainer() const;

  // Computes the size of this compound container assuming the pinned and
  // unpinned containers have the given sizes.
  gfx::Size GetCombinedSizeForTabContainerSizes(gfx::Size pinned_size,
                                                gfx::Size unpinned_size) const;

  // Private getter to retrieve the visible rect of the scroll container.
  std::optional<gfx::Rect> GetVisibleContentRect() const;

  // Animates and scrolls the tab container from the start_edge to the
  // target_edge. If the target_edge is beyond the tab strip it will be clamped
  // bounds of the tabstrip.
  void AnimateScrollToShowXCoordinate(const int start_edge,
                                      const int target_edge);

  const raw_ref<TabContainerController> controller_;

  // Adapts `pinned_tab_container_`'s interactions with the model to account for
  // it only holding pinned tabs.
  const std::unique_ptr<TabContainerController>
      pinned_tab_container_controller_;
  // The TabContainer that holds the pinned tabs.
  const raw_ref<TabContainer, DanglingUntriaged> pinned_tab_container_;

  // Adapts `unpinned_tab_container_`'s interactions with the model to account
  // for it only holding unpinned tabs.
  const std::unique_ptr<TabContainerController>
      unpinned_tab_container_controller_;
  // The TabContainer that holds the unpinned tabs.
  const raw_ref<TabContainer, DanglingUntriaged> unpinned_tab_container_;

  base::RepeatingCallback<int()> available_width_callback_;

  const raw_ptr<TabHoverCardController, DanglingUntriaged>
      hover_card_controller_;

  // The View that is to be scrolled by `tab_scrolling_animation_`. May be
  // nullptr in tests.
  const raw_ptr<views::View> scroll_contents_view_;

  // Responsible for animating the scroll of the tab container.
  std::unique_ptr<gfx::LinearAnimation> tab_scrolling_animation_;

  // Animates tabs between pinned and unpinned states.
  views::BoundsAnimator bounds_animator_;

  // The sub-container that handled the last drag/drop update, if any. Used to
  // ensure HandleDragExited is called when necessary.
  raw_ptr<TabContainer, DanglingUntriaged> current_text_drop_target_ = nullptr;
};

#endif  // CHROME_BROWSER_UI_VIEWS_TABS_COMPOUND_TAB_CONTAINER_H_