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
276
277
278
279
280
281
282
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_CONTROLS_STYLED_LABEL_H_
#define UI_VIEWS_CONTROLS_STYLED_LABEL_H_
#include <list>
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/class_property.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/range/range.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
namespace views {
class Label;
class Link;
class StyledLabelListener;
// A class which can apply mixed styles to a block of text. Currently, text is
// always multiline. Trailing whitespace in the styled label text is not
// supported and will be trimmed on StyledLabel construction. Leading
// whitespace is respected, provided not only whitespace fits in the first line.
// In this case, leading whitespace is ignored.
class VIEWS_EXPORT StyledLabel : public View {
public:
METADATA_HEADER(StyledLabel);
using LinkTargets = std::map<Link*, gfx::Range>;
// TestApi is used for tests to get internal implementation details.
class VIEWS_EXPORT TestApi {
public:
explicit TestApi(StyledLabel* view);
~TestApi();
const LinkTargets& link_targets();
private:
StyledLabel* const view_;
DISALLOW_COPY_AND_ASSIGN(TestApi);
};
// Parameters that define label style for a styled label's text range.
struct VIEWS_EXPORT RangeStyleInfo {
RangeStyleInfo();
RangeStyleInfo(const RangeStyleInfo&);
RangeStyleInfo& operator=(const RangeStyleInfo&);
~RangeStyleInfo();
// Creates a range style info with default values for link.
static RangeStyleInfo CreateForLink();
bool IsLink() const;
// Allows full customization of the font used in the range. Ignores the
// StyledLabel's default text context and |text_style|.
base::Optional<gfx::FontList> custom_font;
// The style::TextStyle for this range.
base::Optional<int> text_style;
// Overrides the text color given by |text_style| for this range.
// DEPRECATED: Use TextStyle.
base::Optional<SkColor> override_color;
// Tooltip for the range.
base::string16 tooltip;
// If set, the whole range will be put on a single line.
bool disable_line_wrapping = false;
// A custom view shown instead of the underlying text. Ownership of custom
// views must be passed to StyledLabel via AddCustomView().
View* custom_view = nullptr;
};
// Sizing information for laying out the label based on a particular width.
struct VIEWS_EXPORT LayoutSizeInfo {
explicit LayoutSizeInfo(int max_valid_width);
LayoutSizeInfo(const LayoutSizeInfo&);
LayoutSizeInfo& operator=(const LayoutSizeInfo&);
~LayoutSizeInfo();
// The maximum width for which this info is guaranteed to be valid.
// Requesting a larger width than this will force a recomputation.
int max_valid_width = 0;
// The actual size needed to lay out the label for a requested width of
// |max_valid_width|. total_size.width() is at most |max_valid_width| but
// may be smaller depending on how line wrapping is computed. Requesting a
// smaller width than this will force a recomputation.
gfx::Size total_size;
// The sizes of each line of child views. |size| can be computed directly
// from these values and is kept separately just for convenience.
std::vector<gfx::Size> line_sizes;
};
// Note that any trailing whitespace in |text| will be trimmed.
StyledLabel(const base::string16& text, StyledLabelListener* listener);
~StyledLabel() override;
// Sets the text to be displayed, and clears any previous styling.
const base::string16& GetText() const;
void SetText(const base::string16& text);
// Returns the font list that results from the default text context and style
// for ranges. This can be used as the basis for a range |custom_font|.
gfx::FontList GetDefaultFontList() const;
// Marks the given range within |text_| with style defined by |style_info|.
// |range| must be contained in |text_|.
void AddStyleRange(const gfx::Range& range, const RangeStyleInfo& style_info);
// Passes ownership of a custom view for use by RangeStyleInfo structs.
void AddCustomView(std::unique_ptr<View> custom_view);
// Get/Set the context of this text. All ranges have the same context.
// |text_context| must be a value from views::style::TextContext.
int GetTextContext() const;
void SetTextContext(int text_context);
// Set the default text style.
// |text_style| must be a value from views::style::TextStyle.
int GetDefaultTextStyle() const;
void SetDefaultTextStyle(int text_style);
// Get or set the distance in pixels between baselines of multi-line text.
// Default is 0, indicating the distance between lines should be the standard
// one for the label's text, font list, and platform.
int GetLineHeight() const;
void SetLineHeight(int height);
// Gets/Sets the color of the background on which the label is drawn. This
// won't be explicitly drawn, but the label will force the text color to be
// readable over it.
base::Optional<SkColor> GetDisplayedOnBackgroundColor() const;
void SetDisplayedOnBackgroundColor(const base::Optional<SkColor>& color);
bool GetAutoColorReadabilityEnabled() const;
void SetAutoColorReadabilityEnabled(bool auto_color_readability);
// Returns the layout size information that would be used to layout the label
// at width |w|. This can be used by callers who need more detail than what's
// provided by GetHeightForWidth().
const LayoutSizeInfo& GetLayoutSizeInfoForWidth(int w) const;
// Resizes the label so its width is set to the fixed width and its height
// deduced accordingly. Even if all widths of the lines are shorter than
// |fixed_width|, the given value is applied to the element's width.
// This is only intended for multi-line labels and is useful when the label's
// text contains several lines separated with \n.
// |fixed_width| is the fixed width that will be used (longer lines will be
// wrapped). If 0, no fixed width is enforced.
void SizeToFit(int fixed_width);
// View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int w) const override;
void Layout() override;
void PreferredSizeChanged() override;
void OnThemeChanged() override;
// Called when any of the child links are clicked.
void LinkClicked(Link* source, int event_flags);
// Sets the horizontal alignment; the argument value is mirrored in RTL UI.
void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);
// Clears all the styles applied to the label.
void ClearStyleRanges();
private:
struct StyleRange {
StyleRange(const gfx::Range& range, const RangeStyleInfo& style_info)
: range(range), style_info(style_info) {}
~StyleRange() = default;
bool operator<(const StyleRange& other) const;
gfx::Range range;
RangeStyleInfo style_info;
};
using StyleRanges = std::list<StyleRange>;
// Child view-related information for layout.
struct LayoutViews;
// Returns the starting X coordinate for the views in a line, based on the
// current |horizontal_alignment_| and insets and given the amount of excess
// space available on that line.
int StartX(int excess_space) const;
// Returns the default line height, based on the default style.
int GetDefaultLineHeight() const;
// Returns the FontList that should be used for |range|.
gfx::FontList GetFontListForRange(
const StyleRanges::const_iterator& range) const;
// Sets |layout_size_info_| and |layout_views_| for the given |width|. No-op
// if current_width <= width <= max_width, where:
// current_width = layout_size_info_.total_size.width()
// width = max(width, GetInsets().width())
// max_width = layout_size_info_.max_valid_width
void CalculateLayout(int width) const;
// Creates a Label for a given |text|, |style_info|, and |range|.
std::unique_ptr<Label> CreateLabel(const base::string16& text,
const RangeStyleInfo& style_info,
const gfx::Range& range) const;
// Update the label background color from the theme or
// |displayed_on_background_color_| if set.
void UpdateLabelBackgroundColor();
// Remove all child views. Place all custom views back into custom_views_ and
// delete the rest.
void RemoveOrDeleteAllChildViews();
// The text to display.
base::string16 text_;
int text_context_ = style::CONTEXT_LABEL;
int default_text_style_ = style::STYLE_PRIMARY;
// Line height. If zero, style::GetLineHeight() is used.
int specified_line_height_ = 0;
// The listener that will be informed of link clicks.
StyledLabelListener* listener_;
// The ranges that should be linkified, sorted by start position.
StyleRanges style_ranges_;
// A mapping from a view to the range it corresponds to in |text_|. Only views
// that correspond to ranges with is_link style set will be added to the map.
LinkTargets link_targets_;
// Temporarily owns the custom views until they've been been placed into the
// StyledLabel's child list. This list also holds the custom views during
// layout.
std::list<std::unique_ptr<View>> custom_views_;
// Saves the effects of the last CalculateLayout() call to avoid repeated
// calculation. |layout_size_info_| can then be cached until the next
// recalculation, while |layout_views_| only exists until the next Layout().
mutable LayoutSizeInfo layout_size_info_{0};
mutable std::unique_ptr<LayoutViews> layout_views_;
// Background color on which the label is drawn, for auto color readability.
base::Optional<SkColor> displayed_on_background_color_;
// Controls whether the text is automatically re-colored to be readable on the
// background.
bool auto_color_readability_enabled_ = true;
// The horizontal alignment. This value is flipped for RTL. The default
// behavior is to align left in LTR UI and right in RTL UI.
gfx::HorizontalAlignment horizontal_alignment_ = gfx::ALIGN_LEFT;
DISALLOW_COPY_AND_ASSIGN(StyledLabel);
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_STYLED_LABEL_H_
|