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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
ash / style / pill_button.h [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_STYLE_PILL_BUTTON_H_
#define ASH_STYLE_PILL_BUTTON_H_
#include "ash/ash_export.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/color/color_id.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/metadata/view_factory.h"
namespace ash {
class BlurredBackgroundShield;
// A label button with a rounded rectangle background. It can have an icon
// inside as well, and its text and background colors will be different based on
// the type of the button.
class ASH_EXPORT PillButton : public views::LabelButton {
METADATA_HEADER(PillButton, views::LabelButton)
public:
using ColorVariant = absl::variant<SkColor, ui::ColorId>;
static constexpr int kPillButtonHorizontalSpacing = 16;
static constexpr int kPaddingReductionForIcon = 4;
// The PillButton style is defined with 4 features:
// 1. Color variant defines which background, text, and icon color scheme to
// be used, for example Default, Floating, Alert, etc.
// 2. Button size indicates whether we should use the default size 32 or a
// large size 36.
// 3. With/without an icon.
// 4. Icon position: leading or following.
// For ease of extracting features from a button type, each feature is
// represented by a different bit mask.
using TypeFlag = int;
static constexpr TypeFlag kDefault = 1;
static constexpr TypeFlag kDefaultElevated = 1 << 1;
static constexpr TypeFlag kPrimary = 1 << 2;
static constexpr TypeFlag kSecondary = 1 << 3;
static constexpr TypeFlag kFloating = 1 << 4;
static constexpr TypeFlag kAlert = 1 << 5;
// TODO(crbug.com/1355517): Get rid of `kAccent` after CrosNext is fully
// launched.
static constexpr TypeFlag kAccent = 1 << 6;
static constexpr TypeFlag kLarge = 1 << 7;
static constexpr TypeFlag kIconLeading = 1 << 8;
static constexpr TypeFlag kIconFollowing = 1 << 9;
// Types of the PillButton. Each type is represented as the bitwise OR
// operation of the feature bit masks. The naming rule of the button type is
// k{Color Variant}{Button Size}{Icon}{Icon Position}.
enum Type {
// PillButton with default text and background colors, a leading icon.
kDefaultWithIconLeading = kDefault | kIconLeading,
// PillButton with default text and background colors, a following icon.
kDefaultWithIconFollowing = kDefault | kIconFollowing,
// PillButton with default text and background colors, a large button size,
// a leading icon.
kDefaultLargeWithIconLeading = kDefault | kLarge | kIconLeading,
// PillButton with default text and background colors, a large button size,
// a following icon.
kDefaultLargeWithIconFollowing = kDefault | kLarge | kIconFollowing,
// PillButton with default text and background colors, no icon.
kDefaultWithoutIcon = kDefault,
// PillButton with default text and background colors, a large button size,
// no icon.
kDefaultLargeWithoutIcon = kDefault | kLarge,
// PillButton with default-elevated text and background colors, a leading
// icon.
kDefaultElevatedWithIconLeading = kDefaultElevated | kIconLeading,
// PillButton with default-elevated text and background colors, a following
// icon.
kDefaultElevatedWithIconFollowing = kDefaultElevated | kIconFollowing,
// PillButton with default-elevated text and background colors, a large
// button size, a leading icon.
kDefaultElevatedLargeWithIconLeading =
kDefaultElevated | kLarge | kIconLeading,
// PillButton with default-elevated text and background colors, a large
// button size, a following icon.
kDefaultElevatedLargeWithIconFollowing =
kDefaultElevated | kLarge | kIconFollowing,
// PillButton with default-elevated text and background colors, no icon.
kDefaultElevatedWithoutIcon = kDefaultElevated,
// PillButton with default-elevated text and background colors, a large
// button size,
// no icon.
kDefaultElevatedLargeWithoutIcon = kDefaultElevated | kLarge,
// PillButton with primary text and background colors, a leading icon.
kPrimaryWithIconLeading = kPrimary | kIconLeading,
// PillButton with primary text and background colors, a following icon.
kPrimaryWithIconFollowing = kPrimary | kIconFollowing,
// PillButton with primary text and background colors, a large button size,
// a leading icon.
kPrimaryLargeWithIconLeading = kPrimary | kLarge | kIconLeading,
// PillButton with primary text and background colors, a large button size,
// a following icon.
kPrimaryLargeWithIconFollowing = kPrimary | kLarge | kIconFollowing,
// PillButton with primary text and background colors, no icon.
kPrimaryWithoutIcon = kPrimary,
// PillButton with primary text and background colors, a large button size,
// no icon.
kPrimaryLargeWithoutIcon = kPrimary | kLarge,
// PillButton with secondary text and background colors, a leading icon.
kSecondaryWithIconLeading = kSecondary | kIconLeading,
// PillButton with secondary text and background colors, a following icon.
kSecondaryWithIconFollowing = kSecondary | kIconFollowing,
// PillButton with secondary text and background colors, a large button
// size, a leading icon.
kSecondaryLargeWithIconLeading = kSecondary | kLarge | kIconLeading,
// PillButton with secondary text and background colors, a large button
// size, a following icon.
kSecondaryLargeWithIconFollowing = kSecondary | kLarge | kIconFollowing,
// PillButton with secondary text and background colors, no icon.
kSecondaryWithoutIcon = kSecondary,
// PillButton with secondary text and background colors, a large button
// size, no icon.
kSecondaryLargeWithoutIcon = kSecondary | kLarge,
// PillButton with floating text colors, no background, a leading icon.
kFloatingWithIconLeading = kFloating | kIconLeading,
// PillButton with floating text colors, no background, a following icon.
kFloatingWithIconFollowing = kFloating | kIconFollowing,
// PillButton with floating text colors, no background, a large button size,
// a leading icon.
kFloatingLargeWithIconLeading = kFloating | kLarge | kIconLeading,
// PillButton with floating text colors, no background, a large button size,
// a following icon.
kFloatingLargeWithIconFollowing = kFloating | kLarge | kIconFollowing,
// PillButton with floating text colors, no background, no icon.
kFloatingWithoutIcon = kFloating,
// PillButton with floating text colors, no background, a large button size,
// no icon.
kFloatingLargeWithoutIcon = kFloating | kLarge,
// PillButton with alert text and background colors, a leading icon.
kAlertWithIconLeading = kAlert | kIconLeading,
// PillButton with alert text and background colors, a following icon.
kAlertWithIconFollowing = kAlert | kIconFollowing,
// PillButton with alert text and background colors, a large button size, a
// leading icon.
kAlertLargeWithIconLeading = kAlert | kLarge | kIconLeading,
// PillButton with alert text and background colors, a large button size, a
// following icon.
kAlertLargeWithIconFollowing = kAlert | kLarge | kIconFollowing,
// PillButton with alert text and background colors, no icon.
kAlertWithoutIcon = kAlert,
// PillButton with alert text and background colors, a large button size, no
// icon.
kAlertLargeWithoutIcon = kAlert | kLarge,
// Old button types.
// TODO(crbug.com/1355517): Get rid of these types after CrosNext is fully
// launched.
// PillButton with accent text and background colors, no icon.
kAccentWithoutIcon = kAccent,
// PillButton with accent text, no background, no icon.
kAccentFloatingWithoutIcon = kAccent | kFloating,
};
explicit PillButton(
PressedCallback callback = PressedCallback(),
const std::u16string& text = std::u16string(),
Type type = Type::kDefaultWithoutIcon,
const gfx::VectorIcon* icon = nullptr,
int horizontal_spacing = kPillButtonHorizontalSpacing,
int padding_reduction_for_icon = kPaddingReductionForIcon);
PillButton(const PillButton&) = delete;
PillButton& operator=(const PillButton&) = delete;
~PillButton() override;
// views::LabelButton:
gfx::Size CalculatePreferredSize(
const views::SizeBounds& available_size) const override;
gfx::Insets GetInsets() const override;
void UpdateBackgroundColor() override;
views::PropertyEffects UpdateStyleToIndicateDefaultStatus() override;
void SetText(const std::u16string& text) override;
void OnSetTooltipText(const std::u16string& tooltip_text) override;
// Sets the button's background color, text's color or icon's color. Note, do
// this only when the button wants to have different colors from the default
// ones.
void SetBackgroundColor(const SkColor background_color);
void SetBackgroundColorId(ui::ColorId background_color_id);
void SetButtonTextColor(const SkColor text_color);
void SetButtonTextColorId(ui::ColorId text_color_id);
void SetIconColor(const SkColor icon_color);
void SetIconColorId(ui::ColorId icon_color_id);
// TODO(b/290639214): This method is deprecating. Try not to change button
// type afterward. If a new button type is needed, please create a new
// instance.
void SetPillButtonType(Type type);
// Sets the button's label to use the default label font, which is smaller
// and less heavily weighted.
void SetUseDefaultLabelFont();
// Sets if the button should enable the background blur. Once the button
// enables the background blur, it will use `BlurredBackgroundShield` as the
// background which is performance consuming so only use it as needed.
void SetEnableBackgroundBlur(bool enable);
void SetTextWithStringId(int message_id);
void SetUseLabelAsDefaultTooltip(bool use_label_as_default_tooltip);
private:
// Initializes the button layout, focus ring and background according to the
// button type.
void Init();
void UpdateTextColor();
void UpdateIconColor();
// Returns the spacing on the side where the icon locates. The value is set
// smaller to make the spacing on two sides visually look the same.
int GetHorizontalSpacingWithIcon() const;
void UpdateTooltipText();
Type type_;
const raw_ptr<const gfx::VectorIcon> icon_;
// Horizontal spacing of this button. `kPillButtonHorizontalSpacing` will be
// set as the default value.
int horizontal_spacing_;
// The padding reduced by icon.
int padding_reduction_for_icon_;
// Custom colors and color IDs.
ColorVariant background_color_ = gfx::kPlaceholderColor;
ColorVariant text_color_ = gfx::kPlaceholderColor;
ColorVariant icon_color_ = gfx::kPlaceholderColor;
bool enable_background_blur_ = false;
std::unique_ptr<BlurredBackgroundShield> blurred_background_;
// Indicates if we are going to use the label contents for tooltip as default.
bool use_label_as_default_tooltip_ = true;
// When the tooltip becomes equal to Label's Text, this variable holds the
// original value of the tooltip text if the Label's Text was not used.
std::u16string original_tooltip_text_;
// Called to update background color when the button is enabled/disabled.
base::CallbackListSubscription enabled_changed_subscription_;
};
BEGIN_VIEW_BUILDER(ASH_EXPORT, PillButton, views::LabelButton)
VIEW_BUILDER_PROPERTY(const SkColor, BackgroundColor)
VIEW_BUILDER_PROPERTY(ui::ColorId, BackgroundColorId)
VIEW_BUILDER_PROPERTY(const SkColor, ButtonTextColor)
VIEW_BUILDER_PROPERTY(ui::ColorId, ButtonTextColorId)
VIEW_BUILDER_PROPERTY(const SkColor, IconColor)
VIEW_BUILDER_PROPERTY(ui::ColorId, IconColorId)
VIEW_BUILDER_PROPERTY(PillButton::Type, PillButtonType)
VIEW_BUILDER_PROPERTY(bool, EnableBackgroundBlur)
VIEW_BUILDER_PROPERTY(int, TextWithStringId)
VIEW_BUILDER_PROPERTY(bool, UseLabelAsDefaultTooltip)
END_VIEW_BUILDER
} // namespace ash
DEFINE_VIEW_BUILDER(ASH_EXPORT, ash::PillButton)
#endif // ASH_STYLE_PILL_BUTTON_H_