Skip to content

Commit

Permalink
Merge pull request gui-cs#3649 from tig/v2_3521-DimAuto-Equality
Browse files Browse the repository at this point in the history
Fixes gui-cs#3521 - `DimAuto` equality broken
  • Loading branch information
tig authored Aug 19, 2024
2 parents c00290f + bb85f90 commit 168d3ca
Show file tree
Hide file tree
Showing 26 changed files with 460 additions and 575 deletions.
46 changes: 19 additions & 27 deletions Terminal.Gui/View/Layout/Dim.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#nullable enable
using System.Diagnostics;

namespace Terminal.Gui;

using System.Numerics;

/// <summary>
/// <para>
/// A Dim object describes the dimensions of a <see cref="View"/>. Dim is the type of the
Expand Down Expand Up @@ -78,7 +78,7 @@ namespace Terminal.Gui;
/// </para>
/// <para></para>
/// </remarks>
public abstract class Dim
public abstract record Dim : IEqualityOperators<Dim, Dim, bool>
{
#region static Dim creation methods

Expand Down Expand Up @@ -113,12 +113,10 @@ public abstract class Dim
/// <param name="maximumContentDim">The maximum dimension the View's ContentSize will be fit to.</param>
public static Dim? Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim? minimumContentDim = null, Dim? maximumContentDim = null)
{
return new DimAuto ()
{
MinimumContentDim = minimumContentDim,
MaximumContentDim = maximumContentDim,
Style = style
};
return new DimAuto (
MinimumContentDim: minimumContentDim,
MaximumContentDim: maximumContentDim,
Style: style);
}

/// <summary>
Expand Down Expand Up @@ -172,28 +170,22 @@ public abstract class Dim

#endregion static Dim creation methods


/// <summary>
/// Indicates whether the specified type is in the hierarchy of this Dim object.
/// Indicates whether the specified type <typeparamref name="T"/> is in the hierarchy of this Dim object.
/// </summary>
/// <param name="type"></param>
/// <param name="dim"></param>
/// <param name="dim">A reference to this <see cref="Dim"/> instance.</param>
/// <returns></returns>
public bool Has (Type type, out Dim dim)
public bool Has<T> (out Dim dim) where T : Dim
{
dim = this;
if (type == GetType ())
{
return true;
}

// If we are a PosCombine, we have to check the left and right
// to see if they are of the type we are looking for.
if (this is DimCombine { } combine && (combine.Left.Has (type, out dim) || combine.Right.Has (type, out dim)))
{
return true;
}

return false;
return this switch
{
DimCombine combine => combine.Left.Has<T> (out dim) || combine.Right.Has<T> (out dim),
T => true,
_ => false
};
}

#region virtual methods
Expand All @@ -208,7 +200,7 @@ public bool Has (Type type, out Dim dim)
/// subclass of Dim that is used. For example, DimAbsolute returns a fixed dimension, DimFactor returns a
/// dimension that is a certain percentage of the super view's size, and so on.
/// </returns>
internal virtual int GetAnchor (int size) { return 0; }
internal abstract int GetAnchor (int size);

/// <summary>
/// Calculates and returns the dimension of a <see cref="View"/> object. It takes into account the location of the
Expand All @@ -228,7 +220,7 @@ public bool Has (Type type, out Dim dim)
/// </returns>
internal virtual int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
{
return Math.Max (GetAnchor (superviewContentSize - location), 0);
return Math.Clamp (GetAnchor (superviewContentSize - location), 0, short.MaxValue);
}

