Dialog/MessageBox use new Justifier

This commit is contained in:
Tig
2024-05-10 07:47:03 -06:00
parent a19b024563
commit cd104e9163
8 changed files with 102 additions and 53 deletions

View File

@@ -13,6 +13,11 @@ public enum Justification
/// Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
/// each item.
/// </summary>
/// <remarks>
/// <para>
/// If the container is smaller than the total size of the items, the right items will be clipped (their locations will be greater than the container size).
/// </para>
/// </remarks>
/// <example>
/// <c>
/// 111 2222 33333
@@ -32,6 +37,11 @@ public enum Justification
/// Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
/// each item.
/// </summary>
/// <remarks>
/// <para>
/// If the container is smaller than the total size of the items, the left items will be clipped (their locations will be negative).
/// </para>
/// </remarks>
/// <example>
/// <c>
/// 111 2222 33333
@@ -52,6 +62,11 @@ public enum Justification
/// Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
/// each item.
/// </summary>
/// <remarks>
/// <para>
/// Extra space will be distributed between the items, biased towards the left.
/// </para>
/// </remarks>
/// <example>
/// <c>
/// 111 2222 33333
@@ -65,6 +80,11 @@ public enum Justification
/// Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
/// each item.
/// </summary>
/// <remarks>
/// <para>
/// Extra space will be distributed between the items, biased towards the left.
/// </para>
/// </remarks>
/// <example>
/// <c>
/// 111 2222 33333
@@ -77,6 +97,11 @@ public enum Justification
/// Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
/// each item.
/// </summary>
/// <remarks>
/// <para>
/// If the container is smaller than the total size of the items, the right items will be clipped (their locations will be greater than the container size).
/// </para>
/// </remarks>
/// <example>
/// <c>
/// 111 2222 33333
@@ -96,6 +121,11 @@ public enum Justification
/// Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
/// each item.
/// </summary>
/// <remarks>
/// <para>
/// If the container is smaller than the total size of the items, the left items will be clipped (their locations will be negative).
/// </para>
/// </remarks>
/// <example>
/// <c>
/// 111 2222 33333
@@ -153,6 +183,12 @@ public class Justifier : INotifyPropertyChanged
/// <see langword="false"/>. If <see langword="true"/>, a space will be
/// placed between each item, which is useful for justifying text.
/// </summary>
/// <remarks>
/// <para>
/// If the total size of the items is greater than the container size, the space between items will be ignored starting
/// from the right.
/// </para>
/// </remarks>
public bool PutSpaceBetweenItems
{
get => _putSpaceBetweenItems;
@@ -234,7 +270,7 @@ public class Justifier : INotifyPropertyChanged
break;
case Justification.Right:
currentPosition = Math.Max (0, containerSize - totalItemsSize - spaces);
currentPosition = containerSize - totalItemsSize - spaces;
for (var i = 0; i < sizes.Length; i++)
{
@@ -297,7 +333,14 @@ public class Justifier : INotifyPropertyChanged
case Justification.LastRightRestLeft:
if (sizes.Length > 1)
{
currentPosition = 0;
if (totalItemsSize > containerSize)
{
currentPosition = containerSize - totalItemsSize - spaces;
}
else
{
currentPosition = 0;
}
for (var i = 0; i < sizes.Length; i++)
{
@@ -337,7 +380,7 @@ public class Justifier : INotifyPropertyChanged
if (i == sizes.Length - 1)
{
// start at right
currentPosition = containerSize - sizes [i];
currentPosition = Math.Max (totalItemsSize, containerSize) - sizes [i];
positions [i] = currentPosition;
}

View File

@@ -204,6 +204,7 @@ public class Pos
/// <returns>The <see cref="Pos"/> returned from the function.</returns>
public static Pos Function (Func<int> function) { return new PosFunc (function); }
/// <summary>
/// Creates a <see cref="Pos"/> object that justifies a set of views according to the specified justification.
/// </summary>
@@ -493,6 +494,7 @@ public class Pos
internal override int Anchor (int width) { return (int)(width * _factor); }
}
/// <summary>
/// Enables justification of a set of views.
/// </summary>
@@ -604,6 +606,7 @@ public class Pos
/// <param name="groupId">The unique identifier for the set of views to justify according to <paramref name="justification"/>.</param>
public PosJustify (Justification justification, int groupId = 0)
{
Justifier.PutSpaceBetweenItems = true;
Justifier.Justification = justification;
_groupId = groupId;
Justifier.PropertyChanged += Justifier_PropertyChanged;

View File

@@ -1,5 +1,4 @@
using System.Diagnostics;
using static Terminal.Gui.Pos;
namespace Terminal.Gui;
@@ -37,7 +36,6 @@ public enum LayoutStyle
Computed
}
public partial class View
{
#region Frame
@@ -200,7 +198,7 @@ public partial class View
get => VerifyIsInitialized (_x, nameof (X));
set
{
if (_x.Equals (value))
if (Equals (_x, value))
{
return;
}
@@ -239,7 +237,7 @@ public partial class View
get => VerifyIsInitialized (_y, nameof (Y));
set
{
if (_y.Equals (value))
if (Equals (_y, value))
{
return;
}

View File

@@ -20,7 +20,7 @@ public class CheckBox : View
_charChecked = Glyphs.Checked;
_charUnChecked = Glyphs.UnChecked;
Height = Dim.Auto (Dim.DimAutoStyle.Text);
Height = 1;
Width = Dim.Auto (Dim.DimAutoStyle.Text);
CanFocus = true;

View File

@@ -80,11 +80,6 @@ public class RadioGroup : View
HighlightStyle = Gui.HighlightStyle.PressedOutside | Gui.HighlightStyle.Pressed;
MouseClick += RadioGroup_MouseClick;
// TOOD: Hack - using Text when we should use SubViews
Add (_dummyView);
Width = Dim.Auto (Dim.DimAutoStyle.Content);
Height = Dim.Auto (Dim.DimAutoStyle.Content);
}
// TODO: Fix InvertColorsOnPress - only highlight the selected item
@@ -177,7 +172,7 @@ public class RadioGroup : View
}
}
if (prevCount != _radioLabels.Count)
if (IsInitialized && prevCount != _radioLabels.Count)
{
SetWidthHeight (_radioLabels);
}
@@ -444,25 +439,21 @@ public class RadioGroup : View
}
}
private void RadioGroup_LayoutStarted (object sender, EventArgs e) { /*SetWidthHeight (_radioLabels);*/ }
private void RadioGroup_LayoutStarted (object sender, EventArgs e) { SetWidthHeight (_radioLabels); }
private void SelectItem () { SelectedItem = _cursor; }
private View _dummyView = new View () {};
private void SetWidthHeight (List<string> radioLabels)
{
switch (_orientation)
{
case Orientation.Vertical:
Rectangle r = MakeRect (0, 0, radioLabels);
// TODO: Hack
_dummyView.X = r.Width + +GetAdornmentsThickness ().Horizontal;
_dummyView.Y = radioLabels.Count + GetAdornmentsThickness ().Vertical;
//if (IsInitialized)
//{
// Width = r.Width + GetAdornmentsThickness ().Horizontal;
// Height = radioLabels.Count + GetAdornmentsThickness ().Vertical;
//}
if (IsInitialized)
{
Width = r.Width + GetAdornmentsThickness ().Horizontal;
Height = radioLabels.Count + GetAdornmentsThickness ().Vertical;
}
break;
@@ -475,15 +466,11 @@ public class RadioGroup : View
length += item.length;
}
// TODO: Hack
_dummyView.X = length + GetAdornmentsThickness ().Horizontal;
_dummyView.Y = 1 + GetAdornmentsThickness ().Vertical;
//if (IsInitialized)
//{
// Width = length + GetAdornmentsThickness ().Vertical;
// Height = 1 + GetAdornmentsThickness ().Horizontal;
//}
if (IsInitialized)
{
Width = length + GetAdornmentsThickness ().Vertical;
Height = 1 + GetAdornmentsThickness ().Horizontal;
}
break;
}

View File

@@ -39,7 +39,7 @@ public class DialogTests
// Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
dlg.Border.Thickness = new (1, 0, 1, 0);
runstate = Begin (dlg);
var buttonRow = $"{CM.Glyphs.VLine} {btn1} {CM.Glyphs.VLine}";
var buttonRow = $"{CM.Glyphs.VLine} {btn1} {CM.Glyphs.VLine}";
TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
// Now add a second button
@@ -64,7 +64,7 @@ public class DialogTests
// Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
dlg.Border.Thickness = new (1, 0, 1, 0);
runstate = Begin (dlg);
buttonRow = $"{CM.Glyphs.VLine} {btn1}{CM.Glyphs.VLine}";
buttonRow = $"{CM.Glyphs.VLine}{btn1} {CM.Glyphs.VLine}";
TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
// Now add a second button
@@ -166,7 +166,7 @@ public class DialogTests
dlg.Dispose ();
// Justify
buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}";
buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}";
Assert.Equal (width, buttonRow.Length);
(runstate, dlg) = RunButtonTestDialog (
@@ -243,7 +243,7 @@ public class DialogTests
// Default - Center
buttonRow =
$"{CM.Glyphs.VLine}es {CM.Glyphs.RightBracket} {btn2} {btn3} {CM.Glyphs.LeftBracket} neve{CM.Glyphs.VLine}";
$"{CM.Glyphs.VLine}{CM.Glyphs.LeftBracket} yes {CM.Glyphs.RightBracket}{btn2}{btn3}{CM.Glyphs.LeftBracket} neve{CM.Glyphs.VLine}";
(runstate, Dialog dlg) = RunButtonTestDialog (
title,
@@ -277,7 +277,8 @@ public class DialogTests
dlg.Dispose ();
// Right
buttonRow = $"{CM.Glyphs.VLine}{CM.Glyphs.RightBracket} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}";
buttonRow = $"{CM.Glyphs.VLine}es {CM.Glyphs.RightBracket}{btn2}{btn3}{btn4}{CM.Glyphs.VLine}";
Assert.Equal (width, buttonRow.Length);
(runstate, dlg) = RunButtonTestDialog (
title,
@@ -293,7 +294,7 @@ public class DialogTests
dlg.Dispose ();
// Left
buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {CM.Glyphs.LeftBracket} n{CM.Glyphs.VLine}";
buttonRow = $"{CM.Glyphs.VLine}{btn1}{btn2}{btn3}{CM.Glyphs.LeftBracket} neve{CM.Glyphs.VLine}";
(runstate, dlg) = RunButtonTestDialog (
title,
@@ -527,7 +528,7 @@ public class DialogTests
// Justify
buttonRow =
$"{CM.Glyphs.VLine} {CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}";
$"{CM.Glyphs.VLine}{CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket} {CM.Glyphs.VLine}";
Assert.Equal (width, buttonRow.Length);
(runstate, dlg) = RunButtonTestDialog (
@@ -589,7 +590,7 @@ public class DialogTests
// Justify
buttonRow =
$"{CM.Glyphs.VLine} {CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}";
$"{CM.Glyphs.VLine}{CM.Glyphs.LeftBracket} {btnText} {CM.Glyphs.RightBracket} {CM.Glyphs.VLine}";
Assert.Equal (width, buttonRow.Length);
(runstate, dlg) = RunButtonTestDialog (
@@ -915,7 +916,7 @@ public class DialogTests
@"
┌┌───────────────┐─┐
││ │ │
││ ⟦ Ok ⟧ │ │
││ ⟦ Ok ⟧ │ │
│└───────────────┘ │
└──────────────────┘"
)]
@@ -925,7 +926,7 @@ public class DialogTests
┌┌───────────────┐─┐
││ │ │
││ │ │
││ ⟦ Ok ⟧ │ │
││ ⟦ Ok ⟧ │ │
│└───────────────┘ │
└──────────────────┘"
)]
@@ -936,7 +937,7 @@ public class DialogTests
│┌───────────────┐ │
││ │ │
││ │ │
││ ⟦ Ok ⟧ │ │
││ ⟦ Ok ⟧ │ │
│└───────────────┘ │
└──────────────────┘"
)]
@@ -948,7 +949,7 @@ public class DialogTests
││ │ │
││ │ │
││ │ │
││ ⟦ Ok ⟧ │ │
││ ⟦ Ok ⟧ │ │
│└───────────────┘ │
└──────────────────┘"
)]
@@ -961,7 +962,7 @@ public class DialogTests
││ │ │
││ │ │
││ │ │
││ ⟦ Ok ⟧ │ │
││ ⟦ Ok ⟧ │ │
│└───────────────┘ │
└──────────────────┘"
)]

