Merge branch 'v2_2432-DimAuto' into tig_v2_2432-DimAuto

This commit is contained in:
BDisp
2024-04-30 11:22:47 +01:00
6 changed files with 123 additions and 33 deletions

View File

@@ -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);

View File

@@ -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
@@ -780,6 +794,7 @@ public partial class View
private void LayoutSubview (View v, Size contentSize)
{
// BUGBUG: Calling SetRelativeLayout before LayoutSubviews is problematic. Need to resolve.
v.SetRelativeLayout (contentSize);
v.LayoutSubviews ();
v.LayoutNeeded = false;
@@ -794,6 +809,9 @@ public partial class View
/// </summary>
internal virtual void OnLayoutComplete (LayoutEventArgs args) { LayoutComplete?.Invoke (this, args); }
// BUGBUG: We need an API/event that is called from SetRelativeLayout instead of/in addition to
// BUGBUG: OnLayoutStarted which is called from LayoutSubviews.
/// <summary>
/// Raises the <see cref="LayoutStarted"/> event. Called from <see cref="LayoutSubviews"/> before any subviews
/// have been laid out.

View File

@@ -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.

View File

@@ -265,11 +265,19 @@ public class Slider<T> : View
Enter += (s, e) => { };
LayoutComplete += (s, e) =>
// BUGBUG: This should not be needed - Need to ensure SetRelativeLayout gets called during EndInit
Initialized += (s, e) =>
{
CalcSpacingConfig ();
SetContentSizeBestFit ();
};
LayoutStarted += (s, e) =>
{
CalcSpacingConfig ();
SetBoundsBestFit ();
SetContentSizeBestFit ();
};
}
#endregion
@@ -374,13 +382,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 +393,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 +417,7 @@ public class Slider<T> : View
if (IsInitialized)
{
CalcSpacingConfig ();
SetBoundsBestFit ();
SetContentSizeBestFit ();
}
}
}
@@ -456,7 +465,7 @@ public class Slider<T> : View
if (IsInitialized)
{
CalcSpacingConfig ();
SetBoundsBestFit ();
SetContentSizeBestFit ();
}
}
@@ -474,7 +483,7 @@ public class Slider<T> : View
if (IsInitialized)
{
CalcSpacingConfig ();
SetBoundsBestFit ();
SetContentSizeBestFit ();
}
}
}
@@ -508,7 +517,7 @@ public class Slider<T> : View
}
CalcSpacingConfig ();
SetBoundsBestFit ();
SetContentSizeBestFit ();
}
}
@@ -537,7 +546,7 @@ public class Slider<T> : View
set
{
_config._showLegends = value;
SetBoundsBestFit ();
SetContentSizeBestFit ();
}
}
@@ -767,9 +776,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 +787,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 +804,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 ()
)
)

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Terminal.Gui;
@@ -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;

View File

@@ -486,5 +486,44 @@ 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 ();
// BUGBUG: This should not be needed. EndInit should have called LayoutSubviews
// BUGBUG: and LayoutSubviews should have
view.LayoutSubviews ();
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.
}