Tig 1 年之前
父节点
当前提交
292ebfb638
共有 2 个文件被更改,包括 414 次插入160 次删除
  1. 132 62
      Terminal.Gui/Drawing/Justification.cs
  2. 282 98
      UnitTests/Drawing/JustifierTests.cs

+ 132 - 62
Terminal.Gui/Drawing/Justification.cs

@@ -6,52 +6,70 @@ namespace Terminal.Gui;
 public enum Justification
 public enum Justification
 {
 {
     /// <summary>
     /// <summary>
-    ///     The items will be left-justified.
+    ///     The items will be aligned to the left.
+    ///     The items will be arranged such that there is no more than <see cref="Justifier.MaxSpaceBetweenItems"/> space between each.
     /// </summary>
     /// </summary>
+    /// <example>
+    /// <c>
+    /// 111 2222 33333
+    /// </c>
+    /// </example>
     Left,
     Left,
 
 
     /// <summary>
     /// <summary>
-    ///     The items will be right-justified.
+    ///     The items will be aligned to the right.
+    ///     The items will be arranged such that there is no more than <see cref="Justifier.MaxSpaceBetweenItems"/> space between each.
     /// </summary>
     /// </summary>
+    /// <example>
+    /// <c>
+    ///    111 2222 33333
+    /// </c>
+    /// </example>
     Right,
     Right,
 
 
     /// <summary>
     /// <summary>
-    ///     The items will be arranged such that there is no more than 1 space between them. The group will be centered in the container.
+    ///     The group will be centered in the container.
+    ///     If centering is not possible, the group will be left-justified.
+    ///     The items will be arranged such that there is no more than <see cref="Justifier.MaxSpaceBetweenItems"/> space between each.
     /// </summary>
     /// </summary>
+    /// <example>
+    /// <c>
+    ///    111 2222 33333
+    /// </c>
+    /// </example>
     Centered,
     Centered,
 
 
     /// <summary>
     /// <summary>
     ///     The items will be justified. Space will be added between the items such that the first item
     ///     The items will be justified. Space will be added between the items such that the first item
     ///     is at the start and the right side of the last item against the end.
     ///     is at the start and the right side of the last item against the end.
+    ///     The items will be arranged such that there is no more than <see cref="Justifier.MaxSpaceBetweenItems"/> space between each.
     /// </summary>
     /// </summary>
     /// <example>
     /// <example>
     /// <c>
     /// <c>
-    /// 111 2222        33333
+    /// 111    2222     33333
     /// </c>
     /// </c>
     /// </example>
     /// </example>
     Justified,
     Justified,
 
 
     /// <summary>
     /// <summary>
-    ///    The items will be left-justified. The first item will be at the start and the last item will be at the end.
-    ///    Those in between will be tight against the right item.
+    ///    The first item will be aligned to the left and the remaining will aligned to the right with no more than <see cref="Justifier.MaxSpaceBetweenItems"/> between each.
     /// </summary>
     /// </summary>
     /// <example>
     /// <example>
     /// <c>
     /// <c>
-    /// 111 2222        33333
+    /// 111        2222 33333
     /// </c>
     /// </c>
     /// </example>
     /// </example>
-    RightJustified,
+    OneLeftRestRight,
 
 
     /// <summary>
     /// <summary>
-    ///    The items will be left-justified. The first item will be at the start and the last item will be at the end.
-    ///    Those in between will be tight against the right item.
+    ///    The last item will be aligned to right and the remaining will aligned to the left with no more than <see cref="Justifier.MaxSpaceBetweenItems"/> between each.
     /// </summary>
     /// </summary>
     /// <example>
     /// <example>
     /// <c>
     /// <c>
-    /// 111        2222 33333
+    /// 111 2222        33333
     /// </c>
     /// </c>
     /// </example>
     /// </example>
-    LeftJustified
+    OneRightRestLeft
 }
 }
 
 
 /// <summary>
 /// <summary>
@@ -59,6 +77,11 @@ public enum Justification
 /// </summary>
 /// </summary>
 public class Justifier
 public class Justifier
 {
 {
+    /// <summary>
+    /// Gets or sets the maximum space between items. The default is 0. For text, this is usually 1.
+    /// </summary>
+    public int MaxSpaceBetweenItems { get; set; } = 0;
+
     /// <summary>
     /// <summary>
     ///     Justifies the <paramref name="sizes"/> within a container <see cref="totalSize"/> wide based on the specified
     ///     Justifies the <paramref name="sizes"/> within a container <see cref="totalSize"/> wide based on the specified
     ///     <see cref="Justification"/>.
     ///     <see cref="Justification"/>.
@@ -67,9 +90,12 @@ public class Justifier
     /// <param name="justification"></param>
     /// <param name="justification"></param>
     /// <param name="totalSize"></param>
     /// <param name="totalSize"></param>
     /// <returns></returns>
     /// <returns></returns>
-    public static int [] Justify (int [] sizes, Justification justification, int totalSize)
+    public int [] Justify (int [] sizes, Justification justification, int totalSize)
     {
     {
-        var positions = new int [sizes.Length];
+        if (sizes.Length == 0)
+        {
+            return new int []{};
+        }
         int totalItemsSize = sizes.Sum ();
         int totalItemsSize = sizes.Sum ();
 
 
         if (totalItemsSize > totalSize)
         if (totalItemsSize > totalSize)
@@ -77,6 +103,21 @@ public class Justifier
             throw new ArgumentException ("The sum of the sizes is greater than the total size.");
             throw new ArgumentException ("The sum of the sizes is greater than the total size.");
         }
         }
 
 
+        var positions = new int [sizes.Length];
+        totalItemsSize = sizes.Sum (); // total size of items
+        int totalGaps = sizes.Length - 1; // total gaps (MinimumSpaceBetweenItems)
+        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 >= totalSize)
+        {
+            spaces = 0;
+        }
+        else if (totalItemsAndSpaces > totalSize)
+        {
+            spaces = totalSize - totalItemsSize;
+        }
+
+
         switch (justification)
         switch (justification)
         {
         {
             case Justification.Left:
             case Justification.Left:
@@ -89,13 +130,21 @@ public class Justifier
                         throw new ArgumentException ("The size of an item cannot be negative.");
                         throw new ArgumentException ("The size of an item cannot be negative.");
                     }
                     }
 
 
-                    positions [i] = currentPosition;
-                    currentPosition += sizes [i];
+                    if (i == 0)
+                    {
+                        positions [0] = 0; // first item position
+                        continue;
+                    }
+
+                    var spaceBefore = spaces-- > 0 ? MaxSpaceBetweenItems : 0;
+
+                    // subsequent items are placed one space after the previous item
+                    positions [i] = positions [i - 1] + sizes [i - 1] + spaceBefore;
                 }
                 }
 
 
                 break;
                 break;
             case Justification.Right:
             case Justification.Right:
