ViewText.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using System.Text;
  2. using System;
  3. namespace Terminal.Gui {
  4. public partial class View {
  5. string _text;
  6. /// <summary>
  7. /// The text displayed by the <see cref="View"/>.
  8. /// </summary>
  9. /// <remarks>
  10. /// <para>
  11. /// The text will be drawn before any subviews are drawn.
  12. /// </para>
  13. /// <para>
  14. /// The text will be drawn starting at the view origin (0, 0) and will be formatted according
  15. /// to <see cref="TextAlignment"/> and <see cref="TextDirection"/>.
  16. /// </para>
  17. /// <para>
  18. /// The text will word-wrap to additional lines if it does not fit horizontally. If <see cref="Bounds"/>'s height
  19. /// is 1, the text will be clipped.
  20. /// </para>
  21. /// <para>
  22. /// Set the <see cref="HotKeySpecifier"/> to enable hotkey support. To disable hotkey support set <see cref="HotKeySpecifier"/> to
  23. /// <c>(Rune)0xffff</c>.
  24. /// </para>
  25. /// </remarks>
  26. public virtual string Text {
  27. get => _text;
  28. set {
  29. _text = value;
  30. SetHotKey ();
  31. UpdateTextFormatterText ();
  32. //TextFormatter.Format ();
  33. OnResizeNeeded ();
  34. #if DEBUG
  35. if (_text != null && string.IsNullOrEmpty (Id)) {
  36. Id = _text;
  37. }
  38. #endif
  39. }
  40. }
  41. /// <summary>
  42. /// Gets or sets the <see cref="Gui.TextFormatter"/> used to format <see cref="Text"/>.
  43. /// </summary>
  44. public TextFormatter TextFormatter { get; set; }
  45. void TextFormatter_HotKeyChanged (object sender, KeyChangedEventArgs e)
  46. {
  47. HotKeyChanged?.Invoke (this, e);
  48. }
  49. /// <summary>
  50. /// Can be overridden if the <see cref="Terminal.Gui.TextFormatter.Text"/> has
  51. /// different format than the default.
  52. /// </summary>
  53. protected virtual void UpdateTextFormatterText ()
  54. {
  55. if (TextFormatter != null) {
  56. TextFormatter.Text = _text;
  57. }
  58. }
  59. /// <summary>
  60. /// Gets or sets whether trailing spaces at the end of word-wrapped lines are preserved
  61. /// or not when <see cref="TextFormatter.WordWrap"/> is enabled.
  62. /// If <see langword="true"/> trailing spaces at the end of wrapped lines will be removed when
  63. /// <see cref="Text"/> is formatted for display. The default is <see langword="false"/>.
  64. /// </summary>
  65. public virtual bool PreserveTrailingSpaces {
  66. get => TextFormatter.PreserveTrailingSpaces;
  67. set {
  68. if (TextFormatter.PreserveTrailingSpaces != value) {
  69. TextFormatter.PreserveTrailingSpaces = value;
  70. TextFormatter.NeedsFormat = true;
  71. }
  72. }
  73. }
  74. /// <summary>
  75. /// Gets or sets how the View's <see cref="Text"/> is aligned horizontally when drawn. Changing this property will redisplay the <see cref="View"/>.
  76. /// </summary>
  77. /// <value>The text alignment.</value>
  78. public virtual TextAlignment TextAlignment {
  79. get => TextFormatter.Alignment;
  80. set {
  81. TextFormatter.Alignment = value;
  82. UpdateTextFormatterText ();
  83. OnResizeNeeded ();
  84. }
  85. }
  86. /// <summary>
  87. /// Gets or sets how the View's <see cref="Text"/> is aligned vertically when drawn. Changing this property will redisplay the <see cref="View"/>.
  88. /// </summary>
  89. /// <value>The text alignment.</value>
  90. public virtual VerticalTextAlignment VerticalTextAlignment {
  91. get => TextFormatter.VerticalAlignment;
  92. set {
  93. TextFormatter.VerticalAlignment = value;
  94. SetNeedsDisplay ();
  95. }
  96. }
  97. /// <summary>
  98. /// Gets or sets the direction of the View's <see cref="Text"/>. Changing this property will redisplay the <see cref="View"/>.
  99. /// </summary>
  100. /// <value>The text alignment.</value>
  101. public virtual TextDirection TextDirection {
  102. get => TextFormatter.Direction;
  103. set {
  104. UpdateTextDirection (value);
  105. TextFormatter.Direction = value;
  106. }
  107. }
  108. private void UpdateTextDirection (TextDirection newDirection)
  109. {
  110. var directionChanged = TextFormatter.IsHorizontalDirection (TextFormatter.Direction)
  111. != TextFormatter.IsHorizontalDirection (newDirection);
  112. TextFormatter.Direction = newDirection;
  113. var isValidOldAutoSize = AutoSize && IsValidAutoSize (out var _);
  114. UpdateTextFormatterText ();
  115. if ((!ForceValidatePosDim && directionChanged && AutoSize)
  116. || (ForceValidatePosDim && directionChanged && AutoSize && isValidOldAutoSize)) {
  117. OnResizeNeeded ();
  118. } else if (directionChanged && IsAdded) {
  119. ResizeBoundsToFit (Bounds.Size);
  120. // BUGBUG: I think this call is redundant.
  121. SetBoundsToFitFrame ();
  122. } else {
  123. SetBoundsToFitFrame ();
  124. }
  125. TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
  126. SetNeedsDisplay ();
  127. }
  128. /// <summary>
  129. /// Gets the width or height of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> characters
  130. /// in the <see cref="Text"/> property.
  131. /// </summary>
  132. /// <remarks>
  133. /// Only the first hotkey specifier found in <see cref="Text"/> is supported.
  134. /// </remarks>
  135. /// <param name="isWidth">If <see langword="true"/> (the default) the width required for the hotkey specifier is returned. Otherwise the height is returned.</param>
  136. /// <returns>The number of characters required for the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>. If the text direction specified
  137. /// by <see cref="TextDirection"/> does not match the <paramref name="isWidth"/> parameter, <c>0</c> is returned.</returns>
  138. public int GetHotKeySpecifierLength (bool isWidth = true)
  139. {
  140. if (isWidth) {
  141. return TextFormatter.IsHorizontalDirection (TextDirection) &&
  142. TextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
  143. ? Math.Max (HotKeySpecifier.GetColumns (), 0) : 0;
  144. } else {
  145. return TextFormatter.IsVerticalDirection (TextDirection) &&
  146. TextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
  147. ? Math.Max (HotKeySpecifier.GetColumns (), 0) : 0;
  148. }
  149. }
  150. /// <summary>
  151. /// Gets the dimensions required for <see cref="Text"/> ignoring a <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>.
  152. /// </summary>
  153. /// <returns></returns>
  154. public Size GetSizeNeededForTextWithoutHotKey ()
  155. {
  156. return new Size (TextFormatter.Size.Width - GetHotKeySpecifierLength (),
  157. TextFormatter.Size.Height - GetHotKeySpecifierLength (false));
  158. }
  159. /// <summary>
  160. /// Gets the dimensions required for <see cref="Text"/> accounting for a <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> .
  161. /// </summary>
  162. /// <returns></returns>
  163. public Size GetTextFormatterSizeNeededForTextAndHotKey ()
  164. {
  165. if (string.IsNullOrEmpty (TextFormatter.Text)) {
  166. if (!IsInitialized) return Size.Empty;
  167. return Bounds.Size;
  168. }
  169. // BUGBUG: This IGNORES what Text is set to, using on only the current View size. This doesn't seem to make sense.
  170. // BUGBUG: This uses Frame; in v2 it should be Bounds
  171. return new Size (Bounds.Size.Width + GetHotKeySpecifierLength (),
  172. Bounds.Size.Height + GetHotKeySpecifierLength (false));
  173. }
  174. }
  175. }