Added unit tests

This commit is contained in:
Tig
2024-05-27 15:27:21 -06:00
parent 7840cea48c
commit f7c451b5fa
7 changed files with 191 additions and 59 deletions

View File

@@ -69,12 +69,15 @@ public class DimAuto () : Dim
if (Style.FastHasFlags (DimAutoStyle.Content))
{
if (us._contentSize is { })
if (!us.ContentSizeTracksViewport)
{
// ContentSize was explicitly set. Ignore subviews.
subviewsSize = dimension == Dimension.Width ? us.ContentSize.Width : us.ContentSize.Height;
}
else
{
// ContentSize was NOT explicitly set. Use subviews to determine size.
// TODO: This whole body of code is a WIP (for https://github.com/gui-cs/Terminal.Gui/pull/3451).
subviewsSize = 0;

View File

@@ -10,11 +10,9 @@ namespace Terminal.Gui;
public enum DimAutoStyle
{
/// <summary>
/// The dimensions will be computed based on the View's non-Text content.
/// The dimensions will be computed based on the View's <see cref="View.ContentSize"/> and/or <see cref="View.Subviews"/>.
/// <para>
/// If <see cref="View.ContentSize"/> is explicitly set (is not <see langword="null"/>) then
/// <see cref="View.ContentSize"/>
/// will be used to determine the dimension.
/// If <see cref="View.ContentSizeTracksViewport"/> is <see langword="true"/>, <see cref="View.ContentSize"/> will be used to determine the dimension.
/// </para>
/// <para>
/// Otherwise, the Subview in <see cref="View.Subviews"/> with the largest corresponding position plus dimension
@@ -33,14 +31,14 @@ public enum DimAutoStyle
/// will be used to determine the dimension.
/// </para>
/// <para>
/// The corresponding dimensions of the <see cref="View.Subviews"/> will be ignored.
/// The corresponding dimensions of <see cref="View.ContentSize"/> and/or <see cref="View.Subviews"/> will be ignored.
/// </para>
/// </summary>
Text = 2,
/// <summary>
/// The dimension will be computed using both the view's <see cref="View.Text"/> and
/// <see cref="View.Subviews"/> (whichever is larger).
/// The dimension will be computed using the largest of the view's <see cref="View.Text"/>, <see cref="View.ContentSize"/>, and
/// <see cref="View.Subviews"/> corresponding dimension
/// </summary>
Auto = Content | Text,
}

View File

@@ -1072,13 +1072,13 @@ public partial class View
// Verify none of the subviews are using Dim objects that depend on the SuperView's dimensions.
foreach (View view in Subviews)
{
if (widthAuto is { } && widthAuto.Style.FastHasFlags (DimAutoStyle.Content) && _contentSize is null)
if (widthAuto is { } && widthAuto.Style.FastHasFlags (DimAutoStyle.Content) && ContentSizeTracksViewport)
{
ThrowInvalid (view, view.Width, nameof (view.Width));
ThrowInvalid (view, view.X, nameof (view.X));
}
if (heightAuto is { } && heightAuto.Style.FastHasFlags (DimAutoStyle.Content) && _contentSize is null)
if (heightAuto is { } && heightAuto.Style.FastHasFlags (DimAutoStyle.Content) && ContentSizeTracksViewport)
{
ThrowInvalid (view, view.Height, nameof (view.Height));
ThrowInvalid (view, view.Y, nameof (view.Y));

View File

@@ -1,6 +1,4 @@
using System.Diagnostics;
namespace Terminal.Gui;
namespace Terminal.Gui;
public partial class View
{
@@ -8,38 +6,9 @@ public partial class View
internal Size? _contentSize;
/// <summary>
/// Sets the size of the View's content.
/// </summary>
/// <remarks>
/// <para>
/// By default, the content size is set to <see langword="null"/>.
/// </para>
/// </remarks>
/// <param name="contentSize">
/// <para>
/// If <see langword="null"/>, and the View has no visible subviews, <see cref="ContentSize"/> will track the size of <see cref="Viewport"/>.
/// </para>
/// <para>
/// If <see langword="null"/>, and the View has visible subviews, <see cref="ContentSize"/> will track the maximum position plus size of any
/// visible Subviews
/// and <c>Viewport.Location</c> will track the minimum position and size of any visible Subviews.
/// </para>
/// <para>
/// If not <see langword="null"/>, <see cref="ContentSize"/> is set to the passed value and <see cref="Viewport"/> describes the portion of the content currently visible
/// to the user. This enables virtual scrolling.
/// </para>
/// <para>
/// If not <see langword="null"/>, <see cref="ContentSize"/> is set to the passed value and the behavior of <see cref="DimAutoStyle.Content"/> will be to use the ContentSize
/// to determine the size of the view.
/// </para>
/// <para>
/// Negative sizes are not supported.
/// </para>
/// </param>
private void SetContentSize (Size? contentSize)
{
if (ContentSize.Width < 0 || ContentSize.Height < 0)
if (contentSize is { } && (contentSize.Value.Width < 0 || contentSize.Value.Height < 0))
{
throw new ArgumentException (@"ContentSize cannot be negative.", nameof (contentSize));
}
@@ -53,17 +22,80 @@ public partial class View
OnContentSizeChanged (new (_contentSize));
}
/// <summary>
/// Gets or sets a value indicating whether the <see cref="ContentSize"/> tracks the <see cref="Viewport"/>'s size or
/// not.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <listheader>
/// <term>Value</term> <description>Result</description>
/// </listheader>
/// <item>
/// <term>
/// <see langword="true"/>
/// </term>
/// <description>
/// <para>
/// <see cref="ContentSize"/> is tracking the <see cref="Viewport"/>'s size. Content scrolling will be
/// disabled.
/// </para>
/// <para>
/// The behavior of <see cref="DimAutoStyle.Content"/> will be to use position and size of the Subviews
/// to
/// determine the size of the view, ignoring <see cref="ContentSize"/>.
/// </para>
/// </description>
/// </item>
/// <item>
/// <term>
/// <see langword="false"/>
/// </term>
/// <description>
/// <para>
/// <see cref="ContentSize"/> is independent of <see cref="Viewport"/> and <see cref="Viewport"/>
/// describes the portion of the content currently visible to the user, bound by
/// <see cref="ContentSize"/>, enabling content scrolling.
/// </para>
/// <para>
/// The behavior of <see cref="DimAutoStyle.Content"/> will be to use <see cref="ContentSize"/> to
/// determine the
/// size of the view, ignoring the position and size of the Subviews.
/// </para>
/// </description>
/// </item>
/// </list>
/// </remarks>
public bool ContentSizeTracksViewport
{
get => _contentSize is null;
set => _contentSize = value ? null : _contentSize;
}
/// <summary>
/// Gets the size of the View's content.
/// </summary>
/// <remarks>
/// <para>
/// Use <see cref="SetContentSize"/> to change to change the content size.
/// Negative sizes are not supported.
/// </para>
/// <para>
/// If the content size has not been explicitly set with <see cref="SetContentSize"/>, the value tracks
/// If not explicitly set, and the View has no visible subviews, <see cref="ContentSize"/> will track the size of
/// <see cref="Viewport"/>.
/// </para>
/// <para>
/// If not explicitly set, and the View has visible subviews, <see cref="ContentSize"/> will track the maximum
/// position + dimension of the Subviews, supporting <see cref="Dim.Auto"/> with the
/// <see cref="DimAutoStyle.Content"/> flag set.
/// </para>
/// <para>
/// If set <see cref="Viewport"/> describes the portion of the content currently visible to the user. This enables
/// virtual scrolling.
/// </para>
/// <para>
/// If set the behavior of <see cref="DimAutoStyle.Content"/> will be to use the ContentSize to determine the size
/// of the view.
/// </para>
/// </remarks>
public Size ContentSize
{
@@ -72,7 +104,7 @@ public partial class View
}
/// <summary>
/// Called when <see cref="ContentSize"/> has changed.
/// Called when <see cref="ContentSize"/> has changed.
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
@@ -83,6 +115,7 @@ public partial class View
if (e.Cancel != true)
{
OnResizeNeeded ();
//SetNeedsLayout ();
//SetNeedsDisplay ();
}
@@ -180,11 +213,12 @@ public partial class View
/// </para>
/// <para>
/// Negative values for the location indicate the visible area is offset above (up-and-left) the View's virtual
/// <see cref="ContentSize"/>. This enables scrolling up and to the left (e.g. in an image viewer that supports zoom
/// <see cref="ContentSize"/>. This enables scrolling up and to the left (e.g. in an image viewer that supports
/// zoom
/// where the image stays centered).
/// </para>
/// <para>
/// The <see cref="ViewportSettings"/> property controls how scrolling is handled.
/// The <see cref="ViewportSettings"/> property controls how scrolling is handled.
/// </para>
/// <para>
/// If <see cref="LayoutStyle"/> is <see cref="LayoutStyle.Computed"/> the value of Viewport is indeterminate until
@@ -211,6 +245,7 @@ public partial class View
}
Thickness thickness = GetAdornmentsThickness ();
return new (
_viewportLocation,
new (
@@ -243,6 +278,7 @@ public partial class View
}
OnViewportChanged (new (IsInitialized ? Viewport : Rectangle.Empty, oldViewport));
return;
}
@@ -293,7 +329,8 @@ public partial class View
}
/// <summary>
/// Fired when the <see cref="Viewport"/> changes. This event is fired after the <see cref="Viewport"/> has been updated.
/// Fired when the <see cref="Viewport"/> changes. This event is fired after the <see cref="Viewport"/> has been
/// updated.
/// </summary>
[CanBeNull]
public event EventHandler<DrawEventArgs> ViewportChanged;
@@ -302,10 +339,7 @@ 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 and size to a screen-relative location and size.
@@ -315,10 +349,7 @@ public partial class View
/// </remarks>
/// <param name="viewport">Viewport-relative location and size.</param>
/// <returns>Screen-relative location and size.</returns>
public Rectangle ViewportToScreen (in Rectangle viewport)
{
return viewport with { Location = ViewportToScreen (viewport.Location) };
}
public Rectangle ViewportToScreen (in Rectangle viewport) { return viewport with { Location = ViewportToScreen (viewport.Location) }; }
/// <summary>
/// Converts a <see cref="Viewport"/>-relative location to a screen-relative location.

View File

@@ -972,6 +972,22 @@ public class DimAutoTests (ITestOutputHelper output)
Assert.Equal (10, calculatedWidth);
}
[Fact]
public void DimAutoStyle_Content_IgnoresSubviews_When_ContentSize_Is_Set ()
{
var view = new View ();
var subview = new View () {
Frame = new Rectangle (50, 50, 1, 1)
};
view.ContentSize = new (10, 5);
var dim = Dim.Auto (DimAutoStyle.Content);
int calculatedWidth = dim.Calculate (0, 100, view, Dimension.Width);
Assert.Equal (10, calculatedWidth);
}
[Fact]
public void DimAutoStyle_Content_IgnoresText_WhenContentSizeNotSet ()
{

View File

@@ -340,16 +340,59 @@ public class ViewportTests (ITestOutputHelper output)
}
[Fact]
public void ContentSize_Matches_ViewportSize_If_Not_Set ()
public void ContentSize_Tracks_ViewportSize_If_Not_Set ()
{
View view = new ()
{
Width = 1,
Height = 1
};
Assert.True (view.ContentSizeTracksViewport);
Assert.Equal (view.Viewport.Size, view.ContentSize);
}
[Fact]
public void ContentSize_Ignores_ViewportSize_If_Set ()
{
View view = new ()
{
Width = 1,
Height = 1,
ContentSize = new Size (5, 5)
};
Assert.False (view.ContentSizeTracksViewport);
Assert.NotEqual (view.Viewport.Size, view.ContentSize);
}
[Fact]
public void ContentSize_Tracks_ViewportSize_If_ContentSizeTracksViewport_Is_True ()
{
View view = new ()
{
Width = 1,
Height = 1,
ContentSize = new Size (5, 5)
};
view.Viewport = new (0, 0, 10, 10);
view.ContentSizeTracksViewport = true;
Assert.Equal (view.Viewport.Size, view.ContentSize);
}
[Fact]
public void ContentSize_Ignores_ViewportSize_If_ContentSizeTracksViewport_Is_False ()
{
View view = new ()
{
Width = 1,
Height = 1,
ContentSize = new Size (5, 5)
};
view.Viewport = new (0, 0, 10, 10);
view.ContentSizeTracksViewport = false;
Assert.NotEqual (view.Viewport.Size, view.ContentSize);
}
//[Theory]
//[InlineData (0, 0, true)]
//[InlineData (-1, 0, true)]

View File

@@ -75,7 +75,7 @@ public class SubviewTests
w2.Dispose ();
top2.Dispose ();
}
[Fact]
[TestRespondersDisposed]
public void Initialized_Event_Comparing_With_Added_Event ()
@@ -332,4 +332,45 @@ public class SubviewTests
top.Dispose ();
view.Dispose ();
}
// TODO: Consider a feature that will change the ContentSize to fit the subviews.
[Fact]
public void Add_Does_Not_Impact_ContentSize ()
{
var view = new View ();
view.ContentSize = new Size (1, 1);
var subview = new View ()
{
X = 10,
Y = 10
};
Assert.Equal (new Size (1, 1), view.ContentSize);
view.Add (subview);
Assert.Equal (new Size (1, 1), view.ContentSize);
}
[Fact]
public void Remove_Does_Not_Impact_ContentSize ()
{
var view = new View ();
view.ContentSize = new Size (1, 1);
var subview = new View ()
{
X = 10,
Y = 10
};
Assert.Equal (new Size (1, 1), view.ContentSize);
view.Add (subview);
Assert.Equal (new Size (1, 1), view.ContentSize);
view.ContentSize = new Size (5, 5);
Assert.Equal (new Size (5, 5), view.ContentSize);
view.Remove (subview);
Assert.Equal (new Size (5, 5), view.ContentSize);
}
}