diff --git a/Terminal.Gui/Text/TextFormatter.cs b/Terminal.Gui/Text/TextFormatter.cs index 99dbfa42c..d518c4e2f 100644 --- a/Terminal.Gui/Text/TextFormatter.cs +++ b/Terminal.Gui/Text/TextFormatter.cs @@ -30,10 +30,10 @@ public class TextFormatter /// Gets or sets whether the should be automatically changed to fit the . /// - /// Used by to resize the view's to fit . + /// Used by to resize the view's to fit . /// - /// AutoSize is ignored if and - /// are used. + /// and + /// are ignored when is . /// /// public bool AutoSize @@ -43,13 +43,81 @@ public class TextFormatter { _autoSize = EnableNeedsFormat (value); - if (_autoSize)// && Alignment != TextAlignment.Justified && VerticalAlignment != VerticalTextAlignment.Justified) + if (_autoSize) { - Size = CalcRect (0, 0, _text, Direction, TabWidth).Size; + Size = GetAutoSize (); } } } + private Size GetAutoSize () + { + if (string.IsNullOrEmpty(_text)) + { + return Size.Empty; + } + + int width = int.MaxValue; + int height = int.MaxValue; + string text = _text; + List lines; + + if (FindHotKey (_text, HotKeySpecifier, out _hotKeyPos, out Key newHotKey)) + { + HotKey = newHotKey; + text = RemoveHotKeySpecifier (Text, _hotKeyPos, HotKeySpecifier); + text = ReplaceHotKeyWithTag (text, _hotKeyPos); + } + + if (IsVerticalDirection (Direction)) + { + int colsWidth = GetSumMaxCharWidth (text, 0, 1, TabWidth); + + lines = Format ( + text, + height, + VerticalAlignment == VerticalTextAlignment.Justified, + width > colsWidth && WordWrap, + PreserveTrailingSpaces, + TabWidth, + Direction, + MultiLine + ); + colsWidth = GetMaxColsForWidth (lines, width, TabWidth); + + if (lines.Count > colsWidth) + { + lines.RemoveRange (colsWidth, lines.Count - colsWidth); + } + height = lines.Max (static line => line.GetColumns ()); + width = lines.Count; + } + else + { + lines = Format ( + text, + width, + false, // Ignore justification because autosize means no justification + height > 1 && WordWrap, + PreserveTrailingSpaces, + TabWidth, + Direction, + MultiLine + ); + + // Format always returns at least 1 line + if (lines.Count == 1 && string.IsNullOrEmpty (lines [0])) + { + return Size.Empty; + } + + width = lines.Max (static line => line.GetColumns ()); + height = lines.Count; + } + + return new (width, height); + } + /// /// Gets the cursor position of the . If the is defined, the cursor will /// be positioned over it. @@ -65,9 +133,9 @@ public class TextFormatter { _textDirection = EnableNeedsFormat (value); - if (AutoSize)// && Alignment != TextAlignment.Justified && VerticalAlignment != VerticalTextAlignment.Justified) + if (AutoSize) { - Size = CalcRect (0, 0, Text, Direction, TabWidth).Size; + Size = GetAutoSize (); } } } @@ -150,7 +218,8 @@ public class TextFormatter { if (AutoSize)// && Alignment != TextAlignment.Justified && VerticalAlignment != VerticalTextAlignment.Justified) { - _size = EnableNeedsFormat (CalcRect (0, 0, Text, Direction, TabWidth).Size); + //_size = EnableNeedsFormat (CalcRect (0, 0, Text, Direction, TabWidth).Size); + _size = EnableNeedsFormat (value); } else { @@ -175,9 +244,10 @@ public class TextFormatter bool textWasNull = _text is null && value != null; _text = EnableNeedsFormat (value); + // BUGBUG: If AutoSize is false, there should be no "automatic behavior" like setting the size if (AutoSize || (textWasNull && Size.IsEmpty)) { - Size = CalcRect (0, 0, _text, Direction, TabWidth).Size; + Size = GetAutoSize (); } } } @@ -287,13 +357,13 @@ public class TextFormatter Rune [] runes = linesFormatted [line].ToRunes (); runes = Direction switch - { - TextDirection.RightLeft_BottomTop => runes.Reverse ().ToArray (), - TextDirection.RightLeft_TopBottom => runes.Reverse ().ToArray (), - TextDirection.BottomTop_LeftRight => runes.Reverse ().ToArray (), - TextDirection.BottomTop_RightLeft => runes.Reverse ().ToArray (), - _ => runes - }; + { + TextDirection.RightLeft_BottomTop => runes.Reverse ().ToArray (), + TextDirection.RightLeft_TopBottom => runes.Reverse ().ToArray (), + TextDirection.BottomTop_LeftRight => runes.Reverse ().ToArray (), + TextDirection.BottomTop_RightLeft => runes.Reverse ().ToArray (), + _ => runes + }; // When text is justified, we lost left or right, so we use the direction to align. @@ -700,48 +770,48 @@ public class TextFormatter public static bool IsHorizontalDirection (TextDirection textDirection) { return textDirection switch - { - TextDirection.LeftRight_TopBottom => true, - TextDirection.LeftRight_BottomTop => true, - TextDirection.RightLeft_TopBottom => true, - TextDirection.RightLeft_BottomTop => true, - _ => false - }; + { + TextDirection.LeftRight_TopBottom => true, + TextDirection.LeftRight_BottomTop => true, + TextDirection.RightLeft_TopBottom => true, + TextDirection.RightLeft_BottomTop => true, + _ => false + }; } /// Check if it is a vertical direction public static bool IsVerticalDirection (TextDirection textDirection) { return textDirection switch - { - TextDirection.TopBottom_LeftRight => true, - TextDirection.TopBottom_RightLeft => true, - TextDirection.BottomTop_LeftRight => true, - TextDirection.BottomTop_RightLeft => true, - _ => false - }; + { + TextDirection.TopBottom_LeftRight => true, + TextDirection.TopBottom_RightLeft => true, + TextDirection.BottomTop_LeftRight => true, + TextDirection.BottomTop_RightLeft => true, + _ => false + }; } /// Check if it is Left to Right direction public static bool IsLeftToRight (TextDirection textDirection) { return textDirection switch - { - TextDirection.LeftRight_TopBottom => true, - TextDirection.LeftRight_BottomTop => true, - _ => false - }; + { + TextDirection.LeftRight_TopBottom => true, + TextDirection.LeftRight_BottomTop => true, + _ => false + }; } /// Check if it is Top to Bottom direction public static bool IsTopToBottom (TextDirection textDirection) { return textDirection switch - { - TextDirection.TopBottom_LeftRight => true, - TextDirection.TopBottom_RightLeft => true, - _ => false - }; + { + TextDirection.TopBottom_LeftRight => true, + TextDirection.TopBottom_RightLeft => true, + _ => false + }; } // TODO: Move to StringExtensions? @@ -1122,21 +1192,21 @@ public class TextFormatter case ' ': return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length); case '\t': - { - length += tabWidth + 1; - - if (length == tabWidth && tabWidth > cWidth) { - return to + 1; - } + length += tabWidth + 1; - if (length > cWidth && tabWidth > cWidth) - { - return to; - } + if (length == tabWidth && tabWidth > cWidth) + { + return to + 1; + } - return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length); - } + if (length > cWidth && tabWidth > cWidth) + { + return to; + } + + return GetNextWhiteSpace (to + 1, cWidth, out incomplete, length); + } default: to++; @@ -1145,11 +1215,11 @@ public class TextFormatter } return cLength switch - { - > 0 when to < runes.Count && runes [to].Value != ' ' && runes [to].Value != '\t' => from, - > 0 when to < runes.Count && (runes [to].Value == ' ' || runes [to].Value == '\t') => from, - _ => to - }; + { + > 0 when to < runes.Count && runes [to].Value != ' ' && runes [to].Value != '\t' => from, + > 0 when to < runes.Count && (runes [to].Value == ' ' || runes [to].Value == '\t') => from, + _ => to + }; } if (start < text.GetRuneCount ()) @@ -1742,7 +1812,7 @@ public class TextFormatter return lineIdx; } - /// Calculates the rectangle required to hold text, assuming no word wrapping or justification. + /// Calculates the rectangle required to hold text, assuming no word wrapping, justification, or hotkeys. /// /// This API will return incorrect results if the text includes glyphs who's width is dependent on surrounding /// glyphs (e.g. Arabic). diff --git a/Terminal.Gui/View/Layout/PosDim.cs b/Terminal.Gui/View/Layout/PosDim.cs index 9941546f7..7fb8cab99 100644 --- a/Terminal.Gui/View/Layout/PosDim.cs +++ b/Terminal.Gui/View/Layout/PosDim.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Runtime.InteropServices.JavaScript; using static System.Net.Mime.MediaTypeNames; using static Terminal.Gui.Dialog; using static Terminal.Gui.Dim; @@ -354,6 +355,16 @@ public class Pos return Anchor (superviewDimension); } + + /// + /// Diagnostics API to determine if this Pos object references other views. + /// + /// + internal virtual bool ReferencesOtherViews () + { + return false; + } + internal class PosAbsolute (int n) : Pos { private readonly int _n = n; @@ -447,6 +458,25 @@ public class Pos return left - right; } + + /// + /// Diagnostics API to determine if this Pos object references other views. + /// + /// + internal override bool ReferencesOtherViews () + { + if (_left.ReferencesOtherViews ()) + { + return true; + } + + if (_right.ReferencesOtherViews ()) + { + return true; + } + + return false; + } } internal class PosFactor (float factor) : Pos @@ -531,6 +561,15 @@ public class Pos _ => 0 }; } + + /// + /// Diagnostics API to determine if this Pos object references other views. + /// + /// + internal override bool ReferencesOtherViews () + { + return true; + } } } @@ -839,6 +878,15 @@ public class Dim return Math.Max (Anchor (superviewContentSize - location), 0); } + /// + /// Diagnostics API to determine if this Dim object references other views. + /// + /// + internal virtual bool ReferencesOtherViews () + { + return false; + } + internal class DimAbsolute (int n) : Dim { private readonly int _n = n; @@ -915,6 +963,15 @@ public class Dim return int.Min (max, _max?.Anchor (superviewContentSize) ?? superviewContentSize); } + /// + /// Diagnostics API to determine if this Dim object references other views. + /// + /// + internal override bool ReferencesOtherViews () + { + return _style is Dim.DimAutoStyle.Subviews or Dim.DimAutoStyle.Auto; + } + } internal class DimCombine (bool add, Dim left, Dim right) : Dim { @@ -955,6 +1012,25 @@ public class Dim return newDimension; } + + /// + /// Diagnostics API to determine if this Dim object references other views. + /// + /// + internal override bool ReferencesOtherViews () + { + if (_left.ReferencesOtherViews ()) + { + return true; + } + + if (_right.ReferencesOtherViews ()) + { + return true; + } + + return false; + } } internal class DimFactor (float factor, bool remaining = false) : Dim @@ -1033,5 +1109,10 @@ public class Dim _ => 0 }; } + + internal override bool ReferencesOtherViews () + { + return true; + } } } \ No newline at end of file diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 24b680fa0..23a6102fa 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -348,6 +348,7 @@ public partial class View { TextFormatter.AutoSize = value; + // BUGBUG: This is all a hack until AutoSize is removed if (value) { UpdateTextFormatterText (); @@ -365,18 +366,9 @@ public partial class View } else { - if (IsInitialized) - { - Height = ContentSize.Height; - Width = ContentSize.Width; - - } - else - { - _height = ContentSize.Height; - _width = ContentSize.Width; - OnResizeNeeded (); - } + _height = ContentSize.Height; + _width = ContentSize.Width; + OnResizeNeeded (); } } } @@ -688,7 +680,7 @@ public partial class View superView = viewToMove.SuperView; } - if (superView.Margin is { } && superView == viewToMove.SuperView) + if (superView?.Margin is { } && superView == viewToMove.SuperView) { maxDimension -= superView.GetAdornmentsThickness ().Left + superView.GetAdornmentsThickness ().Right; } @@ -991,27 +983,27 @@ public partial class View { // TODO: Identify a real-world use-case where this API should be virtual. // TODO: Until then leave it `internal` and non-virtual + // First try SuperView.Viewport, then Application.Top, then Driver.Viewport. // Finally, if none of those are valid, use int.MaxValue (for Unit tests). Size contentSize = SuperView is { IsInitialized: true } ? SuperView.ContentSize : Application.Top is { } && Application.Top != this && Application.Top.IsInitialized ? Application.Top.ContentSize : Application.Driver?.Screen.Size ?? new (int.MaxValue, int.MaxValue); - SetRelativeLayout (contentSize); - // TODO: Determine what, if any of the below is actually needed here. + + + SetTextFormatterSize (); + + SetRelativeLayout (contentSize); if (IsInitialized) { - //if (AutoSize) - { - // SetFrameToFitText (); - SetTextFormatterSize (); - } - LayoutAdornments (); - SetNeedsDisplay (); - SetNeedsLayout (); } + + SetNeedsDisplay (); + SetNeedsLayout (); + } internal bool LayoutNeeded { get; private set; } = true; @@ -1062,22 +1054,6 @@ public partial class View Debug.Assert (_height is { }); CheckDimAuto (); - - SetTextFormatterSize (); - - var autoSize = Size.Empty; - - //if (AutoSize) - //{ - // // TODO: Nuke this from orbit once Dim.Auto is fully implemented - // autoSize = GetTextAutoSize (); - //} - SetTextFormatterSize (); - if (TextFormatter.NeedsFormat) - { - TextFormatter.Format (); - } - int newX = _x.Calculate (superviewContentSize.Width, _width, this, Dim.Dimension.Width); int newW = _width.Calculate (newX, superviewContentSize.Width, this, Dim.Dimension.Width); int newY = _y.Calculate (superviewContentSize.Height, _height, this, Dim.Dimension.Height); diff --git a/Terminal.Gui/View/View.cs b/Terminal.Gui/View/View.cs index 8a04e5170..8eab04bba 100644 --- a/Terminal.Gui/View/View.cs +++ b/Terminal.Gui/View/View.cs @@ -139,6 +139,8 @@ public partial class View : Responder, ISupportInitializeNotification /// public View () { + CreateAdornments (); + HotKeySpecifier = (Rune)'_'; TitleTextFormatter.HotKeyChanged += TitleTextFormatter_HotKeyChanged; @@ -150,8 +152,6 @@ public partial class View : Responder, ISupportInitializeNotification TabStop = false; AddCommands (); - - CreateAdornments (); } /// diff --git a/Terminal.Gui/View/ViewContent.cs b/Terminal.Gui/View/ViewContent.cs index 90fa3ab4a..164346ba2 100644 --- a/Terminal.Gui/View/ViewContent.cs +++ b/Terminal.Gui/View/ViewContent.cs @@ -289,10 +289,10 @@ public partial class View get { #if DEBUG - if (LayoutStyle == LayoutStyle.Computed && !IsInitialized) + if ((_width.ReferencesOtherViews () || _height.ReferencesOtherViews ()) && !IsInitialized) { Debug.WriteLine ( - $"WARNING: Viewport is being accessed before the View has been initialized. This is likely a bug in {this}" + $"WARNING: The dimensions of {this} are dependent on other views and Viewport is being accessed before the View has been initialized. This is likely a bug." ); } #endif // DEBUG @@ -305,6 +305,26 @@ public partial class View Thickness thickness = GetAdornmentsThickness (); + if (Frame.Size == Size.Empty) + { + // The Frame has not been set yet (e.g. the view has not been added to a SuperView yet). + // + if ((Width is Dim.DimAuto widthAuto && widthAuto._style != Dim.DimAutoStyle.Subviews) + || (Height is Dim.DimAuto heightAuto && heightAuto._style != Dim.DimAutoStyle.Subviews)) + { + if (TextFormatter.NeedsFormat) + { + // This updates TextFormatter.Size to the text size + TextFormatter.AutoSize = true; + + // Whenever DimAutoStyle.Text is set, ContentSize will match TextFormatter.Size. + ContentSize = TextFormatter.Size; + + } + } + //SetRelativeLayout (SuperView?.ContentSize ?? new Size (int.MaxValue, int.MaxValue)); + } + return new ( _viewportLocation, new ( diff --git a/Terminal.Gui/View/ViewDrawing.cs b/Terminal.Gui/View/ViewDrawing.cs index cc7109a5b..a252a4c76 100644 --- a/Terminal.Gui/View/ViewDrawing.cs +++ b/Terminal.Gui/View/ViewDrawing.cs @@ -413,7 +413,7 @@ public partial class View { if (!IsInitialized) { - return false; + return false; } // Each of these renders lines to either this View's LineCanvas diff --git a/Terminal.Gui/View/ViewText.cs b/Terminal.Gui/View/ViewText.cs index 9dab46773..e119c1acc 100644 --- a/Terminal.Gui/View/ViewText.cs +++ b/Terminal.Gui/View/ViewText.cs @@ -48,19 +48,9 @@ public partial class View get => _text; set { - if (value == _text) - { - return; - } - string old = _text; _text = value; - if (!string.IsNullOrEmpty (_text)) - { - - } - UpdateTextFormatterText (); OnResizeNeeded (); #if DEBUG @@ -180,38 +170,32 @@ public partial class View : 0; } - // BUGBUG: This API is fundamentally broken. Text autosize should have nothing to do with what's visible (Viewport) and only ContentSize. - /// - /// Gets the Frame dimensions required to fit within using the text - /// specified by the property and accounting for any - /// characters. - /// - /// - /// - /// The of the required to fit the formatted text. - public Size GetTextAutoSize () - { - var x = 0; - var y = 0; + ///// + ///// Gets dimensions required to fit within using the text + ///// specified by the property and accounting for any + ///// characters. + ///// + ///// + ///// + ///// The of the required to fit the formatted text. + //public Size GetTextAutoSize () + //{ + // var x = 0; + // var y = 0; - if (IsInitialized) - { - x = Viewport.X; - y = Viewport.Y; - } + // if (IsInitialized) + // { + // x = Viewport.X; + // y = Viewport.Y; + // } - Rectangle rect = TextFormatter.CalcRect (x, y, TextFormatter.Text, TextFormatter.Direction); + // // Get the size of the text without the hot key specifier + // Rectangle rect = TextFormatter.CalcRect (x, y, TextFormatter.Text, TextFormatter.Direction); + // int newWidth = rect.Size.Width - GetHotKeySpecifierLength (); + // int newHeight = rect.Size.Height - GetHotKeySpecifierLength (false); - int newWidth = rect.Size.Width - - GetHotKeySpecifierLength () - + (Margin == null ? 0 : Margin.Thickness.Horizontal + Border.Thickness.Horizontal + Padding.Thickness.Horizontal); - - int newHeight = rect.Size.Height - - GetHotKeySpecifierLength (false) - + (Margin == null ? 0 : Margin.Thickness.Vertical + Border.Thickness.Vertical + Padding.Thickness.Vertical); - - return new (newWidth, newHeight); - } + // return new (newWidth, newHeight); + //} /// /// Can be overridden if the has @@ -248,82 +232,60 @@ public partial class View /// internal void SetTextFormatterSize () { + UpdateTextFormatterText (); + //if (!IsInitialized) //{ - // TextFormatter.Size = Size.Empty; - // return; //} - if (string.IsNullOrEmpty (TextFormatter.Text)) - { - TextFormatter.Size = ContentSize; + //Dim.DimAuto widthAuto = Width as Dim.DimAuto; + //Dim.DimAuto heightAuto = Height as Dim.DimAuto; + // TODO: This is a hack. Figure out how to move this into DimDimAuto + if ((Width is Dim.DimAuto widthAuto && widthAuto._style != Dim.DimAutoStyle.Subviews) + || (Height is Dim.DimAuto heightAuto && heightAuto._style != Dim.DimAutoStyle.Subviews)) + { + // This updates TextFormatter.Size to the text size + TextFormatter.AutoSize = true; + + // Whenever DimAutoStyle.Text is set, ContentSize will match TextFormatter.Size. + ContentSize = TextFormatter.Size; return; } - int w = Viewport.Size.Width + GetHotKeySpecifierLength (); - - // TODO: This is a hack. Figure out how to move this into DimDimAuto - if (Width is Dim.DimAuto widthAuto && widthAuto._style != Dim.DimAutoStyle.Subviews) - { - if (Height is Dim.DimAuto) - { - // Both are auto. - TextFormatter.Size = new Size (SuperView?.ContentSize.Width ?? int.MaxValue, SuperView?.ContentSize.Height ?? int.MaxValue); - } - else - { - TextFormatter.Size = new Size (SuperView?.ContentSize.Width ?? int.MaxValue, ContentSize.Height + GetHotKeySpecifierLength ()); - } - - w = TextFormatter.FormatAndGetSize ().Width; - } - else - { - TextFormatter.Size = new Size (w, SuperView?.Viewport.Height ?? 0); - } - - int h = ContentSize.Height + GetHotKeySpecifierLength (); - - // TODO: This is a hack. Figure out how to move this into DimDimAuto - if (Height is Dim.DimAuto heightAuto && heightAuto._style != Dim.DimAutoStyle.Subviews) - { - TextFormatter.NeedsFormat = true; - h = TextFormatter.FormatAndGetSize ().Height; - } - - TextFormatter.Size = new Size (w, h); + TextFormatter.AutoSize = false; + TextFormatter.Size = new Size (ContentSize.Width, ContentSize.Height); } - //private bool IsValidAutoSize (out Size autoSize) + ////private bool IsValidAutoSize (out Size autoSize) + ////{ + //// Rectangle 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)); + ////} + + //private bool IsValidAutoSizeHeight (Dim height) //{ // Rectangle rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); + // int dimValue = height.Anchor (0); - // 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)); + // return !((ValidatePosDim && !(height is Dim.DimAbsolute)) || dimValue != rect.Size.Height - GetHotKeySpecifierLength (false)); //} - private bool IsValidAutoSizeHeight (Dim height) - { - Rectangle rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); - int dimValue = height.Anchor (0); + //private bool IsValidAutoSizeWidth (Dim width) + //{ + // Rectangle rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); + // int dimValue = width.Anchor (0); - return !((ValidatePosDim && !(height is Dim.DimAbsolute)) || dimValue != rect.Size.Height - GetHotKeySpecifierLength (false)); - } - - private bool IsValidAutoSizeWidth (Dim width) - { - Rectangle rect = TextFormatter.CalcRect (_frame.X, _frame.Y, TextFormatter.Text, TextDirection); - int dimValue = width.Anchor (0); - - return !((ValidatePosDim && !(width is Dim.DimAbsolute)) || dimValue != rect.Size.Width - GetHotKeySpecifierLength ()); - } + // return !((ValidatePosDim && !(width is Dim.DimAbsolute)) || dimValue != rect.Size.Width - GetHotKeySpecifierLength ()); + //} ///// ///// Sets the size of the View to the minimum width or height required to fit . diff --git a/Terminal.Gui/Views/CheckBox.cs b/Terminal.Gui/Views/CheckBox.cs index 7b8dc08a8..656e42ba3 100644 --- a/Terminal.Gui/Views/CheckBox.cs +++ b/Terminal.Gui/Views/CheckBox.cs @@ -20,11 +20,10 @@ public class CheckBox : View _charChecked = Glyphs.Checked; _charUnChecked = Glyphs.UnChecked; - // Ensures a height of 1 if AutoSize is set to false + Width = Dim.Auto (Dim.DimAutoStyle.Text); Height = 1; CanFocus = true; - AutoSize = true; // Things this view knows how to do AddCommand (Command.Accept, OnToggled); diff --git a/Terminal.Gui/Views/ScrollBarView.cs b/Terminal.Gui/Views/ScrollBarView.cs index 3f47a5cfa..e22e68864 100644 --- a/Terminal.Gui/Views/ScrollBarView.cs +++ b/Terminal.Gui/Views/ScrollBarView.cs @@ -944,7 +944,7 @@ public class ScrollBarView : View // BUGBUG: v2 - If Host is also the ScrollBarView's superview, this is all bogus because it's not // supported that a view can reference it's superview's Dims. This code also assumes the host does // not have a margin/borderframe/padding. - if (!IsInitialized) + if (!IsInitialized || _otherScrollBarView is { IsInitialized: false }) { return; } diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 33590a7e0..55320f4c4 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -33,7 +33,14 @@ public class Buttons : Scenario defaultButton.Accept += (s, e) => Application.RequestStop (); main.Add (defaultButton); - var swapButton = new Button { X = 50, Text = "S_wap Default (Absolute Layout)" }; + var swapButton = new Button + { + X = 50, + Width = 45, + Height = 3, + Text = "S_wap Default (Size = 45, 3)", + ColorScheme = Colors.ColorSchemes ["Error"] + }; swapButton.Accept += (s, e) => { @@ -51,29 +58,23 @@ public class Buttons : Scenario }; } - var colorButtonsLabel = new Label { X = 0, Y = Pos.Bottom (editLabel) + 1, Text = "Color Buttons:" }; + var colorButtonsLabel = new Label { X = 0, Y = Pos.Bottom (swapButton) + 1, Text = "Color Buttons: " }; main.Add (colorButtonsLabel); View prev = colorButtonsLabel; - //With this method there is no need to call Application.TopReady += () => Application.TopRedraw (Top.Bounds); - Pos x = Pos.Right (colorButtonsLabel) + 2; - foreach (KeyValuePair colorScheme in Colors.ColorSchemes) { var colorButton = new Button { - ColorScheme = colorScheme.Value, - X = Pos.Right (prev) + 2, + X = Pos.Right (prev), Y = Pos.Y (colorButtonsLabel), - Text = $"_{colorScheme.Key}" + Text = $"_{colorScheme.Key}", + ColorScheme = colorScheme.Value, }; DoMessage (colorButton, colorButton.Text); main.Add (colorButton); prev = colorButton; - - // BUGBUG: AutoSize is true and the X doesn't change - //x += colorButton.Frame.Width + 2; } Button button; @@ -91,7 +92,7 @@ public class Buttons : Scenario // Note the 'N' in 'Newline' will be the hotkey main.Add ( - button = new () { X = 2, Y = Pos.Bottom (button) + 1, Text = "a Newline\nin the button" } + button = new () { X = 2, Y = Pos.Bottom (button) + 1, Height = 2, Text = "a Newline\nin the button" } ); button.Accept += (s, e) => MessageBox.Query ("Message", "Question?", "Yes", "No"); @@ -110,16 +111,14 @@ public class Buttons : Scenario var removeButton = new Button { - X = 2, Y = Pos.Bottom (button) + 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Remove this button" + X = 2, Y = Pos.Bottom (button) + 1, + ColorScheme = Colors.ColorSchemes ["Error"], Text = "Remove this button" }; main.Add (removeButton); // This in interesting test case because `moveBtn` and below are laid out relative to this one! removeButton.Accept += (s, e) => { - // Now this throw a InvalidOperationException on the TopologicalSort method as is expected. - //main.Remove (removeButton); - removeButton.Visible = false; }; @@ -138,7 +137,6 @@ public class Buttons : Scenario { X = 0, Y = Pos.Center () - 1, - AutoSize = false, Width = 30, Height = 1, ColorScheme = Colors.ColorSchemes ["Error"], @@ -148,29 +146,23 @@ public class Buttons : Scenario moveBtn.Accept += (s, e) => { moveBtn.X = moveBtn.Frame.X + 5; - - // This is already fixed with the call to SetNeedDisplay() in the Pos Dim. - //computedFrame.LayoutSubviews (); // BUGBUG: This call should not be needed. View.X is not causing relayout correctly }; computedFrame.Add (moveBtn); // Demonstrates how changing the View.Frame property can SIZE Views (#583) var sizeBtn = new Button { - X = 0, Y = Pos.Center () + 1, - AutoSize = false, + X = 0, Width = 30, Height = 1, + Text = "Grow This \u263a Button _via Pos", ColorScheme = Colors.ColorSchemes ["Error"], - Text = "Size This \u263a Button _via Pos" }; sizeBtn.Accept += (s, e) => { sizeBtn.Width = sizeBtn.Frame.Width + 5; - - //computedFrame.LayoutSubviews (); // FIXED: This call should not be needed. View.X is not causing relayout correctly }; computedFrame.Add (sizeBtn); diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs index fa8cacd21..68e75b99b 100644 --- a/UICatalog/Scenarios/Dialogs.cs +++ b/UICatalog/Scenarios/Dialogs.cs @@ -21,10 +21,10 @@ public class Dialogs : Scenario Text = "_Number of Buttons:" }; - var label = new Label { - X = 0, + var label = new Label + { + X = 0, Y = 0, - AutoSize = false, Width = Dim.Width (numButtonsLabel), Height = 1, TextAlignment = TextAlignment.Right, diff --git a/UnitTests/Text/TextFormatterTests.cs b/UnitTests/Text/TextFormatterTests.cs index bde94ccf7..1222f9c8f 100644 --- a/UnitTests/Text/TextFormatterTests.cs +++ b/UnitTests/Text/TextFormatterTests.cs @@ -2197,33 +2197,30 @@ ssb { var tf = new TextFormatter { Direction = textDirection, Text = "你你" }; - if (textDirection == TextDirection.LeftRight_TopBottom) - { - Assert.Equal (4, tf.Size.Width); - Assert.Equal (1, tf.Size.Height); - } - else - { - Assert.Equal (2, tf.Size.Width); - Assert.Equal (2, tf.Size.Height); - } + //if (textDirection == TextDirection.LeftRight_TopBottom) + //{ + // Assert.Equal (4, tf.Size.Width); + // Assert.Equal (1, tf.Size.Height); + //} + //else + //{ + // Assert.Equal (2, tf.Size.Width); + // Assert.Equal (2, tf.Size.Height); + //} Assert.False (tf.AutoSize); tf.Size = new (1, 1); - Assert.Equal (1, tf.Size.Width); - Assert.Equal (1, tf.Size.Height); + Assert.Equal (new Size (1, 1), tf.Size); tf.AutoSize = true; if (textDirection == TextDirection.LeftRight_TopBottom) { - Assert.Equal (4, tf.Size.Width); - Assert.Equal (1, tf.Size.Height); + Assert.Equal (new Size (4, 1), tf.Size); } else { - Assert.Equal (2, tf.Size.Width); - Assert.Equal (2, tf.Size.Height); + Assert.Equal (new Size (2, 2), tf.Size); } } @@ -2396,6 +2393,26 @@ ssb } } + [Theory] + // BUGBUG: This is a bug in the current implementation, the expected size should be 0, 0 because autosize is false + [InlineData ("你", TextDirection.LeftRight_TopBottom, false, 2, 1)] + [InlineData ("你", TextDirection.LeftRight_TopBottom, true, 2, 1)] + // BUGBUG: This is a bug in the current implementation, the expected size should be 0, 0 because autosize is false + [InlineData ("你", TextDirection.TopBottom_LeftRight, false, 1, 2)] + [InlineData ("你", TextDirection.TopBottom_LeftRight, true, 1, 2)] + + // BUGBUG: This is a bug in the current implementation, the expected size should be 0, 0 because autosize is false + [InlineData ("你你", TextDirection.LeftRight_TopBottom, false, 4, 1)] + [InlineData ("你你", TextDirection.LeftRight_TopBottom, true, 4, 1)] + // BUGBUG: This is a bug in the current implementation, the expected size should be 0, 0 because autosize is false + [InlineData ("你你", TextDirection.TopBottom_LeftRight, false, 1, 4)] + [InlineData ("你你", TextDirection.TopBottom_LeftRight, true, 1, 4)] + public void Text_Set_SizeIsCorrect (string text, TextDirection textDirection, bool autoSize, int expectedWidth, int expectedHeight) + { + var tf = new TextFormatter { Direction = textDirection, Text = text, AutoSize = autoSize }; + Assert.Equal (new Size (expectedWidth, expectedHeight), tf.Size); + } + [Theory] [InlineData (TextDirection.LeftRight_TopBottom, false)] [InlineData (TextDirection.LeftRight_TopBottom, true)] @@ -2404,8 +2421,7 @@ ssb public void TestSize_TextChange (TextDirection textDirection, bool autoSize) { var tf = new TextFormatter { Direction = textDirection, Text = "你", AutoSize = autoSize }; - Assert.Equal (2, tf.Size.Width); - Assert.Equal (1, tf.Size.Height); + Assert.Equal (new Size (2, 1), tf.Size); tf.Text = "你你"; Assert.Equal (autoSize, tf.AutoSize); diff --git a/UnitTests/View/Layout/Dim.AutoTests.cs b/UnitTests/View/Layout/Dim.AutoTests.cs index d3c9ce4bb..71ef8a3d1 100644 --- a/UnitTests/View/Layout/Dim.AutoTests.cs +++ b/UnitTests/View/Layout/Dim.AutoTests.cs @@ -203,6 +203,28 @@ public class DimAutoTests Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame); } + [Fact] + public void NoSubViews_Does_Nothing_Vertical () + { + var superView = new View + { + X = 0, + Y = 0, + Width = Dim.Auto (), + Height = Dim.Auto (), + TextDirection = TextDirection.TopBottom_LeftRight, + ValidatePosDim = true + }; + + superView.BeginInit (); + superView.EndInit (); + superView.SetRelativeLayout (new (10, 10)); + Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame); + + superView.SetRelativeLayout (new (10, 10)); + Assert.Equal (new Rectangle (0, 0, 0, 0), superView.Frame); + } + [Theory] [InlineData (0, 0, 0, 0, 0, 0)] [InlineData (0, 0, 5, 0, 5, 0)] @@ -648,6 +670,8 @@ public class DimAutoTests super.Add (view); Rectangle expectedViewport = new (0, 0, 8, 1); + Assert.Equal (expectedViewport.Size, view.ContentSize); + Assert.Equal (expectedViewport, view.Frame); Assert.Equal (expectedViewport, view.Viewport); super.LayoutSubviews (); diff --git a/UnitTests/View/Text/AutoSizeTrueTests.cs b/UnitTests/View/Text/AutoSizeTrueTests.cs index d43c70bbe..1fc1071d4 100644 --- a/UnitTests/View/Text/AutoSizeTrueTests.cs +++ b/UnitTests/View/Text/AutoSizeTrueTests.cs @@ -918,205 +918,205 @@ public class AutoSizeTrueTests Assert.Equal (expectedLabelBounds, label.Viewport); } - [Fact] - [AutoInitShutdown] - public void AutoSize_GetAutoSize_Centered () - { - var text = "This is some text."; - var view = new View { Text = text, TextAlignment = TextAlignment.Centered, AutoSize = true }; - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (view); - var top = new Toplevel (); - top.Add (win); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (10, 4); + //[Fact] + //[AutoInitShutdown] + //public void AutoSize_GetAutoSize_Centered () + //{ + // var text = "This is some text."; + // var view = new View { Text = text, TextAlignment = TextAlignment.Centered, AutoSize = true }; + // var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; + // win.Add (view); + // var top = new Toplevel (); + // top.Add (win); + // Application.Begin (top); + // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); - Size size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 1), size); + // Size size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 1), size); - view.Text = $"{text}\n{text}"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 2), size); + // view.Text = $"{text}\n{text}"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 2), size); - view.Text = $"{text}\n{text}\n{text}+"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length + 1, 3), size); + // view.Text = $"{text}\n{text}\n{text}+"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length + 1, 3), size); - text = string.Empty; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (0, 0), size); + // text = string.Empty; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (0, 0), size); - text = "1"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (1, 1), size); + // text = "1"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (1, 1), size); - text = "界"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (2, 1), size); - } + // text = "界"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (2, 1), size); + //} - [Fact] - [AutoInitShutdown] - public void AutoSize_GetAutoSize_Horizontal () - { - var text = "text"; - var view = new View { Text = text, AutoSize = true }; - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (view); - var top = new Toplevel (); - top.Add (win); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (10, 4); + //[Fact] + //[AutoInitShutdown] + //public void AutoSize_GetAutoSize_Horizontal () + //{ + // var text = "text"; + // var view = new View { Text = text, AutoSize = true }; + // var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; + // win.Add (view); + // var top = new Toplevel (); + // top.Add (win); + // Application.Begin (top); + // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); - Size size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 1), size); + // Size size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 1), size); - view.Text = $"{text}\n{text}"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 2), size); + // view.Text = $"{text}\n{text}"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 2), size); - view.Text = $"{text}\n{text}\n{text}+"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length + 1, 3), size); + // view.Text = $"{text}\n{text}\n{text}+"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length + 1, 3), size); - text = string.Empty; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (0, 0), size); + // text = string.Empty; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (0, 0), size); - text = "1"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (1, 1), size); + // text = "1"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (1, 1), size); - text = "界"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (2, 1), size); - } + // text = "界"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (2, 1), size); + //} - [Fact] - [AutoInitShutdown] - public void AutoSize_GetAutoSize_Left () - { - var text = "This is some text."; - var view = new View { Text = text, TextAlignment = TextAlignment.Left, AutoSize = true }; - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (view); - var top = new Toplevel (); - top.Add (win); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (10, 4); + //[Fact] + //[AutoInitShutdown] + //public void AutoSize_GetAutoSize_Left () + //{ + // var text = "This is some text."; + // var view = new View { Text = text, TextAlignment = TextAlignment.Left, AutoSize = true }; + // var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; + // win.Add (view); + // var top = new Toplevel (); + // top.Add (win); + // Application.Begin (top); + // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); - Size size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 1), size); + // Size size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 1), size); - view.Text = $"{text}\n{text}"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 2), size); + // view.Text = $"{text}\n{text}"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 2), size); - view.Text = $"{text}\n{text}\n{text}+"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length + 1, 3), size); + // view.Text = $"{text}\n{text}\n{text}+"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length + 1, 3), size); - text = string.Empty; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (0, 0), size); + // text = string.Empty; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (0, 0), size); - text = "1"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (1, 1), size); + // text = "1"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (1, 1), size); - text = "界"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (2, 1), size); - } + // text = "界"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (2, 1), size); + //} - [Fact] - [AutoInitShutdown] - public void AutoSize_GetAutoSize_Right () - { - var text = "This is some text."; - var view = new View { Text = text, TextAlignment = TextAlignment.Right, AutoSize = true }; - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (view); - var top = new Toplevel (); - top.Add (win); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (10, 4); + //[Fact] + //[AutoInitShutdown] + //public void AutoSize_GetAutoSize_Right () + //{ + // var text = "This is some text."; + // var view = new View { Text = text, TextAlignment = TextAlignment.Right, AutoSize = true }; + // var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; + // win.Add (view); + // var top = new Toplevel (); + // top.Add (win); + // Application.Begin (top); + // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); - Size size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 1), size); + // Size size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 1), size); - view.Text = $"{text}\n{text}"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length, 2), size); + // view.Text = $"{text}\n{text}"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length, 2), size); - view.Text = $"{text}\n{text}\n{text}+"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (text.Length + 1, 3), size); + // view.Text = $"{text}\n{text}\n{text}+"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (text.Length + 1, 3), size); - text = string.Empty; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (0, 0), size); + // text = string.Empty; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (0, 0), size); - text = "1"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (1, 1), size); + // text = "1"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (1, 1), size); - text = "界"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (2, 1), size); - } + // text = "界"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (2, 1), size); + //} - [Fact] - [AutoInitShutdown] - public void AutoSize_GetAutoSize_Vertical () - { - var text = "text"; - var view = new View { Text = text, TextDirection = TextDirection.TopBottom_LeftRight, AutoSize = true }; - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (view); - var top = new Toplevel (); - top.Add (win); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (10, 4); + //[Fact] + //[AutoInitShutdown] + //public void AutoSize_GetAutoSize_Vertical () + //{ + // var text = "text"; + // var view = new View { Text = text, TextDirection = TextDirection.TopBottom_LeftRight, AutoSize = true }; + // var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; + // win.Add (view); + // var top = new Toplevel (); + // top.Add (win); + // Application.Begin (top); + // ((FakeDriver)Application.Driver).SetBufferSize (10, 4); - Size size = view.GetTextAutoSize (); - Assert.Equal (new Size (1, text.Length), size); + // Size size = view.GetTextAutoSize (); + // Assert.Equal (new Size (1, text.Length), size); - view.Text = $"{text}\n{text}"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (2, text.Length), size); + // view.Text = $"{text}\n{text}"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (2, text.Length), size); - view.Text = $"{text}\n{text}\n{text}+"; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (3, text.Length + 1), size); + // view.Text = $"{text}\n{text}\n{text}+"; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (3, text.Length + 1), size); - text = string.Empty; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (0, 0), size); + // text = string.Empty; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (0, 0), size); - text = "1"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (1, 1), size); + // text = "1"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (1, 1), size); - text = "界"; - view.Text = text; - size = view.GetTextAutoSize (); - Assert.Equal (new Size (2, 1), size); - } + // text = "界"; + // view.Text = text; + // size = view.GetTextAutoSize (); + // Assert.Equal (new Size (2, 1), size); + //} [Fact] [SetupFakeDriver] @@ -1721,6 +1721,7 @@ Y view.TextDirection = TextDirection.TopBottom_LeftRight; Application.Refresh (); + Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame); Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame); expected = @" @@ -1746,7 +1747,7 @@ Y // Setting to false causes Width and Height to be set to the current ContentSize view.AutoSize = false; - Assert.Equal (new Rectangle (0, 0, 12, 12), view.Frame); + Assert.Equal (new Rectangle (0, 0, 1, 12), view.Frame); view.Height = 1; view.Width = 12; diff --git a/UnitTests/View/Text/TextTests.cs b/UnitTests/View/Text/TextTests.cs index 080450c6f..104574564 100644 --- a/UnitTests/View/Text/TextTests.cs +++ b/UnitTests/View/Text/TextTests.cs @@ -8,10 +8,9 @@ namespace Terminal.Gui.ViewTests; /// Tests of the and properties (independent of /// AutoSize). /// -public class TextTests +public class TextTests (ITestOutputHelper output) { - private readonly ITestOutputHelper _output; - public TextTests (ITestOutputHelper output) { _output = output; } + private readonly ITestOutputHelper _output = output; // Test that View.PreserveTrailingSpaces removes trailing spaces [Fact] @@ -111,6 +110,47 @@ public class TextTests protected override void UpdateTextFormatterText () { TextFormatter.Text = $">{Text}<"; } } + [Fact] + public void TextDirection_Horizontal_Dims_Correct () + { + // Initializes a view with a vertical direction + var view = new View + { + Text = "01234", + TextDirection = TextDirection.LeftRight_TopBottom, + Width = Dim.Auto (Dim.DimAutoStyle.Text), + Height = Dim.Auto (Dim.DimAutoStyle.Text) + }; + Assert.Equal (new Rectangle (0, 0, 5, 1), view.Frame); + Assert.Equal (new Rectangle (0, 0, 5, 1), view.Viewport); + + view.BeginInit (); + view.EndInit (); + Assert.Equal (new Rectangle (0, 0, 5, 1), view.Frame); + Assert.Equal (new Rectangle (0, 0, 5, 1), view.Viewport); + } + + [Fact] + public void TextDirection_Vertical_Dims_Correct () + { + // Initializes a view with a vertical direction + var view = new View + { + TextDirection = TextDirection.TopBottom_LeftRight, + Text = "01234", + Width = Dim.Auto (Dim.DimAutoStyle.Text), + Height = Dim.Auto (Dim.DimAutoStyle.Text), + }; + Assert.Equal (new Rectangle (0, 0, 1, 5), view.Frame); + Assert.Equal (new Rectangle (0, 0, 1, 5), view.Viewport); + + view.BeginInit (); + Assert.Equal (new Rectangle (0, 0, 1, 5), view.Frame); + view.EndInit (); + Assert.Equal (new Rectangle (0, 0, 1, 5), view.Frame); + Assert.Equal (new Rectangle (0, 0, 1, 5), view.Viewport); + } + // Test behavior of AutoSize property. // - Default is false // - Setting to true invalidates Height/Width diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs index 4e1162a0c..b5079dbd6 100644 --- a/UnitTests/View/ViewTests.cs +++ b/UnitTests/View/ViewTests.cs @@ -829,7 +829,10 @@ At 0,0 // Initializes a view with a vertical direction r = new View { - Text = "Vertical View", TextDirection = TextDirection.TopBottom_LeftRight, AutoSize = true + Text = "Vertical View", + TextDirection = TextDirection.TopBottom_LeftRight, + Width = Dim.Auto (), + Height = Dim.Auto () }; // BUGBUG: AutoSize or Height need be set Assert.NotNull (r); Assert.Equal (LayoutStyle.Computed, r.LayoutStyle); diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs index 7bdb202a7..fbf0c29d2 100644 --- a/UnitTests/Views/ButtonTests.cs +++ b/UnitTests/Views/ButtonTests.cs @@ -32,253 +32,278 @@ public class ButtonTests (ITestOutputHelper output) view.Dispose (); } - // BUGBUG: This test is NOT a unit test and needs to be broken apart into - // more specific tests (e.g. it tests Checkbox as well as Button) - [Fact] - [AutoInitShutdown] - public void AutoSize_False_With_Fixed_Width () +// // BUGBUG: This test is NOT a unit test and needs to be broken apart into +// // more specific tests (e.g. it tests Checkbox as well as Button) +// [Fact] +// [AutoInitShutdown] +// public void AutoSize_False_With_Fixed_Width () +// { +// var tab = new View (); + +// var lblWidth = 8; + +// var view = new View +// { +// Y = 1, +// Width = lblWidth, +// Height = 1, +// TextAlignment = TextAlignment.Right, +// Text = "Find:" +// }; +// tab.Add (view); + +// var txtToFind = new TextField +// { +// X = Pos.Right (view) + 1, Y = Pos.Top (view), Width = 20, Text = "Testing buttons." +// }; +// tab.Add (txtToFind); + +// var btnFindNext = new Button +// { +// X = Pos.Right (txtToFind) + 1, +// Y = Pos.Top (view), +// Width = 20, +// Enabled = !string.IsNullOrEmpty (txtToFind.Text), +// TextAlignment = TextAlignment.Centered, +// IsDefault = true, +// Text = "Find _Next" +// }; +// tab.Add (btnFindNext); + +// var btnFindPrevious = new Button +// { +// X = Pos.Right (txtToFind) + 1, +// Y = Pos.Top (btnFindNext) + 1, +// Width = 20, +// Enabled = !string.IsNullOrEmpty (txtToFind.Text), +// TextAlignment = TextAlignment.Centered, +// Text = "Find _Previous" +// }; +// tab.Add (btnFindPrevious); + +// var btnCancel = new Button +// { +// X = Pos.Right (txtToFind) + 1, +// Y = Pos.Top (btnFindPrevious) + 2, +// Width = 20, +// TextAlignment = TextAlignment.Centered, +// Text = "Cancel" +// }; +// tab.Add (btnCancel); + +// var ckbMatchCase = new CheckBox +// { +// X = 0, +// Y = Pos.Top (txtToFind) + 2, +// Checked = true, Text = "Match c_ase" +// }; +// tab.Add (ckbMatchCase); +// Assert.Equal (new (0, 3, 10, 1), ckbMatchCase.Frame); + +// var ckbMatchWholeWord = new CheckBox +// { +// X = 0, +// Y = Pos.Top (ckbMatchCase) + 1, +// Checked = false, +// Text = "Match _whole word" +// }; +// tab.Add (ckbMatchWholeWord); + +// var tabView = new TabView { Width = Dim.Fill (), Height = Dim.Fill () }; +// tabView.AddTab (new () { DisplayText = "Find", View = tab }, true); + +// var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; + +// tab.Width = view.Width + txtToFind.Width + btnFindNext.Width + 2; +// tab.Height = btnFindNext.Height + btnFindPrevious.Height + btnCancel.Height + 4; + +// win.Add (tabView); +// var top = new Toplevel (); +// top.Add (win); + +// Application.Begin (top); +// ((FakeDriver)Application.Driver).SetBufferSize (54, 11); + +// Assert.Equal (new (0, 3, 10, 1), ckbMatchCase.Frame); + +// Assert.Equal (new (0, 0, 54, 11), win.Frame); +// Assert.Equal (new (0, 0, 52, 9), tabView.Frame); +// Assert.Equal (new (0, 0, 50, 7), tab.Frame); +// Assert.Equal (new (0, 1, 8, 1), view.Frame); +// Assert.Equal (new (9, 1, 20, 1), txtToFind.Frame); + +// Assert.Equal (0, txtToFind.ScrollOffset); +// Assert.Equal (16, txtToFind.CursorPosition); + +// Assert.Equal (new (30, 1, 20, 1), btnFindNext.Frame); +// Assert.Equal (new (30, 2, 20, 1), btnFindPrevious.Frame); +// Assert.Equal (new (30, 4, 20, 1), btnCancel.Frame); + +// // Assert.Equal (new (0, 3, 12, 1), ckbMatchCase.Frame); +// // Assert.Equal (new (0, 4, 18, 1), ckbMatchWholeWord.Frame); + +// var btn1 = +// $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} Find Next {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}"; +// var btn2 = $"{CM.Glyphs.LeftBracket} Find Previous {CM.Glyphs.RightBracket}"; +// var btn3 = $"{CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket}"; + +// var expected = @$" +//┌────────────────────────────────────────────────────┐ +//│╭────╮ │ +//││Find│ │ +//││ ╰─────────────────────────────────────────────╮│ +//││ ││ +//││ Find: Testing buttons. {btn1} ││ +//││ {btn2} ││ +//││{CM.Glyphs.Checked} Match case ││ +//││{CM.Glyphs.UnChecked} Match whole word {btn3} ││ +//│└──────────────────────────────────────────────────┘│ +//└────────────────────────────────────────────────────┘ +//"; + +// TestHelpers.AssertDriverContentsWithFrameAre (expected, output); +// view.Dispose (); +// } + +// [Fact] +// [AutoInitShutdown] +// public void AutoSize_Stays_True_AnchorEnd () +// { +// var btn = new Button { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true }; +// var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; + +// btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); +// btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); + +// var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; +// win.Add (btn); +// var top = new Toplevel (); +// top.Add (win); + +// Assert.True (btn.AutoSize); + +// Application.Begin (top); +// ((FakeDriver)Application.Driver).SetBufferSize (30, 5); + +// var expected = @$" +//┌────────────────────────────┐ +//│ │ +//│ {btnTxt}│ +//│ │ +//└────────────────────────────┘ +//"; + +// TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + +// Assert.True (btn.AutoSize); +// btn.Text = "Say Hello 你 changed"; +// btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; +// Assert.True (btn.AutoSize); +// Application.Refresh (); + +// expected = @$" +//┌────────────────────────────┐ +//│ │ +//│ {btnTxt}│ +//│ │ +//└────────────────────────────┘ +//"; + +// TestHelpers.AssertDriverContentsWithFrameAre (expected, output); +// top.Dispose (); +// } + +// [Fact] +// [AutoInitShutdown] +// public void AutoSize_Stays_True_With_EmptyText () +// { +// var btn = new Button { X = Pos.Center (), Y = Pos.Center (), AutoSize = true }; + +// var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; +// win.Add (btn); +// var top = new Toplevel (); +// top.Add (win); + +// Assert.True (btn.AutoSize); + +// btn.Text = "Say Hello 你"; + +// Assert.True (btn.AutoSize); + +// Application.Begin (top); +// ((FakeDriver)Application.Driver).SetBufferSize (30, 5); + +// var expected = @$" +//┌────────────────────────────┐ +//│ │ +//│ {CM.Glyphs.LeftBracket} Say Hello 你 {CM.Glyphs.RightBracket} │ +//│ │ +//└────────────────────────────┘ +//"; + +// TestHelpers.AssertDriverContentsWithFrameAre (expected, output); +// top.Dispose (); +// } + + [Theory] + [InlineData ("01234", 0, 0, 0, 0)] + [InlineData ("01234", 1, 0, 1, 0)] + [InlineData ("01234", 0, 1, 0, 1)] + [InlineData ("01234", 1, 1, 1, 1)] + [InlineData ("01234", 10, 1, 10, 1)] + [InlineData ("01234", 10, 3, 10, 3)] + [InlineData ("0_1234", 0, 0, 0, 0)] + [InlineData ("0_1234", 1, 0, 1, 0)] + [InlineData ("0_1234", 0, 1, 0, 1)] + [InlineData ("0_1234", 1, 1, 1, 1)] + [InlineData ("0_1234", 10, 1, 10, 1)] + [InlineData ("0_12你", 10, 3, 10, 3)] + [InlineData ("0_12你", 0, 0, 0, 0)] + [InlineData ("0_12你", 1, 0, 1, 0)] + [InlineData ("0_12你", 0, 1, 0, 1)] + [InlineData ("0_12你", 1, 1, 1, 1)] + [InlineData ("0_12你", 10, 1, 10, 1)] + [InlineData ("0_12你", 10, 3, 10, 3)] + public void Button_AbsoluteSize_Text (string text, int width, int height, int expectedWidth, int expectedHeight) { - var tab = new View (); - - var lblWidth = 8; - - var view = new View - { - Y = 1, - Width = lblWidth, - Height = 1, - TextAlignment = TextAlignment.Right, - Text = "Find:" - }; - tab.Add (view); - - var txtToFind = new TextField - { - X = Pos.Right (view) + 1, Y = Pos.Top (view), Width = 20, Text = "Testing buttons." - }; - tab.Add (txtToFind); - - var btnFindNext = new Button - { - AutoSize = false, - X = Pos.Right (txtToFind) + 1, - Y = Pos.Top (view), - Width = 20, - Enabled = !string.IsNullOrEmpty (txtToFind.Text), - TextAlignment = TextAlignment.Centered, - IsDefault = true, - Text = "Find _Next" - }; - tab.Add (btnFindNext); - - var btnFindPrevious = new Button - { - AutoSize = false, - X = Pos.Right (txtToFind) + 1, - Y = Pos.Top (btnFindNext) + 1, - Width = 20, - Enabled = !string.IsNullOrEmpty (txtToFind.Text), - TextAlignment = TextAlignment.Centered, - Text = "Find _Previous" - }; - tab.Add (btnFindPrevious); - - var btnCancel = new Button - { - AutoSize = false, - X = Pos.Right (txtToFind) + 1, - Y = Pos.Top (btnFindPrevious) + 2, - Width = 20, - TextAlignment = TextAlignment.Centered, - Text = "Cancel" - }; - tab.Add (btnCancel); - - var ckbMatchCase = new CheckBox { X = 0, Y = Pos.Top (txtToFind) + 2, Checked = true, Text = "Match c_ase" }; - tab.Add (ckbMatchCase); - - var ckbMatchWholeWord = new CheckBox - { - X = 0, Y = Pos.Top (ckbMatchCase) + 1, Checked = false, Text = "Match _whole word" - }; - tab.Add (ckbMatchWholeWord); - - var tabView = new TabView { Width = Dim.Fill (), Height = Dim.Fill () }; - tabView.AddTab (new () { DisplayText = "Find", View = tab }, true); - - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - - tab.Width = view.Width + txtToFind.Width + btnFindNext.Width + 2; - tab.Height = btnFindNext.Height + btnFindPrevious.Height + btnCancel.Height + 4; - - win.Add (tabView); - var top = new Toplevel (); - top.Add (win); - - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (54, 11); - - Assert.Equal (new (0, 0, 54, 11), win.Frame); - Assert.Equal (new (0, 0, 52, 9), tabView.Frame); - Assert.Equal (new (0, 0, 50, 7), tab.Frame); - Assert.Equal (new (0, 1, 8, 1), view.Frame); - Assert.Equal (new (9, 1, 20, 1), txtToFind.Frame); - - Assert.Equal (0, txtToFind.ScrollOffset); - Assert.Equal (16, txtToFind.CursorPosition); - - Assert.Equal (new (30, 1, 20, 1), btnFindNext.Frame); - Assert.Equal (new (30, 2, 20, 1), btnFindPrevious.Frame); - Assert.Equal (new (30, 4, 20, 1), btnCancel.Frame); - - // Assert.Equal (new (0, 3, 12, 1), ckbMatchCase.Frame); - // Assert.Equal (new (0, 4, 18, 1), ckbMatchWholeWord.Frame); - - var btn1 = - $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} Find Next {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}"; - var btn2 = $"{CM.Glyphs.LeftBracket} Find Previous {CM.Glyphs.RightBracket}"; - var btn3 = $"{CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket}"; - - var expected = @$" -┌────────────────────────────────────────────────────┐ -│╭────╮ │ -││Find│ │ -││ ╰─────────────────────────────────────────────╮│ -││ ││ -││ Find: Testing buttons. {btn1} ││ -││ {btn2} ││ -││{CM.Glyphs.Checked} Match case ││ -││{CM.Glyphs.UnChecked} Match whole word {btn3} ││ -│└──────────────────────────────────────────────────┘│ -└────────────────────────────────────────────────────┘ -"; - - TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - view.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void AutoSize_Stays_True_AnchorEnd () - { - var btn = new Button { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true }; - var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; - - btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); - btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ()); - - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (btn); - var top = new Toplevel (); - top.Add (win); - - Assert.True (btn.AutoSize); - - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - - var expected = @$" -┌────────────────────────────┐ -│ │ -│ {btnTxt}│ -│ │ -└────────────────────────────┘ -"; - - TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - - Assert.True (btn.AutoSize); - btn.Text = "Say Hello 你 changed"; - btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; - Assert.True (btn.AutoSize); - Application.Refresh (); - - expected = @$" -┌────────────────────────────┐ -│ │ -│ {btnTxt}│ -│ │ -└────────────────────────────┘ -"; - - TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - top.Dispose (); - } - - [Fact] - [AutoInitShutdown] - public void AutoSize_Stays_True_With_EmptyText () - { - var btn = new Button { X = Pos.Center (), Y = Pos.Center (), AutoSize = true }; - - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; - win.Add (btn); - var top = new Toplevel (); - top.Add (win); - - Assert.True (btn.AutoSize); - - btn.Text = "Say Hello 你"; - - Assert.True (btn.AutoSize); - - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - - var expected = @$" -┌────────────────────────────┐ -│ │ -│ {CM.Glyphs.LeftBracket} Say Hello 你 {CM.Glyphs.RightBracket} │ -│ │ -└────────────────────────────┘ -"; - - TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - top.Dispose (); - } - - [Fact] - [SetupFakeDriver] - public void Button_AutoSize_False_With_Fixed_Width () - { - ((FakeDriver)Application.Driver).SetBufferSize (20, 5); - - var top = new View { Width = 20, Height = 5 }; - var btn1 = new Button { - AutoSize = false, - X = Pos.Center (), - Y = Pos.Center (), - Width = 16, - Height = 1, - Text = "Open me!" + X = 0, + Y = 0, + Width = width, + Height = height, + Text = text }; - var btn2 = new Button + Assert.Equal (new Size (expectedWidth, expectedHeight), btn1.Frame.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), btn1.Viewport.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), btn1.TextFormatter.Size); + + btn1.Dispose (); + } + + [Theory] + [InlineData (0, 0, 0, 0)] + [InlineData (1, 0, 1, 0)] + [InlineData (0, 1, 0, 1)] + [InlineData (1, 1, 1, 1)] + [InlineData (10, 1, 10, 1)] + [InlineData (10, 3, 10, 3)] + public void Button_AbsoluteSize_DefaultText (int width, int height, int expectedWidth, int expectedHeight) + { + var btn1 = new Button { - AutoSize = false, - X = Pos.Center (), - Y = Pos.Center () + 1, - Width = 16, - Height = 1, - Text = "Close me!" + X = 0, + Y = 0, + Width = width, + Height = height, }; - top.Add (btn1, btn2); - top.BeginInit (); - top.EndInit (); - top.Draw (); - Assert.Equal ("{Width=16, Height=1}", btn1.TextFormatter.Size.ToString ()); - Assert.Equal ("{Width=16, Height=1}", btn2.TextFormatter.Size.ToString ()); + Assert.Equal (new Size (expectedWidth, expectedHeight), btn1.Frame.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), btn1.Viewport.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), btn1.TextFormatter.Size); - TestHelpers.AssertDriverContentsWithFrameAre ( - @$" - {CM.Glyphs.LeftBracket} {btn1.Text} {CM.Glyphs.RightBracket} - {CM.Glyphs.LeftBracket} {btn2.Text} {CM.Glyphs.RightBracket}", - output - ); - top.Dispose (); + btn1.Dispose (); } [Fact] @@ -342,7 +367,7 @@ public class ButtonTests (ITestOutputHelper output) Assert.Equal (string.Empty, btn.Text); btn.BeginInit (); btn.EndInit (); - btn.SetRelativeLayout(new (25,25)); + btn.SetRelativeLayout (new (100, 100)); Assert.Equal ($"{CM.Glyphs.LeftBracket} {CM.Glyphs.RightBracket}", btn.TextFormatter.Text); Assert.False (btn.IsDefault); @@ -384,6 +409,10 @@ public class ButtonTests (ITestOutputHelper output) Assert.True (btn.IsDefault); Assert.Equal (TextAlignment.Centered, btn.TextAlignment); Assert.True (btn.CanFocus); + + btn.SetRelativeLayout (new (100, 100)); + // 0123456789012345678901234567890123456789 + // [* Test *] Assert.Equal (new (0, 0, 10, 1), btn.Viewport); Assert.Equal (new (0, 0, 10, 1), btn.Frame); Assert.Equal (KeyCode.T, btn.HotKey); @@ -715,7 +744,7 @@ public class ButtonTests (ITestOutputHelper output) Assert.Equal (new (0, 0, 30, 5), pos); top.Dispose (); } - + [Theory] [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)] [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] diff --git a/UnitTests/Views/CheckBoxTests.cs b/UnitTests/Views/CheckBoxTests.cs index c906f29e4..697628f4f 100644 --- a/UnitTests/Views/CheckBoxTests.cs +++ b/UnitTests/Views/CheckBoxTests.cs @@ -10,6 +10,67 @@ public class CheckBoxTests public CheckBoxTests (ITestOutputHelper output) { _output = output; } + [Theory] + [InlineData ("01234", 0, 0, 0, 0)] + [InlineData ("01234", 1, 0, 1, 0)] + [InlineData ("01234", 0, 1, 0, 1)] + [InlineData ("01234", 1, 1, 1, 1)] + [InlineData ("01234", 10, 1, 10, 1)] + [InlineData ("01234", 10, 3, 10, 3)] + [InlineData ("0_1234", 0, 0, 0, 0)] + [InlineData ("0_1234", 1, 0, 1, 0)] + [InlineData ("0_1234", 0, 1, 0, 1)] + [InlineData ("0_1234", 1, 1, 1, 1)] + [InlineData ("0_1234", 10, 1, 10, 1)] + [InlineData ("0_12你", 10, 3, 10, 3)] + [InlineData ("0_12你", 0, 0, 0, 0)] + [InlineData ("0_12你", 1, 0, 1, 0)] + [InlineData ("0_12你", 0, 1, 0, 1)] + [InlineData ("0_12你", 1, 1, 1, 1)] + [InlineData ("0_12你", 10, 1, 10, 1)] + [InlineData ("0_12你", 10, 3, 10, 3)] + public void CheckBox_AbsoluteSize_Text (string text, int width, int height, int expectedWidth, int expectedHeight) + { + var checkBox = new CheckBox + { + X = 0, + Y = 0, + Width = width, + Height = height, + Text = text + }; + + Assert.Equal (new Size (expectedWidth, expectedHeight), checkBox.Frame.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), checkBox.Viewport.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), checkBox.TextFormatter.Size); + + checkBox.Dispose (); + } + + [Theory] + [InlineData (0, 0, 0, 0)] + [InlineData (1, 0, 1, 0)] + [InlineData (0, 1, 0, 1)] + [InlineData (1, 1, 1, 1)] + [InlineData (10, 1, 10, 1)] + [InlineData (10, 3, 10, 3)] + public void CheckBox_AbsoluteSize_DefaultText (int width, int height, int expectedWidth, int expectedHeight) + { + var checkBox = new CheckBox + { + X = 0, + Y = 0, + Width = width, + Height = height, + }; + + Assert.Equal (new Size (expectedWidth, expectedHeight), checkBox.Frame.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), checkBox.Viewport.Size); + Assert.Equal (new Size (expectedWidth, expectedHeight), checkBox.TextFormatter.Size); + + checkBox.Dispose (); + } + // Test that Title and Text are the same [Fact] public void Text_Mirrors_Title () @@ -71,93 +132,93 @@ public class CheckBoxTests Assert.False (checkBox.Checked); } - [Fact] - [AutoInitShutdown] - public void AutoSize_Stays_True_AnchorEnd_With_HotKeySpecifier () - { - var checkBox = new CheckBox { Y = Pos.Center (), Text = "C_heck this out 你" }; +// [Fact] +// [AutoInitShutdown] +// public void AutoSize_Stays_True_AnchorEnd_With_HotKeySpecifier () +// { +// var checkBox = new CheckBox { Y = Pos.Center (), Text = "C_heck this out 你" }; - checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); +// checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; - win.Add (checkBox); - var top = new Toplevel (); - top.Add (win); +// var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; +// win.Add (checkBox); +// var top = new Toplevel (); +// top.Add (win); - Assert.True (checkBox.AutoSize); +// //Assert.True (checkBox.AutoSize); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); +// Application.Begin (top); +// ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - var expected = @$" -┌┤Test Demo 你├──────────────┐ -│ │ -│ {CM.Glyphs.UnChecked} Check this out 你│ -│ │ -└────────────────────────────┘ -"; +// var expected = @$" +//┌┤Test Demo 你├──────────────┐ +//│ │ +//│ {CM.Glyphs.UnChecked} Check this out 你│ +//│ │ +//└────────────────────────────┘ +//"; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - Assert.True (checkBox.AutoSize); - checkBox.Text = "Check this out 你 changed"; - Assert.True (checkBox.AutoSize); - Application.Refresh (); +// //Assert.True (checkBox.AutoSize); +// checkBox.Text = "Check this out 你 changed"; +//// Assert.True (checkBox.AutoSize); +// Application.Refresh (); - expected = @$" -┌┤Test Demo 你├──────────────┐ -│ │ -│ {CM.Glyphs.UnChecked} Check this out 你 changed│ -│ │ -└────────────────────────────┘ -"; +// expected = @$" +//┌┤Test Demo 你├──────────────┐ +//│ │ +//│ {CM.Glyphs.UnChecked} Check this out 你 changed│ +//│ │ +//└────────────────────────────┘ +//"; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - } +// TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// } - [Fact] - [AutoInitShutdown] - public void AutoSize_Stays_True_AnchorEnd_Without_HotKeySpecifier () - { - var checkBox = new CheckBox { Y = Pos.Center (), Text = "Check this out 你" }; +// [Fact] +// [AutoInitShutdown] +// public void AutoSize_Stays_True_AnchorEnd_Without_HotKeySpecifier () +// { +// var checkBox = new CheckBox { Y = Pos.Center (), Text = "Check this out 你" }; - checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); +// checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width); - var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; - win.Add (checkBox); - var top = new Toplevel (); - top.Add (win); +// var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; +// win.Add (checkBox); +// var top = new Toplevel (); +// top.Add (win); - Assert.True (checkBox.AutoSize); +//// Assert.True (checkBox.AutoSize); - Application.Begin (top); - ((FakeDriver)Application.Driver).SetBufferSize (30, 5); +// Application.Begin (top); +// ((FakeDriver)Application.Driver).SetBufferSize (30, 5); - var expected = @$" -┌┤Test Demo 你├──────────────┐ -│ │ -│ {CM.Glyphs.UnChecked} Check this out 你│ -│ │ -└────────────────────────────┘ -"; +// var expected = @$" +//┌┤Test Demo 你├──────────────┐ +//│ │ +//│ {CM.Glyphs.UnChecked} Check this out 你│ +//│ │ +//└────────────────────────────┘ +//"; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - Assert.True (checkBox.AutoSize); - checkBox.Text = "Check this out 你 changed"; - Assert.True (checkBox.AutoSize); - Application.Refresh (); +// // Assert.True (checkBox.AutoSize); +// checkBox.Text = "Check this out 你 changed"; +//// Assert.True (checkBox.AutoSize); +// Application.Refresh (); - expected = @$" -┌┤Test Demo 你├──────────────┐ -│ │ -│ {CM.Glyphs.UnChecked} Check this out 你 changed│ -│ │ -└────────────────────────────┘ -"; +// expected = @$" +//┌┤Test Demo 你├──────────────┐ +//│ │ +//│ {CM.Glyphs.UnChecked} Check this out 你 changed│ +//│ │ +//└────────────────────────────┘ +//"; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - } +// TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); +// } // [Fact] // [AutoInitShutdown] @@ -241,7 +302,8 @@ public class CheckBoxTests public void Constructors_Defaults () { var ckb = new CheckBox (); - Assert.True (ckb.AutoSize); + Assert.True (ckb.Width is Dim.DimAuto); + Assert.Equal (Dim.Sized (1), ckb.Height); Assert.False (ckb.Checked); Assert.False (ckb.AllowNullChecked); Assert.Equal (string.Empty, ckb.Text); @@ -250,7 +312,8 @@ public class CheckBoxTests Assert.Equal (new Rectangle (0, 0, 2, 1), ckb.Frame); ckb = new CheckBox { Text = "Test", Checked = true }; - Assert.True (ckb.AutoSize); + Assert.True (ckb.Width is Dim.DimAuto); + Assert.Equal (Dim.Sized (1), ckb.Height); Assert.True (ckb.Checked); Assert.False (ckb.AllowNullChecked); Assert.Equal ("Test", ckb.Text); @@ -259,7 +322,8 @@ public class CheckBoxTests Assert.Equal (new Rectangle (0, 0, 6, 1), ckb.Frame); ckb = new CheckBox { Text = "Test", X = 1, Y = 2 }; - Assert.True (ckb.AutoSize); + Assert.True (ckb.Width is Dim.DimAuto); + Assert.Equal (Dim.Sized (1), ckb.Height); Assert.False (ckb.Checked); Assert.False (ckb.AllowNullChecked); Assert.Equal ("Test", ckb.Text); @@ -268,7 +332,8 @@ public class CheckBoxTests Assert.Equal (new Rectangle (1, 2, 6, 1), ckb.Frame); ckb = new CheckBox { Text = "Test", X = 3, Y = 4, Checked = true }; - Assert.True (ckb.AutoSize); + Assert.True (ckb.Width is Dim.DimAuto); + Assert.Equal (Dim.Sized (1), ckb.Height); Assert.True (ckb.Checked); Assert.False (ckb.AllowNullChecked); Assert.Equal ("Test", ckb.Text); @@ -405,7 +470,6 @@ public class CheckBoxTests Y = Pos.Center (), Text = "Check first out 你", TextAlignment = TextAlignment.Justified, - AutoSize = false, Width = 25 }; @@ -415,7 +479,6 @@ public class CheckBoxTests Y = Pos.Bottom (checkBox1), Text = "Check second out 你", TextAlignment = TextAlignment.Justified, - AutoSize = false, Width = 25 }; var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" }; diff --git a/UnitTests/Views/LabelTests.cs b/UnitTests/Views/LabelTests.cs index 6b863f808..9f2bb151a 100644 --- a/UnitTests/Views/LabelTests.cs +++ b/UnitTests/Views/LabelTests.cs @@ -55,7 +55,7 @@ public class LabelTests [Fact] public void MouseClick_SetsFocus_OnNextSubview () { - var superView = new View () { CanFocus = true, Height = 1, Width = 15}; + var superView = new View () { CanFocus = true, Height = 1, Width = 15 }; var focusedView = new View () { CanFocus = true, Width = 1, Height = 1 }; var label = new Label () { X = 2, Title = "_x" }; var nextSubview = new View () { CanFocus = true, X = 4, Width = 4, Height = 1 }; @@ -215,66 +215,66 @@ public class LabelTests Assert.Equal (KeyCode.Null, label.HotKey); } -// [Fact] -// [AutoInitShutdown] -// public void Label_Draw_Fill_Remaining_AutoSize_True () -// { -// var label = new Label { Text = "This label needs to be cleared before rewritten." }; + // [Fact] + // [AutoInitShutdown] + // public void Label_Draw_Fill_Remaining_AutoSize_True () + // { + // var label = new Label { Text = "This label needs to be cleared before rewritten." }; -// var tf1 = new TextFormatter { Direction = TextDirection.LeftRight_TopBottom }; -// tf1.Text = "This TextFormatter (tf1) without fill will not be cleared on rewritten."; -// Size tf1Size = tf1.Size; + // var tf1 = new TextFormatter { Direction = TextDirection.LeftRight_TopBottom }; + // tf1.Text = "This TextFormatter (tf1) without fill will not be cleared on rewritten."; + // Size tf1Size = tf1.Size; -// var tf2 = new TextFormatter { Direction = TextDirection.LeftRight_TopBottom, FillRemaining = true }; -// tf2.Text = "This TextFormatter (tf2) with fill will be cleared on rewritten."; -// Size tf2Size = tf2.Size; + // var tf2 = new TextFormatter { Direction = TextDirection.LeftRight_TopBottom, FillRemaining = true }; + // tf2.Text = "This TextFormatter (tf2) with fill will be cleared on rewritten."; + // Size tf2Size = tf2.Size; -// var top = new Toplevel (); -// top.Add (label); -// Application.Begin (top); + // var top = new Toplevel (); + // top.Add (label); + // Application.Begin (top); -// Assert.True (label.AutoSize); + // Assert.True (label.AutoSize); -// tf1.Draw ( -// new Rectangle (new Point (0, 1), tf1Size), -// label.GetNormalColor (), -// label.ColorScheme.HotNormal -// ); + // tf1.Draw ( + // new Rectangle (new Point (0, 1), tf1Size), + // label.GetNormalColor (), + // label.ColorScheme.HotNormal + // ); -// tf2.Draw (new Rectangle (new Point (0, 2), tf2Size), label.GetNormalColor (), label.ColorScheme.HotNormal); + // tf2.Draw (new Rectangle (new Point (0, 2), tf2Size), label.GetNormalColor (), label.ColorScheme.HotNormal); -// TestHelpers.AssertDriverContentsWithFrameAre ( -// @" -//This label needs to be cleared before rewritten. -//This TextFormatter (tf1) without fill will not be cleared on rewritten. -//This TextFormatter (tf2) with fill will be cleared on rewritten. -//", -// _output -// ); + // TestHelpers.AssertDriverContentsWithFrameAre ( + // @" + //This label needs to be cleared before rewritten. + //This TextFormatter (tf1) without fill will not be cleared on rewritten. + //This TextFormatter (tf2) with fill will be cleared on rewritten. + //", + // _output + // ); -// label.Text = "This label is rewritten."; -// label.Draw (); + // label.Text = "This label is rewritten."; + // label.Draw (); -// tf1.Text = "This TextFormatter (tf1) is rewritten."; + // tf1.Text = "This TextFormatter (tf1) is rewritten."; -// tf1.Draw ( -// new Rectangle (new Point (0, 1), tf1Size), -// label.GetNormalColor (), -// label.ColorScheme.HotNormal -// ); + // tf1.Draw ( + // new Rectangle (new Point (0, 1), tf1Size), + // label.GetNormalColor (), + // label.ColorScheme.HotNormal + // ); -// tf2.Text = "This TextFormatter (tf2) is rewritten."; -// tf2.Draw (new Rectangle (new Point (0, 2), tf2Size), label.GetNormalColor (), label.ColorScheme.HotNormal); + // tf2.Text = "This TextFormatter (tf2) is rewritten."; + // tf2.Draw (new Rectangle (new Point (0, 2), tf2Size), label.GetNormalColor (), label.ColorScheme.HotNormal); -// TestHelpers.AssertDriverContentsWithFrameAre ( -// @" -//This label is rewritten. -//This TextFormatter (tf1) is rewritten.will not be cleared on rewritten. -//This TextFormatter (tf2) is rewritten. -//", -// _output -// ); -// } + // TestHelpers.AssertDriverContentsWithFrameAre ( + // @" + //This label is rewritten. + //This TextFormatter (tf1) is rewritten.will not be cleared on rewritten. + //This TextFormatter (tf2) is rewritten. + //", + // _output + // ); + // } [Fact] [AutoInitShutdown] @@ -476,16 +476,18 @@ e [Fact] - [AutoInitShutdown] + [SetupFakeDriver] public void Full_Border () { - var label = new Label { Text = "Test", /*Width = 6, Height = 3, */BorderStyle = LineStyle.Single }; - var top = new Toplevel (); - top.Add (label); - Application.Begin (top); + var label = new Label { BorderStyle = LineStyle.Single , Text = "Test",} ; + label.BeginInit(); + label.EndInit(); + label.SetRelativeLayout (Application.Driver.Screen.Size); - Assert.Equal (new (0, 0, 6, 3), label.Frame); Assert.Equal (new (0, 0, 4, 1), label.Viewport); + Assert.Equal (new (0, 0, 6, 3), label.Frame); + + label.Draw (); TestHelpers.AssertDriverContentsWithFrameAre ( @" @@ -494,6 +496,7 @@ e └────┘", _output ); + label.Dispose (); } [Fact]