瀏覽代碼

rebased and fixed

Tig 1 年之前
父節點
當前提交
bb37689df0

+ 72 - 53
Terminal.Gui/Drawing/Justification.cs

@@ -1,7 +1,9 @@
+using static Terminal.Gui.Pos;
+
 namespace Terminal.Gui;
 
 /// <summary>
-///     Controls how the <see cref="Justifier"/> justifies items within a container. 
+///     Controls how the <see cref="Justifier"/> justifies items within a container.
 /// </summary>
 public enum Justification
 {
@@ -17,6 +19,13 @@ public enum Justification
     /// </example>
     Left,
 
+    /// <summary>
+    ///     The items will be aligned to the top.
+    ///     Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one line between
+    ///     each item.
+    /// </summary>
+    Top = Left,
+
     /// <summary>
     ///     The items will be aligned to the right.
     ///     Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
@@ -29,6 +38,13 @@ public enum Justification
     /// </example>
     Right,
 
+    /// <summary>
+    ///     The items will be aligned to the bottom.
+    ///     Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one line between
+    ///     each item.
+    /// </summary>
+    Bottom = Right,
+
     /// <summary>
     ///     The group will be centered in the container.
     ///     If centering is not possible, the group will be left-justified.
@@ -67,6 +83,13 @@ public enum Justification
     /// </example>
     FirstLeftRestRight,
 
+    /// <summary>
+    ///     The first item will be aligned to the top and the remaining will aligned to the bottom.
+    ///     Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one line between
+    ///     each item.
+    /// </summary>
+    FirstTopRestBottom = FirstLeftRestRight,
+
     /// <summary>
     ///     The last item will be aligned to the right and the remaining will aligned to the left.
     ///     Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one space between
@@ -77,7 +100,14 @@ public enum Justification
     ///         111 2222        33333
     ///     </c>
     /// </example>
-    LastRightRestLeft
+    LastRightRestLeft,
+
+    /// <summary>
+    ///     The last item will be aligned to the bottom and the remaining will aligned to the left.
+    ///     Set <see cref="Justifier.PutSpaceBetweenItems"/> to <see langword="true"/> to ensure at least one line between
+    ///     each item.
+    /// </summary>
+    LastBottomRestTop = LastRightRestLeft,
 }
 
 /// <summary>
