浏览代码

Messing with Pos.Justify

Tig 1 年之前
父节点
当前提交
a89ffaf6d0

+ 33 - 24
Terminal.Gui/Drawing/Justification.cs

@@ -85,17 +85,31 @@ public enum Justification
 /// </summary>
 public class Justifier
 {
-    private int _maxSpaceBetweenItems;
+    /// <summary>
+    /// 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.
+    /// </summary>
+    public int ContainerSize { get; set; }
 
     /// <summary>
     ///     Gets or sets whether <see cref="Justify"/> 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.
+    ///     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
+    ///     <see cref="Justification"/>.
     /// </summary>
-    public bool PutSpaceBetweenItems
+    /// <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)
     {
-        get => _maxSpaceBetweenItems == 1;
-        set => _maxSpaceBetweenItems = value ? 1 : 0;
+        return Justify (Justification, PutSpaceBetweenItems, ContainerSize, sizes);
     }
 
     /// <summary>
@@ -104,28 +118,23 @@ public class Justifier
     /// </summary>
     /// <param name="sizes">The sizes of the items to justify.</param>
     /// <param name="justification">The justification style.</param>
-    /// <param name="containerSize">The width of the container.</param>
+    /// <param name="containerSize">The size of the container.</param>
     /// <returns>The locations of the items, from left to right.</returns>
-    public int [] Justify (int [] sizes, Justification justification, int containerSize)
+    public static int [] Justify (Justification justification, bool putSpaceBetweenItems, int containerSize, int [] sizes)
     {
         if (sizes.Length == 0)
         {
             return new int [] { };
         }
 
-        int totalItemsSize = sizes.Sum ();
-
-        if (totalItemsSize > containerSize)
-        {
-           // throw new ArgumentException ("The sum of the sizes is greater than the total size.");
-        }
+        int maxSpaceBetweenItems = putSpaceBetweenItems ? 1 : 0;
 
-        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
+        var positions = new int [sizes.Length]; // positions of the items. the return value.
+        int totalItemsSize = sizes.Sum ();
+        int totalGaps = sizes.Length - 1; // total gaps between items
+        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;
@@ -154,7 +163,7 @@ public class Justifier
                         continue;
                     }
 
-                    int spaceBefore = spaces-- > 0 ? _maxSpaceBetweenItems : 0;
+                    int spaceBefore = spaces-- > 0 ? maxSpaceBetweenItems : 0;
 
                     // subsequent items are placed one space after the previous item
                     positions [i] = positions [i - 1] + sizes [i - 1] + spaceBefore;
@@ -171,7 +180,7 @@ public class Justifier
                         throw new ArgumentException ("The size of an item cannot be negative.");
                     }
 
-                    int spaceBefore = spaces-- > 0 ? _maxSpaceBetweenItems : 0;
+                    int spaceBefore = spaces-- > 0 ? maxSpaceBetweenItems : 0;
 
                     positions [i] = currentPosition;
                     currentPosition += sizes [i] + spaceBefore;
@@ -199,7 +208,7 @@ public class Justifier
                             continue;
                         }
 
-                        int spaceBefore = spaces-- > 0 ? _maxSpaceBetweenItems : 0;
+                        int spaceBefore = spaces-- > 0 ? maxSpaceBetweenItems : 0;
 
                         // subsequent items are placed one space after the previous item
                         positions [i] = positions [i - 1] + sizes [i - 1] + spaceBefore;
