diff --git a/Terminal.Gui/View/Layout/DimAuto.cs b/Terminal.Gui/View/Layout/DimAuto.cs
index dc8a55aa9..d956fb94d 100644
--- a/Terminal.Gui/View/Layout/DimAuto.cs
+++ b/Terminal.Gui/View/Layout/DimAuto.cs
@@ -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;
diff --git a/Terminal.Gui/View/Layout/DimAutoStyle.cs b/Terminal.Gui/View/Layout/DimAutoStyle.cs
index 4a3ecbb66..df7f7065c 100644
--- a/Terminal.Gui/View/Layout/DimAutoStyle.cs
+++ b/Terminal.Gui/View/Layout/DimAutoStyle.cs
@@ -10,11 +10,9 @@ namespace Terminal.Gui;
public enum DimAutoStyle
{
///
- /// The dimensions will be computed based on the View's non-Text content.
+ /// The dimensions will be computed based on the View's and/or .
///
- /// If is explicitly set (is not ) then
- ///
- /// will be used to determine the dimension.
+ /// If is , will be used to determine the dimension.
///
///
/// Otherwise, the Subview in with the largest corresponding position plus dimension
@@ -33,14 +31,14 @@ public enum DimAutoStyle
/// will be used to determine the dimension.
///
///
- /// The corresponding dimensions of the will be ignored.
+ /// The corresponding dimensions of and/or will be ignored.
///
///
Text = 2,
///
- /// The dimension will be computed using both the view's and
- /// (whichever is larger).
+ /// The dimension will be computed using the largest of the view's , , and
+ /// corresponding dimension
///
Auto = Content | Text,
}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs
index f9f55503c..110cc2238 100644
--- a/Terminal.Gui/View/Layout/ViewLayout.cs
+++ b/Terminal.Gui/View/Layout/ViewLayout.cs
@@ -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));
diff --git a/Terminal.Gui/View/ViewContent.cs b/Terminal.Gui/View/ViewContent.cs
index decd143d9..b94213d30 100644
--- a/Terminal.Gui/View/ViewContent.cs
+++ b/Terminal.Gui/View/ViewContent.cs
@@ -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;
- ///
- /// Sets the size of the View's content.
- ///
- ///
- ///
- /// By default, the content size is set to .
- ///
- ///
- ///
- ///
- /// If , and the View has no visible subviews, will track the size of .
- ///
- ///
- /// If , and the View has visible subviews, will track the maximum position plus size of any
- /// visible Subviews
- /// and Viewport.Location will track the minimum position and size of any visible Subviews.
- ///
- ///
- /// If not , is set to the passed value and describes the portion of the content currently visible
- /// to the user. This enables virtual scrolling.
- ///
- ///
- /// If not , is set to the passed value and the behavior of will be to use the ContentSize
- /// to determine the size of the view.
- ///
- ///
- /// Negative sizes are not supported.
- ///
- ///
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));
}
+ ///
+ /// Gets or sets a value indicating whether the tracks the 's size or
+ /// not.
+ ///
+ ///
+ ///
+ ///
+ /// Value Result
+ ///
+ /// -
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// is tracking the 's size. Content scrolling will be
+ /// disabled.
+ ///
+ ///
+ /// The behavior of will be to use position and size of the Subviews
+ /// to
+ /// determine the size of the view, ignoring .
+ ///
+ ///
+ ///
+ /// -
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// is independent of and
+ /// describes the portion of the content currently visible to the user, bound by
+ /// , enabling content scrolling.
+ ///
+ ///
+ /// The behavior of will be to use to
+ /// determine the
+ /// size of the view, ignoring the position and size of the Subviews.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool ContentSizeTracksViewport
+ {
+ get => _contentSize is null;
+ set => _contentSize = value ? null : _contentSize;
+ }
+
///
/// Gets the size of the View's content.
///
///
///
- /// Use to change to change the content size.
+ /// Negative sizes are not supported.
///
///
- /// If the content size has not been explicitly set with , the value tracks
+ /// If not explicitly set, and the View has no visible subviews, will track the size of
/// .
///
+ ///
+ /// If not explicitly set, and the View has visible subviews, will track the maximum
+ /// position + dimension of the Subviews, supporting with the
+ /// flag set.
+ ///
+ ///
+ /// If set describes the portion of the content currently visible to the user. This enables
+ /// virtual scrolling.
+ ///
+ ///
+ /// If set the behavior of will be to use the ContentSize to determine the size
+ /// of the view.
+ ///
///
public Size ContentSize
{
@@ -72,7 +104,7 @@ public partial class View
}
///
- /// Called when has changed.
+ /// Called when has changed.
///
///
///
@@ -83,6 +115,7 @@ public partial class View
if (e.Cancel != true)
{
OnResizeNeeded ();
+
//SetNeedsLayout ();
//SetNeedsDisplay ();
}
@@ -180,11 +213,12 @@ public partial class View
///
///
/// Negative values for the location indicate the visible area is offset above (up-and-left) the View's virtual
- /// . This enables scrolling up and to the left (e.g. in an image viewer that supports zoom
+ /// . This enables scrolling up and to the left (e.g. in an image viewer that supports
+ /// zoom
/// where the image stays centered).
///
///
- /// The property controls how scrolling is handled.
+ /// The property controls how scrolling is handled.
///
///
/// If is 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
}
///
- /// Fired when the changes. This event is fired after the has been updated.
+ /// Fired when the changes. This event is fired after the has been
+ /// updated.
///
[CanBeNull]
public event EventHandler ViewportChanged;
@@ -302,10 +339,7 @@ public partial class View
/// Called when the changes. Invokes the event.
///
///
- protected virtual void OnViewportChanged (DrawEventArgs e)
- {
- ViewportChanged?.Invoke (this, e);
- }
+ protected virtual void OnViewportChanged (DrawEventArgs e) { ViewportChanged?.Invoke (this, e); }
///
/// Converts a -relative location and size to a screen-relative location and size.
@@ -315,10 +349,7 @@ public partial class View
///
/// Viewport-relative location and size.
/// Screen-relative location and size.
- 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) }; }
///
/// Converts a -relative location to a screen-relative location.
diff --git a/UnitTests/View/Layout/Dim.AutoTests.cs b/UnitTests/View/Layout/Dim.AutoTests.cs
index 87e2dd95e..9abf6b315 100644
--- a/UnitTests/View/Layout/Dim.AutoTests.cs
+++ b/UnitTests/View/Layout/Dim.AutoTests.cs
@@ -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 ()
{
diff --git a/UnitTests/View/Layout/ViewportTests.cs b/UnitTests/View/Layout/ViewportTests.cs
index 5ba27d6d0..8a2126303 100644
--- a/UnitTests/View/Layout/ViewportTests.cs
+++ b/UnitTests/View/Layout/ViewportTests.cs
@@ -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)]
diff --git a/UnitTests/View/SubviewTests.cs b/UnitTests/View/SubviewTests.cs
index 6f9d84f54..768b5d1ea 100644
--- a/UnitTests/View/SubviewTests.cs
+++ b/UnitTests/View/SubviewTests.cs
@@ -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);
+ }
}