-                currentPosition = totalSize - totalItemsSize;
+                currentPosition = Math.Max (0, totalSize - totalItemsSize - spaces);
 
 
                 for (var i = 0; i < sizes.Length; i++)
                 for (var i = 0; i < sizes.Length; i++)
                 {
                 {
@@ -104,8 +153,10 @@ public class Justifier
                         throw new ArgumentException ("The size of an item cannot be negative.");
                         throw new ArgumentException ("The size of an item cannot be negative.");
                     }
                     }
 
 
+                    var spaceBefore = spaces-- > 0 ? MaxSpaceBetweenItems : 0;
+
                     positions [i] = currentPosition;
                     positions [i] = currentPosition;
-                    currentPosition += sizes [i];
+                    currentPosition += sizes [i] + spaceBefore;
                 }
                 }
 
 
                 break;
                 break;
@@ -113,44 +164,35 @@ public class Justifier
             case Justification.Centered:
             case Justification.Centered:
                 if (sizes.Length > 1)
                 if (sizes.Length > 1)
                 {
                 {
-                    totalItemsSize = sizes.Sum (); // total size of items
-                    int totalGaps = sizes.Length - 1; // total gaps (0 or 1 space)
-                    int totalItemsAndSpaces = totalItemsSize + totalGaps; // total size of items and spaces
+                    // remaining space to be distributed before first and after the items
+                    int remainingSpace = Math.Max(0, totalSize - totalItemsSize - spaces);
 
 
-                    int spaces = totalGaps;
-
-                    if (totalItemsSize >= totalSize)
-                    {
-                        spaces = 0;
-                    } 
-                    else if (totalItemsAndSpaces > totalSize)
+                    for (var i = 0; i < sizes.Length; i++)
                     {
                     {
-                        spaces = totalItemsAndSpaces - totalSize;
-                    }
-
-                    int remainingSpace = Math.Max(0, totalSize - totalItemsSize - spaces); // remaining space to be distributed before and after the items
-                    int spaceBefore = remainingSpace / 2; // space before the items
+                        if (sizes [i] < 0)
+                        {
+                            throw new ArgumentException ("The size of an item cannot be negative.");
+                        }
 
 
-                    positions [0] = spaceBefore; // first item position
-                    for (var i = 1; i < sizes.Length; i++)
-                    {
-                        int aSpace = 0;
-                        if (spaces > 0)
+                        if (i == 0)
                         {
                         {
-                            spaces--;
-                            aSpace = 1;
+                            positions [i] = remainingSpace / 2; // first item position
+
+                            continue;
                         }
                         }
+
+                        var spaceBefore = spaces-- > 0 ? MaxSpaceBetweenItems : 0;
+
                         // subsequent items are placed one space after the previous item
                         // subsequent items are placed one space after the previous item
-                        positions [i] = positions [i - 1] + sizes [i - 1] + aSpace;
-                    }
-                    // Adjust the last position if there is an extra space
-                    if (positions [sizes.Length - 1] + sizes [sizes.Length - 1] > totalSize)
-                    {
-                        positions [sizes.Length - 1]--;
+                        positions [i] = positions [i - 1] + sizes [i - 1] + spaceBefore;
                     }
                     }
                 }
                 }
                 else if (sizes.Length == 1)
                 else if (sizes.Length == 1)
                 {
                 {
+                    if (sizes [0] < 0)
+                    {
+                        throw new ArgumentException ("The size of an item cannot be negative.");
+                    }
                     positions [0] = (totalSize - sizes [0]) / 2; // single item is centered
                     positions [0] = (totalSize - sizes [0]) / 2; // single item is centered
                 }
                 }
                 break;
                 break;
@@ -172,46 +214,74 @@ public class Justifier
                 }
                 }
                 break;
                 break;
 
 