@@ -86,39 +116,39 @@ public enum Justification
 public class Justifier
 {
     /// <summary>
-    /// Gets or sets how the <see cref="Justifier"/> justifies items within a container.
+    ///     Gets or sets how the <see cref="Justifier"/> justifies items within a container.
     /// </summary>
     public Justification Justification { get; set; }
 
     /// <summary>
-    /// The size of the container.
+    ///     The size of the container.
     /// </summary>
     public int ContainerSize { get; set; }
 
     /// <summary>
-    ///     Gets or sets whether <see cref="Justify(int[])"/> puts a space is placed between items. Default is <see langword="false"/>. If <see langword="true"/>, a space will be
+    ///     Gets or sets whether <see cref="Justifier"/> puts a space is placed between items. Default is
+    ///     <see langword="false"/>. If <see langword="true"/>, a space will be
     ///     placed between each item, which is useful for justifying text.
     /// </summary>
     public bool PutSpaceBetweenItems { get; set; }
 
     /// <summary>
-    ///     Takes a list of items and returns their positions when justified within a container <see name="ContainerSize"/> wide based on the specified
+    ///     Takes a list of items and returns their positions when justified within a container <see name="ContainerSize"/>
+    ///     wide based on the specified
     ///     <see cref="Justification"/>.
     /// </summary>
     /// <param name="sizes">The sizes of the items to justify.</param>
     /// <returns>The locations of the items, from left to right.</returns>
-    public int [] Justify (int [] sizes)
-    {
-        return Justify (Justification, PutSpaceBetweenItems, ContainerSize, sizes);
-    }
+    public int [] Justify (int [] sizes) { return Justify (Justification, PutSpaceBetweenItems, ContainerSize, sizes); }
 
     /// <summary>
-    ///     Takes a list of items and returns their positions when justified within a container <paramref name="containerSize"/> wide based on the specified
+    ///     Takes a list of items and returns their positions when justified within a container
+    ///     <paramref name="containerSize"/> wide based on the specified
     ///     <see cref="Justification"/>.
     /// </summary>
     /// <param name="sizes">The sizes of the items to justify.</param>
     /// <param name="justification">The justification style.</param>
-    /// <param name="putSpaceBetweenItems"></param>
+    /// <param name="putSpaceBetweenItems">Puts a space is placed between items.</param>
     /// <param name="containerSize">The size of the container.</param>
     /// <returns>The locations of the items, from left to right.</returns>
     public static int [] Justify (Justification justification, bool putSpaceBetweenItems, int containerSize, int [] sizes)
@@ -136,6 +166,7 @@ public class Justifier
         int totalItemsAndSpaces = totalItemsSize + totalGaps * maxSpaceBetweenItems; // total size of items and spaces if we had enough room
 
         int spaces = totalGaps * maxSpaceBetweenItems; // We'll decrement this below to place one space between each item until we run out
+
         if (totalItemsSize >= containerSize)
         {
             spaces = 0;
@@ -152,10 +183,7 @@ public class Justifier
 
                 for (var i = 0; i < sizes.Length; i++)
                 {
-                    if (sizes [i] < 0)
-                    {
-                        throw new ArgumentException ("The size of an item cannot be negative.");
-                    }
+                    CheckSizeCannotBeNegative (i, sizes);
 
                     if (i == 0)
                     {
@@ -176,11 +204,7 @@ public class Justifier
 
                 for (var i = 0; i < sizes.Length; i++)
                 {
-                    if (sizes [i] < 0)
-                    {
-                        throw new ArgumentException ("The size of an item cannot be negative.");
-                    }
-
+                    CheckSizeCannotBeNegative (i, sizes);
                     int spaceBefore = spaces-- > 0 ? maxSpaceBetweenItems : 0;
 
                     positions [i] = currentPosition;
@@ -197,10 +221,7 @@ public class Justifier
 
                     for (var i = 0; i < sizes.Length; i++)
                     {
-                        if (sizes [i] < 0)
-                        {
-                            throw new ArgumentException ("The size of an item cannot be negative.");
-                        }
+                        CheckSizeCannotBeNegative (i, sizes);
 
                         if (i == 0)
                         {
@@ -217,11 +238,7 @@ public class Justifier
                 }
                 else if (sizes.Length == 1)
                 {
-                    if (sizes [0] < 0)
-                    {
-                        throw new ArgumentException ("The size of an item cannot be negative.");
-                    }
-
+                    CheckSizeCannotBeNegative (0, sizes);
                     positions [0] = (containerSize - sizes [0]) / 2; // single item is centered
                 }
 
@@ -234,11 +251,7 @@ public class Justifier
 
                 for (var i = 0; i < sizes.Length; i++)
                 {
-                    if (sizes [i] < 0)
-                    {
-                        throw new ArgumentException ("The size of an item cannot be negative.");
-                    }
-
+                    CheckSizeCannotBeNegative (i, sizes);
                     positions [i] = currentPosition;
                     int extraSpace = i < remainder ? 1 : 0;
                     currentPosition += sizes [i] + spaceBetween + extraSpace;
@@ -254,10 +267,7 @@ public class Justifier
 
                     for (var i = 0; i < sizes.Length; i++)
                     {
-                        if (sizes [i] < 0)
-                        {
-                            throw new ArgumentException ("The size of an item cannot be negative.");
-                        }
+                        CheckSizeCannotBeNegative (i, sizes);
 
                         if (i < sizes.Length - 1)
                         {
@@ -268,14 +278,11 @@ public class Justifier
                         }
                     }
 
-                    positions [sizes.Length - 1] = containerSize - sizes [sizes.Length - 1];
+                    positions [sizes.Length - 1] = containerSize - sizes [^1];
                 }
                 else if (sizes.Length == 1)
                 {
-                    if (sizes [0] < 0)
-                    {
-                        throw new ArgumentException ("The size of an item cannot be negative.");
-                    }
+                    CheckSizeCannotBeNegative (0, sizes);
 
                     positions [0] = containerSize - sizes [0]; // single item is flush right
                 }
@@ -291,10 +298,7 @@ public class Justifier
 
                     for (int i = sizes.Length - 1; i >= 0; i--)
                     {
-                        if (sizes [i] < 0)
-                        {
-                            throw new ArgumentException ("The size of an item cannot be negative.");
-                        }
+                        CheckSizeCannotBeNegative (i, sizes);
 
                         if (i == sizes.Length - 1)
                         {
@@ -314,11 +318,7 @@ public class Justifier
                 }
                 else if (sizes.Length == 1)
                 {
-                    if (sizes [0] < 0)
-                    {
-                        throw new ArgumentException ("The size of an item cannot be negative.");
-                    }
-
+                    CheckSizeCannotBeNegative (0, sizes);
                     positions [0] = 0; // single item is flush left
                 }
 
@@ -330,4 +330,23 @@ public class Justifier
 
         return positions;
     }
+
+    private static void CheckSizeCannotBeNegative (int i, int [] sizes)
+    {
+        if (sizes [i] < 0)
+        {
+            throw new ArgumentException ("The size of an item cannot be negative.");
+        }
+    }
+    public override bool Equals (object other)
+    {
+        if (other is Justifier justifier)
+        {
+            return Justification == justifier.Justification &&
+                   ContainerSize == justifier.ContainerSize &&
+                   PutSpaceBetweenItems == justifier.PutSpaceBetweenItems;
+        }
+
+        return false;
+    }
 }

+ 1 - 1
Terminal.Gui/Resources/config.json

@@ -24,7 +24,7 @@
   "Themes": [
     {
       "Default": {
-        "Dialog.DefaultButtonAlignment": "Center",
+        "Dialog.DefaultButtonAlignment": "Centered",
         "FrameView.DefaultBorderStyle": "Single",
         "Window.DefaultBorderStyle": "Single",
         "ColorSchemes": [

+ 122 - 0
Terminal.Gui/View/Layout/PosDim.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using static Terminal.Gui.Dim;
 
 namespace Terminal.Gui;
 
@@ -203,6 +204,14 @@ 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>
+    /// <param name="views"></param>
+    /// <param name="justification"></param>
+    /// <returns></returns>
+    public static Pos Justify (Justification justification) { return new PosJustify (justification); }
+
     /// <summary>Serves as the default hash function. </summary>
     /// <returns>A hash code for the current object.</returns>
     public override int GetHashCode () { return Anchor (0).GetHashCode (); }
@@ -484,6 +493,119 @@ public class Pos
         internal override int Anchor (int width) { return (int)(width * _factor); }
     }
 
+
+    /// <summary>
+    /// Enables justification of a set of views. 
+    /// </summary>
+    public class PosJustify : Pos
+    {
+        public Justifier Justifier { get; } = new ();
+        public int? _location;
+
+        public int GroupId { get; set; }
+
+        public static void JustifyGroup (int groupId, IList<View> views, Dim.Dimension dimension, int size)
+        {
+            if (views is null)
+            {
+                return;
+            }
+            Justifier firstInGroup = null;
+            List<int> dimensionsList = new ();
+            List<View> viewsInGroup = views.Where (
+                                                   v =>
+                                                   {
+                                                       if (dimension == Dimension.Width && v.X is PosJustify justifyX)
+                                                       {
+                                                           return justifyX.GroupId == groupId;
+                                                       }
+
+                                                       if (dimension == Dimension.Height && v.Y is PosJustify justifyY)
+                                                       {
+                                                           return justifyY.GroupId == groupId;
+                                                       }
+
+                                                       return false;
+                                                   }).ToList ();
+            if (viewsInGroup.Count == 0)
+            {
+                return;
+            }
+
+            foreach (var view in viewsInGroup)
+            {
+                var posJustify = dimension == Dimension.Width ? view.X as PosJustify : view.Y as PosJustify;
+
+                if (posJustify is { })
+                {
+                    if (firstInGroup is null)
+                    {
+                        firstInGroup = posJustify.Justifier;
+                    }
+
+                    dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height);
+                }
+            }
+
+            if (firstInGroup is null)
+            {
+                return;
+            }
+
+            firstInGroup.ContainerSize = size;
+            var locations = firstInGroup.Justify (dimensionsList.ToArray ());
+
+            for (var index = 0; index < viewsInGroup.Count; index++)
+            {
+                View view = viewsInGroup [index];
+                PosJustify justify = dimension == Dimension.Width ? view.X as PosJustify : view.Y as PosJustify;
+
+                if (justify is { })
+                {
+                    justify._location = locations [index];
+                }
+            }
+        }
+
+        /// <summary>
+        /// Enables justification of a set of views.
+        /// </summary>
+        /// <param name="views">The set of views to justify according to <paramref name="justification"/>.</param>
+        /// <param name="justification"></param>
+        public PosJustify (Justification justification)
+        {
+            Justifier.Justification = justification;
+        }
+
+        public override bool Equals (object other)
+        {
+            return other is PosJustify justify && justify.Justifier.Equals (Justifier);
+        }
+
+        public override int GetHashCode () { return Justifier.GetHashCode (); }
+
+
+        public override string ToString ()
+        {
+            return $"Justify(justification={Justifier.Justification})";
+        }
+
+        internal override int Anchor (int width)
+        {
+            return _location ?? 0 - width;
+        }
+
+        internal override int Calculate (int superviewDimension, Dim dim, View us, Dim.Dimension dimension)
+        {
+            if (_location.HasValue)
+            {
+                return _location.Value;
+            }
+
+            return 0;
+        }
+
+    }
     // Helper class to provide dynamic value by the execution of a function that returns an integer.
     internal class PosFunc (Func<int> n) : Pos
     {

+ 7 - 2
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using static Terminal.Gui.Pos;
 
 namespace Terminal.Gui;
 
@@ -36,6 +37,7 @@ public enum LayoutStyle
     Computed
 }
 
+
 public partial class View
 {
     #region Frame
@@ -198,7 +200,7 @@ public partial class View
         get => VerifyIsInitialized (_x, nameof (X));
         set
         {
-            if (Equals (_x, value))
+            if (_x.Equals (value))
             {
                 return;
             }
@@ -237,7 +239,7 @@ public partial class View
         get => VerifyIsInitialized (_y, nameof (Y));
         set
         {
-            if (Equals (_y, value))
+            if (_y.Equals (value))
             {
                 return;
             }
@@ -677,6 +679,9 @@ public partial class View
 
         SetTextFormatterSize ();
 
+        PosJustify.JustifyGroup (0, Subviews, Dim.Dimension.Width, Viewport.Width);
+        PosJustify.JustifyGroup (0, Subviews, Dim.Dimension.Height, Viewport.Height);
+
         // Sort out the dependencies of the X, Y, Width, Height properties
         HashSet<View> nodes = new ();
         HashSet<(View, View)> edges = new ();

+ 1 - 1
Terminal.Gui/Views/Button.cs

@@ -45,7 +45,7 @@ public class Button : View
         _leftDefault = Glyphs.LeftDefaultIndicator;
         _rightDefault = Glyphs.RightDefaultIndicator;
 
-        Height = 1;
+        Height = Dim.Auto (Dim.DimAutoStyle.Text);
         Width = Dim.Auto (Dim.DimAutoStyle.Text);
 
         CanFocus = true;

+ 1 - 1
Terminal.Gui/Views/CheckBox.cs

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

+ 123 - 134
Terminal.Gui/Views/Dialog.cs

@@ -15,21 +15,6 @@ namespace Terminal.Gui;
 /// </remarks>
 public class Dialog : Window
 {
-    /// <summary>Determines the horizontal alignment of the Dialog buttons.</summary>
-    public enum ButtonAlignments
-    {
-        /// <summary>Center-aligns the buttons (the default).</summary>
-        Center = 0,
-
-        /// <summary>Justifies the buttons</summary>
-        Justify,
-
-        /// <summary>Left-aligns the buttons</summary>
-        Left,
-
-        /// <summary>Right-aligns the buttons</summary>
-        Right
-    }
 
     // TODO: Reenable once border/borderframe design is settled
     /// <summary>
@@ -107,8 +92,9 @@ public class Dialog : Window
         }
     }
 
+    // TODO: Update button.X = Pos.Justify when alignment changes
     /// <summary>Determines how the <see cref="Dialog"/> <see cref="Button"/>s are aligned along the bottom of the dialog.</summary>
-    public ButtonAlignments ButtonAlignment { get; set; }
+    public Justification ButtonAlignment { get; set; }
 
     /// <summary>Optional buttons to lay out at the bottom of the dialog.</summary>
     public Button [] Buttons
@@ -128,11 +114,11 @@ public class Dialog : Window
         }
     }
 
-    /// <summary>The default <see cref="ButtonAlignments"/> for <see cref="Dialog"/>.</summary>
+    /// <summary>The default <see cref="Justification"/> for <see cref="Dialog"/>.</summary>
     /// <remarks>This property can be set in a Theme.</remarks>
     [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
     [JsonConverter (typeof (JsonStringEnumConverter))]
-    public static ButtonAlignments DefaultButtonAlignment { get; set; } = ButtonAlignments.Center;
+    public static Justification DefaultButtonAlignment { get; set; } = Justification.Centered;
 
     /// <summary>
     ///     Adds a <see cref="Button"/> to the <see cref="Dialog"/>, its layout will be controlled by the
@@ -146,6 +132,9 @@ public class Dialog : Window
             return;
         }
 
+        button.X = Pos.Justify (ButtonAlignment);
+        button.Y = Pos.AnchorEnd () - 1;
+
         _buttons.Add (button);
         Add (button);
 
@@ -158,18 +147,18 @@ public class Dialog : Window
     }
 
     /// <inheritdoc/>
-    public override void LayoutSubviews ()
-    {
-        if (_inLayout)
-        {
-            return;
-        }
-
-        _inLayout = true;
-        LayoutButtons ();
-        base.LayoutSubviews ();
-        _inLayout = false;
-    }
+    //public override void LayoutSubviews ()
+    //{
+    //    if (_inLayout)
+    //    {
+    //        return;
+    //    }
+
+    //    _inLayout = true;
+    //    //LayoutButtons ();
+    //    base.LayoutSubviews ();
+    //    _inLayout = false;
+    //}
 
     // Get the width of all buttons, not including any Margin.
     internal int GetButtonsWidth ()
@@ -185,108 +174,108 @@ public class Dialog : Window
         return widths.Sum ();
     }
 
-    private void LayoutButtons ()
-    {
-        if (_buttons.Count == 0 || !IsInitialized)
-        {
-            return;
-        }
-
-        var shiftLeft = 0;
-
-        int buttonsWidth = GetButtonsWidth ();
-
-        switch (ButtonAlignment)
-        {
-            case ButtonAlignments.Center:
-                // Center Buttons
-                shiftLeft = (Viewport.Width - buttonsWidth - _buttons.Count - 1) / 2 + 1;
-
-                for (int i = _buttons.Count - 1; i >= 0; i--)
-                {
-                    Button button = _buttons [i];
-                    shiftLeft += button.Frame.Width + (i == _buttons.Count - 1 ? 0 : 1);
-
-                    if (shiftLeft > -1)
-                    {
-                        button.X = Pos.AnchorEnd (shiftLeft);
-                    }
-                    else
-                    {
-                        button.X = Viewport.Width - shiftLeft;
-                    }
-
-                    button.Y = Pos.AnchorEnd (1);
-                }
-
-                break;
-
-            case ButtonAlignments.Justify:
-                // Justify Buttons
-                // leftmost and rightmost buttons are hard against edges. The rest are evenly spaced.
-
-                var spacing = (int)Math.Ceiling ((double)(Viewport.Width - buttonsWidth) / (_buttons.Count - 1));
-
-                for (int i = _buttons.Count - 1; i >= 0; i--)
-                {
-                    Button button = _buttons [i];
-
-                    if (i == _buttons.Count - 1)
-                    {
-                        shiftLeft += button.Frame.Width;
-                        button.X = Pos.AnchorEnd (shiftLeft);
-                    }
-                    else
-                    {
-                        if (i == 0)
-                        {
-                            // first (leftmost) button 
-                            int left = Viewport.Width;
-                            button.X = Pos.AnchorEnd (left);
-                        }
-                        else
-                        {
-                            shiftLeft += button.Frame.Width + spacing;
-                            button.X = Pos.AnchorEnd (shiftLeft);
-                        }
-                    }
-
-                    button.Y = Pos.AnchorEnd (1);
-                }
-
-                break;
-
-            case ButtonAlignments.Left:
-                // Left Align Buttons
-                Button prevButton = _buttons [0];
-                prevButton.X = 0;
-                prevButton.Y = Pos.AnchorEnd (1);
-
-                for (var i = 1; i < _buttons.Count; i++)
-                {
-                    Button button = _buttons [i];
-                    button.X = Pos.Right (prevButton) + 1;
-                    button.Y = Pos.AnchorEnd (1);
-                    prevButton = button;
-                }
-
-                break;
-
-            case ButtonAlignments.Right:
-                // Right align buttons
-                shiftLeft = _buttons [_buttons.Count - 1].Frame.Width;
-                _buttons [_buttons.Count - 1].X = Pos.AnchorEnd (shiftLeft);
-                _buttons [_buttons.Count - 1].Y = Pos.AnchorEnd (1);
-
-                for (int i = _buttons.Count - 2; i >= 0; i--)
-                {
-                    Button button = _buttons [i];
-                    shiftLeft += button.Frame.Width + 1;
-                    button.X = Pos.AnchorEnd (shiftLeft);
-                    button.Y = Pos.AnchorEnd (1);
-                }
-
-                break;
-        }
-    }
+    //private void LayoutButtons ()
+    //{
+    //    if (_buttons.Count == 0 || !IsInitialized)
+    //    {
+    //        return;
+    //    }
+
+    //    var shiftLeft = 0;
+
+    //    int buttonsWidth = GetButtonsWidth ();
+
+    //    switch (ButtonAlignment)
+    //    {
+    //        case Justification.Centered:
+    //            // Center Buttons
+    //            shiftLeft = (Viewport.Width - buttonsWidth - _buttons.Count - 1) / 2 + 1;
+
+    //            for (int i = _buttons.Count - 1; i >= 0; i--)
+    //            {
+    //                Button button = _buttons [i];
+    //                shiftLeft += button.Frame.Width + (i == _buttons.Count - 1 ? 0 : 1);
+
+    //                if (shiftLeft > -1)
+    //                {
+    //                    button.X = Pos.AnchorEnd (shiftLeft);
+    //                }
+    //                else
+    //                {
+    //                    button.X = Viewport.Width - shiftLeft;
+    //                }
+
+    //                button.Y = Pos.AnchorEnd (1);
+    //            }
+
+    //            break;
+
+    //        case Justification.Justified:
+    //            // Justify Buttons
+    //            // leftmost and rightmost buttons are hard against edges. The rest are evenly spaced.
+
+    //            var spacing = (int)Math.Ceiling ((double)(Viewport.Width - buttonsWidth) / (_buttons.Count - 1));
+
+    //            for (int i = _buttons.Count - 1; i >= 0; i--)
+    //            {
+    //                Button button = _buttons [i];
+
+    //                if (i == _buttons.Count - 1)
+    //                {
+    //                    shiftLeft += button.Frame.Width;
+    //                    button.X = Pos.AnchorEnd (shiftLeft);
+    //                }
+    //                else
+    //                {
+    //                    if (i == 0)
+    //                    {
+    //                        // first (leftmost) button 
+    //                        int left = Viewport.Width;
+    //                        button.X = Pos.AnchorEnd (left);
+    //                    }
+    //                    else
+    //                    {
+    //                        shiftLeft += button.Frame.Width + spacing;
+    //                        button.X = Pos.AnchorEnd (shiftLeft);
+    //                    }
+    //                }
+
+    //                button.Y = Pos.AnchorEnd (1);
+    //            }
+
+    //            break;
+
+    //        case Justification.Left:
+    //            // Left Align Buttons
+    //            Button prevButton = _buttons [0];
+    //            prevButton.X = 0;
+    //            prevButton.Y = Pos.AnchorEnd (1);
+
+    //            for (var i = 1; i < _buttons.Count; i++)
+    //            {
+    //                Button button = _buttons [i];
+    //                button.X = Pos.Right (prevButton) + 1;
+    //                button.Y = Pos.AnchorEnd (1);
+    //                prevButton = button;
+    //            }
+
+    //            break;
+
+    //        case Justification.Right:
+    //            // Right align buttons
+    //            shiftLeft = _buttons [_buttons.Count - 1].Frame.Width;
+    //            _buttons [_buttons.Count - 1].X = Pos.AnchorEnd (shiftLeft);
+    //            _buttons [_buttons.Count - 1].Y = Pos.AnchorEnd (1);
+
+    //            for (int i = _buttons.Count - 2; i >= 0; i--)
+    //            {
+    //                Button button = _buttons [i];
+    //                shiftLeft += button.Frame.Width + 1;
+    //                button.X = Pos.AnchorEnd (shiftLeft);
+    //                button.Y = Pos.AnchorEnd (1);
+    //            }
+
+    //            break;
+    //    }
+    //}
 }

+ 6 - 1
Terminal.Gui/Views/MessageBox.cs

@@ -325,7 +325,12 @@ public static class MessageBox
 
             foreach (string s in buttons)
             {
-                var b = new Button { Text = s };
+                var b = new Button
+                {
+                    Text = s, 
+                    Y = Pos.AnchorEnd (), 
+                    X = Pos.Justify (Justification.Centered)
+                };
 
                 if (count == defaultButton)
                 {

+ 25 - 12
Terminal.Gui/Views/RadioGroup.cs

@@ -80,6 +80,11 @@ 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
@@ -172,7 +177,7 @@ public class RadioGroup : View
                 }
             }
 
-            if (IsInitialized && prevCount != _radioLabels.Count)
+            if (prevCount != _radioLabels.Count)
             {
                 SetWidthHeight (_radioLabels);
             }
@@ -439,21 +444,25 @@ 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;
 
@@ -466,11 +475,15 @@ public class RadioGroup : View
                     length += item.length;
                 }
 
-                if (IsInitialized)
-                {
-                    Width = length + GetAdornmentsThickness ().Vertical;
-                    Height = 1 + GetAdornmentsThickness ().Horizontal;
-                }
+                // TODO: Hack
+                _dummyView.X = length + GetAdornmentsThickness ().Horizontal;
+                _dummyView.Y = 1 + GetAdornmentsThickness ().Vertical;
+
+                //if (IsInitialized)
+                //{
+                //    Width = length + GetAdornmentsThickness ().Vertical;
+                //    Height = 1 + GetAdornmentsThickness ().Horizontal;
+                //}
 
                 break;
         }

+ 4 - 1
Terminal.Gui/Views/TextView.cs

@@ -4163,7 +4163,10 @@ public class TextView : View
         }
         else
         {
-            PositionCursor ();
+            if (IsInitialized)
+            {
+                PositionCursor ();
+            }
         }
 
         OnUnwrappedCursorPosition ();

+ 1 - 1
Terminal.Gui/Views/Wizard/Wizard.cs

@@ -85,7 +85,7 @@ public class Wizard : Dialog
     {
         // Using Justify causes the Back and Next buttons to be hard justified against
         // the left and right edge
-        ButtonAlignment = ButtonAlignments.Justify;
+        ButtonAlignment = Justification.Justified;
         BorderStyle = LineStyle.Double;
 
         //// Add a horiz separator

+ 1 - 0
Terminal.sln.DotSettings

@@ -439,5 +439,6 @@
 	<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=B0C2F2A1AF61DA42BBF270980E3DCEF7/Name/@EntryValue">Concurrency Issue</s:String>
 	<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=B0C2F2A1AF61DA42BBF270980E3DCEF7/Pattern/@EntryValue">(?&lt;=\W|^)(?&lt;TAG&gt;CONCURRENCY:)(\W|$)(.*)</s:String>
 	<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=B0C2F2A1AF61DA42BBF270980E3DCEF7/TodoIconStyle/@EntryValue">Warning</s:String>
+	<s:Boolean x:Key="/Default/UserDictionary/Words/=Justifier/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=unsynchronized/@EntryIndexedValue">True</s:Boolean>
 </wpf:ResourceDictionary>

+ 2 - 3
UICatalog/Scenarios/Buttons.cs

@@ -418,9 +418,8 @@ public class Buttons : Scenario
                 throw new InvalidOperationException ("T must be a numeric type that supports addition and subtraction.");
             }
 
-            // TODO: Use Dim.Auto for the Width and Height
-            Height = 1;
-            Width = Dim.Function (() => Digits + 2); // button + 3 for number + button
+            Width = Dim.Auto (Dim.DimAutoStyle.Content); //Dim.Function (() => Digits + 2); // button + 3 for number + button
+            Height = Dim.Auto (Dim.DimAutoStyle.Content);
 
             _down = new ()
             {

+ 14 - 11
UICatalog/Scenarios/ComputedLayout.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using Terminal.Gui;
+using static Terminal.Gui.Dialog;
 
 namespace UICatalog.Scenarios;
 
@@ -322,12 +323,12 @@ public class ComputedLayout : Scenario
         // This is intentionally convoluted to illustrate potential bugs.
         var anchorEndLabel1 = new Label
         {
-            Text = "This Label should be the 2nd to last line (AnchorEnd (2)).",
+            Text = "This Label should be the 3rd to last line (AnchorEnd (3)).",
             TextAlignment = TextAlignment.Centered,
             ColorScheme = Colors.ColorSchemes ["Menu"],
             Width = Dim.Fill (5),
             X = 5,
-            Y = Pos.AnchorEnd (2)
+            Y = Pos.AnchorEnd (3)
         };
         app.Add (anchorEndLabel1);
 
@@ -336,19 +337,18 @@ public class ComputedLayout : Scenario
         var anchorEndLabel2 = new TextField
         {
             Text =
-                "This TextField should be the 3rd to last line (AnchorEnd (2) - 1).",
+                "This TextField should be the 4th to last line (AnchorEnd (3) - 1).",
             TextAlignment = TextAlignment.Left,
             ColorScheme = Colors.ColorSchemes ["Menu"],
             Width = Dim.Fill (5),
             X = 5,
-            Y = Pos.AnchorEnd (2) - 1 // Pos.Combine
+            Y = Pos.AnchorEnd (3) - 1 // Pos.Combine
         };
         app.Add (anchorEndLabel2);
 
-        // Show positioning vertically using Pos.AnchorEnd via Pos.Combine
         var leftButton = new Button
         {
-            Text = "Left", Y = Pos.AnchorEnd (0) - 1 // Pos.Combine
+            Text = "Left", Y = Pos.AnchorEnd () - 1
         };
 
         leftButton.Accept += (s, e) =>
@@ -364,7 +364,7 @@ public class ComputedLayout : Scenario
         // show positioning vertically using Pos.AnchorEnd
         var centerButton = new Button
         {
-            Text = "Center", X = Pos.Center (), Y = Pos.AnchorEnd (1) // Pos.AnchorEnd(1)
+            Text = "Center", Y = Pos.AnchorEnd (2) // Pos.AnchorEnd(1)
         };
 
         centerButton.Accept += (s, e) =>
@@ -390,14 +390,17 @@ public class ComputedLayout : Scenario
                                    app.LayoutSubviews ();
                                };
 
-        // Center three buttons with 5 spaces between them
-        leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5;
-        rightButton.X = Pos.Right (centerButton) + 5;
-
+        View [] buttons = { leftButton, centerButton, rightButton };
         app.Add (leftButton);
         app.Add (centerButton);
         app.Add (rightButton);
 
+
+        // Center three buttons with 
+        leftButton.X = Pos.Justify (Justification.Centered);
+        centerButton.X = Pos.Justify (Justification.Centered);
+        rightButton.X = Pos.Justify (Justification.Centered);
+
         Application.Run (app);
         app.Dispose ();
     }

