// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_VIEWS_CONTROLS_LABEL_H_
#define UI_VIEWS_CONTROLS_LABEL_H_

#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>

#include "base/gtest_prod_util.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
#include "ui/color/color_id.h"
#include "ui/color/color_variant.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/render_text.h"
#include "ui/gfx/text_constants.h"
#include "ui/menus/simple_menu_model.h"
#include "ui/views/buildflags.h"
#include "ui/views/cascading_property.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/selection_controller_delegate.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
#include "ui/views/word_lookup_client.h"

namespace views {
class LabelSelectionTest;
class MenuRunner;
class SelectionController;

VIEWS_EXPORT extern const ui::ClassProperty<CascadingProperty<SkColor>*>* const
    kCascadingLabelEnabledColor;

// A view subclass that can display a string.
class VIEWS_EXPORT Label : public View,
                           public ContextMenuController,
                           public WordLookupClient,
                           public SelectionControllerDelegate,
                           public ui::SimpleMenuModel::Delegate {
  METADATA_HEADER(Label, View)

 public:
  enum MenuCommands {
    kCopy = 1,
    kSelectAll,
    kLastCommandId = kSelectAll,
  };

  // Helper to construct a Label that doesn't use the views typography spec.
  // Using this causes Label to obtain colors from ui::NativeTheme and line
  // spacing from gfx::FontList::GetHeight().
  // TODO(tapted): Audit users of this class when MD is default. Then add
  // foreground/background colors, line spacing and everything else that
  // views::TextContext abstracts away so the separate setters can be removed.
  struct CustomFont {
    // TODO(tapted): Change this to a size delta and font weight since that's
    // typically all the callers really care about, and would allow Label to
    // guarantee caching of the FontList in ResourceBundle.
    const gfx::FontList font_list;
  };

  // Create Labels with style::CONTEXT_CONTROL_LABEL and style::STYLE_PRIMARY.
  // TODO(tapted): Remove these. Callers must specify a context or use the
  // constructor taking a CustomFont.
  explicit Label(std::u16string_view text = {});

  // Construct a Label in the given |text_context|. The |text_style| can change
  // later, so provide a default. The |text_context| is fixed.
  // By default text directionality will be derived from the label text, however
  // it can be overriden with |directionality_mode|.
  Label(std::u16string_view text,
        int text_context,
        int text_style = style::STYLE_PRIMARY,
        gfx::DirectionalityMode directionality_mode =
            gfx::DirectionalityMode::DIRECTIONALITY_FROM_TEXT);

  // Construct a Label with the given |font| description.
  Label(std::u16string_view text, const CustomFont& font);

  Label(const Label&) = delete;
  Label& operator=(const Label&) = delete;

  ~Label() override;

  static const gfx::FontList& GetDefaultFontList();

  // Gets or sets the fonts used by this label.
  const gfx::FontList& font_list() const { return full_text_->font_list(); }

  // TODO(tapted): Replace this with a private method, e.g., OnFontChanged().
  virtual void SetFontList(const gfx::FontList& font_list);

  // Get or set the label text.
  std::u16string_view GetText() const;
  virtual void SetText(std::u16string_view text);

  void AdjustAccessibleName(std::u16string& new_name,
                            ax::mojom::NameFrom& name_from) override;

  // Where the label appears in the UI. Passed in from the constructor. This is
  // a value from views::style::TextContext or an enum that extends it.
  int GetTextContext() const;
  void SetTextContext(int text_context);

  // The style of the label.  This is a value from views::style::TextStyle or an
  // enum that extends it.
  int GetTextStyle() const;
  void SetTextStyle(int style);

  // Applies |style| to a specific |range|.  This is unimplemented for styles
  // that vary from the global text style by anything besides weight.
  void SetTextStyleRange(int style, const gfx::Range& range);

  // Apply the baseline style range across the entire label.
  void ApplyBaselineTextStyle();

  // Enables or disables auto-color-readability (enabled by default).  If this
  // is enabled, then calls to set any foreground or background color will
  // trigger an automatic mapper that uses color_utils::BlendForMinContrast()
  // to ensure that the foreground colors are readable over the background
  // color.
  bool GetAutoColorReadabilityEnabled() const;
  void SetAutoColorReadabilityEnabled(bool enabled);

  // Gets/Sets the color.  This will automatically force the color to be
  // readable over the current background color, if auto color readability is
  // enabled.
  SkColor GetEnabledColor() const;
  virtual void SetEnabledColor(ui::ColorVariant color);
  std::optional<ui::ColorVariant> GetRequestedEnabledColor() const;

  // Gets/Sets the background color. This won't be explicitly drawn, but the
  // label will force the text color to be readable over it.
  SkColor GetBackgroundColor() const;
  void SetBackgroundColor(ui::ColorVariant color);

  // Gets/Sets the selection text color. This will automatically force the color
  // to be readable over the selection background color, if auto color
  // readability is enabled. Initialized with system default.
  SkColor GetSelectionTextColor() const;
  void SetSelectionTextColor(SkColor color);

  // Gets/Sets the selection background color. Initialized with system default.
  SkColor GetSelectionBackgroundColor() const;
  void SetSelectionBackgroundColor(SkColor color);

  // Get/Set drop shadows underneath the text.
  const gfx::ShadowValues& GetShadows() const;
  void SetShadows(const gfx::ShadowValues& shadows);

  // Gets/Sets whether subpixel rendering is used; the default is true, but this
  // feature also requires an opaque background color.
  // TODO(mukai): rename this as SetSubpixelRenderingSuppressed() to keep the
  // consistency with RenderText field name.
  bool GetSubpixelRenderingEnabled() const;
  void SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled);