-            case Justification.LeftJustified:
+            /// 111 2222        33333
+            case Justification.OneRightRestLeft:
                 if (sizes.Length > 1)
                 if (sizes.Length > 1)
                 {
                 {
-                    int spaceBetweenLeft = totalSize - sizes.Sum () + 1; // +1 for the extra space
                     currentPosition = 0;
                     currentPosition = 0;
-                    for (var i = 0; i < sizes.Length - 1; i++)
+                    for (var i = 0; i < sizes.Length; i++)
                     {
                     {
                         if (sizes [i] < 0)
                         if (sizes [i] < 0)
                         {
                         {
                             throw new ArgumentException ("The size of an item cannot be negative.");
                             throw new ArgumentException ("The size of an item cannot be negative.");
                         }
                         }
-                        positions [i] = currentPosition;
-                        currentPosition += sizes [i] + 1; // +1 for the extra space
+
+                        if (i < sizes.Length - 1)
+                        {
+                            var spaceBefore = spaces-- > 0 ? MaxSpaceBetweenItems : 0;
+
+                            positions [i] = currentPosition;
+                            currentPosition += sizes [i] + spaceBefore; 
+                        }
                     }
                     }
                     positions [sizes.Length - 1] = totalSize - sizes [sizes.Length - 1];
                     positions [sizes.Length - 1] = totalSize - sizes [sizes.Length - 1];
                 }
                 }
                 else if (sizes.Length == 1)
                 else if (sizes.Length == 1)
                 {
                 {
-                    positions [0] = 0;
+                    if (sizes [0] < 0)
+                    {
+                        throw new ArgumentException ("The size of an item cannot be negative.");
+                    }
+                    positions [0] = totalSize - sizes [0]; // single item is flush right
                 }
                 }
                 break;
                 break;
 
 
-            case Justification.RightJustified:
+            /// 111        2222 33333
+            case Justification.OneLeftRestRight:
                 if (sizes.Length > 1)
                 if (sizes.Length > 1)
                 {
                 {
-                    totalItemsSize = sizes.Sum ();
-                    int totalSpaces = totalSize - totalItemsSize;
-                    int bigSpace = totalSpaces - (sizes.Length - 2);
-
-                    positions [0] = 0; // first item is flush left
-                    positions [1] = sizes [0] + bigSpace; // second item has the big space before it
+                    currentPosition = 0;
+                    positions [0] = currentPosition; // first item is flush left
 
 
-                    // remaining items have one space between them
-                    for (var i = 2; i < sizes.Length; i++)
+                    for (var i = sizes.Length - 1 ; i >= 0; i--)
                     {
                     {
-                        positions [i] = positions [i - 1] + sizes [i - 1] + 1;
+                        if (sizes [i] < 0)
+                        {
+                            throw new ArgumentException ("The size of an item cannot be negative.");
+                        }
+
+                        if (i == sizes.Length - 1)
+                        {
+                            // start at right
+                            currentPosition = totalSize - sizes [i];
+                            positions [i] = currentPosition;
+                        }
+
+                        if (i < sizes.Length - 1 && i > 0)
+                        {
+                            var spaceBefore = spaces-- > 0 ? MaxSpaceBetweenItems : 0;
+
+                            positions [i] = currentPosition - sizes [i] - spaceBefore;
+                            currentPosition -= sizes [i + 1];
+                        }
                     }
                     }
                 }
                 }
                 else if (sizes.Length == 1)
                 else if (sizes.Length == 1)
                 {
                 {
+                    if (sizes [0] < 0)
+                    {
+                        throw new ArgumentException ("The size of an item cannot be negative.");
+                    }
                     positions [0] = 0; // single item is flush left
                     positions [0] = 0; // single item is flush left
                 }
                 }
                 break;
                 break;

+ 282 - 98
UnitTests/Drawing/JustifierTests.cs

@@ -10,77 +10,199 @@ public class JustifierTests (ITestOutputHelper output)
 
 
     private readonly ITestOutputHelper _output = output;
     private readonly ITestOutputHelper _output = output;
 
 
-    [Fact]
-    public void TestLeftJustification ()
+    public static IEnumerable<object []> JustificationEnumValues ()
     {
     {
-        int [] sizes = { 10, 20, 30 };
-        var positions = Justifier.Justify (sizes, Justification.Left, 100);
-        Assert.Equal (new List<int> { 0, 10, 30 }, positions);
+        foreach (var number in Enum.GetValues (typeof (Justification)))
+        {
+            yield return new object [] { number };
+        }
     }
     }
 
 
-    [Fact]
-    public void TestRightJustification ()
+    [Theory]
+    [MemberData (nameof (JustificationEnumValues))]
+    public void NoItems_Works (Justification justification)
     {
     {
-        int [] sizes = { 10, 20, 30 };
-        var positions = Justifier.Justify (sizes, Justification.Right, 100);
-        Assert.Equal (new List<int> { 40, 50, 70 }, positions);
+        int [] sizes = { };
+        var positions = new Justifier ().Justify (sizes, justification, 100);
+        Assert.Equal (new int [] { }, positions);
     }
     }
 
 
-    [Fact]
-    public void TestCenterJustification ()
+    [Theory]
+    [MemberData (nameof (JustificationEnumValues))]
+    public void Items_Width_Cannot_Exceed_TotalSize (Justification justification)
     {
     {
-        int [] sizes = { 10, 20, 30 };
-        var positions = Justifier.Justify (sizes, Justification.Centered, 100);
-        Assert.Equal (new List<int> { 20, 30, 50 }, positions);
+        int [] sizes = { 1000, 2000, 3000 };
+        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (sizes, justification, 100));
     }
     }
 
 