+ 20 - 3
UICatalog/Scenarios/Dialogs.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using Terminal.Gui;
 
 namespace UICatalog.Scenarios;
@@ -131,11 +132,24 @@ public class Dialogs : Scenario
         };
         frame.Add (label);
 
+        static IEnumerable<string> GetUniqueEnumNames<T> () where T : Enum
+        {
+            var values = new HashSet<int> ();
+            foreach (var name in Enum.GetNames (typeof (T)))
+            {
+                var value = (int)Enum.Parse (typeof (T), name);
+                if (values.Add (value))
+                {
+                    yield return name;
+                }
+            }
+        }
+
         var styleRadioGroup = new RadioGroup
         {
             X = Pos.Right (label) + 1,
             Y = Pos.Top (label),
-            RadioLabels = new [] { "_Center", "_Justify", "_Left", "_Right" }
+            RadioLabels = GetUniqueEnumNames<Justification> ().ToArray (),
         };
         frame.Add (styleRadioGroup);
 
@@ -239,7 +253,10 @@ public class Dialogs : Scenario
                 }
                 else
                 {
-                    button = new() { Text = NumberToWords.Convert (buttonId), IsDefault = buttonId == 0 };
+                    button = new Button
+                    {
+                        Text = NumberToWords.Convert (buttonId), IsDefault = buttonId == 0
+                    };
                 }
 
                 button.Accept += (s, e) =>