  // Gets/Sets whether the DCHECK() checking that subpixel-rendered text is
  // only drawn onto opaque layers is skipped. Use this to suppress false
  // positives - for example, if the label is drawn onto an opaque region of a
  // non-opaque layer. If possible, prefer making the layer opaque or painting
  // onto an opaque views::Background, as those cases are detected and
  // excluded by this DCHECK automatically.
  bool GetSkipSubpixelRenderingOpacityCheck() const;
  void SetSkipSubpixelRenderingOpacityCheck(
      bool skip_subpixel_rendering_opacity_check);

  // Gets/Sets the horizontal alignment; the argument value is mirrored in RTL
  // UI.
  gfx::HorizontalAlignment GetHorizontalAlignment() const;
  void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);

  // Gets/Sets the vertical alignment. Affects how whitespace is distributed
  // vertically around the label text, or if the label is not tall enough to
  // render all of the text, what gets cut off. ALIGN_MIDDLE is default and is
  // strongly suggested for single-line labels because it produces a consistent
  // baseline even when rendering with mixed fonts.
  gfx::VerticalAlignment GetVerticalAlignment() const;
  void SetVerticalAlignment(gfx::VerticalAlignment alignment);

  // Get or set the distance in pixels between baselines of multi-line text.
  // Default is the height of the default font.
  int GetLineHeight() const;
  void SetLineHeight(int line_height);

  // Get or set if the label text can wrap on multiple lines; default is false.
  bool GetMultiLine() const;
  void SetMultiLine(bool multi_line);

  // If multi-line, a non-zero value will cap the number of lines rendered, and
  // elide the rest (currently only ELIDE_TAIL supported). See gfx::RenderText.
  size_t GetMaxLines() const;
  void SetMaxLines(size_t max_lines);

  // If single-line, a non-zero value will help determine the amount of space
  // needed *after* elision, which may be less than the passed |max_width|.
  void SetMaximumWidthSingleLine(int max_width);

  // Returns the number of lines required to render all text. The actual number
  // of rendered lines might be limited by |max_lines_| which elides the rest.
  size_t GetRequiredLines() const;

  // Get or set if the label text should be obscured before rendering (e.g.
  // should "Password!" display as "*********"); default is false.
  bool GetObscured() const;
  void SetObscured(bool obscured);

  // Returns true if some portion of the text is not displayed because of
  // clipping.
  bool IsDisplayTextClipped() const;

  // Returns true if some portion of the text is not displayed, either because
  // of eliding or clipping.
  bool IsDisplayTextTruncated() const;

  // Gets/Sets whether multi-line text can wrap mid-word; the default is false.
  // TODO(mukai): allow specifying WordWrapBehavior.
  bool GetAllowCharacterBreak() const;
  void SetAllowCharacterBreak(bool allow_character_break);

  // For the provided line index, gets the corresponding rendered line and
  // returns the text position of the first character of that line.
  size_t GetTextIndexOfLine(size_t line) const;

  // Set the truncate length of the |full_text_|.
  // NOTE: This does not affect the |display_text_|, since right now the only
  // consumer does not need that; if you need this function, you may need to
  // implement this.
  void SetTruncateLength(size_t truncate_length);

  // Gets/Sets the eliding or fading behavior, applied as necessary. The default
  // is to elide at the end. Eliding is not well-supported for multi-line
  // labels.
  gfx::ElideBehavior GetElideBehavior() const;
  void SetElideBehavior(gfx::ElideBehavior elide_behavior);

  // Get or set the flags that control display of accelerator characters.
  void SetDrawStringsFlags(int flags);
  int GetDrawStringsFlags() const { return draw_strings_flags_; }

  // Sets the custom local tooltip text.  Default behavior for a label
  // (single-line) is to show the full text if it is wider than its bounds.
  // Calling this overrides the default behavior and lets you set a custom
  // tooltip.  To revert to default behavior, call this with an empty string.
  void SetCustomTooltipText(std::u16string_view tooltip_text);

  // Updates the tooltip text cached on the View.
  void UpdateTooltipText();

  // This function returns the computed tooltip for the label, irrespective of
  // the `handles_tooltips_` value. If `handles_tooltips_` is false, the tooltip
  // will be suppressed and not shown to the user, but the unsuppressed value
  // will still be locally cached if available.
  std::u16string_view GetComputedTooltip();

  // Get or set whether this label can act as a tooltip handler; the default is
  // true.  Set to false whenever an ancestor view should handle tooltips
  // instead.
  bool GetHandlesTooltips() const;
  void SetHandlesTooltips(bool enabled);

  // 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.
  int GetFixedWidth() const;
  void SizeToFit(int fixed_width);

  // Like SizeToFit, but uses a smaller width if possible.
  int GetMaximumWidth() const;
  void SetMaximumWidth(int max_width);

  // Gets/Sets whether the preferred size is empty when the label is not
  // visible.
  bool GetCollapseWhenHidden() const;
  void SetCollapseWhenHidden(bool value);

  // Get the text as displayed to the user, respecting the obscured flag.
  std::u16string_view GetDisplayTextForTesting() const;

  // Get the text direction, as displayed to the user.
  base::i18n::TextDirection GetTextDirectionForTesting();

  // Returns true if the label can be made selectable. For example, links do not
  // support text selection.
  // Subclasses should override this function in case they want to selectively
  // support text selection. If a subclass stops supporting text selection, it
  // should call SetSelectable(false).
  virtual bool IsSelectionSupported() const;

  // Returns true if the label is selectable. Default is false.
  bool GetSelectable() const;

  // Sets whether the label is selectable. False is returned if the call fails,
  // i.e. when selection is not supported but |selectable| is true. For example,
  // obscured labels do not support text selection.
  bool SetSelectable(bool selectable);

  // Returns true if the label has a selection.
  bool HasSelection() const;

  // Returns true if the label has the whole text selected.
  bool HasFullSelection() const;

  // Selects the entire text. NO-OP if the label is not selectable.
  void SelectAll();

  // Clears any active selection.
  void ClearSelection();

  // Selects the given text range. NO-OP if the label is not selectable or the
  // |range| endpoints don't lie on grapheme boundaries.
  void SelectRange(const gfx::Range& range);

  // Get the visual bounds containing the logical substring of the full text
  // within the |range|. See gfx::RenderText.
  std::vector<gfx::Rect> GetSubstringBounds(const gfx::Range& range);

  [[nodiscard]] base::CallbackListSubscription AddTextChangedCallback(
      views::PropertyChangedCallback callback);

  [[nodiscard]] base::CallbackListSubscription
  AddAccessibleTextOffsetsChangedCallback(
      views::PropertyChangedCallback callback);

  [[nodiscard]] base::CallbackListSubscription AddTextContextChangedCallback(
      PropertyChangedCallback callback);

  // View:
  int GetBaseline() const override;
  gfx::Size CalculatePreferredSize(
      const SizeBounds& available_size) const override;
  gfx::Size GetMinimumSize() const override;
  gfx::Size GetMaximumSize() const override;
  View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
  bool GetCanProcessEventsWithinSubtree() const override;
  WordLookupClient* GetWordLookupClient() override;

