Add DependsOnSuperViewContentSize property to Dim and Pos base classes

Co-authored-by: tig <585482+tig@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-03 04:02:59 +00:00
parent 459cf0142d
commit 8bb1d24947
11 changed files with 293 additions and 0 deletions

View File

@@ -427,6 +427,25 @@ public abstract record Dim : IEqualityOperators<Dim, Dim, bool>
yield break;
}
/// <summary>
/// Indicates whether this Dim depends on the SuperView's content size for its calculation.
/// </summary>
/// <remarks>
/// <para>
/// This property is used by <see cref="DimAuto"/> to categorize subviews during auto-sizing calculations
/// without needing to perform type checking.
/// </para>
/// <para>
/// Types that depend on SuperView content size include <see cref="DimPercent"/> and <see cref="DimFill"/>
/// (unless it has a <see cref="DimFill.MinimumContentDim"/> without a <see cref="DimFill.To"/>).
/// </para>
/// </remarks>
/// <returns>
/// <see langword="true"/> if this Dim's calculation depends on the SuperView's content size;
/// otherwise, <see langword="false"/>.
/// </returns>
internal virtual bool DependsOnSuperViewContentSize => false;
#endregion virtual methods
#region operators

View File

@@ -89,6 +89,9 @@ public record DimCombine (AddOrSubtract Add, Dim Left, Dim Right) : Dim
}
}
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => Left.DependsOnSuperViewContentSize || Right.DependsOnSuperViewContentSize;
/// <inheritdoc/>
protected override bool HasInner<TDim> (out TDim dim) => Left.Has (out dim) || Right.Has (out dim);
}

View File

@@ -88,6 +88,9 @@ public record DimFill (Dim Margin, Dim? MinimumContentDim = null, View? To = nul
}
}
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => true;
/// <inheritdoc/>
protected override bool HasInner<TDim> (out TDim dim)
{

View File

@@ -29,4 +29,7 @@ public record DimPercent (int Percentage, DimPercentMode Mode = DimPercentMode.C
internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension) =>
Mode == DimPercentMode.Position ? Math.Max (GetAnchor (superviewContentSize - location), 0) : GetAnchor (superviewContentSize);
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => true;
}

View File

@@ -394,6 +394,24 @@ public abstract record Pos
yield break;
}
/// <summary>
/// Indicates whether this Pos depends on the SuperView's content size for its calculation.
/// </summary>
/// <remarks>
/// <para>
/// This property is used by <see cref="DimAuto"/> to categorize subviews during auto-sizing calculations
/// without needing to perform type checking.
/// </para>
/// <para>
/// Types that depend on SuperView content size include <see cref="PosCenter"/> and <see cref="PosPercent"/>.
/// </para>
/// </remarks>
/// <returns>
/// <see langword="true"/> if this Pos's calculation depends on the SuperView's content size;
/// otherwise, <see langword="false"/>.
/// </returns>
internal virtual bool DependsOnSuperViewContentSize => false;
/// <summary>
/// Indicates whether the specified type <typeparamref name="TPos"/> is in the hierarchy of this Pos object.
/// </summary>

View File

@@ -175,5 +175,8 @@ public record PosAlign : Pos
internal override bool ReferencesOtherViews () => true;
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => true;
private void Aligner_PropertyChanged (object? sender, PropertyChangedEventArgs e) => _cachedLocation = null;
}

View File

@@ -131,4 +131,7 @@ public record PosAnchorEnd : Pos
return newLocation;
}
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => true;
}

View File

@@ -17,4 +17,7 @@ public record PosCenter : Pos
return (superviewDimension - newDimension) / 2;
}
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => true;
}

View File

@@ -83,6 +83,9 @@ public record PosCombine (AddOrSubtract Add, Pos Left, Pos Right) : Pos
}
}
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => Left.DependsOnSuperViewContentSize || Right.DependsOnSuperViewContentSize;
/// <inheritdoc/>
protected override bool HasInner<TPos> (out TPos pos) => Left.Has (out pos) || Right.Has (out pos);
}

View File

@@ -21,4 +21,7 @@ public record PosPercent (int Percent) : Pos
public override string ToString () => $"Percent({Percent})";
internal override int GetAnchor (int size) => (int)(size * (Percent / 100f));
/// <inheritdoc/>
internal override bool DependsOnSuperViewContentSize => true;
}

View File