-    [Fact]
-    public void TestJustifiedJustification ()
+    [Theory]
+    [MemberData (nameof (JustificationEnumValues))]
+    public void Negative_Widths_Not_Allowed (Justification justification)
     {
     {
-        int [] sizes = { 10, 20, 30 };
-        var positions = Justifier.Justify (sizes, Justification.Justified, 100);
-        Assert.Equal (new List<int> { 0, 30, 70 }, positions);
+        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (new int [] { -10, 20, 30 }, justification, 100));
+        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (new int [] { 10, -20, 30 }, justification, 100));
+        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (new int [] { 10, 20, -30 }, justification, 100));
     }
     }
 
 
-    [Fact]
-    public void TestNoItems ()
-    {
-        int [] sizes = { };
-        var positions = Justifier.Justify (sizes, Justification.Left, 100);
-        Assert.Equal (new int [] { }, positions);
-    }
+    [Theory]
+    [InlineData (Justification.Left, new int [] { 0 }, 1, new int [] { 0 })]
+    [InlineData (Justification.Left, new int [] { 0, 0 }, 1, new int [] { 0, 1 })]
+    [InlineData (Justification.Left, new int [] { 0, 0, 0 }, 1, new int [] { 0, 1, 1 })]
+    [InlineData (Justification.Left, new int [] { 1 }, 1, new int [] { 0 })]
+    [InlineData (Justification.Left, new int [] { 1 }, 2, new int [] { 0 })]
+    [InlineData (Justification.Left, new int [] { 1 }, 3, new int [] { 0 })]
+    [InlineData (Justification.Left, new int [] { 1, 1 }, 2, new int [] { 0, 1 })]
+    [InlineData (Justification.Left, new int [] { 1, 1 }, 3, new int [] { 0, 2 })]
+    [InlineData (Justification.Left, new int [] { 1, 1 }, 4, new int [] { 0, 2 })]
+    [InlineData (Justification.Left, new int [] { 1, 1, 1 }, 3, new int [] { 0, 1, 2 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3 }, 7, new int [] { 0, 2, 4 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3 }, 10, new int [] { 0, 2, 5 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3 }, 11, new int [] { 0, 2, 5 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3 }, 12, new int [] { 0, 2, 5 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3 }, 13, new int [] { 0, 2, 5 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    [InlineData (Justification.Left, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 2, 4, 7 })]
+    [InlineData (Justification.Left, new int [] { 33, 33, 33 }, 100, new int [] { 0, 34, 67 })]
+    [InlineData (Justification.Left, new int [] { 10 }, 101, new int [] { 0 })]
+    [InlineData (Justification.Left, new int [] { 10, 20 }, 101, new int [] { 0, 11 })]
+    [InlineData (Justification.Left, new int [] { 10, 20, 30 }, 100, new int [] { 0, 11, 32 })]
+    [InlineData (Justification.Left, new int [] { 10, 20, 30 }, 101, new int [] { 0, 11, 32 })]
+    [InlineData (Justification.Left, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
+    [InlineData (Justification.Left, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
 
 
-    [Fact]
-    public void TestTenItems ()
-    {
-        int [] sizes = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };
-        var positions = Justifier.Justify (sizes, Justification.Left, 100);
-        Assert.Equal (new int [] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 }, positions);
-    }
+    [InlineData (Justification.Right, new int [] { 0 }, 1, new int [] { 1 })]
+    [InlineData (Justification.Right, new int [] { 0, 0 }, 1, new int [] { 0, 1 })]
+    [InlineData (Justification.Right, new int [] { 0, 0, 0 }, 1, new int [] { 0, 1, 1 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3 }, 7, new int [] { 0, 2, 4 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3 }, 10, new int [] { 2, 4, 7 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3 }, 11, new int [] { 3, 5, 8 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3 }, 12, new int [] { 4, 6, 9 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3 }, 13, new int [] { 5, 7, 10 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    [InlineData (Justification.Right, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 2, 4, 7 })]
+    [InlineData (Justification.Right, new int [] { 10, 20, 30 }, 100, new int [] { 38, 49, 70 })]
+    [InlineData (Justification.Right, new int [] { 33, 33, 33 }, 100, new int [] { 0, 34, 67 })]
+    [InlineData (Justification.Right, new int [] { 10 }, 101, new int [] { 91 })]
+    [InlineData (Justification.Right, new int [] { 10, 20 }, 101, new int [] { 70, 81 })]
+    [InlineData (Justification.Right, new int [] { 10, 20, 30 }, 101, new int [] { 39, 50, 71 })]
+    [InlineData (Justification.Right, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
+    [InlineData (Justification.Right, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
 
 
-    [Fact]
-    public void TestZeroLengthItems ()
-    {
-        int [] sizes = { 0, 0, 0 };
-        var positions = Justifier.Justify (sizes, Justification.Left, 100);
-        Assert.Equal (new int [] { 0, 0, 0 }, positions);
-    }
+    [InlineData (Justification.Centered, new int [] { 0 }, 1, new int [] { 0 })]
+    [InlineData (Justification.Centered, new int [] { 0, 0 }, 1, new int [] { 0, 1 })]
+    [InlineData (Justification.Centered, new int [] { 0, 0, 0 }, 1, new int [] { 0, 1, 1 })]
+    [InlineData (Justification.Centered, new int [] { 1 }, 1, new int [] { 0 })]
+    [InlineData (Justification.Centered, new int [] { 1 }, 2, new int [] { 0 })]
+    [InlineData (Justification.Centered, new int [] { 1 }, 3, new int [] { 1 })]
+    [InlineData (Justification.Centered, new int [] { 1, 1 }, 2, new int [] { 0, 1 })]
+    [InlineData (Justification.Centered, new int [] { 1, 1 }, 3, new int [] { 0, 2 })]
+    [InlineData (Justification.Centered, new int [] { 1, 1 }, 4, new int [] { 0, 2 })]
+    [InlineData (Justification.Centered, new int [] { 1, 1, 1 }, 3, new int [] { 0, 1, 2 })]
+    [InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    [InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 7, new int [] { 0, 2, 4 })]
+    [InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 10, new int [] { 1, 3, 6 })]
+    [InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 11, new int [] { 1, 3, 6 })]
+    [InlineData (Justification.Centered, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    [InlineData (Justification.Centered, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 2, 4, 7 })]
+    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 9, new int [] { 0, 3, 6 })]
+    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 10, new int [] { 0, 4, 7 })]
+    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 11, new int [] { 0, 4, 8 })]
+    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 12, new int [] { 0, 4, 8 })]
+    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 13, new int [] { 1, 5, 9 })]
+    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 100, new int [] { 0, 34, 67 })]
+    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 101, new int [] { 0, 34, 68 })]
+    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 102, new int [] { 0, 34, 68 })]
+    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 103, new int [] { 1, 35, 69 })]
+    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 104, new int [] { 1, 35, 69 })]
+    [InlineData (Justification.Centered, new int [] { 10 }, 101, new int [] { 45 })]
+    [InlineData (Justification.Centered, new int [] { 10, 20 }, 101, new int [] { 35, 46 })]
+    [InlineData (Justification.Centered, new int [] { 10, 20, 30 }, 100, new int [] { 19, 30, 51 })]
+    [InlineData (Justification.Centered, new int [] { 10, 20, 30 }, 101, new int [] { 19, 30, 51 })]
+    [InlineData (Justification.Centered, new int [] { 10, 20, 30, 40 }, 100, new int [] { 0, 10, 30, 60 })]
+    [InlineData (Justification.Centered, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
+    [InlineData (Justification.Centered, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
+    [InlineData (Justification.Centered, new int [] { 3, 4, 5, 6 }, 25, new int [] { 2, 6, 11, 17 })]
 
 
-    [Fact]
-    public void TestLongItems ()
-    {
-        int [] sizes = { 1000, 2000, 3000 };
-        Assert.Throws<ArgumentException> (() => Justifier.Justify (sizes, Justification.Left, 100));
-    }
+    [InlineData (Justification.Justified, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
+    [InlineData (Justification.Justified, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
+    [InlineData (Justification.Justified, new int [] { 10, 20, 30 }, 100, new int [] { 0, 30, 70 })]
+    [InlineData (Justification.Justified, new int [] { 10, 20, 30 }, 101, new int [] { 0, 31, 71 })]
+    [InlineData (Justification.Justified, new int [] { 33, 33, 33 }, 100, new int [] { 0, 34, 67 })]
+    [InlineData (Justification.Justified, new int [] { 11, 17, 23 }, 100, new int [] { 0, 36, 77 })]
+    [InlineData (Justification.Justified, new int [] { 1, 2, 3 }, 11, new int [] { 0, 4, 8 })]
+    [InlineData (Justification.Justified, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
+    [InlineData (Justification.Justified, new int [] { 10 }, 101, new int [] { 0 })]
+    [InlineData (Justification.Justified, new int [] { 3, 3, 3 }, 21, new int [] { 0, 9, 18 })]
+    [InlineData (Justification.Justified, new int [] { 3, 4, 5 }, 21, new int [] { 0, 8, 16 })]
+    [InlineData (Justification.Justified, new int [] { 3, 4, 5, 6 }, 18, new int [] { 0, 3, 7, 12 })]
+    [InlineData (Justification.Justified, new int [] { 3, 4, 5, 6 }, 19, new int [] { 0, 4, 8, 13 })]
+    [InlineData (Justification.Justified, new int [] { 3, 4, 5, 6 }, 20, new int [] { 0, 4, 9, 14 })]
+    [InlineData (Justification.Justified, new int [] { 3, 4, 5, 6 }, 21, new int [] { 0, 4, 9, 15 })]
+    [InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 22, new int [] { 0, 8, 14, 19 })]
+    [InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 23, new int [] { 0, 8, 15, 20, })]
+    [InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 24, new int [] { 0, 8, 15, 21 })]
+    [InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 25, new int [] { 0, 9, 16, 22 })]
+    [InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 26, new int [] { 0, 9, 17, 23 })]
+    [InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 31, new int [] { 0, 11, 20, 28 })]
+
+    [InlineData (Justification.OneRightRestLeft, new int [] { 0 }, 1, new int [] { 0 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 0, 0 }, 1, new int [] { 0, 1 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 0, 0, 0 }, 1, new int [] { 0, 1, 1 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1 }, 1, new int [] { 0 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1 }, 2, new int [] { 0 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1 }, 3, new int [] { 0 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 1 }, 2, new int [] { 0, 1 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 1 }, 3, new int [] { 0, 2 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 1 }, 4, new int [] { 0, 3 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 1, 1 }, 3, new int [] { 0, 1, 2 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 7, new int [] { 0, 2, 4 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 8, new int [] { 0, 2, 5 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 9, new int [] { 0, 2, 6 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 10, new int [] { 0, 2, 7 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 11, new int [] { 0, 2, 8 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 2, 4, 7 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 3, 3, 3 }, 21, new int [] { 0, 4, 18 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 3, 4, 5 }, 21, new int [] { 0, 4, 16 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 33, 33, 33 }, 100, new int [] { 0, 34, 67 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 10 }, 101, new int [] { 0 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30 }, 100, new int [] { 0, 11, 70 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30 }, 101, new int [] { 0, 11, 71 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
+    [InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
+
+    //[InlineData (Justification.SplitLeft, new int [] { 10, 20, 30 }, 100, new int [] { 0, 49, 70 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 67 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 10 }, 101, new int [] { 0 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 10, 20, 30 }, 101, new int [] { 0, 50, 71 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 9, 30, 61 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 8, 29, 60, 101 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 3, 3, 3 }, 21, new int [] { 0, 14, 18 })]
+    //[InlineData (Justification.SplitLeft, new int [] { 3, 4, 5 }, 21, new int [] { 0, 11, 16 })]
 
 
-    [Fact]
-    public void TestNegativeLengths ()
+    public void TestJustifications_1Space (Justification justification, int [] sizes, int totalSize, int [] expected)
     {
     {
-        int [] sizes = { -10, -20, -30 };
-        Assert.Throws<ArgumentException> (() => Justifier.Justify (sizes, Justification.Left, 100));
+        var positions = new Justifier () { MaxSpaceBetweenItems = 1 }.Justify (sizes, justification, totalSize);
+        AssertJustification (justification, sizes, totalSize, positions, expected);
     }
     }
 
 
     [Theory]
     [Theory]
+    //[InlineData (Justification.Left, new int [] { 0 }, 1, new int [] { 0 })]
+    //[InlineData (Justification.Left, new int [] { 0, 0 }, 1, new int [] { 0, 0 })]
+    //[InlineData (Justification.Left, new int [] { 0, 0, 0 }, 1, new int [] { 0, 0, 0 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3 }, 7, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3 }, 10, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3 }, 11, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3 }, 12, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3 }, 13, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    //[InlineData (Justification.Left, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 1, 3, 6 })]
     //[InlineData (Justification.Left, new int [] { 10, 20, 30 }, 100, new int [] { 0, 10, 30 })]
     //[InlineData (Justification.Left, new int [] { 10, 20, 30 }, 100, new int [] { 0, 10, 30 })]
     //[InlineData (Justification.Left, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 66 })]
     //[InlineData (Justification.Left, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 66 })]
     //[InlineData (Justification.Left, new int [] { 10 }, 101, new int [] { 0 })]
     //[InlineData (Justification.Left, new int [] { 10 }, 101, new int [] { 0 })]
@@ -89,6 +211,17 @@ public class JustifierTests (ITestOutputHelper output)
     //[InlineData (Justification.Left, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 10, 30, 60 })]
     //[InlineData (Justification.Left, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 10, 30, 60 })]
     //[InlineData (Justification.Left, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 10, 30, 60, 100 })]
     //[InlineData (Justification.Left, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 10, 30, 60, 100 })]
 
 
+    //[InlineData (Justification.Right, new int [] { 0 }, 1, new int [] { 1 })]
+    //[InlineData (Justification.Right, new int [] { 0, 0 }, 1, new int [] { 1, 1 })]
+    //[InlineData (Justification.Right, new int [] { 0, 0, 0 }, 1, new int [] { 1, 1, 1 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3 }, 7, new int [] { 1, 2, 4 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3 }, 10, new int [] { 4, 5, 7 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3 }, 11, new int [] { 5, 6, 8 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3 }, 12, new int [] { 6, 7, 9 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3 }, 13, new int [] { 7, 8, 10 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    //[InlineData (Justification.Right, new int [] { 1, 2, 3, 4 }, 11, new int [] { 1, 2, 4, 7 })]
     //[InlineData (Justification.Right, new int [] { 10, 20, 30 }, 100, new int [] { 40, 50, 70 })]
     //[InlineData (Justification.Right, new int [] { 10, 20, 30 }, 100, new int [] { 40, 50, 70 })]
     //[InlineData (Justification.Right, new int [] { 33, 33, 33 }, 100, new int [] { 1, 34, 67 })]
     //[InlineData (Justification.Right, new int [] { 33, 33, 33 }, 100, new int [] { 1, 34, 67 })]
     //[InlineData (Justification.Right, new int [] { 10 }, 101, new int [] { 91 })]
     //[InlineData (Justification.Right, new int [] { 10 }, 101, new int [] { 91 })]
@@ -97,21 +230,30 @@ public class JustifierTests (ITestOutputHelper output)
     //[InlineData (Justification.Right, new int [] { 10, 20, 30, 40 }, 101, new int [] { 1, 11, 31, 61 })]
     //[InlineData (Justification.Right, new int [] { 10, 20, 30, 40 }, 101, new int [] { 1, 11, 31, 61 })]
     //[InlineData (Justification.Right, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 1, 11, 31, 61, 101 })]
     //[InlineData (Justification.Right, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 1, 11, 31, 61, 101 })]
 
 
-    [InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 10, new int [] { 1, 3, 6 })]
-    [InlineData (Justification.Centered, new int [] { 10, 20, 30 }, 100, new int [] { 19, 30, 51 })]
-    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 9, new int [] { 0, 3, 6 })]
-    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 10, new int [] { 0, 4, 7 })]
-    [InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 11, new int [] { 0, 4, 8 })]
-    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 66 })]
-    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 101, new int [] { 1, 34, 67 })]
-    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 102, new int [] { 1, 34, 67 })]
-    [InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 104, new int [] { 2, 35, 68 })]
-    [InlineData (Justification.Centered, new int [] { 10 }, 101, new int [] { 45 })]
-    [InlineData (Justification.Centered, new int [] { 10, 20 }, 101, new int [] { 35, 45 })]
-    [InlineData (Justification.Centered, new int [] { 10, 20, 30 }, 101, new int [] { 20, 30, 50 })]
-    [InlineData (Justification.Centered, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 10, 30, 60 })]
-    [InlineData (Justification.Centered, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 10, 30, 60, 100 })]
-    [InlineData (Justification.Centered, new int [] { 3, 4, 5, 6 }, 25, new int [] { 2, 6, 11, 17 })]
+    //[InlineData (Justification.Centered, new int [] { 1 }, 1, new int [] { 0 })]
+    //[InlineData (Justification.Centered, new int [] { 1 }, 2, new int [] { 0 })]
+    //[InlineData (Justification.Centered, new int [] { 1 }, 3, new int [] { 1 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 1 }, 2, new int [] { 0, 1 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 1 }, 3, new int [] { 0, 1 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 1 }, 4, new int [] { 1, 2 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 1, 1 }, 3, new int [] { 0, 1, 2 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 7, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 10, new int [] { 2, 3, 5 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 2, 3 }, 11, new int [] { 2, 3, 5 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    //[InlineData (Justification.Centered, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 1, 3, 6 })]
+    //[InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 9, new int [] { 0, 3, 6 })]
+    //[InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 10, new int [] { 0, 3, 6 })]
+    //[InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 11, new int [] { 1, 4, 7 })]
+    //[InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 12, new int [] { 1, 4, 7 })]
+    //[InlineData (Justification.Centered, new int [] { 3, 3, 3 }, 13, new int [] { 2, 5, 8 })]
+    //[InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 66 })]
+    //[InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 101, new int [] { 1, 34, 67 })]
+    //[InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 102, new int [] { 1, 34, 67 })]
+    //[InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 103, new int [] { 2, 35, 68 })]
+    //[InlineData (Justification.Centered, new int [] { 33, 33, 33 }, 104, new int [] { 2, 35, 68 })]
+    //[InlineData (Justification.Centered, new int [] { 3, 4, 5, 6 }, 25, new int [] { 3, 6, 10, 15 })]
 
 
     //[InlineData (Justification.Justified, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
     //[InlineData (Justification.Justified, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 31, 61, 101 })]
     //[InlineData (Justification.Justified, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
     //[InlineData (Justification.Justified, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 31, 61 })]