@@ -263,7 +280,7 @@ public class Dialogs : Scenario
             dialog = new()
             {
                 Title = titleEdit.Text,
-                ButtonAlignment = (Dialog.ButtonAlignments)styleRadioGroup.SelectedItem,
+                ButtonAlignment = (Justification)styleRadioGroup.SelectedItem,
                 Buttons = buttons.ToArray ()
             };
 

+ 334 - 0
UICatalog/Scenarios/PosJustification.cs

@@ -0,0 +1,334 @@
+using System.Collections.Generic;
+using System;
+using Terminal.Gui;
+using System.Linq;
+using System.Reflection.Emit;
+
+namespace UICatalog.Scenarios;
+
+[ScenarioMetadata ("PosJustification", "Shows off Pos.Justify")]
+[ScenarioCategory ("Layout")]
+public sealed class PosJustification : Scenario
+{
+
+    private Justifier _horizJustifier = new Justifier ();
+    private int _leftMargin = 0;
+    private Justifier _vertJustifier = new Justifier ();
+    private int _topMargin = 0;
+
+    public override void Main ()
+    {
+        // Init
+        Application.Init ();
+
+        // Setup - Create a top-level application window and configure it.
+        Window appWindow = new ()
+        {
+            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()} - {GetDescription ()}"
+        };
+
+        SetupHorizontalControls (appWindow);
+
+        SetupVerticalControls (appWindow);
+
+        // Run - Start the application.
+        Application.Run (appWindow);
+        appWindow.Dispose ();
+
+        // Shutdown - Calling Application.Shutdown is required.
+        Application.Shutdown ();
+    }
+
+    private void SetupHorizontalControls (Window appWindow)
+    {
+        ColorScheme colorScheme = Colors.ColorSchemes ["Toplevel"];
+        RadioGroup justification = new ()
+        {
+            X = Pos.Justify (_horizJustifier.Justification),
+            Y = Pos.Center (),
+            RadioLabels = GetUniqueEnumNames<Justification> (false).ToArray (),
+            ColorScheme = colorScheme
+        };
+
+        justification.SelectedItemChanged += (s, e) =>
+        {
+            _horizJustifier.Justification = (Justification)Enum.Parse (typeof (Justification), justification.SelectedItem.ToString ());
+            foreach (var view in appWindow.Subviews.Where (v => v.X is Pos.PosJustify))
+            {
+                if (view.X is Pos.PosJustify j)
+                {
+                    var newJust = new Pos.PosJustify (_horizJustifier.Justification)
+                    {
+                        Justifier =
+                        {
+                            PutSpaceBetweenItems = _horizJustifier.PutSpaceBetweenItems
+                        }
+                    };
+                    view.X = newJust;
+                }
+            }
+        };
+        appWindow.Add (justification);
+
+        CheckBox putSpaces = new ()
+        {
+            X = Pos.Justify (_horizJustifier.Justification),
+            Y = Pos.Top (justification),
+            ColorScheme = colorScheme,
+            Text = "Spaces",
+        };
+        putSpaces.Toggled += (s, e) =>
+                             {
+                                 _horizJustifier.PutSpaceBetweenItems = e.NewValue is { } && e.NewValue.Value;
+                                 foreach (var view in appWindow.Subviews.Where (v => v.X is Pos.PosJustify))
+                                 {
+                                     if (view.X is Pos.PosJustify j)
+                                     {
+                                         j.Justifier.PutSpaceBetweenItems = _horizJustifier.PutSpaceBetweenItems;
+                                     }
+                                 }
+                             };
+        appWindow.Add (putSpaces);
+
+        CheckBox margin = new ()
+        {
+            X = Pos.Left (putSpaces),
+            Y = Pos.Bottom (putSpaces),
+            ColorScheme = colorScheme,
+            Text = "Margin",
+        };
+        margin.Toggled += (s, e) =>
+        {
+            _leftMargin = e.NewValue is { } && e.NewValue.Value ? 1 : 0;
+            foreach (var view in appWindow.Subviews.Where (v => v.X is Pos.PosJustify))
+            {
+                // Skip the justification radio group
+                if (view != justification)
+                {
+                    view.Margin.Thickness = new Thickness (_leftMargin, 0, 0, 0);
+                }
+            }
+            appWindow.LayoutSubviews ();
+
+        };
+        appWindow.Add (margin);
+
+        var addedViews = new List<Button> ();
+        addedViews.Add (new Button
+        {
+            X = Pos.Justify (_horizJustifier.Justification),
+            Y = Pos.Center (),
+            Text = NumberToWords.Convert (0)
+        });
+
+        var addedViewsUpDown = new Buttons.NumericUpDown<int> ()
+        {
+            X = Pos.Justify (_horizJustifier.Justification),
+            Y = Pos.Top (justification),
+            Width = 9,
+            Title = "Added",
+            ColorScheme = colorScheme,
+            BorderStyle = LineStyle.None,
+            Value = addedViews.Count
+        };
+        addedViewsUpDown.Border.Thickness = new Thickness (0, 1, 0, 0);
+        addedViewsUpDown.ValueChanging += (s, e) =>
+                                            {
+                                                if (e.NewValue < 0)
+                                                {
+                                                    e.Cancel = true;
+
+                                                    return;
+                                                }
+
+                                                // Add or remove buttons
+                                                if (e.NewValue < e.OldValue)
+                                                {
+                                                    // Remove buttons
+                                                    for (int i = e.OldValue - 1; i >= e.NewValue; i--)
+                                                    {
+                                                        var button = addedViews [i];
+                                                        appWindow.Remove (button);
+                                                        addedViews.RemoveAt (i);
+                                                        button.Dispose ();
+                                                    }
+                                                }
+
+                                                if (e.NewValue > e.OldValue)
+                                                {
+                                                    // Add buttons
+                                                    for (int i = e.OldValue; i < e.NewValue; i++)
+                                                    {
+                                                        var button = new Button
+                                                        {
+                                                            X = Pos.Justify (_horizJustifier.Justification),
+                                                            Y = Pos.Center (),
+                                                            Text = NumberToWords.Convert (i + 1)
+                                                        };
+                                                        appWindow.Add (button);
+                                                        addedViews.Add (button);
+                                                    }
+                                                }
+                                            };
+        appWindow.Add (addedViewsUpDown);
+
+        appWindow.Add (addedViews [0]);
+
+    }
+
+    private void SetupVerticalControls (Window appWindow)
+    {
+        ColorScheme colorScheme = Colors.ColorSchemes ["Error"];
+        RadioGroup justification = new ()
+        {
+            X = 0,
+            Y = Pos.Justify (_vertJustifier.Justification),
+            RadioLabels = GetUniqueEnumNames<Justification> (true).Reverse ().ToArray (),
+            ColorScheme = colorScheme
+        };
+
+        justification.SelectedItemChanged += (s, e) =>
+        {
+            _vertJustifier.Justification = (Justification)Enum.Parse (typeof (Justification), justification.SelectedItem.ToString ());
+            foreach (var view in appWindow.Subviews.Where (v => v.Y is Pos.PosJustify))
+            {
+                if (view.Y is Pos.PosJustify j)
+                {
+                    var newJust = new Pos.PosJustify (_vertJustifier.Justification)
+                    {
+                        Justifier =
+                        {
+                            PutSpaceBetweenItems = _vertJustifier.PutSpaceBetweenItems
+                        }
+                    };
+                    view.Y = newJust;
+                }
+            }
+        };
+        appWindow.Add (justification);
+
+        CheckBox putSpaces = new ()
+        {
+            X = 0,
+            Y = Pos.Justify (_vertJustifier.Justification),
+            ColorScheme = colorScheme,
+            Text = "Spaces",
+        };
+        putSpaces.Toggled += (s, e) =>
+        {
+            _vertJustifier.PutSpaceBetweenItems = e.NewValue is { } && e.NewValue.Value;
+            foreach (var view in appWindow.Subviews.Where (v => v.Y is Pos.PosJustify))
+            {
+                if (view.Y is Pos.PosJustify j)
+                {
+                    j.Justifier.PutSpaceBetweenItems = _vertJustifier.PutSpaceBetweenItems;
+                }
+            }
+
+        };
+        appWindow.Add (putSpaces);
+
+        CheckBox margin = new ()
+        {
+            X = Pos.Right (putSpaces) + 1,
+            Y = Pos.Top (putSpaces),
+            ColorScheme = colorScheme,
+            Text = "Margin",
+        };
+        margin.Toggled += (s, e) =>
+        {
+            _topMargin = e.NewValue is { } && e.NewValue.Value ? 1 : 0;
+            foreach (var view in appWindow.Subviews.Where (v => v.Y is Pos.PosJustify))
+            {
+                // Skip the justification radio group
+                if (view != justification)
+                {
+                    view.Margin.Thickness = new Thickness (0, _topMargin, 0, 0);
+                }
+            }
+            appWindow.LayoutSubviews ();
+        };
+        appWindow.Add (margin);
+
+        var addedViews = new List<CheckBox> ();
+        addedViews.Add (new CheckBox
+        {
+            X = 0,
+            Y = Pos.Justify (_vertJustifier.Justification),
+            Text = NumberToWords.Convert (0)
+        });
+
+        var addedViewsUpDown = new Buttons.NumericUpDown<int> ()
+        {
+            X = 0,
+            Y = Pos.Justify (_vertJustifier.Justification),
+            Width = 9,
+            Title = "Added",
+            ColorScheme = colorScheme,
+            BorderStyle = LineStyle.None,
+            Value = addedViews.Count
+        };
+        addedViewsUpDown.Border.Thickness = new Thickness (0, 1, 0, 0);
+        addedViewsUpDown.ValueChanging += (s, e) =>
+        {
+            if (e.NewValue < 0)
+            {
+                e.Cancel = true;
+
+                return;
+            }
+
+            // Add or remove buttons
+            if (e.NewValue < e.OldValue)
+            {
+                // Remove buttons
+                for (int i = e.OldValue - 1; i >= e.NewValue; i--)
+                {
+                    var button = addedViews [i];
+                    appWindow.Remove (button);
+                    addedViews.RemoveAt (i);
+                    button.Dispose ();
+                }
+            }
+
+            if (e.NewValue > e.OldValue)
+            {
+                // Add buttons
+                for (int i = e.OldValue; i < e.NewValue; i++)
+                {
+                    var button = new CheckBox ()
+                    {
+                        X = 0,
+                        Y = Pos.Justify (_vertJustifier.Justification),
+                        Text = NumberToWords.Convert (i + 1)
+                    };
+                    appWindow.Add (button);
+                    addedViews.Add (button);
+                }
+            }
+        };
+        appWindow.Add (addedViewsUpDown);
+
+        appWindow.Add (addedViews [0]);
+
+    }
+
+    static IEnumerable<string> GetUniqueEnumNames<T> (bool reverse) where T : Enum
+    {
+        var values = new HashSet<int> ();
+        var names = Enum.GetNames (typeof (T));
+
+        if (reverse)
+        {
+            names = Enum.GetNames (typeof (T)).Reverse ().ToArray ();
+        }
+        foreach (var name in names)
+        {
+            var value = (int)Enum.Parse (typeof (T), name);
+            if (values.Add (value))
+            {
+                yield return name;
+            }
+        }
+    }
+}

