File: hover_button.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 (178 lines) | stat: -rw-r--r-- 6,513 bytes parent folder | download | duplicates (3)
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
// Copyright 2017 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_CONTROLS_HOVER_BUTTON_H_
#define CHROME_BROWSER_UI_VIEWS_CONTROLS_HOVER_BUTTON_H_

#include <string>
#include <vector>

#include "base/callback_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/types/pass_key.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/metadata/view_factory.h"

namespace media_router {
FORWARD_DECLARE_TEST(CastDialogSinkButtonTest, SetTitleLabel);
FORWARD_DECLARE_TEST(CastDialogSinkButtonTest, SetStatusLabel);
}  // namespace media_router

namespace webid {
class AccountSelectionViewTestBase;
}

namespace ui {
class ImageModel;
}

namespace views {
class Label;
class View;
}  // namespace views

class HoverButtonTest;
class HoverButtonController;
class PageInfoBubbleViewBrowserTest;

// A button taking the full width of its parent that shows a background color
// when hovered over.
class HoverButton : public views::LabelButton {
  METADATA_HEADER(HoverButton, views::LabelButton)

 public:
  HoverButton();

  // Creates a single line hover button with no icon.
  HoverButton(PressedCallback callback, const std::u16string& text);

  // Creates a single line hover button with an icon.
  HoverButton(PressedCallback callback,
              const ui::ImageModel& icon,
              const std::u16string& text);

  // Creates a HoverButton with custom subviews. |icon_view| replaces the
  // LabelButton icon, and titles appear on separate rows. An empty |subtitle|
  // and |footer| will vertically center |title|. |footer| will be shown below
  // |title| and |subtitle|. |secondary_view|, when set, is shown on the
  // opposite side of the button from |icon_view|. When
  // |add_vertical_label_spacing| is false it will not add vertical spacing to
  // the label wrapper. Warning: |icon_view| must have a fixed size and be
  // correctly set during its constructor for the HoverButton to layout
  // correctly.
  HoverButton(
      PressedCallback callback,
      std::unique_ptr<views::View> icon_view,
      const std::u16string& title,
      const std::u16string& subtitle = std::u16string(),
      std::unique_ptr<views::View> secondary_view = nullptr,
      bool add_vertical_label_spacing = true,
      const std::u16string& footer = std::u16string(),
      int icon_label_spacing = ChromeLayoutProvider::Get()->GetDistanceMetric(
          views::DISTANCE_RELATED_LABEL_HORIZONTAL),
      bool multiline_subtitle = false);

  HoverButton(const HoverButton&) = delete;
  HoverButton& operator=(const HoverButton&) = delete;
  ~HoverButton() override;

  // views::LabelButton:
  void SetCallback(PressedCallback callback) override;
  gfx::Size CalculatePreferredSize(
      const views::SizeBounds& available_size) const override;
  void SetBorder(std::unique_ptr<views::Border> b) override;
  void PreferredSizeChanged() override;
  void OnViewBoundsChanged(View* observed_view) override;

  // Sets the text style of the title considering the color of the background.
  // Passing |background_color| makes sure that the text color will not be
  // changed to a color that is not readable on the specified background.
  // Sets the title's enabled color to |color_id|, if present.
  void SetTitleTextStyle(views::style::TextStyle text_style,
                         SkColor background_color,
                         std::optional<ui::ColorId> color_id);

  // Set the text context and style of the subtitle.
  void SetSubtitleTextStyle(int text_context,
                            views::style::TextStyle text_style);

  // Set the text context and style of the footer.
  void SetFooterTextStyle(int text_context, views::style::TextStyle text_style);

  // Adds a11y text to the button, which will be read out when the button is
  // focused.
  void AddExtraAccessibleText(const std::u16string& text);

  void SetIconHorizontalMargins(int left, int right);

  PressedCallback& callback(base::PassKey<HoverButtonController>) {
    return callback_;
  }

  views::Label* title() { return title_; }
  const views::Label* title() const { return title_; }

 protected:
  // views::MenuButton:
  KeyClickAction GetKeyClickActionForEvent(const ui::KeyEvent& event) override;
  void StateChanged(ButtonState old_state) override;
  views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;

  views::Label* subtitle() const { return subtitle_; }
  views::Label* footer() const { return footer_; }
  views::View* icon_view() const { return icon_view_; }
  views::View* secondary_view() const { return secondary_view_; }

 private:
  FRIEND_TEST_ALL_PREFIXES(media_router::CastDialogSinkButtonTest,
                           SetTitleLabel);
  FRIEND_TEST_ALL_PREFIXES(media_router::CastDialogSinkButtonTest,
                           SetStatusLabel);
  friend class webid::AccountSelectionViewTestBase;
  friend class HoverButtonTest;
  friend class PageInfoBubbleViewBrowserTest;

  // Updates the accessible name and tooltip of the button if necessary based on
  // `title_` and `subtitle_` labels.
  void UpdateTooltipAndAccessibleName();

  void OnPressed(const ui::Event& event);

  // Create the label for subtitle or footer.
  std::unique_ptr<views::Label> CreateSecondaryLabel(
      const std::u16string& text);

  PressedCallback callback_;

  raw_ptr<views::Label> title_ = nullptr;
  raw_ptr<views::View> icon_wrapper_ = nullptr;
  raw_ptr<views::View> label_wrapper_ = nullptr;
  raw_ptr<views::Label> subtitle_ = nullptr;
  raw_ptr<views::Label> footer_ = nullptr;
  raw_ptr<views::View> icon_view_ = nullptr;
  raw_ptr<views::View> secondary_view_ = nullptr;

  std::u16string additional_accessible_text_;

  std::vector<base::CallbackListSubscription> text_changed_subscriptions_;

  base::ScopedObservation<views::View, views::ViewObserver> label_observation_{
      this};
};

BEGIN_VIEW_BUILDER(, HoverButton, views::LabelButton)
VIEW_BUILDER_METHOD(SetTitleTextStyle,
                    views::style::TextStyle,
                    SkColor,
                    std::optional<ui::ColorId>)
END_VIEW_BUILDER

DEFINE_VIEW_BUILDER(, HoverButton)

#endif  // CHROME_BROWSER_UI_VIEWS_CONTROLS_HOVER_BUTTON_H_