View File

@@ -278,7 +278,7 @@ public class MessageBoxTests
│ffffffffffffffffff│
│ ffffffffffffff │
│ │
{btn} │
│ {btn}
└──────────────────┘",
_output
);
@@ -302,7 +302,7 @@ public class MessageBoxTests
│ffffffffffffffffff│
│ffffffffffffffffff│
│ffffffffffffffffff│
{btn} │",
│ {btn} │",
_output
);
Application.RequestStop ();
@@ -377,7 +377,7 @@ ff ff ff ff ff ff ff
────────────────────
ffffffffffffffffffff
⟦► btn ◄⟧
⟦► btn ◄⟧
────────────────────
",
_output
@@ -459,7 +459,7 @@ ffffffffffffffffffff
│ffffffffffffffffff│
│ffffffffffffffffff│
│ffffffffffffffffff│
{btn} │",
│ {btn} │",
_output
);
Application.RequestStop ();
@@ -509,7 +509,7 @@ ffffffffffffffffffff
────────────────────
ffffffffffffffffffff
⟦► btn ◄⟧
⟦► btn ◄⟧
────────────────────
",
_output
@@ -529,7 +529,7 @@ ffffffffffffffffffff
────────────────────
ffffffffffffffffffff
⟦► btn ◄⟧
⟦► btn ◄⟧
────────────────────
",
_output

