#nullable enable namespace Terminal.Gui; public partial class View // Text Property APIs { private string _text = string.Empty; /// /// Called when the has changed. Fires the event. /// public void OnTextChanged () { TextChanged?.Invoke (this, EventArgs.Empty); } /// /// Gets or sets whether trailing spaces at the end of word-wrapped lines are preserved /// or not when is enabled. /// If trailing spaces at the end of wrapped lines will be removed when /// is formatted for display. The default is . /// public bool PreserveTrailingSpaces { get => TextFormatter.PreserveTrailingSpaces; set { if (TextFormatter.PreserveTrailingSpaces != value) { TextFormatter.PreserveTrailingSpaces = value; TextFormatter.NeedsFormat = true; SetLayoutNeeded (); } } } /// /// The text displayed by the . /// /// /// /// The text will be drawn before any subviews are drawn. /// /// /// The text will be drawn starting at the view origin (0, 0) and will be formatted according /// to and . /// /// /// The text will word-wrap to additional lines if it does not fit horizontally. If /// 's height /// is 1, the text will be clipped. /// /// /// If or are using , /// the will be adjusted to fit the text. /// /// When the text changes, the is fired. /// public virtual string Text { get => _text; set { if (_text == value) { return; } string old = _text; _text = value; UpdateTextFormatterText (); SetLayoutNeeded (); #if DEBUG if (_text is { } && string.IsNullOrEmpty (Id)) { Id = _text; } #endif OnTextChanged (); } } // TODO: Make this non-virtual. Nobody overrides it. /// /// Gets or sets how the View's is aligned horizontally when drawn. Changing this property will /// redisplay the . /// /// /// /// or are using , the /// will be adjusted to fit the text. /// /// /// The text alignment. public virtual Alignment TextAlignment { get => TextFormatter.Alignment; set { TextFormatter.Alignment = value; UpdateTextFormatterText (); SetLayoutNeeded (); } } /// /// Text changed event, raised when the text has changed. /// public event EventHandler? TextChanged; // TODO: Make this non-virtual. Nobody overrides it. /// /// Gets or sets the direction of the View's . Changing this property will redisplay the /// . /// /// /// /// or are using , the /// will be adjusted to fit the text. /// /// /// The text direction. public virtual TextDirection TextDirection { get => TextFormatter.Direction; set => UpdateTextDirection (value); } /// /// Gets or sets the used to format . /// public TextFormatter TextFormatter { get; init; } = new (); // TODO: Make this non-virtual. Nobody overrides it. /// /// Gets or sets how the View's is aligned vertically when drawn. Changing this property will /// redisplay /// the . /// /// /// /// or are using , the /// will be adjusted to fit the text. /// /// /// The vertical text alignment. public virtual Alignment VerticalTextAlignment { get => TextFormatter.VerticalAlignment; set { TextFormatter.VerticalAlignment = value; SetNeedsDisplay (); } } // TODO: Add a OnUpdateTextFormatterText method that invokes UpdateTextFormatterText so that overrides don't have to call base. /// /// Can be overridden if the has /// different format than the default. /// /// /// Overrides must call base.UpdateTextFormatterText before updating . /// protected virtual void UpdateTextFormatterText () { TextFormatter.Text = _text; TextFormatter.ConstrainToWidth = null; TextFormatter.ConstrainToHeight = null; } /// /// Internal API. Sets .Width/Height. /// /// /// Use this API to set /Height when the view has changed such that the /// size required to fit the text has changed. /// changes. /// /// internal void SetTextFormatterSize () { // View subclasses can override UpdateTextFormatterText to modify the Text it holds (e.g. Checkbox and Button). // We need to ensure TextFormatter is accurate by calling it here. UpdateTextFormatterText (); // Default is to use GetContentSize (). Size? size = _contentSize; // Use _width & _height instead of Width & Height to avoid debug spew var widthAuto = _width as DimAuto; var heightAuto = _height as DimAuto; if (widthAuto is { } && widthAuto.Style.FastHasFlags (DimAutoStyle.Text)) { TextFormatter.ConstrainToWidth = null; } else { if (size is { }) { TextFormatter.ConstrainToWidth = size?.Width; } } if (heightAuto is { } && heightAuto.Style.FastHasFlags (DimAutoStyle.Text)) { TextFormatter.ConstrainToHeight = null; } else { if (size is { }) { TextFormatter.ConstrainToHeight = size?.Height; } } } /// /// Initializes the Text of the View. Called by the constructor. /// private void SetupText () { Text = string.Empty; TextDirection = TextDirection.LeftRight_TopBottom; } private void UpdateTextDirection (TextDirection newDirection) { bool directionChanged = TextFormatter.IsHorizontalDirection (TextFormatter.Direction) != TextFormatter.IsHorizontalDirection (newDirection); TextFormatter.Direction = newDirection; UpdateTextFormatterText (); if (directionChanged) { TextFormatter.ConstrainToWidth = null; TextFormatter.ConstrainToHeight = null; SetLayoutNeeded (); } SetNeedsDisplay (); } }