diff --git a/Terminal.Gui/View/Layout/Dim.cs b/Terminal.Gui/View/Layout/Dim.cs index 31842c9c3..8d2fbfe73 100644 --- a/Terminal.Gui/View/Layout/Dim.cs +++ b/Terminal.Gui/View/Layout/Dim.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Drawing; namespace Terminal.Gui; @@ -176,10 +177,10 @@ public class Dim /// The maximum dimension the View's ContentSize will be fit to. NOT CURRENTLY SUPPORTED. public static Dim Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim minimumContentDim = null, Dim maximumContentDim = null) { - if (maximumContentDim != null) - { - throw new NotImplementedException (@"maximumContentDim is not implemented"); - } + //if (maximumContentDim != null) + //{ + // throw new NotImplementedException (@"maximumContentDim is not implemented"); + //} return new DimAuto (style, minimumContentDim, maximumContentDim); } @@ -459,29 +460,71 @@ public class DimAuto (DimAutoStyle style, Dim minimumContentDim, Dim maximumCont // TODO: If _min > 0 we can SetRelativeLayout for the subviews? subviewsSize = 0; - if (us.Subviews.Count > 0) + List subviews; + + if (dimension == Dimension.Width) { - for (var i = 0; i < us.Subviews.Count; i++) + subviews = us.Subviews.Where (v => v.X is not PosAnchorEnd && v.Width is not DimFill).ToList (); + } + else + { + subviews = us.Subviews.Where (v => v.Y is not PosAnchorEnd && v.Height is not DimFill).ToList (); + } + + for (var i = 0; i < subviews.Count; i++) + { + View v = subviews [i]; + + int size = dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height; + + if (size > subviewsSize) { - View v = us.Subviews [i]; - bool isNotPosAnchorEnd = dimension == Dimension.Width ? v.X is not PosAnchorEnd : v.Y is not PosAnchorEnd; - - //if (!isNotPosAnchorEnd) - //{ - // v.SetRelativeLayout(dimension == Dimension.Width ? (new Size (autoMin, 0)) : new Size (0, autoMin)); - //} - - if (isNotPosAnchorEnd) - { - int size = dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height; - - if (size > subviewsSize) - { - subviewsSize = size; - } - } + subviewsSize = size; } } + + if (dimension == Dimension.Width) + { + subviews = us.Subviews.Where (v => v.X is PosAnchorEnd).ToList (); + } + else + { + subviews = us.Subviews.Where (v => v.Y is PosAnchorEnd).ToList (); + } + + int maxAnchorEnd = 0; + for (var i = 0; i < subviews.Count; i++) + { + View v = subviews [i]; + maxAnchorEnd = dimension == Dimension.Width ? v.Frame.Width : v.Frame.Height; + } + + subviewsSize += maxAnchorEnd; + + + if (dimension == Dimension.Width) + { + subviews = us.Subviews.Where (v => v.Width is DimFill).ToList (); + } + else + { + subviews = us.Subviews.Where (v => v.Height is DimFill).ToList (); + } + + for (var i = 0; i < subviews.Count; i++) + { + View v = subviews [i]; + + if (dimension == Dimension.Width) + { + v.SetRelativeLayout (new Size (subviewsSize, 0)); + } + else + { + v.SetRelativeLayout (new Size (0, autoMin - subviewsSize)); + } + } + } } @@ -743,11 +786,11 @@ public class DimView : Dim } string dimString = Dimension switch - { - Dimension.Height => "Height", - Dimension.Width => "Width", - _ => "unknown" - }; + { + Dimension.Height => "Height", + Dimension.Width => "Width", + _ => "unknown" + }; return $"View({dimString},{Target})"; } @@ -755,11 +798,11 @@ public class DimView : Dim internal override int Anchor (int size) { return Dimension switch - { - Dimension.Height => Target.Frame.Height, - Dimension.Width => Target.Frame.Width, - _ => 0 - }; + { + Dimension.Height => Target.Frame.Height, + Dimension.Width => Target.Frame.Width, + _ => 0 + }; } internal override bool ReferencesOtherViews () { return true; } diff --git a/Terminal.Gui/View/ViewContent.cs b/Terminal.Gui/View/ViewContent.cs index a362c8f79..e21796779 100644 --- a/Terminal.Gui/View/ViewContent.cs +++ b/Terminal.Gui/View/ViewContent.cs @@ -314,14 +314,14 @@ public partial class View { get { -#if DEBUG - if ((_width.ReferencesOtherViews () || _height.ReferencesOtherViews ()) && !IsInitialized) - { - Debug.WriteLine ( - $"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 +//#if DEBUG +// if ((_width.ReferencesOtherViews () || _height.ReferencesOtherViews ()) && !IsInitialized) +// { +// Debug.WriteLine ( +// $"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 if (Margin is null || Border is null || Padding is null) { diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs index e318298a7..96cc41f1b 100644 --- a/Terminal.Gui/Views/Dialog.cs +++ b/Terminal.Gui/Views/Dialog.cs @@ -75,8 +75,14 @@ public class Dialog : Window return true; }); KeyBindings.Add (Key.Esc, Command.QuitToplevel); + + Initialized += Dialog_Initialized; ; } + private void Dialog_Initialized (object sender, EventArgs e) + { + LayoutButtons (); + } private bool _canceled; @@ -158,18 +164,19 @@ public class Dialog : Window } /// - public override void LayoutSubviews () - { - if (_inLayout) - { - return; - } + //public override void LayoutSubviews () + //{ + // if (_inLayout) + // { + // return; + // } - _inLayout = true; - LayoutButtons (); - base.LayoutSubviews (); - _inLayout = false; - } + // _inLayout = true; + // SetRelativeLayout(SuperView?.ContentSize ?? Driver.Screen.Size); + // LayoutButtons (); + // base.LayoutSubviews (); + // _inLayout = false; + //} // Get the width of all buttons, not including any Margin. internal int GetButtonsWidth () @@ -216,7 +223,7 @@ public class Dialog : Window button.X = Viewport.Width - shiftLeft; } - button.Y = Pos.AnchorEnd (1); + button.Y = Pos.AnchorEnd (); } break; @@ -251,7 +258,7 @@ public class Dialog : Window } } - button.Y = Pos.AnchorEnd (1); + button.Y = Pos.AnchorEnd (); } break; @@ -283,7 +290,7 @@ public class Dialog : Window Button button = _buttons [i]; shiftLeft += button.Frame.Width + 1; button.X = Pos.AnchorEnd (shiftLeft); - button.Y = Pos.AnchorEnd (1); + button.Y = Pos.AnchorEnd (); } break; diff --git a/Terminal.Gui/Views/MessageBox.cs b/Terminal.Gui/Views/MessageBox.cs index b0f9fc6af..ef53b3fa0 100644 --- a/Terminal.Gui/Views/MessageBox.cs +++ b/Terminal.Gui/Views/MessageBox.cs @@ -344,8 +344,8 @@ public static class MessageBox Buttons = buttonList.ToArray (), Title = title, BorderStyle = DefaultBorderStyle, - Width = Dim.Percent (60), - Height = 5 // Border + one line of text + vspace + buttons + Width = Dim.Auto (DimAutoStyle.Content), + Height = Dim.Auto (DimAutoStyle.Content), }; if (width != 0) @@ -372,17 +372,26 @@ public static class MessageBox Text = message, TextAlignment = TextAlignment.Centered, X = Pos.Center (), - Y = 0 + Y = 0, + // ColorScheme = Colors.ColorSchemes ["Error"] }; + messageLabel.TextFormatter.WordWrap = wrapMessage; + messageLabel.TextFormatter.MultiLine = !wrapMessage; + if (wrapMessage) { messageLabel.Width = Dim.Fill (); messageLabel.Height = Dim.Fill (1); + int GetWrapSize () + { + // A bit of a hack to get the height of the wrapped text. + messageLabel.TextFormatter.Size = new (d.ContentSize.Width, 1000); + return messageLabel.TextFormatter.FormatAndGetSize ().Height; + } + d.Height = Dim.Auto (DimAutoStyle.Content, minimumContentDim: Dim.Func (GetWrapSize) + 1); } - messageLabel.TextFormatter.WordWrap = wrapMessage; - messageLabel.TextFormatter.MultiLine = !wrapMessage; d.Add (messageLabel); // Setup actions @@ -405,69 +414,11 @@ public static class MessageBox } } - d.Loaded += Dialog_Loaded; - // Run the modal; do not shutdown the mainloop driver when done Application.Run (d); d.Dispose (); return Clicked; - void Dialog_Loaded (object s, EventArgs e) - { - if (width != 0 || height != 0) - { - return; - } - - // TODO: replace with Dim.Fit when implemented - Rectangle maxBounds = d.SuperView?.Viewport ?? Application.Top.Viewport; - - Thickness adornmentsThickness = d.GetAdornmentsThickness (); - - if (wrapMessage) - { - messageLabel.TextFormatter.Size = new ( - maxBounds.Size.Width - - adornmentsThickness.Horizontal, - maxBounds.Size.Height - - adornmentsThickness.Vertical); - } - - string msg = messageLabel.TextFormatter.Format (); - Size messageSize = messageLabel.TextFormatter.FormatAndGetSize (); - - // Ensure the width fits the text + buttons - int newWidth = Math.Max ( - width, - Math.Max ( - messageSize.Width + adornmentsThickness.Horizontal, - d.GetButtonsWidth () + d.Buttons.Length + adornmentsThickness.Horizontal)); - - if (newWidth > d.Frame.Width) - { - d.Width = newWidth; - } - - // Ensure height fits the text + vspace + buttons - if (messageSize.Height == 0) - { - d.Height = Math.Max (height, 3 + adornmentsThickness.Vertical); - } - else - { - string lastLine = messageLabel.TextFormatter.GetLines () [^1]; - - // INTENT: Instead of the check against \n or \r\n, how about just Environment.NewLine? - d.Height = Math.Max ( - height, - messageSize.Height - + (lastLine.EndsWith ("\r\n") || lastLine.EndsWith ('\n') ? 1 : 2) - + adornmentsThickness.Vertical); - } - - d.SetRelativeLayout (d.SuperView?.ContentSize ?? Application.Top.ContentSize); - d.LayoutSubviews (); - } } } diff --git a/UICatalog/Scenarios/DimAutoDemo.cs b/UICatalog/Scenarios/DimAutoDemo.cs index a85904ada..1ced9cf7d 100644 --- a/UICatalog/Scenarios/DimAutoDemo.cs +++ b/UICatalog/Scenarios/DimAutoDemo.cs @@ -153,7 +153,7 @@ public class DimAutoDemo : Scenario { Text = "_Reset Button (AnchorEnd)", X = Pos.AnchorEnd (), - Y = Pos.AnchorEnd () + Y = Pos.AnchorEnd (1) }; resetButton.Accept += (s, e) => { movingButton.Y = Pos.Bottom (hlabel); }; diff --git a/UICatalog/Scenarios/MessageBoxes.cs b/UICatalog/Scenarios/MessageBoxes.cs index 6eda68499..1e90c4a0f 100644 --- a/UICatalog/Scenarios/MessageBoxes.cs +++ b/UICatalog/Scenarios/MessageBoxes.cs @@ -114,7 +114,7 @@ public class MessageBoxes : Scenario var messageEdit = new TextView { - Text = "Message", + Text = "Message line 1.\nMessage line two. This is a really long line to force wordwrap. It needs to be long for it to work.", X = Pos.Right (label) + 1, Y = Pos.Top (label), Width = Dim.Fill (), @@ -186,7 +186,7 @@ public class MessageBoxes : Scenario var ckbWrapMessage = new CheckBox { - X = Pos.Right (label) + 1, Y = Pos.Bottom (styleRadioGroup), Text = "_Wrap Message", Checked = true + X = Pos.Right (label) + 1, Y = Pos.Bottom (styleRadioGroup), Text = "_Wrap Message", Checked = false }; frame.Add (ckbWrapMessage);