+ 3 - 3
UnitTests/Configuration/ThemeScopeTests.cs

@@ -29,12 +29,12 @@ public class ThemeScopeTests
     {
         Reset ();
         Assert.NotEmpty (Themes);
-        Assert.Equal (Dialog.ButtonAlignments.Center, Dialog.DefaultButtonAlignment);
+        Assert.Equal (Justification.Centered, Dialog.DefaultButtonAlignment);
 
-        Themes ["Default"] ["Dialog.DefaultButtonAlignment"].PropertyValue = Dialog.ButtonAlignments.Right;
+        Themes ["Default"] ["Dialog.DefaultButtonAlignment"].PropertyValue = Justification.Right;
 
         ThemeManager.Themes! [ThemeManager.SelectedTheme]!.Apply ();
-        Assert.Equal (Dialog.ButtonAlignments.Right, Dialog.DefaultButtonAlignment);
+        Assert.Equal (Justification.Right, Dialog.DefaultButtonAlignment);
         Reset ();
     }
 

+ 3 - 3
UnitTests/Configuration/ThemeTests.cs

@@ -77,15 +77,15 @@ public class ThemeTests
     public void TestSerialize_RoundTrip ()
     {
         var theme = new ThemeScope ();
-        theme ["Dialog.DefaultButtonAlignment"].PropertyValue = Dialog.ButtonAlignments.Right;
+        theme ["Dialog.DefaultButtonAlignment"].PropertyValue = Justification.Right;
 
         string json = JsonSerializer.Serialize (theme, _jsonOptions);
 
         var deserialized = JsonSerializer.Deserialize<ThemeScope> (json, _jsonOptions);
 
         Assert.Equal (
-                      Dialog.ButtonAlignments.Right,
-                      (Dialog.ButtonAlignments)deserialized ["Dialog.DefaultButtonAlignment"].PropertyValue
+                      Justification.Right,
+                      (Justification)deserialized ["Dialog.DefaultButtonAlignment"].PropertyValue
                      );
         Reset ();
     }