#if BUILDFLAG(SUPPORTS_AX_TEXT_OFFSETS)
  void OnAccessibilityInitializing(ui::AXNodeData* data) override;
#endif  // BUILDFLAG(SUPPORTS_AX_TEXT_OFFSETS)

  // ui::SimpleMenuModel::Delegate:
  void ExecuteCommand(int command_id, int event_flags) override;

  void AddDisplayTextTruncationCallback(
      base::RepeatingCallback<void(Label*)> callback);

  void AddLabelTooltipTextChangedCallback(
      base::RepeatingCallback<void()> callback);

 protected:
  // Create a single RenderText instance to actually be painted.
  virtual std::unique_ptr<gfx::RenderText> CreateRenderText() const;

  // Returns the preferred size and position of the text in local coordinates,
  // which may exceed the local bounds of the label.
  gfx::Rect GetTextBounds() const;

  // Returns the Y coordinate the font_list() will actually be drawn at, in
  // local coordinates.  This may differ from GetTextBounds().y() since the font
  // is positioned inside the display rect.
  int GetFontListY() const;

  void PaintText(gfx::Canvas* canvas);

  // View:
  void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
  void VisibilityChanged(View* starting_from, bool is_visible) override;
  void OnPaint(gfx::Canvas* canvas) override;
  void OnDeviceScaleFactorChanged(float old_device_scale_factor,
                                  float new_device_scale_factor) override;
  void OnThemeChanged() override;
  ui::Cursor GetCursor(const ui::MouseEvent& event) override;
  void OnFocus() override;
  void OnBlur() override;
  bool OnMousePressed(const ui::MouseEvent& event) override;
  bool OnMouseDragged(const ui::MouseEvent& event) override;
  void OnMouseReleased(const ui::MouseEvent& event) override;
  void OnMouseCaptureLost() override;
  bool OnKeyPressed(const ui::KeyEvent& event) override;
  bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
  bool CanHandleAccelerators() const override;

 private:
  FRIEND_TEST_ALL_PREFIXES(LabelTest, ResetRenderTextData);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, MultilineSupportedRenderText);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, TextChangeWithoutLayout);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, EmptyLabel);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, FocusBounds);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, MultiLineSizingWithElide);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, IsDisplayTextTruncated);
  FRIEND_TEST_ALL_PREFIXES(LabelTest, ChecksSubpixelRenderingOntoOpaqueSurface);
  FRIEND_TEST_ALL_PREFIXES(ViewAXPlatformNodeDelegateWinInnerTextRangeTest,
                           Label_LTR);
  FRIEND_TEST_ALL_PREFIXES(ViewAXPlatformNodeDelegateWinInnerTextRangeTest,
                           Label_RTL);
  friend class LabelSelectionTest;

  // ContextMenuController overrides:
  void ShowContextMenuForViewImpl(
      View* source,
      const gfx::Point& point,
      ui::mojom::MenuSourceType source_type) override;

  // WordLookupClient overrides:
  bool GetWordLookupDataAtPoint(const gfx::Point& point,
                                gfx::DecoratedText* decorated_word,
                                gfx::Rect* rect) override;

  bool GetWordLookupDataFromSelection(gfx::DecoratedText* decorated_text,
                                      gfx::Rect* rect) override;

  // SelectionControllerDelegate overrides:
  gfx::RenderText* GetRenderTextForSelectionController() override;
  bool IsReadOnly() const override;
  bool SupportsDrag() const override;
  bool HasTextBeingDragged() const override;
  void SetTextBeingDragged(bool value) override;
  int GetViewHeight() const override;
  int GetViewWidth() const override;
  int GetDragSelectionDelay() const override;
  void OnBeforePointerAction() override;
  void OnAfterPointerAction(bool text_changed, bool selection_changed) override;
  bool PasteSelectionClipboard() override;
  void UpdateSelectionClipboard() override;

  // ui::SimpleMenuModel::Delegate overrides:
  bool IsCommandIdChecked(int command_id) const override;
  bool IsCommandIdEnabled(int command_id) const override;
  bool GetAcceleratorForCommandId(int command_id,
                                  ui::Accelerator* accelerator) const override;

  const gfx::RenderText* GetRenderTextForSelectionController() const;

  void Init(std::u16string_view text,
            const gfx::FontList& font_list,
            gfx::DirectionalityMode directionality_mode);

  // Set up |display_text_| to actually be painted.
  void MaybeBuildDisplayText() const;

  // Get the text size for the current layout.
  gfx::Size GetTextSize() const;

  // Get the text size that ignores the current layout and respects
  // `available_size`.
  gfx::Size GetBoundedTextSize(const SizeBounds& available_size) const;

  // Returns the height of the Label given the width `w`.
  int GetLabelHeightForWidth(int w) const;

  // Returns the appropriate foreground color to use given the proposed
  // |foreground| and |background| colors.
  SkColor GetForegroundColor(SkColor foreground, SkColor background) const;

  // Updates text and selection colors from requested colors.
  void RecalculateColors();

  // Applies the foreground color to |display_text_|.
  void ApplyTextColors() const;

  // Updates any colors that have not been explicitly set from the theme.
  void UpdateColorsFromTheme();

  bool ShouldShowDefaultTooltip() const;

  // Clears |display_text_| and updates |stored_selection_range_|.
  // TODO(crbug.com/40704805) Most uses of this function are inefficient; either
  // replace with setting attributes on both RenderTexts or collapse them to one
  // RenderText.
  void ClearDisplayText();

  // Returns the currently selected text.
  std::u16string_view GetSelectedText() const;

  // Updates the clipboard with the currently selected text.
  void CopyToClipboard();

  // Builds |context_menu_contents_|.
  void BuildContextMenuContents();

  // Updates the elide behavior used by |full_text_|.
  void UpdateFullTextElideBehavior();

  void OnDisplayTextTruncation();

