WIP: Fixing MessagBox to use Dim.Auto

This commit is contained in:
Tig
2024-05-16 22:27:35 -07:00
parent c372c065ac
commit 01c30ef99f
6 changed files with 122 additions and 121 deletions

View File

@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Drawing;
namespace Terminal.Gui;
@@ -176,10 +177,10 @@ public class Dim
/// <param name="maximumContentDim">The maximum dimension the View's ContentSize will be fit to. NOT CURRENTLY SUPPORTED.</param>
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<View> 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; }

View File

@@ -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)
{

View File

@@ -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
}
/// <inheritdoc/>
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;

View File

@@ -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 ();
}
}
}

View File

@@ -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); };

View File

@@ -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);