+ 236 - 236
UnitTests/Dialogs/DialogTests.cs

@@ -32,8 +32,8 @@ public class DialogTests
             Title = title,
             Width = width,
             Height = 1,
-            ButtonAlignment = Dialog.ButtonAlignments.Center,
-            Buttons = [new () { Text = btn1Text }]
+            ButtonAlignment = Justification.Centered,
+            Buttons = [new Button { Text = btn1Text }]
         };
 
         // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
@@ -57,8 +57,8 @@ public class DialogTests
             Title = title,
             Width = width,
             Height = 1,
-            ButtonAlignment = Dialog.ButtonAlignments.Justify,
-            Buttons = [new () { Text = btn1Text }]
+            ButtonAlignment = Justification.Justified,
+            Buttons = [new Button { Text = btn1Text }]
         };
 
         // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
@@ -82,8 +82,8 @@ public class DialogTests
             Title = title,
             Width = width,
             Height = 1,
-            ButtonAlignment = Dialog.ButtonAlignments.Right,
-            Buttons = [new () { Text = btn1Text }]
+            ButtonAlignment = Justification.Right,
+            Buttons = [new Button { Text = btn1Text }]
         };
 
         // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
@@ -107,8 +107,8 @@ public class DialogTests
             Title = title,
             Width = width,
             Height = 1,