#if BUILDFLAG(SUPPORTS_AX_TEXT_OFFSETS)
  void MaybeRefreshAccessibleTextOffsets() const;

  // Calculate widths for each grapheme and word starts and ends. Used for
  // accessibility. Currently only on Windows when UIA is enabled.
  bool RefreshAccessibleTextOffsetsIfNeeded() const;

  // The string used to compute the text offsets for accessibility. This is used
  // to determine if the offsets need to be recomputed.
  mutable std::u16string ax_name_used_to_compute_offsets_;
#endif  // BUILDFLAG(SUPPORTS_AX_TEXT_OFFSETS)

  int text_context_;
  int text_style_;
  std::optional<int> line_height_;

  // An un-elided and single-line RenderText object used for preferred sizing.
  std::unique_ptr<gfx::RenderText> full_text_;

  // The RenderText instance used for drawing.
  mutable std::unique_ptr<gfx::RenderText> display_text_;

  // Persists the current selection range between the calls to
  // ClearDisplayText() and MaybeBuildDisplayText(). Holds an InvalidRange when
  // not in use.
  mutable gfx::Range stored_selection_range_ = gfx::Range::InvalidRange();

  std::optional<ui::ColorVariant> requested_enabled_color_;
  std::optional<SkColor> resolved_enabled_color_;
  SkColor actual_enabled_color_ = gfx::kPlaceholderColor;

  std::optional<ui::ColorVariant> requested_background_color_;
  std::optional<SkColor> resolved_background_color_;
  SkColor actual_background_color_ = gfx::kPlaceholderColor;

  SkColor requested_selection_text_color_ = gfx::kPlaceholderColor;
  SkColor actual_selection_text_color_ = gfx::kPlaceholderColor;
  SkColor selection_background_color_ = gfx::kPlaceholderColor;

  // Set to true once the corresponding setter is invoked.
  bool selection_text_color_set_ = false;
  bool selection_background_color_set_ = false;

  gfx::ElideBehavior elide_behavior_ = gfx::ELIDE_TAIL;

  bool subpixel_rendering_enabled_ = true;
  bool skip_subpixel_rendering_opacity_check_ = false;
  bool auto_color_readability_enabled_ = true;
  // TODO(mukai): remove |multi_line_| when all RenderText can render multiline.
  bool multi_line_ = false;
  size_t max_lines_ = 0;
  std::u16string custom_tooltip_text_;
  bool handles_tooltips_ = true;
  // Whether to collapse the label when it's not visible.
  bool collapse_when_hidden_ = false;
  int fixed_width_ = 0;
  // This is used only for multi-line mode.
  int max_width_ = 0;
  // This is used in single-line mode.
  int max_width_single_line_ = 0;
  int draw_strings_flags_ = 0;

  std::unique_ptr<SelectionController> selection_controller_;

  // Context menu related members.
  ui::SimpleMenuModel context_menu_contents_;
  std::unique_ptr<views::MenuRunner> context_menu_runner_;

  std::u16string suppressed_tooltip_text_;

  base::RepeatingCallback<void(Label*)>
      on_display_text_truncation_changed_callback_;
  base::RepeatingCallback<void()> label_tooltip_text_changed_callback_;
};

