瀏覽代碼

WIP to get rid of Slider.AutoSize

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

+ 12 - 5
Terminal.Gui/View/Layout/PosDim.cs

@@ -939,11 +939,18 @@ public class Dim
 
             if (_style is Dim.DimAutoStyle.Subviews or Dim.DimAutoStyle.Auto)
             {
-                subviewsSize = us.Subviews.Count == 0
-                                   ? 0
-                                   : us.Subviews
-                                         .Where (v => dimension == Dimension.Width ? v.X is not Pos.PosAnchorEnd : v.Y is not Pos.PosAnchorEnd)
-                                         .Max (v => dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height);
+                if (us.IdealContentSize.HasValue)
+                {
+                    subviewsSize = dimension == Dimension.Width ? us.IdealContentSize.Value.Width : us.IdealContentSize.Value.Height;
+                }
+                else
+                {
+                    subviewsSize = us.Subviews.Count == 0
+                                       ? 0
+                                       : us.Subviews
+                                           .Where (v => dimension == Dimension.Width ? v.X is not Pos.PosAnchorEnd : v.Y is not Pos.PosAnchorEnd)
+                                           .Max (v => dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height);
+                }
             }
 
             int max = int.Max (textSize, subviewsSize);

+ 14 - 0
Terminal.Gui/View/Layout/ViewLayout.cs

@@ -91,10 +91,12 @@ public partial class View
     private void SetFrame (Rectangle frame)
     {
         var oldViewport = Rectangle.Empty;
+        var oldContentSize = Size.Empty;
 
         if (IsInitialized)
         {
             oldViewport = Viewport;
+            oldContentSize = ContentSize;
         }
 
         // This is the only place where _frame should be set directly. Use Frame = or SetFrame instead.
@@ -341,6 +343,18 @@ public partial class View
 
     #region Layout Engine
 
+
+    // @tig Notes on layout flow. Ignore for now.
+    // BeginLayout
+    //   If !LayoutNeeded return
+    //   If !SizeNeeded return
+    //   Call OnLayoutStarted
+    //      Views and subviews can update things
+    //   
+
+
+    // EndLayout
+
     /// <summary>
     ///     Controls how the View's <see cref="Frame"/> is computed during <see cref="LayoutSubviews"/>. If the style is
     ///     set to <see cref="LayoutStyle.Absolute"/>, LayoutSubviews does not change the <see cref="Frame"/>. If the style is

+ 6 - 4
Terminal.Gui/View/ViewContent.cs

@@ -155,6 +155,8 @@ public partial class View
         }
     }
 
+    public Size? IdealContentSize { get; set; }
+
     /// <summary>
     ///     Called when <see cref="ContentSize"/> changes. Invokes the <see cref="ContentSizeChanged"/> event.
     /// </summary>
@@ -319,10 +321,8 @@ public partial class View
 
                         // Whenever DimAutoStyle.Text is set, ContentSize will match TextFormatter.Size.
                         ContentSize = TextFormatter.Size;
-
                     }
                 }
-                //SetRelativeLayout (SuperView?.ContentSize ?? new Size (int.MaxValue, int.MaxValue));
             }
 
             return new (
@@ -357,7 +357,6 @@ public partial class View
             }
 
             OnViewportChanged (new (IsInitialized ? Viewport : Rectangle.Empty, oldViewport));
-
             return;
         }
 
@@ -417,7 +416,10 @@ public partial class View
     ///     Called when the <see cref="Viewport"/> changes. Invokes the <see cref="ViewportChanged"/> event.
     /// </summary>
     /// <param name="e"></param>
-    protected virtual void OnViewportChanged (DrawEventArgs e) { ViewportChanged?.Invoke (this, e); }
+    protected virtual void OnViewportChanged (DrawEventArgs e)
+    {
+        ViewportChanged?.Invoke (this, e);
+    }
 
     /// <summary>
     ///     Converts a <see cref="Viewport"/>-relative location to a screen-relative location.

+ 26 - 24
Terminal.Gui/Views/Slider.cs

@@ -265,11 +265,12 @@ public class Slider<T> : View
 
         Enter += (s, e) => { };
 
-        LayoutComplete += (s, e) =>
+        LayoutStarted += (s, e) =>
                           {
                               CalcSpacingConfig ();
-                              SetBoundsBestFit ();
+                              SetContentSizeBestFit ();
                           };
+
     }
 
     #endregion
@@ -374,13 +375,9 @@ public class Slider<T> : View
     }
 
     /// <summary>
-    ///     If <see langword="true"/> the slider will be sized to fit the available space (the Viewport of the the
-    ///     SuperView).
+    ///     If <see langword="true"/>, <see cref="View.Width"/> and <see cref="View.Height"/> will be automatically set
+    /// such that the slider will be optimally sized to fit the options using the various slider settings.
     /// </summary>
-    /// <remarks>
-    ///     For testing, if there is no SuperView, the slider will be sized based on what <see cref="InnerSpacing"/> is
-    ///     set to.
-    /// </remarks>
     [ObsoleteAttribute ("Use Dim.Auto instead.", false)]
     public override bool AutoSize
     {
@@ -389,10 +386,15 @@ public class Slider<T> : View
         {
             _config._autoSize = value;
 
-            if (IsInitialized)
+            if (value)
             {
-                CalcSpacingConfig ();
-                SetBoundsBestFit ();
+                Width = Dim.Auto (Dim.DimAutoStyle.Subviews);
+                Height = Dim.Auto (Dim.DimAutoStyle.Subviews);
+            }
+            else
+            {
+                Width = ContentSize.Width;
+                Height = ContentSize.Height;
             }
         }
     }