-            ButtonAlignment = Dialog.ButtonAlignments.Left,
-            Buttons = [new () { Text = btn1Text }]
+            ButtonAlignment = Justification.Left,
+            Buttons = [new Button { Text = btn1Text }]
         };
 
         // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
@@ -153,14 +153,14 @@ public class DialogTests
 
         // Default - Center
         (runstate, Dialog dlg) = RunButtonTestDialog (
-                                                      title,
-                                                      width,
-                                                      Dialog.ButtonAlignments.Center,
-                                                      new Button { Text = btn1Text },
-                                                      new Button { Text = btn2Text },
-                                                      new Button { Text = btn3Text },
-                                                      new Button { Text = btn4Text }
-                                                     );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -170,14 +170,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                      title,
+                                                      width,
+                                                      Justification.Justified,
+                                                      new Button { Text = btn1Text },
+                                                      new Button { Text = btn2Text },
+                                                      new Button { Text = btn3Text },
+                                                      new Button { Text = btn4Text }
+                                                     );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -187,14 +187,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                      title,
+                                                      width,
+                                                      Justification.Right,
+                                                      new Button { Text = btn1Text },
+                                                      new Button { Text = btn2Text },
+                                                      new Button { Text = btn3Text },
+                                                      new Button { Text = btn4Text }
+                                                     );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -204,14 +204,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                      title,
+                                                      width,
+                                                      Justification.Left,
+                                                      new Button { Text = btn1Text },
+                                                      new Button { Text = btn2Text },
+                                                      new Button { Text = btn3Text },
+                                                      new Button { Text = btn4Text }
+                                                     );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -248,7 +248,7 @@ public class DialogTests
         (runstate, Dialog dlg) = RunButtonTestDialog (
                                                       title,
                                                       width,
-                                                      Dialog.ButtonAlignments.Center,
+                                                      Justification.Centered,
                                                       new Button { Text = btn1Text },
                                                       new Button { Text = btn2Text },
                                                       new Button { Text = btn3Text },
@@ -264,14 +264,14 @@ public class DialogTests
             $"{CM.Glyphs.VLine}{CM.Glyphs.LeftBracket} yes {CM.Glyphs.LeftBracket} no {CM.Glyphs.LeftBracket} maybe {CM.Glyphs.LeftBracket} never {CM.Glyphs.RightBracket}{CM.Glyphs.VLine}";
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -280,14 +280,14 @@ public class DialogTests
         buttonRow = $"{CM.Glyphs.VLine}{CM.Glyphs.RightBracket} {btn2} {btn3} {btn4}{CM.Glyphs.VLine}";
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -296,14 +296,14 @@ public class DialogTests
         buttonRow = $"{CM.Glyphs.VLine}{btn1} {btn2} {btn3} {CM.Glyphs.LeftBracket} n{CM.Glyphs.VLine}";
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -337,14 +337,14 @@ public class DialogTests
 
         // Default - Center
         (runstate, Dialog dlg) = RunButtonTestDialog (
-                                                      title,
-                                                      width,
-                                                      Dialog.ButtonAlignments.Center,
-                                                      new Button { Text = btn1Text },
-                                                      new Button { Text = btn2Text },
-                                                      new Button { Text = btn3Text },
-                                                      new Button { Text = btn4Text }
-                                                     );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -354,14 +354,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -371,14 +371,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -388,14 +388,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -431,14 +431,14 @@ public class DialogTests
 
         // Default - Center
         (runstate, Dialog dlg) = RunButtonTestDialog (
-                                                      title,
-                                                      width,
-                                                      Dialog.ButtonAlignments.Center,
-                                                      new Button { Text = btn1Text },
-                                                      new Button { Text = btn2Text },
-                                                      new Button { Text = btn3Text },
-                                                      new Button { Text = btn4Text }
-                                                     );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -448,14 +448,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.GetColumns ());
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -465,14 +465,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.GetColumns ());
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -482,14 +482,14 @@ public class DialogTests
         Assert.Equal (width, buttonRow.GetColumns ());
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text },
-                                               new Button { Text = btn4Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text },
+                                                    new Button { Text = btn4Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -514,11 +514,11 @@ public class DialogTests
         d.SetBufferSize (width, 1);
 
         (runstate, Dialog dlg) = RunButtonTestDialog (
-                                                      title,
-                                                      width,
-                                                      Dialog.ButtonAlignments.Center,
-                                                      new Button { Text = btnText }
-                                                     );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btnText }
+                                                   );
 
         // Center
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
@@ -531,11 +531,11 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -546,11 +546,11 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -561,11 +561,11 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -578,11 +578,11 @@ public class DialogTests
         d.SetBufferSize (width, 1);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Center,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -593,11 +593,11 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -608,11 +608,11 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -623,11 +623,11 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btnText }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btnText }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -657,13 +657,13 @@ public class DialogTests
         d.SetBufferSize (buttonRow.Length, 3);
 
         (runstate, Dialog dlg) = RunButtonTestDialog (
-                                                      title,
-                                                      width,
-                                                      Dialog.ButtonAlignments.Center,
-                                                      new Button { Text = btn1Text },
-                                                      new Button { Text = btn2Text },
-                                                      new Button { Text = btn3Text }
-                                                     );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -673,13 +673,13 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -689,13 +689,13 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -705,13 +705,13 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text },
-                                               new Button { Text = btn3Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text },
+                                                    new Button { Text = btn3Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -739,12 +739,12 @@ public class DialogTests
         d.SetBufferSize (buttonRow.Length, 3);
 
         (runstate, Dialog dlg) = RunButtonTestDialog (
-                                                      title,
-                                                      width,
-                                                      Dialog.ButtonAlignments.Center,
-                                                      new Button { Text = btn1Text },
-                                                      new Button { Text = btn2Text }
-                                                     );
+                                                    title,
+                                                    width,
+                                                    Justification.Centered,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -754,12 +754,12 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Justify,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Justified,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -769,12 +769,12 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Right,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Right,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -784,12 +784,12 @@ public class DialogTests
         Assert.Equal (width, buttonRow.Length);
 
         (runstate, dlg) = RunButtonTestDialog (
-                                               title,
-                                               width,
-                                               Dialog.ButtonAlignments.Left,
-                                               new Button { Text = btn1Text },
-                                               new Button { Text = btn2Text }
-                                              );
+                                                    title,
+                                                    width,
+                                                    Justification.Left,
+                                                    new Button { Text = btn1Text },
+                                                    new Button { Text = btn2Text }
+                                                   );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
         End (runstate);
         dlg.Dispose ();