@@ -135,29 +277,70 @@ public class JustifierTests (ITestOutputHelper output)
     //[InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 26, new int [] { 0, 9, 17, 23 })]
     //[InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 26, new int [] { 0, 9, 17, 23 })]
     //[InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 31, new int [] { 0, 11, 20, 28 })]
     //[InlineData (Justification.Justified, new int [] { 6, 5, 4, 3 }, 31, new int [] { 0, 11, 20, 28 })]
 
 
-    //[InlineData (Justification.LeftJustified, new int [] { 10, 20, 30 }, 100, new int [] { 0, 11, 70 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 33, 33, 33 }, 100, new int [] { 0, 34, 67 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 10 }, 101, new int [] { 0 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 10, 20, 30 }, 101, new int [] { 0, 11, 71 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 11, 32, 61 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 11, 32, 63, 101 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 3, 3, 3 }, 21, new int [] { 0, 4, 18 })]
-    //[InlineData (Justification.LeftJustified, new int [] { 3, 4, 5 }, 21, new int [] { 0, 4, 16 })]
-
-    //[InlineData (Justification.RightJustified, new int [] { 10, 20, 30 }, 100, new int [] { 0, 49, 70 })]
-    //[InlineData (Justification.RightJustified, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 67 })]
-    //[InlineData (Justification.RightJustified, new int [] { 10 }, 101, new int [] { 0 })]
-    //[InlineData (Justification.RightJustified, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
-    //[InlineData (Justification.RightJustified, new int [] { 10, 20, 30 }, 101, new int [] { 0, 50, 71 })]
-    //[InlineData (Justification.RightJustified, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 9, 30, 61 })]
-    //[InlineData (Justification.RightJustified, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 8, 29, 60, 101 })]
-    //[InlineData (Justification.RightJustified, new int [] { 3, 3, 3 }, 21, new int [] { 0, 14, 18 })]
-    //[InlineData (Justification.RightJustified, new int [] { 3, 4, 5 }, 21, new int [] { 0, 11, 16 })]
-
-    public void TestJustifications (Justification justification, int [] sizes, int totalSize, int [] expected)
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 0 }, 1, new int [] { 0 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 0, 0 }, 1, new int [] { 0, 1 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 0, 0, 0 }, 1, new int [] { 0, 0, 1 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1 }, 1, new int [] { 0 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1 }, 2, new int [] { 0 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1 }, 3, new int [] { 0 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 1 }, 2, new int [] { 0, 1 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 1 }, 3, new int [] { 0, 2 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 1 }, 4, new int [] { 0, 3 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 1, 1 }, 3, new int [] { 0, 1, 2 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 7, new int [] { 0, 1, 4 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 8, new int [] { 0, 1, 5 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 9, new int [] { 0, 1, 6 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 10, new int [] { 0, 1, 7 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3 }, 11, new int [] { 0, 1, 8 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 1, 3, 7 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 1, 2, 3, 4 }, 12, new int [] { 0, 1, 3, 8 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 3, 3, 3 }, 21, new int [] { 0, 3, 18 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 3, 4, 5 }, 21, new int [] { 0, 3, 16 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 67 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 10 }, 101, new int [] { 0 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30 }, 100, new int [] { 0, 10, 70 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30 }, 101, new int [] { 0, 10, 71 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 10, 30, 61 })]
+    //[InlineData (Justification.OneRightRestLeft, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 10, 30, 60, 101, })]
+
+
+    [InlineData (Justification.OneLeftRestRight, new int [] { 0 }, 1, new int [] { 0 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 0, 0 }, 1, new int [] { 0, 1 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 0, 0, 0 }, 1, new int [] { 0, 1, 1 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1 }, 1, new int [] { 0 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1 }, 2, new int [] { 1 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1 }, 3, new int [] { 2 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 1 }, 2, new int [] { 0, 1 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 1 }, 3, new int [] { 0, 2 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 1 }, 4, new int [] { 0, 3 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 1, 1 }, 3, new int [] { 0, 1, 2 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3 }, 6, new int [] { 0, 1, 3 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3 }, 7, new int [] { 0, 2, 4 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3 }, 8, new int [] { 0, 3, 5 })]
+    [InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3 }, 9, new int [] { 0, 4, 6 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3 }, 10, new int [] { 0, 1, 7 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3 }, 11, new int [] { 0, 1, 8 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3, 4 }, 10, new int [] { 0, 1, 3, 6 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3, 4 }, 11, new int [] { 0, 1, 3, 7 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 1, 2, 3, 4 }, 12, new int [] { 0, 1, 3, 8 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 3, 3, 3 }, 21, new int [] { 0, 3, 18 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 3, 4, 5 }, 21, new int [] { 0, 3, 16 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 33, 33, 33 }, 100, new int [] { 0, 33, 67 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 10 }, 101, new int [] { 0 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 10, 20 }, 101, new int [] { 0, 81 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 10, 20, 30 }, 100, new int [] { 0, 10, 70 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 10, 20, 30 }, 101, new int [] { 0, 10, 71 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 10, 20, 30, 40 }, 101, new int [] { 0, 10, 30, 61 })]
+    //[InlineData (Justification.OneLeftRestRight, new int [] { 10, 20, 30, 40, 50 }, 151, new int [] { 0, 10, 30, 60, 101, })]
+
+
+
+    public void TestJustifications_0Space (Justification justification, int [] sizes, int totalSize, int [] expected)
     {
     {
-        var positions = Justifier.Justify (sizes, justification, totalSize);
+        var positions = new Justifier () { MaxSpaceBetweenItems = 0 }.Justify (sizes, justification, totalSize);
         AssertJustification (justification, sizes, totalSize, positions, expected);
         AssertJustification (justification, sizes, totalSize, positions, expected);
     }
     }
 
 