@@ -251,7 +260,7 @@ public class Justifier
 
                         if (i < sizes.Length - 1)
                         {
-                            int spaceBefore = spaces-- > 0 ? _maxSpaceBetweenItems : 0;
+                            int spaceBefore = spaces-- > 0 ? maxSpaceBetweenItems : 0;
 
                             positions [i] = currentPosition;
                             currentPosition += sizes [i] + spaceBefore;
@@ -295,7 +304,7 @@ public class Justifier
 
                         if (i < sizes.Length - 1 && i > 0)
                         {
-                            int spaceBefore = spaces-- > 0 ? _maxSpaceBetweenItems : 0;
+                            int spaceBefore = spaces-- > 0 ? maxSpaceBetweenItems : 0;
 
                             positions [i] = currentPosition - sizes [i] - spaceBefore;
                             currentPosition = positions [i];

+ 14 - 55
Terminal.Gui/View/Layout/PosDim.cs

@@ -469,7 +469,8 @@ public class Pos
     /// </summary>
     public class PosJustify : Pos
     {
-        private readonly Justification _justification;
+        internal readonly Justifier _justifier;
+        internal int? _location;
 
         /// <summary>
         /// Enables justification of a set of views.
@@ -478,81 +479,39 @@ public class Pos
         /// <param name="justification"></param>
         public PosJustify (Justification justification)
         {
-            _justification = justification;
+            _justifier = new ()
+            {
+                PutSpaceBetweenItems = false,
+                Justification = justification,
+            };
         }
 
         public override bool Equals (object other)
         {
-            return other is PosJustify justify && justify._justification == _justification;
+            return other is PosJustify justify && justify._justifier == _justifier;
         }
 
-        public override int GetHashCode () { return _justification.GetHashCode (); }
+        public override int GetHashCode () { return _justifier.GetHashCode (); }
 
 
         public override string ToString ()
         {
-            return $"Justify(alignment={_justification})";
+            return $"Justify(justification={_justifier.Justification})";
         }
 
         internal override int Anchor (int width)
         {
-            return width;
+            return _location ?? 0 - width;
         }
 
         internal override int Calculate (int superviewDimension, Dim dim, View us, Dim.Dimension dimension)
         {
-            if (us.SuperView is null)
-            {
-                return 0;
-            }
-            // Find all the views that are being justified - they have the same justification and opposite position as us
-            // Then, pass the array of views to the Justify method
-            int [] dimensions;
-            int [] positions;
-
-            int ourIndex = 0;
-            if (dimension == Dim.Dimension.Width)
-            {
-                List<int> dimensionsList = new List<int> ();
-                for (int i = 0; i < us.SuperView.Subviews.Count; i++)
-                {
-                    var v = us.SuperView.Subviews [i];
-                    var j = v.X as PosJustify;
-                    if (j?._justification == _justification && v.Frame.Y == us.Frame.Y)
-                    {
-                        dimensionsList.Add (v.Frame.Width);
-
-                        if (v == us)
-                        {
-                            ourIndex = dimensionsList.Count - 1;
-                        }
-                    }
-                }
-                dimensions = dimensionsList.ToArray ();
-                positions = new Justifier () { PutSpaceBetweenItems = true }.Justify (dimensions, _justification, superviewDimension);
-            }
-            else
+            if (_location.HasValue)
             {
-                List<int> dimensionsList = new List<int> ();
-                for (int i = 0; i < us.SuperView.Subviews.Count; i++)
-                {
-                    var v = us.SuperView.Subviews [i];
-                    var j = v.Y as PosJustify;
-                    if (j?._justification == _justification && v.Frame.X == us.Frame.X)
-                    {
-                        dimensionsList.Add (v.Frame.Height);
-
-                        if (v == us)
-                        {
-                            ourIndex = dimensionsList.Count - 1;
-                        }
-                    }
-                }
-                dimensions = dimensionsList.ToArray ();
-                positions = new Justifier () { PutSpaceBetweenItems = false }.Justify (dimensions, _justification, superviewDimension);
+                return _location.Value;
             }
 
-            return positions [ourIndex];
+            return 0;
         }
 
     }

+ 54 - 13
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using static Terminal.Gui.Pos;
 
 namespace Terminal.Gui;
 
@@ -850,13 +851,62 @@ public partial class View
 
         foreach (View v in ordered)
         {
-            // TODO: Move this logic into the Pos/Dim classes
+            var justifyX = v.X as PosJustify;
+            var justifyY = v.Y as PosJustify;
+
+            if (justifyX is { } || justifyY is { })
+            {
+                int xIndex = 0;
+                int yIndex = 0;
+                List<int> XdimensionsList = new ();
+                List<int> YdimensionsList = new ();
+                for (int i = 0; i < v.SuperView.Subviews.Count; i++)
+                {
+                    var viewI = v.SuperView.Subviews [i];
+
+                    var jX = viewI.X as PosJustify;
+                    var jY = viewI.Y as PosJustify;
+
+                    if (jX?._justifier.Justification == justifyX?._justifier.Justification && viewI.Frame.Y == v.Frame.Y)
+                    {
+                        XdimensionsList.Add (viewI.Frame.Width);
+
+                        if (viewI == v)
+                        {
+                            xIndex = XdimensionsList.Count - 1;
+                        }
+                    }
+
+                    if (jY?._justifier.Justification == justifyY?._justifier.Justification && viewI.Frame.X == v.Frame.X)
+                    {
+                        YdimensionsList.Add (viewI.Frame.Height);
+
+                        if (viewI == v)
+                        {
+                            yIndex = YdimensionsList.Count - 1;
+                        }
+                    }
+                }
 
+                if (justifyX is { })
+                {
+                    justifyX._justifier.ContainerSize = Viewport.Size.Width;
+                    justifyX._location = justifyX._justifier.Justify (XdimensionsList.ToArray ()) [xIndex];
+                }
+
+                if (justifyY is { })
+                {
+                    justifyY._justifier.ContainerSize = Viewport.Size.Height;
+                    justifyY._location = justifyY._justifier.Justify (YdimensionsList.ToArray ()) [yIndex];
+                }
+            }
+
+            // TODO: Move this logic into the Pos/Dim classes
             if (v.Width is Dim.DimAuto || v.Height is Dim.DimAuto)
             {
                 // If the view is auto-sized...
                 Rectangle f = v.Frame;
-                v._frame = new (v.Frame.X, v.Frame.Y, 0, 0);
+                v._frame = v.Frame with { Width = 0, Height = 0 };
                 LayoutSubview (v, Viewport.Size);
 
                 if (v.Frame != f)
@@ -1005,8 +1055,8 @@ public partial class View
         {
             //if (AutoSize)
             {
-            //    SetFrameToFitText ();
-               SetTextFormatterSize ();
+                //    SetFrameToFitText ();
+                SetTextFormatterSize ();
             }
 
             LayoutAdornments ();
@@ -1064,15 +1114,6 @@ public partial class View
 
         CheckDimAuto ();
 
-        SetTextFormatterSize ();
-
-        var autoSize = Size.Empty;
-
-        //if (AutoSize)
-        //{
-        //    // TODO: Nuke this from orbit once Dim.Auto is fully implemented
-        //    autoSize = GetTextAutoSize ();
-        //}
         SetTextFormatterSize ();
         if (TextFormatter.NeedsFormat)
         {

+ 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;

+ 2 - 1
UICatalog/Scenarios/Generic.cs

@@ -18,9 +18,10 @@ public sealed class MyScenario : Scenario
         };
 
         int leftMargin = 0;
-        var just = Justification.Justified;
+        var just = Justification.Centered;
 
         var button = new Button { X = Pos.Justify(just), Y = Pos.Center (), Text = "Press me!" };
+        //button.Margin.Thickness = new Thickness (leftMargin, 0, 0, 0);
         button.Accept += (s, e) => MessageBox.ErrorQuery ("Error", "You pressed the button!", "Ok");
         appWindow.Add (button);
 

+ 33 - 19
UnitTests/Drawing/JustifierTests.cs

@@ -19,26 +19,30 @@ public class JustifierTests (ITestOutputHelper output)
     [MemberData (nameof (JustificationEnumValues))]
     public void NoItems_Works (Justification justification)
     {
-        int [] sizes = { };
-        int [] positions = new Justifier ().Justify (sizes, justification, 100);
+        int [] sizes = [];
+        int [] positions = Justifier.Justify (justification, false, 100, sizes);
         Assert.Equal (new int [] { }, positions);
     }
 
-    //[Theory]
-    //[MemberData (nameof (JustificationEnumValues))]
-    //public void Items_Width_Cannot_Exceed_TotalSize (Justification justification)
-    //{
-    //    int [] sizes = { 1000, 2000, 3000 };
-    //    Assert.Throws<ArgumentException> (() => new Justifier ().Justify (sizes, justification, 100));
-    //}
-
     [Theory]
     [MemberData (nameof (JustificationEnumValues))]
     public void Negative_Widths_Not_Allowed (Justification justification)
     {
-        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (new [] { -10, 20, 30 }, justification, 100));
-        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (new [] { 10, -20, 30 }, justification, 100));
-        Assert.Throws<ArgumentException> (() => new Justifier ().Justify (new [] { 10, 20, -30 }, justification, 100));
+        Assert.Throws<ArgumentException> (() => new Justifier ()
+        {
+            Justification = justification,
+            ContainerSize = 100
+        }.Justify (new [] { -10, 20, 30 }));
+        Assert.Throws<ArgumentException> (() => new Justifier ()
+        {
+            Justification = justification,
+            ContainerSize = 100
+        }.Justify (new [] { 10, -20, 30 }));
+        Assert.Throws<ArgumentException> (() => new Justifier ()
+        {
+            Justification = justification,
+            ContainerSize = 100
+        }.Justify (new [] { 10, 20, -30 }));
     }
 
     [Theory]
@@ -197,10 +201,15 @@ public class JustifierTests (ITestOutputHelper output)
     [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 totalSize, int [] expected)
+    public void TestJustifications_PutSpaceBetweenItems (Justification justification, int [] sizes, int containerSize, int [] expected)
     {
-        int [] positions = new Justifier { PutSpaceBetweenItems = true }.Justify (sizes, justification, totalSize);
-        AssertJustification (justification, sizes, totalSize, positions, expected);
+        int [] positions = new Justifier
+        {
+            PutSpaceBetweenItems = true,
+            Justification = justification,
+            ContainerSize = containerSize
+        }.Justify (sizes);
+        AssertJustification (justification, sizes, containerSize, positions, expected);
     }
 
     [Theory]
@@ -341,10 +350,15 @@ public class JustifierTests (ITestOutputHelper output)
     [InlineData (Justification.FirstLeftRestRight, new [] { 10, 20, 30 }, 101, new [] { 0, 51, 71 })]
     [InlineData (Justification.FirstLeftRestRight, new [] { 10, 20, 30, 40 }, 101, new [] { 0, 11, 31, 61 })]
     [InlineData (Justification.FirstLeftRestRight, new [] { 10, 20, 30, 40, 50 }, 151, new [] { 0, 11, 31, 61, 101 })]
-    public void TestJustifications_NoSpaceBetweenItems (Justification justification, int [] sizes, int totalSize, int [] expected)
+    public void TestJustifications_NoSpaceBetweenItems (Justification justification, int [] sizes, int containerSize, int [] expected)
     {
-        int [] positions = new Justifier { PutSpaceBetweenItems = false }.Justify (sizes, justification, totalSize);
-        AssertJustification (justification, sizes, totalSize, positions, expected);
+        int [] positions = new Justifier
+        {
+            PutSpaceBetweenItems = false,
+            Justification = justification,
+            ContainerSize = containerSize
+        }.Justify (sizes);
+        AssertJustification (justification, sizes, containerSize, positions, expected);
     }
 
     public void AssertJustification (Justification justification, int [] sizes, int totalSize, int [] positions, int [] expected)