@@ -821,9 +821,9 @@ public class DialogTests
         Button button1, button2;
 
         // Default (Center)
-        button1 = new () { Text = btn1Text };
-        button2 = new () { Text = btn2Text };
-        (runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, button1, button2);
+        button1 = new Button { Text = btn1Text };
+        button2 = new Button { Text = btn2Text };
+        (runstate, dlg) = RunButtonTestDialog (title, width, Justification.Centered, button1, button2);
         button1.Visible = false;
         RunIteration (ref runstate, ref firstIteration);
         buttonRow = $@"{CM.Glyphs.VLine}         {btn2} {CM.Glyphs.VLine}";
@@ -833,9 +833,9 @@ public class DialogTests
 
         // Justify
         Assert.Equal (width, buttonRow.Length);
-        button1 = new () { Text = btn1Text };
-        button2 = new () { Text = btn2Text };
-        (runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Justify, button1, button2);
+        button1 = new Button { Text = btn1Text };
+        button2 = new Button { Text = btn2Text };
+        (runstate, dlg) = RunButtonTestDialog (title, width, Justification.Justified, button1, button2);
         button1.Visible = false;
         RunIteration (ref runstate, ref firstIteration);
         buttonRow = $@"{CM.Glyphs.VLine}          {btn2}{CM.Glyphs.VLine}";
@@ -845,9 +845,9 @@ public class DialogTests
 
         // Right
         Assert.Equal (width, buttonRow.Length);
-        button1 = new () { Text = btn1Text };
-        button2 = new () { Text = btn2Text };
-        (runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Right, button1, button2);
+        button1 = new Button { Text = btn1Text };
+        button2 = new Button { Text = btn2Text };
+        (runstate, dlg) = RunButtonTestDialog (title, width, Justification.Right, button1, button2);
         button1.Visible = false;
         RunIteration (ref runstate, ref firstIteration);
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
@@ -856,9 +856,9 @@ public class DialogTests
 
         // Left
         Assert.Equal (width, buttonRow.Length);
-        button1 = new () { Text = btn1Text };
-        button2 = new () { Text = btn2Text };
-        (runstate, dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Left, button1, button2);
+        button1 = new Button { Text = btn1Text };
+        button2 = new Button { Text = btn2Text };
+        (runstate, dlg) = RunButtonTestDialog (title, width, Justification.Left, button1, button2);
         button1.Visible = false;
         RunIteration (ref runstate, ref firstIteration);
         buttonRow = $@"{CM.Glyphs.VLine}        {btn2}  {CM.Glyphs.VLine}";
@@ -1281,7 +1281,7 @@ public class DialogTests
         (runstate, Dialog _) = RunButtonTestDialog (
                                                     title,
                                                     width,
-                                                    Dialog.ButtonAlignments.Center,
+                                                    Justification.Centered,
                                                     new Button { Text = btnText }
                                                    );
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
@@ -1334,7 +1334,7 @@ public class DialogTests
         int width = buttonRow.Length;
         d.SetBufferSize (buttonRow.Length, 3);
 
-        (runstate, Dialog dlg) = RunButtonTestDialog (title, width, Dialog.ButtonAlignments.Center, null);
+        (runstate, Dialog dlg) = RunButtonTestDialog (title, width, Justification.Centered, null);
         TestHelpers.AssertDriverContentsWithFrameAre ($"{buttonRow}", _output);
 
         End (runstate);
@@ -1344,7 +1344,7 @@ public class DialogTests
     private (RunState, Dialog) RunButtonTestDialog (
         string title,
         int width,
-        Dialog.ButtonAlignments align,
+        Justification align,
         params Button [] btns
     )
     {

+ 2 - 0
UnitTests/Drawing/JustifierTests.cs

@@ -199,6 +199,8 @@ public class JustifierTests (ITestOutputHelper output)
     [InlineData (Justification.FirstLeftRestRight, new [] { 10, 20, 30 }, 101, new [] { 0, 50, 71 })]
     [InlineData (Justification.FirstLeftRestRight, new [] { 10, 20, 30, 40 }, 101, new [] { 0, 10, 30, 61 })]
     [InlineData (Justification.FirstLeftRestRight, new [] { 10, 20, 30, 40, 50 }, 151, new [] { 0, 10, 30, 60, 101 })]
+    [InlineData (Justification.FirstLeftRestRight, new [] { 3, 3, 3 }, 21, new [] { 0, 14, 18 })]
+    [InlineData (Justification.FirstLeftRestRight, new [] { 3, 4, 5 }, 21, new [] { 0, 11, 16 })]
     public void TestJustifications_PutSpaceBetweenItems (Justification justification, int [] sizes, int containerSize, int [] expected)
     {
         int [] positions = new Justifier