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
|
// 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_GROUP_HEADER_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_GROUP_HEADER_H_
#include <string_view>
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/time/time.h"
#include "chrome/browser/ui/views/tabs/tab_slot_view.h"
#include "components/tab_groups/tab_group_id.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/view_targeter_delegate.h"
#include "ui/views/widget/widget_observer.h"
class TabSlotController;
class TabGroupStyle;
struct TabSizeInfo;
class TabStyle;
namespace views {
class ImageView;
class Label;
class View;
} // namespace views
// View for tab group headers in the tab strip, which are markers of group
// boundaries. There is one header for each group, which is included in the tab
// strip flow and positioned left of the leftmost tab in the group.
class TabGroupHeader : public TabSlotView,
public views::ContextMenuController,
public views::ViewTargeterDelegate {
METADATA_HEADER(TabGroupHeader, TabSlotView)
public:
TabGroupHeader(TabSlotController& tab_slot_controller,
const tab_groups::TabGroupId& group,
const TabGroupStyle& style);
TabGroupHeader(const TabGroupHeader&) = delete;
TabGroupHeader& operator=(const TabGroupHeader&) = delete;
~TabGroupHeader() override;
void Init(const tab_groups::TabGroupId& group);
// TabSlotView:
bool OnKeyPressed(const ui::KeyEvent& event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnFocus() override;
void OnThemeChanged() override;
TabSlotView::ViewType GetTabSlotViewType() const override;
TabSizeInfo GetTabSizeInfo() const override;
gfx::Rect GetAnchorBoundsInScreen() const override;
void OnGroupContentsChanged();
// views::ContextMenuController:
void ShowContextMenuForViewImpl(
views::View* source,
const gfx::Point& point,
ui::mojom::MenuSourceType source_type) override;
// views::ViewTargeterDelegate:
bool DoesIntersectRect(const views::View* target,
const gfx::Rect& rect) const override;
// Updates our visual state according to the tab_groups::TabGroupVisualData
// for our group.
// TODO(crbug.com/372296676): Make TabGroupHeader observe the group for
// changes to cut down on the number of times we recalculate the view.
void VisualsChanged();
int GetCollapsedHeaderWidth() const;
// Removes {editor_bubble_tracker_} from observing the widget.
void RemoveObserverFromWidget(views::Widget* widget);
// Enables or disables attention indicator on a tab group.
void SetTabGroupNeedsAttention(bool needs_attention);
// Returns whether the attention indicator should be shown.
bool GetShowingAttentionIndicator();
// Returns the title text for testing.
std::u16string_view GetTitleTextForTesting() const;
bool is_collapsed_for_testing() const { return is_collapsed_; }
private:
friend class TabGroupEditorBubbleViewDialogBrowserTest;
FRIEND_TEST_ALL_PREFIXES(TabStripSaveBrowsertest, AttentionIndicatorIsShown);
// Calculate the width for this View.
int GetDesiredWidth() const;
// Determines if the sync icon should be shown in the header.
bool ShouldShowHeaderIcon() const;
// Updates the local is_collapsed_ state.
void SetCollapsedState();
void UpdateTitleView();
void UpdateSyncIconView();
void UpdateAttentionIndicatorView();
void UpdateIsCollapsed();
// Creates a squircle (cross between a square and a circle).
void CreateHeaderWithoutTitle();
// Creates a round rect, similar to the shape of a tab when hovered but not
// selected.
void CreateHeaderWithTitle();
void UpdateTooltipText();
void UpdateAccessibleName();
const raw_ref<TabSlotController> tab_slot_controller_;
// The title chip for the tab group header which comprises of title text if
// there is any, and a background color. The size and color of the chip are
// set in VisualsChanged().
const raw_ptr<views::View> title_chip_;
// The title of the tab group. Text and color of the title are set in
// VisualsChanged().
const raw_ptr<views::Label> title_;
// The sync icon that is displayed in the tab group header of saved groups in
// the tabstrip.
const raw_ptr<views::ImageView> sync_icon_;
// The circle indicator rendered after the title when a tab group has
// needs_attention_ set to true.
const raw_ptr<views::ImageView> attention_indicator_;
const raw_ref<const TabGroupStyle> group_style_;
const raw_ptr<const TabStyle> tab_style_;
// The current title of the group.
std::u16string group_title_;
// The current color of the group.
SkColor color_;
// Determines if we should show the header icon in front of the title.
bool should_show_header_icon_;
// Local saved collapsed state. When this differs from
// `TabSlotController::IsGroupCollapsed()`, then the collapsed state has
// changed in the model and we need to react to that.
bool is_collapsed_;
// Determines if the tab group should show the attention indicator.
bool needs_attention_ = false;
base::CallbackListSubscription title_text_changed_subscription_;
// Tracks whether our editor bubble is open. At most one can be open
// at once.
class EditorBubbleTracker : public views::WidgetObserver {
public:
explicit EditorBubbleTracker(TabSlotController& tab_slot_controller);
~EditorBubbleTracker() override;
void Opened(views::Widget* bubble_widget);
bool is_open() const { return is_open_; }
views::Widget* widget() const { return widget_; }
// views::WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override;
private:
bool is_open_ = false;
raw_ptr<views::Widget, AcrossTasksDanglingUntriaged> widget_;
// Outlives this because it's a dependency inversion interface for the
// header's parent View.
raw_ref<TabSlotController> tab_slot_controller_;
};
EditorBubbleTracker editor_bubble_tracker_;
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_GROUP_HEADER_H_
|