@@ -173,11 +356,11 @@ public class JustifierTests (ITestOutputHelper output)
             _output.WriteLine ($"Actual: {RenderJustification (justification, sizes, totalSize, positions)}");
             _output.WriteLine ($"Actual: {RenderJustification (justification, sizes, totalSize, positions)}");
         }
         }
 
 
-        if (!expected.SequenceEqual(positions))
+        if (!expected.SequenceEqual (positions))
         {
         {
             _output.WriteLine ($"Expected: {RenderJustification (justification, sizes, totalSize, expected)}");
             _output.WriteLine ($"Expected: {RenderJustification (justification, sizes, totalSize, expected)}");
             _output.WriteLine ($"Actual: {RenderJustification (justification, sizes, totalSize, positions)}");
             _output.WriteLine ($"Actual: {RenderJustification (justification, sizes, totalSize, positions)}");
-            Assert.Fail(" Expected and actual do not match");
+            Assert.Fail (" Expected and actual do not match");
         }
         }
     }
     }
 
 
@@ -201,19 +384,20 @@ public class JustifierTests (ITestOutputHelper output)
         var items = new char [totalSize];
         var items = new char [totalSize];
         for (int position = 0; position < positions.Length; position++)
         for (int position = 0; position < positions.Length; position++)
         {
         {
-            try
+            // try
             {
             {
-                for (int j = 0; j < sizes [position]; j++)
+                for (int j = 0; j < sizes [position] && positions [position] + j < totalSize; j++)
                 {
                 {
                     items [positions [position] + j] = (position + 1).ToString () [0];
                     items [positions [position] + j] = (position + 1).ToString () [0];
                 }
                 }
-            } catch(Exception e)
-            {
-                output.AppendLine ($"{e.Message} - position = {position}, positions[{position}]: {positions[position]}, sizes[{position}]: {sizes[position]}, totalSize: {totalSize}");
-                output.Append (new string (items).Replace ('\0', ' '));
-
-               Assert.Fail(e.Message + output.ToString ());
             }
             }
+            //catch (Exception e)
+            //{
+            //    output.AppendLine ($"{e.Message} - position = {position}, positions[{position}]: {positions [position]}, sizes[{position}]: {sizes [position]}, totalSize: {totalSize}");
+            //    output.Append (new string (items).Replace ('\0', ' '));
+
+            //    Assert.Fail (e.Message + output.ToString ());
+            //}
         }
         }
 
 
         output.Append (new string (items).Replace ('\0', ' '));
         output.Append (new string (items).Replace ('\0', ' '));