/// <summary>
Expand Down
12 changes: 3 additions & 9 deletions Terminal.Gui/View/Layout/DimAbsolute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,13 @@ namespace Terminal.Gui;
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// </para>
/// </remarks>
/// <param name="size"></param>
public class DimAbsolute (int size) : Dim
/// <param name="Size"></param>
public record DimAbsolute (int Size) : Dim
{
/// <inheritdoc/>
public override bool Equals (object? other) { return other is DimAbsolute abs && abs.Size == Size; }

/// <inheritdoc/>
public override int GetHashCode () { return Size.GetHashCode (); }

/// <summary>
/// Gets the size of the dimension.
/// </summary>
public int Size { get; } = size;
public int Size { get; } = Size;

/// <inheritdoc/>
public override string ToString () { return $"Absolute({Size})"; }
Expand Down
73 changes: 13 additions & 60 deletions Terminal.Gui/View/Layout/DimAuto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,17 @@ namespace Terminal.Gui;
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// </para>
/// </remarks>
public class DimAuto : Dim
/// <param name="MaximumContentDim">The maximum dimension the View's ContentSize will be fit to.</param>
/// <param name="MinimumContentDim">The minimum dimension the View's ContentSize will be constrained to.</param>
/// <param name="Style">The <see cref="DimAutoStyle"/> of the <see cref="DimAuto"/>.</param>
public record DimAuto (Dim? MaximumContentDim, Dim? MinimumContentDim, DimAutoStyle Style) : Dim
{
private readonly Dim? _maximumContentDim;

private readonly Dim? _minimumContentDim;

private readonly DimAutoStyle _style;

/// <inheritdoc/>
public override bool Equals (object? other)
{
if (other is not DimAuto auto)
{
return false;
}

return auto.MinimumContentDim == MinimumContentDim && auto.MaximumContentDim == MaximumContentDim && auto.Style == Style;
}

/// <inheritdoc/>
public override int GetHashCode () { return HashCode.Combine (MinimumContentDim, MaximumContentDim, Style); }

/// <summary>
/// Gets the maximum dimension the View's ContentSize will be fit to. NOT CURRENTLY SUPPORTED.
/// </summary>

// ReSharper disable once ConvertToAutoProperty
public required Dim? MaximumContentDim
{
get => _maximumContentDim;
init => _maximumContentDim = value;
}

/// <summary>
/// Gets the minimum dimension the View's ContentSize will be constrained to.
/// </summary>

// ReSharper disable once ConvertToAutoProperty
public required Dim? MinimumContentDim
{
get => _minimumContentDim;
init => _minimumContentDim = value;
}

/// <summary>
/// Gets the style of the DimAuto.
/// </summary>

// ReSharper disable once ConvertToAutoProperty
public required DimAutoStyle Style
{
get => _style;
init => _style = value;
}

/// <inheritdoc/>
public override string ToString () { return $"Auto({Style},{MinimumContentDim},{MaximumContentDim})"; }

/// <inheritdoc />
internal override int GetAnchor (int size) => 0;

internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
{
var textSize = 0;
Expand Down Expand Up @@ -181,8 +134,8 @@ internal override int Calculate (int location, int superviewContentSize, View us
&& !v.X.Has (typeof (PosAnchorEnd), out _)
&& !v.X.Has (typeof (PosAlign), out _)
&& !v.X.Has (typeof (PosCenter), out _)
&& !v.Width.Has (typeof (DimFill), out _)
&& !v.Width.Has (typeof (DimPercent), out _)
&& !v.Width.Has<DimFill> (out _)
&& !v.Width.Has<DimPercent> (out _)
)
.ToList ();
}
Expand All @@ -194,8 +147,8 @@ internal override int Calculate (int location, int superviewContentSize, View us
&& !v.Y.Has (typeof (PosAnchorEnd), out _)
&& !v.Y.Has (typeof (PosAlign), out _)
&& !v.Y.Has (typeof (PosCenter), out _)
&& !v.Height.Has (typeof (DimFill), out _)
&& !v.Height.Has (typeof (DimPercent), out _)
&& !v.Height.Has<DimFill> (out _)
&& !v.Height.Has<DimPercent> (out _)
)
.ToList ();
}
Expand Down Expand Up @@ -419,11 +372,11 @@ internal override int Calculate (int location, int superviewContentSize, View us

if (dimension == Dimension.Width)
{
dimViewSubViews = includedSubviews.Where (v => v.Width is { } && v.Width.Has (typeof (DimView), out _)).ToList ();
dimViewSubViews = includedSubviews.Where (v => v.Width is { } && v.Width.Has<DimView> (out _)).ToList ();
}
else
{
dimViewSubViews = includedSubviews.Where (v => v.Height is { } && v.Height.Has (typeof (DimView), out _)).ToList ();
dimViewSubViews = includedSubviews.Where (v => v.Height is { } && v.Height.Has<DimView> (out _)).ToList ();
}

for (var i = 0; i < dimViewSubViews.Count; i++)
Expand Down
14 changes: 7 additions & 7 deletions Terminal.Gui/View/Layout/DimCombine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@ namespace Terminal.Gui;
/// <summary>
/// Represents a dimension that is a combination of two other dimensions.
/// </summary>
/// <param name="add">
/// <param name="Add">
/// Indicates whether the two dimensions are added or subtracted.
/// </param>
/// <remarks>
/// This is a low-level API that is typically used internally by the layout system. Use the various static
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// </remarks>
/// <param name="left">The left dimension.</param>
/// <param name="right">The right dimension.</param>
public class DimCombine (AddOrSubtract add, Dim left, Dim right) : Dim
/// <param name="Left">The left dimension.</param>
/// <param name="Right">The right dimension.</param>
public record DimCombine (AddOrSubtract Add, Dim Left, Dim Right) : Dim
{
/// <summary>
/// Gets whether the two dimensions are added or subtracted.
/// </summary>
public AddOrSubtract Add { get; } = add;
public AddOrSubtract Add { get; } = Add;

/// <summary>
/// Gets the left dimension.
/// </summary>
public Dim Left { get; } = left;
public Dim Left { get; } = Left;

/// <summary>
/// Gets the right dimension.
/// </summary>
public Dim Right { get; } = right;
public Dim Right { get; } = Right;

/// <inheritdoc/>
public override string ToString () { return $"Combine({Left}{(Add == AddOrSubtract.Add ? '+' : '-')}{Right})"; }
Expand Down
15 changes: 2 additions & 13 deletions Terminal.Gui/View/Layout/DimFill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,9 @@ namespace Terminal.Gui;
/// This is a low-level API that is typically used internally by the layout system. Use the various static
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// </remarks>
/// <param name="margin">The margin to not fill.</param>
public class DimFill (int margin) : Dim
/// <param name="Margin">The margin to not fill.</param>
public record DimFill (int Margin) : Dim
{
/// <inheritdoc/>
public override bool Equals (object? other) { return other is DimFill fill && fill.Margin == Margin; }

/// <inheritdoc/>
public override int GetHashCode () { return Margin.GetHashCode (); }

/// <summary>
/// Gets the margin to not fill.
/// </summary>
public int Margin { get; } = margin;

/// <inheritdoc/>
public override string ToString () { return $"Fill({Margin})"; }

Expand Down
20 changes: 7 additions & 13 deletions Terminal.Gui/View/Layout/DimFunc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,22 @@
namespace Terminal.Gui;

/// <summary>
/// Represents a function <see cref="Dim"/> object that computes the dimension by executing the provided function.
/// Represents a function <see cref="Gui.Dim"/> object that computes the dimension by executing the provided function.
/// </summary>
/// <remarks>
/// This is a low-level API that is typically used internally by the layout system. Use the various static
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// methods on the <see cref="Gui.Dim"/> class to create <see cref="Gui.Dim"/> objects instead.
/// </remarks>
/// <param name="dim"></param>
public class DimFunc (Func<int> dim) : Dim
/// <param name="Fn">The function that computes the dimension.</param>
public record DimFunc (Func<int> Fn) : Dim
{
/// <inheritdoc/>
public override bool Equals (object? other) { return other is DimFunc f && f.Func () == Func (); }

/// <summary>
/// Gets the function that computes the dimension.
/// </summary>
public new Func<int> Func { get; } = dim;

/// <inheritdoc/>
public override int GetHashCode () { return Func.GetHashCode (); }
public Func<int> Fn { get; } = Fn;

/// <inheritdoc/>
public override string ToString () { return $"DimFunc({Func ()})"; }
public override string ToString () { return $"DimFunc({Fn ()})"; }

internal override int GetAnchor (int size) { return Func (); }
internal override int GetAnchor (int size) { return Fn (); }
}
23 changes: 6 additions & 17 deletions Terminal.Gui/View/Layout/DimPercent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,24 @@ namespace Terminal.Gui;
/// This is a low-level API that is typically used internally by the layout system. Use the various static
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// </remarks>
/// <param name="percent">The percentage.</param>
/// <param name="mode">
/// <param name="Percentage">The percentage.</param>
/// <param name="Mode">
/// If <see cref="DimPercentMode.Position"/> the dimension is computed using the View's position (<see cref="View.X"/> or
/// <see cref="View.Y"/>); otherwise, the dimension is computed using the View's <see cref="View.GetContentSize ()"/>.
/// </param>
public class DimPercent (int percent, DimPercentMode mode = DimPercentMode.ContentSize) : Dim
public record DimPercent (int Percentage, DimPercentMode Mode = DimPercentMode.ContentSize) : Dim
{
/// <inheritdoc/>
public override bool Equals (object? other) { return other is DimPercent f && f.Percent == Percent && f.Mode == Mode; }

/// <inheritdoc/>
public override int GetHashCode () { return Percent.GetHashCode (); }

/// <summary>
/// Gets the percentage.
/// </summary>
public new int Percent { get; } = percent;

/// <summary>
/// </summary>
/// <returns></returns>
public override string ToString () { return $"Percent({Percent},{Mode})"; }
public override string ToString () { return $"Percent({Percentage},{Mode})"; }

/// <summary>
/// Gets whether the dimension is computed using the View's position or GetContentSize ().
/// </summary>
public DimPercentMode Mode { get; } = mode;
public DimPercentMode Mode { get; } = Mode;

internal override int GetAnchor (int size) { return (int)(size * (Percent / 100f)); }
internal override int GetAnchor (int size) { return (int)(size * (Percentage / 100f)); }

internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
{
Expand Down
8 changes: 1 addition & 7 deletions Terminal.Gui/View/Layout/DimView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Terminal.Gui;
/// This is a low-level API that is typically used internally by the layout system. Use the various static
/// methods on the <see cref="Dim"/> class to create <see cref="Dim"/> objects instead.
/// </remarks>
public class DimView : Dim
public record DimView : Dim
{
/// <summary>
/// Initializes a new instance of the <see cref="DimView"/> class.
Expand All @@ -26,12 +26,6 @@ public DimView (View? view, Dimension dimension)
/// </summary>
public Dimension Dimension { get; }

/// <inheritdoc/>
public override bool Equals (object? other) { return other is DimView abs && abs.Target == Target && abs.Dimension == Dimension; }

/// <inheritdoc/>
public override int GetHashCode () { return Target!.GetHashCode (); }

/// <summary>
/// Gets the View the dimension is anchored to.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/View/Layout/Pos.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ namespace Terminal.Gui;
/// </list>
/// </para>
/// </remarks>
public abstract class Pos
public abstract record Pos
{
#region static Pos creation methods

Expand Down
Loading

0 comments on commit 168d3ca

Please sign in to comment.