// 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 #include #include #include #include #include "base/callback_forward.h" #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/controls/link.h" #include "ui/views/style/typography.h" #include "ui/views/view.h" namespace views { class Label; class Link; // 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); // 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(Link::ClickedCallback callback); static RangeStyleInfo CreateForLink(base::RepeatingClosure callback); // Allows full customization of the font used in the range. Ignores the // StyledLabel's default text context and |text_style|. base::Optional custom_font; // The style::TextStyle for this range. base::Optional text_style; // Overrides the text color given by |text_style| for this range. // DEPRECATED: Use TextStyle. base::Optional override_color; // A callback to be called when this link is clicked. Only used if // |text_style| is style::STYLE_LINK. Link::ClickedCallback callback; // 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. |total_size| can be computed // directly from these values and is kept separately just for convenience. std::vector line_sizes; }; StyledLabel(); ~StyledLabel() override; // Sets the text to be displayed, and clears any previous styling. Trailing // whitespace is trimmed from the text. const base::string16& GetText() const; void SetText(base::string16 text); // Returns the FontList that should be used. |style_info| is an optional // argument that takes precedence over the default values. gfx::FontList GetFontList( const RangeStyleInfo& style_info = RangeStyleInfo()) 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 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 GetDisplayedOnBackgroundColor() const; void SetDisplayedOnBackgroundColor(const base::Optional& 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; // 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(); // Sends a space keypress to the first child that is a link. Assumes at least // one such child exists. void ClickLinkForTesting(); 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; // 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; // 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