@@ -0,0 +1,232 @@
#nullable disable
// Claude - Opus 4.5
namespace ViewBaseTests.Layout;
/// <summary>
/// Tests for the DependsOnSuperViewContentSize property on Dim and Pos types.
/// This property is used by DimAuto to categorize subviews without type checking.
/// </summary>
public class DependsOnSuperViewContentSizeTests
{
#region Dim Tests
[Fact]
public void DimAbsolute_DoesNotDependOnSuperViewContentSize ()
{
Dim dim = Dim.Absolute (10);
Assert.False (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimAuto_DoesNotDependOnSuperViewContentSize ()
{
Dim dim = Dim.Auto ();
Assert.False (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimFunc_DoesNotDependOnSuperViewContentSize ()
{
Dim dim = Dim.Func (_ => 10);
Assert.False (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimView_DoesNotDependOnSuperViewContentSize ()
{
View view = new ();
Dim dim = Dim.Width (view);
Assert.False (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimPercent_DependsOnSuperViewContentSize ()
{
Dim dim = Dim.Percent (50);
Assert.True (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimPercent_AllModes_DependOnSuperViewContentSize ()
{
Dim dimContentSize = Dim.Percent (50, DimPercentMode.ContentSize);
Assert.True (dimContentSize.DependsOnSuperViewContentSize);
Dim dimPosition = Dim.Percent (50, DimPercentMode.Position);
Assert.True (dimPosition.DependsOnSuperViewContentSize);
}
[Fact]
public void DimFill_DependsOnSuperViewContentSize ()
{
Dim dim = Dim.Fill ();
Assert.True (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimFill_WithMargin_DependsOnSuperViewContentSize ()
{
Dim dim = Dim.Fill (2);
Assert.True (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimFill_WithMinimumContentDim_DependsOnSuperViewContentSize ()
{
Dim dim = Dim.Fill (0, 10);
Assert.True (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimFill_WithTo_DependsOnSuperViewContentSize ()
{
View view = new ();
Dim dim = Dim.Fill (view);
Assert.True (dim.DependsOnSuperViewContentSize);
}
[Fact]
public void DimCombine_DependsIfEitherChildDepends ()
{
// Both depend
Dim dim1 = Dim.Percent (50) + Dim.Fill ();
Assert.True (dim1.DependsOnSuperViewContentSize);
// Left depends
Dim dim2 = Dim.Percent (50) + Dim.Absolute (10);
Assert.True (dim2.DependsOnSuperViewContentSize);
// Right depends
Dim dim3 = Dim.Absolute (10) + Dim.Fill ();
Assert.True (dim3.DependsOnSuperViewContentSize);
// Neither depends
Dim dim4 = Dim.Absolute (10) + Dim.Absolute (5);
Assert.False (dim4.DependsOnSuperViewContentSize);
}
[Fact]
public void DimCombine_Subtraction_DependsIfEitherChildDepends ()
{
// Both depend
Dim dim1 = Dim.Fill () - Dim.Percent (10);
Assert.True (dim1.DependsOnSuperViewContentSize);
// Left depends
Dim dim2 = Dim.Percent (50) - Dim.Absolute (10);
Assert.True (dim2.DependsOnSuperViewContentSize);
// Right depends
Dim dim3 = Dim.Absolute (100) - Dim.Fill ();
Assert.True (dim3.DependsOnSuperViewContentSize);
// Neither depends
Dim dim4 = Dim.Absolute (100) - Dim.Absolute (10);
Assert.False (dim4.DependsOnSuperViewContentSize);
}
#endregion
#region Pos Tests
[Fact]
public void PosAbsolute_DoesNotDependOnSuperViewContentSize ()
{
Pos pos = Pos.Absolute (10);
Assert.False (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosFunc_DoesNotDependOnSuperViewContentSize ()
{
Pos pos = Pos.Func (_ => 10);
Assert.False (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosView_DoesNotDependOnSuperViewContentSize ()
{
View view = new ();
Pos pos = Pos.Left (view);
Assert.False (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosCenter_DependsOnSuperViewContentSize ()
{
Pos pos = Pos.Center ();
Assert.True (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosPercent_DependsOnSuperViewContentSize ()
{
Pos pos = Pos.Percent (50);
Assert.True (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosAnchorEnd_DependsOnSuperViewContentSize ()
{
Pos pos = Pos.AnchorEnd ();
Assert.True (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosAnchorEnd_WithOffset_DependsOnSuperViewContentSize ()
{
Pos pos = Pos.AnchorEnd (10);
Assert.True (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosAlign_DependsOnSuperViewContentSize ()
{
Pos pos = Pos.Align (Alignment.Center);
Assert.True (pos.DependsOnSuperViewContentSize);
}
[Fact]
public void PosCombine_DependsIfEitherChildDepends ()
{
// Both depend
Pos pos1 = Pos.Center () + Pos.Percent (10);
Assert.True (pos1.DependsOnSuperViewContentSize);
// Left depends
Pos pos2 = Pos.Center () + Pos.Absolute (10);
Assert.True (pos2.DependsOnSuperViewContentSize);
// Right depends
Pos pos3 = Pos.Absolute (10) + Pos.Percent (50);
Assert.True (pos3.DependsOnSuperViewContentSize);
// Neither depends
Pos pos4 = Pos.Absolute (10) + Pos.Absolute (5);
Assert.False (pos4.DependsOnSuperViewContentSize);
}
[Fact]
public void PosCombine_Subtraction_DependsIfEitherChildDepends ()
{
// Both depend
Pos pos1 = Pos.AnchorEnd () - Pos.Percent (10);
Assert.True (pos1.DependsOnSuperViewContentSize);
// Left depends
Pos pos2 = Pos.Center () - Pos.Absolute (10);
Assert.True (pos2.DependsOnSuperViewContentSize);
// Right depends (unusual but possible)
Pos pos3 = Pos.Absolute (100) - Pos.Percent (10);
Assert.True (pos3.DependsOnSuperViewContentSize);
// Neither depends
Pos pos4 = Pos.Absolute (100) - Pos.Absolute (10);
Assert.False (pos4.DependsOnSuperViewContentSize);
}
#endregion
}