BEGIN_VIEW_BUILDER(VIEWS_EXPORT, Label, View)
VIEW_BUILDER_PROPERTY(const gfx::FontList&, FontList)
VIEW_BUILDER_PROPERTY(std::u16string, Text)
VIEW_BUILDER_PROPERTY(int, TextStyle)
VIEW_BUILDER_PROPERTY(int, TextContext)
VIEW_BUILDER_PROPERTY(bool, AutoColorReadabilityEnabled)
VIEW_BUILDER_PROPERTY(ui::ColorVariant, EnabledColor)
VIEW_BUILDER_PROPERTY(ui::ColorVariant, BackgroundColor)
VIEW_BUILDER_PROPERTY(SkColor, SelectionTextColor)
VIEW_BUILDER_PROPERTY(SkColor, SelectionBackgroundColor)
VIEW_BUILDER_PROPERTY(const gfx::ShadowValues&, Shadows)
VIEW_BUILDER_PROPERTY(bool, SubpixelRenderingEnabled)
VIEW_BUILDER_PROPERTY(bool, SkipSubpixelRenderingOpacityCheck)
VIEW_BUILDER_PROPERTY(gfx::HorizontalAlignment, HorizontalAlignment)
VIEW_BUILDER_PROPERTY(gfx::VerticalAlignment, VerticalAlignment)
VIEW_BUILDER_PROPERTY(int, LineHeight)
VIEW_BUILDER_PROPERTY(bool, MultiLine)
VIEW_BUILDER_PROPERTY(size_t, MaxLines)
VIEW_BUILDER_PROPERTY(bool, Obscured)
VIEW_BUILDER_PROPERTY(bool, AllowCharacterBreak)
VIEW_BUILDER_PROPERTY(size_t, TruncateLength)
VIEW_BUILDER_PROPERTY(gfx::ElideBehavior, ElideBehavior)
VIEW_BUILDER_PROPERTY(std::u16string, TooltipText)
VIEW_BUILDER_PROPERTY(bool, HandlesTooltips)
VIEW_BUILDER_PROPERTY(int, MaximumWidth)
VIEW_BUILDER_PROPERTY(int, MaximumWidthSingleLine)
VIEW_BUILDER_PROPERTY(bool, CollapseWhenHidden)
VIEW_BUILDER_PROPERTY(bool, Selectable)
VIEW_BUILDER_METHOD(SizeToFit, int)
END_VIEW_BUILDER

}  // namespace views

DEFINE_VIEW_BUILDER(VIEWS_EXPORT, Label)

#endif  // UI_VIEWS_CONTROLS_LABEL_H_