From 304a6c914ec302284ad00e23f5c167b63270fac2 Mon Sep 17 00:00:00 2001 From: Tig Kindel Date: Mon, 8 Jan 2024 10:08:29 -0700 Subject: [PATCH] Refactored TextFormatter.Size setting logic --- Terminal.Gui/Text/TextFormatter.cs | 82 +++++++++++++++------- Terminal.Gui/View/Layout/ViewLayout.cs | 81 ++++++---------------- Terminal.Gui/View/ViewText.cs | 96 +++++++++++++++++++++----- 3 files changed, 159 insertions(+), 100 deletions(-) diff --git a/Terminal.Gui/Text/TextFormatter.cs b/Terminal.Gui/Text/TextFormatter.cs index 104532270..47390077e 100644 --- a/Terminal.Gui/Text/TextFormatter.cs +++ b/Terminal.Gui/Text/TextFormatter.cs @@ -50,23 +50,50 @@ namespace Terminal.Gui { Justified } - /// TextDirection [H] = Horizontal [V] = Vertical - /// ============= - /// LeftRight_TopBottom [H] Normal - /// TopBottom_LeftRight [V] Normal - /// - /// RightLeft_TopBottom [H] Invert Text - /// TopBottom_RightLeft [V] Invert Lines - /// - /// LeftRight_BottomTop [H] Invert Lines - /// BottomTop_LeftRight [V] Invert Text - /// - /// RightLeft_BottomTop [H] Invert Text + Invert Lines - /// BottomTop_RightLeft [V] Invert Text + Invert Lines - /// /// /// Text direction enumeration, controls how text is displayed. /// + /// + /// TextDirection [H] = Horizontal [V] = Vertical + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
TextDirectionDescription
LeftRight_TopBottom [H]Normal
TopBottom_LeftRight [V]Normal
RightLeft_TopBottom [H]Invert Text
TopBottom_RightLeft [V]Invert Lines
LeftRight_BottomTop [H]Invert Lines
BottomTop_LeftRight [V]Invert Text
RightLeft_BottomTop [H]Invert Text + Invert Lines
BottomTop_RightLeft [V]Invert Text + Invert Lines
+ ///
public enum TextDirection { /// /// Normal horizontal direction. @@ -1087,13 +1114,15 @@ namespace Terminal.Gui { } /// - /// Used by to resize the view's with the . - /// Setting to true only work if the and are null or - /// values and doesn't work with layout, - /// to avoid breaking the and settings. + /// Gets or sets whether the should be automatically changed to fit the . /// /// - /// Auto size is ignored if the and are used. + /// + /// Used by to resize the view's to fit . + /// + /// + /// AutoSize is ignored if and are used. + /// /// public bool AutoSize { get => _autoSize; @@ -1204,7 +1233,7 @@ namespace Terminal.Gui { } /// - /// Allows word wrap the to fit the available container width. + /// Gets or sets whether word wrap will be used to fit to . /// public bool WordWrap { get => _wordWrap; @@ -1212,10 +1241,10 @@ namespace Terminal.Gui { } /// - /// Gets or sets the size of the area the text will be constrained to when formatted. + /// Gets or sets the size will be constrained to when formatted. /// /// - /// Does not return the size the formatted text; just the value that was set. + /// Does not return the size of the formatted text but the size that will be used to constrain the text when formatted. /// public Size Size { get => _size; @@ -1325,11 +1354,16 @@ namespace Terminal.Gui { } /// - /// Gets or sets whether the needs to format the text when is called. - /// If it is false when Draw is called, the Draw call will be faster. + /// Gets or sets whether the needs to format the text. /// /// /// + /// If false when Draw is called, the Draw call will be faster. + /// + /// + /// Used by + /// + /// /// This is set to true when the properties of are set. /// /// diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 0ae1e4e2b..1c5d9bc76 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -87,7 +87,7 @@ public partial class View { // TODO: Figure out if the below can be optimized. if (IsInitialized /*|| LayoutStyle == LayoutStyle.Absolute*/) { LayoutFrames (); - TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); + SetTextFormatterSize (); SetNeedsLayout (); SetNeedsDisplay (); } @@ -195,7 +195,7 @@ public partial class View { /// /// - /// Indicates the LayoutStyle for the . + /// Gets the LayoutStyle for the . /// /// /// If Absolute, the , , , and @@ -227,7 +227,7 @@ public partial class View { /// /// /// If is the value of Bounds is indeterminate until - /// the view has been initialized ( is true) and has been + /// the view has been initialized ( is true) and has been /// called. /// /// @@ -279,12 +279,12 @@ public partial class View { /// /// /// If set to a relative value (e.g. ) the value is indeterminate until the - /// view has been initialized ( is true) and has been + /// view has been initialized ( is true) and has been /// called. /// /// /// Changing this property will eventually (when the view is next drawn) cause the - /// and + /// and /// methods to be called. /// /// @@ -311,7 +311,7 @@ public partial class View { /// /// /// If set to a relative value (e.g. ) the value is indeterminate until the - /// view has been initialized ( is true) and has been + /// view has been initialized ( is true) and has been /// called. /// /// @@ -337,13 +337,13 @@ public partial class View { } /// - /// Gets or sets the width of the view. + /// Gets or sets the width dimension of the view. /// /// The object representing the width of the view (the number of columns). /// /// /// If set to a relative value (e.g. ) the value is indeterminate until the - /// view has been initialized ( is true) and has been + /// view has been initialized ( is true) and has been /// called. /// /// @@ -377,13 +377,13 @@ public partial class View { } /// - /// Gets or sets the height of the view. + /// Gets or sets the height dimension of the view. /// /// The object representing the height of the view (the number of rows). /// /// /// If set to a relative value (e.g. ) the value is indeterminate until the - /// view has been initialized ( is true) and has been + /// view has been initialized ( is true) and has been /// called. /// /// @@ -422,7 +422,7 @@ public partial class View { /// /// Setting this to will enable validation of , , , /// and - /// during set operations and in .If invalid settings are discovered exceptions will be thrown + /// during set operations and in . If invalid settings are discovered exceptions will be thrown /// indicating the error. /// This will impose a performance penalty and thus should only be used for debugging. /// @@ -440,8 +440,12 @@ public partial class View { /// if won't fit the view will be resized as needed. /// /// - /// In addition, if is the new values of and - /// must be of the same types of the existing one to avoid breaking the settings. + /// If is set to then and + /// will be changed to if they are not already. + /// + /// + /// If is set to then and + /// will left unchanged. /// /// public virtual bool AutoSize { @@ -585,7 +589,7 @@ public partial class View { if (IsInitialized) { SetFrameToFitText (); LayoutFrames (); - TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); + SetTextFormatterSize (); SetNeedsLayout (); SetNeedsDisplay (); } @@ -853,14 +857,14 @@ public partial class View { if (IsInitialized) { // TODO: Figure out what really is needed here. All unit tests (except AutoSize) pass as-is //LayoutFrames (); - //TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); + SetTextFormatterSize (); SetNeedsLayout (); //SetNeedsDisplay (); } // BUGBUG: Why is this AFTER setting Frame? Seems duplicative. if (!SetFrameToFitText ()) { - TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); + SetTextFormatterSize (); } } } @@ -1084,7 +1088,7 @@ public partial class View { var oldBounds = Bounds; OnLayoutStarted (new LayoutEventArgs { OldBounds = oldBounds }); - TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); + SetTextFormatterSize (); // Sort out the dependencies of the X, Y, Width, Height properties var nodes = new HashSet (); @@ -1163,49 +1167,6 @@ public partial class View { return boundsChanged; } - /// - /// Gets the Frame dimensions required to fit within using the text - /// specified by the - /// property and accounting for any characters. - /// - /// The of the view required to fit the text. - public Size GetAutoSize () - { - var x = 0; - var y = 0; - if (IsInitialized) { - x = Bounds.X; - y = Bounds.Y; - } - var rect = TextFormatter.CalcRect (x, y, TextFormatter.Text, TextFormatter.Direction); - var newWidth = rect.Size.Width - GetHotKeySpecifierLength () + Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal; - var newHeight = rect.Size.Height - GetHotKeySpecifierLength (false) + Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical; - return new Size (newWidth, newHeight); - } - - bool IsValidAutoSize (out Size autoSize) - { - var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); - autoSize = new Size (rect.Size.Width - GetHotKeySpecifierLength (), - rect.Size.Height - GetHotKeySpecifierLength (false)); - return !(ValidatePosDim && (!(Width is Dim.DimAbsolute) || !(Height is Dim.DimAbsolute)) || - _frame.Size.Width != rect.Size.Width - GetHotKeySpecifierLength () || - _frame.Size.Height != rect.Size.Height - GetHotKeySpecifierLength (false)); - } - - bool IsValidAutoSizeWidth (Dim width) - { - var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); - var dimValue = width.Anchor (0); - return !(ValidatePosDim && !(width is Dim.DimAbsolute) || dimValue != rect.Size.Width - GetHotKeySpecifierLength ()); - } - - bool IsValidAutoSizeHeight (Dim height) - { - var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); - var dimValue = height.Anchor (0); - return !(ValidatePosDim && !(height is Dim.DimAbsolute) || dimValue != rect.Size.Height - GetHotKeySpecifierLength (false)); - } /// /// Determines if the View's can be set to a new value. diff --git a/Terminal.Gui/View/ViewText.cs b/Terminal.Gui/View/ViewText.cs index 25cfc5aa5..6151708a3 100644 --- a/Terminal.Gui/View/ViewText.cs +++ b/Terminal.Gui/View/ViewText.cs @@ -26,6 +26,9 @@ public partial class View { /// to /// (Rune)0xffff. /// + /// + /// If is true, the will be adjusted to fit the text. + /// /// public virtual string Text { get => _text; @@ -69,6 +72,11 @@ public partial class View { /// Gets or sets how the View's is aligned horizontally when drawn. Changing this property will /// redisplay the . /// + /// + /// + /// If is true, the will be adjusted to fit the text. + /// + /// /// The text alignment. public virtual TextAlignment TextAlignment { get => TextFormatter.Alignment; @@ -83,6 +91,11 @@ public partial class View { /// Gets or sets how the View's is aligned vertically when drawn. Changing this property will redisplay /// the . /// + /// + /// + /// If is true, the will be adjusted to fit the text. + /// + /// /// The text alignment. public virtual VerticalTextAlignment VerticalTextAlignment { get => TextFormatter.VerticalAlignment; @@ -96,6 +109,11 @@ public partial class View { /// Gets or sets the direction of the View's . Changing this property will redisplay the /// . /// + /// + /// + /// If is true, the will be adjusted to fit the text. + /// + /// /// The text alignment. public virtual TextDirection TextDirection { get => TextFormatter.Direction; @@ -134,7 +152,7 @@ public partial class View { } else { SetFrameToFitText (); } - TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); + SetTextFormatterSize (); SetNeedsDisplay (); } @@ -210,18 +228,18 @@ public partial class View { } /// - /// Gets the width or height of the characters + /// Gets the width or height of the characters /// in the property. /// /// - /// Only the first hotkey specifier found in is supported. + /// Only the first HotKey specifier found in is supported. /// /// - /// If (the default) the width required for the hotkey specifier is returned. Otherwise the height + /// If (the default) the width required for the HotKey specifier is returned. Otherwise the height /// is returned. /// /// - /// The number of characters required for the . If the text + /// The number of characters required for the . If the text /// direction specified /// by does not match the parameter, 0 is returned. /// @@ -238,31 +256,77 @@ public partial class View { } /// - /// Gets the dimensions required for ignoring a - /// . + /// Gets the dimensions required for ignoring a . /// /// - public Size GetSizeNeededForTextWithoutHotKey () => new (TextFormatter.Size.Width - GetHotKeySpecifierLength (), + internal Size GetSizeNeededForTextWithoutHotKey () => new (TextFormatter.Size.Width - GetHotKeySpecifierLength (), TextFormatter.Size.Height - GetHotKeySpecifierLength (false)); /// - /// Gets the dimensions required for accounting for a - /// . + /// Sets .Size to the current size, adjusted for + /// . /// + /// + /// Use this API to set when the view has changed such that the + /// size required to fit the text has changed. + /// changes. + /// /// - public Size GetTextFormatterSizeNeededForTextAndHotKey () + internal void SetTextFormatterSize () { if (!IsInitialized) { - return Size.Empty; + TextFormatter.Size = Size.Empty; } if (string.IsNullOrEmpty (TextFormatter.Text)) { - return Bounds.Size; + TextFormatter.Size = Bounds.Size; } - // BUGBUG: This IGNORES what Text is set to, using on only the current View size. This doesn't seem to make sense. - // BUGBUG: This uses Frame; in v2 it should be Bounds - return new Size (Bounds.Size.Width + GetHotKeySpecifierLength (), + TextFormatter.Size = new Size (Bounds.Size.Width + GetHotKeySpecifierLength (), Bounds.Size.Height + GetHotKeySpecifierLength (false)); } + + /// + /// Gets the Frame dimensions required to fit within using the text + /// specified by the + /// property and accounting for any characters. + /// + /// The the needs to be set to fit the text. + public Size GetAutoSize () + { + var x = 0; + var y = 0; + if (IsInitialized) { + x = Bounds.X; + y = Bounds.Y; + } + var rect = TextFormatter.CalcRect (x, y, TextFormatter.Text, TextFormatter.Direction); + var newWidth = rect.Size.Width - GetHotKeySpecifierLength () + Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal; + var newHeight = rect.Size.Height - GetHotKeySpecifierLength (false) + Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical; + return new Size (newWidth, newHeight); + } + + bool IsValidAutoSize (out Size autoSize) + { + var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); + autoSize = new Size (rect.Size.Width - GetHotKeySpecifierLength (), + rect.Size.Height - GetHotKeySpecifierLength (false)); + return !(ValidatePosDim && (!(Width is Dim.DimAbsolute) || !(Height is Dim.DimAbsolute)) || + _frame.Size.Width != rect.Size.Width - GetHotKeySpecifierLength () || + _frame.Size.Height != rect.Size.Height - GetHotKeySpecifierLength (false)); + } + + bool IsValidAutoSizeWidth (Dim width) + { + var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); + var dimValue = width.Anchor (0); + return !(ValidatePosDim && !(width is Dim.DimAbsolute) || dimValue != rect.Size.Width - GetHotKeySpecifierLength ()); + } + + bool IsValidAutoSizeHeight (Dim height) + { + var rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); + var dimValue = height.Anchor (0); + return !(ValidatePosDim && !(height is Dim.DimAbsolute) || dimValue != rect.Size.Height - GetHotKeySpecifierLength (false)); + } } \ No newline at end of file