mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Added unit tests
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 ()
|
||||
{
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user