View File

@@ -62,6 +62,7 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.Left, new [] { 1, 2, 3 }, 11, new [] { 0, 2, 5 })]
[InlineData (Justification.Left, new [] { 1, 2, 3 }, 12, new [] { 0, 2, 5 })]
[InlineData (Justification.Left, new [] { 1, 2, 3 }, 13, new [] { 0, 2, 5 })]
[InlineData (Justification.Left, new [] { 1, 2, 3 }, 5, new [] { 0, 1, 3 })] // 5 is too small to fit the items. The first item is at 0, the items to the right are clipped.
[InlineData (Justification.Left, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.Left, new [] { 1, 2, 3, 4 }, 11, new [] { 0, 2, 4, 7 })]
[InlineData (Justification.Left, new [] { 33, 33, 33 }, 100, new [] { 0, 34, 67 })]
@@ -80,6 +81,9 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 11, new [] { 3, 5, 8 })]
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 12, new [] { 4, 6, 9 })]
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 13, new [] { 5, 7, 10 })]
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 5, new [] { -1, 0, 2 })] // 5 is too small to fit the items. The first item is at -1.
[InlineData (Justification.Right, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.Right, new [] { 1, 2, 3, 4 }, 11, new [] { 0, 2, 4, 7 })]
[InlineData (Justification.Right, new [] { 10, 20, 30 }, 100, new [] { 38, 49, 70 })]
@@ -103,6 +107,7 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.Centered, new [] { 1, 2, 3 }, 7, new [] { 0, 2, 4 })]
[InlineData (Justification.Centered, new [] { 1, 2, 3 }, 10, new [] { 1, 3, 6 })]
[InlineData (Justification.Centered, new [] { 1, 2, 3 }, 11, new [] { 1, 3, 6 })]
[InlineData (Justification.Centered, new [] { 1, 2, 3 }, 5, new [] { 0, 1, 3 })] // 5 is too small to fit the items. The first item is at 0, the items to the right are clipped.
[InlineData (Justification.Centered, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.Centered, new [] { 1, 2, 3, 4 }, 11, new [] { 0, 2, 4, 7 })]
[InlineData (Justification.Centered, new [] { 3, 3, 3 }, 9, new [] { 0, 3, 6 })]
@@ -160,6 +165,7 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.LastRightRestLeft, new [] { 1, 2, 3 }, 9, new [] { 0, 2, 6 })]
[InlineData (Justification.LastRightRestLeft, new [] { 1, 2, 3 }, 10, new [] { 0, 2, 7 })]
[InlineData (Justification.LastRightRestLeft, new [] { 1, 2, 3 }, 11, new [] { 0, 2, 8 })]
[InlineData (Justification.LastRightRestLeft, new [] { 1, 2, 3 }, 5, new [] { -1, 0, 2 })] // 5 is too small to fit the items. The first item is at -1.})]
[InlineData (Justification.LastRightRestLeft, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.LastRightRestLeft, new [] { 1, 2, 3, 4 }, 11, new [] { 0, 2, 4, 7 })]
[InlineData (Justification.LastRightRestLeft, new [] { 3, 3, 3 }, 21, new [] { 0, 4, 18 })]
@@ -187,6 +193,7 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3 }, 9, new [] { 0, 3, 6 })]
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3 }, 10, new [] { 0, 4, 7 })]
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3 }, 11, new [] { 0, 5, 8 })]
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3 }, 5, new [] { 0, 1, 3 })]
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3, 4 }, 11, new [] { 0, 1, 3, 7 })]
[InlineData (Justification.FirstLeftRestRight, new [] { 1, 2, 3, 4 }, 12, new [] { 0, 1, 4, 8 })]
@@ -224,6 +231,8 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.Left, new [] { 1, 2, 3 }, 13, new [] { 0, 1, 3 })]
[InlineData (Justification.Left, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.Left, new [] { 1, 2, 3, 4 }, 11, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.Left, new [] { 1, 2, 3 }, 5, new [] { 0, 1, 3 })] // 5 is too small to fit the items. The first item is at 0, the items to the right are clipped.
[InlineData (Justification.Left, new [] { 10, 20, 30 }, 100, new [] { 0, 10, 30 })]
[InlineData (Justification.Left, new [] { 33, 33, 33 }, 100, new [] { 0, 33, 66 })]
[InlineData (Justification.Left, new [] { 10 }, 101, new [] { 0 })]
@@ -240,6 +249,9 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 11, new [] { 5, 6, 8 })]
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 12, new [] { 6, 7, 9 })]
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 13, new [] { 7, 8, 10 })]
[InlineData (Justification.Right, new [] { 1, 2, 3 }, 5, new [] { -1, 0, 2 })] // 5 is too small to fit the items. The first item is at -1.
[InlineData (Justification.Right, new [] { 1, 2, 3, 4 }, 10, new [] { 0, 1, 3, 6 })]
[InlineData (Justification.Right, new [] { 1, 2, 3, 4 }, 11, new [] { 1, 2, 4, 7 })]
[InlineData (Justification.Right, new [] { 10, 20, 30 }, 100, new [] { 40, 50, 70 })]
@@ -267,6 +279,8 @@ public class JustifierTests (ITestOutputHelper output)
[InlineData (Justification.Centered, new [] { 3, 3, 3 }, 11, new [] { 1, 4, 7 })]
[InlineData (Justification.Centered, new [] { 3, 3, 3 }, 12, new [] { 1, 4, 7 })]
[InlineData (Justification.Centered, new [] { 3, 3, 3 }, 13, new [] { 2, 5, 8 })]
[InlineData (Justification.Centered, new [] { 1, 2, 3 }, 5, new [] { 0, 1, 3 })] // 5 is too small to fit the items. The first item is at 0, the items to the right are clipped.
[InlineData (Justification.Centered, new [] { 33, 33, 33 }, 100, new [] { 0, 33, 66 })]
[InlineData (Justification.Centered, new [] { 33, 33, 33 }, 101, new [] { 1, 34, 67 })]
[InlineData (Justification.Centered, new [] { 33, 33, 33 }, 102, new [] { 1, 34, 67 })]
@@ -408,7 +422,10 @@ public class JustifierTests (ITestOutputHelper output)
{
for (var j = 0; j < sizes [position] && positions [position] + j < totalSize; j++)
{
items [positions [position] + j] = (position + 1).ToString () [0];
if (positions [position] + j >= 0)
{
items [positions [position] + j] = (position + 1).ToString () [0];
}
}
}