@@ -408,7 +410,7 @@ public class Slider<T> : View
             if (IsInitialized)
             {
                 CalcSpacingConfig ();
-                SetBoundsBestFit ();
+                SetContentSizeBestFit ();
             }
         }
     }
@@ -456,7 +458,7 @@ public class Slider<T> : View
             if (IsInitialized)
             {
                 CalcSpacingConfig ();
-                SetBoundsBestFit ();
+                SetContentSizeBestFit ();
             }
         }
 
@@ -474,7 +476,7 @@ public class Slider<T> : View
             if (IsInitialized)
             {
                 CalcSpacingConfig ();
-                SetBoundsBestFit ();
+                SetContentSizeBestFit ();
             }
         }
     }
@@ -508,7 +510,7 @@ public class Slider<T> : View
             }
 
             CalcSpacingConfig ();
-            SetBoundsBestFit ();
+            SetContentSizeBestFit ();
         }
     }
 
@@ -537,7 +539,7 @@ public class Slider<T> : View
         set
         {
             _config._showLegends = value;
-            SetBoundsBestFit ();
+            SetContentSizeBestFit ();
         }
     }
 
@@ -767,9 +769,9 @@ public class Slider<T> : View
     }
 
     /// <summary>Adjust the dimensions of the Slider to the best value if <see cref="AutoSize"/> is true.</summary>
-    public void SetBoundsBestFit ()
+    public void SetContentSizeBestFit ()
     {
-        if (!IsInitialized || AutoSize == false)
+        if (!IsInitialized || !(Height is Dim.DimAuto && Width is Dim.DimAuto))
         {
             return;
         }
@@ -778,15 +780,16 @@ public class Slider<T> : View
 
         if (_config._sliderOrientation == Orientation.Horizontal)
         {
+            // BUGBUG: For this View, ContentSize == Viewport.Size, so this works. But for correctness we should be setting ContentSize here
             Viewport = new (
                           Viewport.Location,
                           new (
                                int.Min (
-                                        SuperView.Viewport.Width - adornmentsThickness.Horizontal,
+                                        SuperView.ContentSize.Width - adornmentsThickness.Horizontal,
                                         CalcBestLength ()
                                        ),
                                int.Min (
-                                        SuperView.Viewport.Height - adornmentsThickness.Vertical,
+                                        SuperView.ContentSize.Height - adornmentsThickness.Vertical,
                                         CalcThickness ()
                                        )
                               )
@@ -794,15 +797,14 @@ public class Slider<T> : View
         }
         else
         {
-            Viewport = new (
-                          Viewport.Location,
+            IdealContentSize = new (
                           new (
                                int.Min (
-                                        SuperView.Viewport.Width - adornmentsThickness.Horizontal,
+                                        SuperView.ContentSize.Width - adornmentsThickness.Horizontal,
                                         CalcThickness ()
                                        ),
                                int.Min (
-                                        SuperView.Viewport.Height - adornmentsThickness.Vertical,
+                                        SuperView.ContentSize.Height - adornmentsThickness.Vertical,
                                         CalcBestLength ()
                                        )
                               )

+ 16 - 1
UICatalog/Scenarios/ContentScrolling.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
 using Terminal.Gui;
@@ -26,7 +27,7 @@ public class ContentScrolling : Scenario
             BorderStyle = LineStyle.Rounded;
             Arrangement = ViewArrangement.Fixed;
 
-            ContentSize = new (60, 40);
+            ContentSize = new (10, 40);
             ViewportSettings |= ViewportSettings.ClearContentOnly;
             ViewportSettings |= ViewportSettings.ClipContentOnly;
 
@@ -384,6 +385,20 @@ public class ContentScrolling : Scenario
         longLabel.TextFormatter.WordWrap = true;
         view.Add (longLabel);
 
+        List<object> options = new () { "Option 1", "Option 2", "Option 3" };
+        Slider slider = new (options)
+        {
+            X = 0,
+            Y = Pos.Bottom (textField) + 1,
+            AutoSize = true,
+            Orientation = Orientation.Vertical,
+            Type = SliderType.Multiple,
+            AllowEmpty = false,
+            BorderStyle = LineStyle.Double,
+            Title = "_Slider"
+        };
+        view.Add(slider);
+
         editor.Initialized += (s, e) => { editor.ViewToEdit = view; };
 
         app.Closed += (s, e) => View.Diagnostics = _diagnosticFlags;

+ 38 - 0
UnitTests/Views/SliderTests.cs

@@ -486,5 +486,43 @@ public class SliderTests
         Assert.Throws<ArgumentNullException> (() => slider.Options = null);
     }
 
+    [Fact]
+    private void AutoSize_Respects_SuperView_ContentSize ()
+    {
+        View view = new ()
+        {
+            Width = Dim.Fill (),
+            Height = Dim.Fill (),
+        };
+
+        List<object> options = new () { "01234", "01234" };
+        Slider slider = new (options)
+        {
+            Orientation = Orientation.Vertical,
+            Type = SliderType.Multiple,
+            Width = Dim.Auto (Dim.DimAutoStyle.Subviews),
+            Height = Dim.Auto (Dim.DimAutoStyle.Subviews),
+            //IdealContentSize = new (6, 2)
+        };
+        view.Add (slider);
+        view.BeginInit ();
+        view.EndInit ();
+
+        view.LayoutSubviews ();
+        slider.SetRelativeLayout(view.Viewport.Size);
+
+        Size expectedSize = slider.Frame.Size;
+
+        Assert.Equal (new (6, 2), expectedSize);
+
+        view.ContentSize = new (1, 1);
+
+        view.LayoutSubviews ();
+        slider.SetRelativeLayout (view.Viewport.Size);
+
+        Assert.Equal(new (1, 1), slider.Frame.Size);
+
+    }
+
     // Add more tests for different scenarios and edge cases.
 }