Tweaked primary constructors

This commit is contained in:
Tig
2024-08-14 13:06:15 -06:00
parent 6a13e777ff
commit 1b802d4b8f
11 changed files with 147 additions and 148 deletions

View File

@@ -10,13 +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 record DimAbsolute (int size) : Dim
/// <param name="Size"></param>
public record DimAbsolute (int Size) : Dim
{
/// <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})"; }

View File

@@ -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 record 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})"; }

View File

@@ -8,13 +8,13 @@ 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 record DimFill (int margin) : Dim
/// <param name="Margin">The margin to not fill.</param>
public record DimFill (int Margin) : Dim
{
/// <summary>
/// Gets the margin to not fill.
/// </summary>
public int Margin { get; } = margin;
public int Margin { get; } = Margin;
/// <inheritdoc/>
public override string ToString () { return $"Fill({Margin})"; }

View File

@@ -2,19 +2,19 @@
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 record DimFunc (Func<int> dim) : Dim
/// <param name="Dim"></param>
public record DimFunc (Func<int> Dim) : Dim
{
/// <summary>
/// Gets the function that computes the dimension.
/// </summary>
public new Func<int> Func { get; } = dim;
public new Func<int> Func { get; } = Dim;
/// <inheritdoc/>
public override int GetHashCode () { return Func.GetHashCode (); }

View File

@@ -8,17 +8,17 @@ 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="Percent">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 record DimPercent (int percent, DimPercentMode mode = DimPercentMode.ContentSize) : Dim
public record DimPercent (int Percent, DimPercentMode Mode = DimPercentMode.ContentSize) : Dim
{
/// <summary>
/// Gets the percentage.
/// </summary>
public new int Percent { get; } = percent;
public new int Percent { get; } = Percent;
/// <summary>
/// </summary>
@@ -28,7 +28,7 @@ public record DimPercent (int percent, DimPercentMode mode = DimPercentMode.Cont
/// <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)); }

View File

@@ -10,13 +10,13 @@ namespace Terminal.Gui;
/// methods on the <see cref="Pos"/> class to create <see cref="Pos"/> objects instead.
/// </para>
/// </remarks>
/// <param name="position"></param>
public record PosAbsolute (int position) : Pos
/// <param name="Position"></param>
public record PosAbsolute (int Position) : Pos
{
/// <summary>
/// The position of the <see cref="View"/> in the layout.
/// </summary>
public int Position { get; } = position;
public int Position { get; } = Position;
/// <inheritdoc/>
public override string ToString () { return $"Absolute({Position})"; }

View File

@@ -1,7 +1,6 @@
#nullable enable
using System.ComponentModel;
using System.Drawing;
namespace Terminal.Gui;
@@ -31,12 +30,6 @@ public record PosAlign : Pos
/// </summary>
public int? _cachedLocation;
/// <summary>
/// Gets the identifier of a set of views that should be aligned together. When only a single
/// set of views in a SuperView is aligned, setting <see cref="GroupId"/> is not needed because it defaults to 0.
/// </summary>
public int GroupId { get; init; }
private readonly Aligner? _aligner;
/// <summary>
@@ -57,6 +50,88 @@ public record PosAlign : Pos
}
}
// TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
/// <summary>
/// Returns the minimum size a group of views with the same <paramref name="groupId"/> can be.
/// </summary>
/// <param name="groupId"></param>
/// <param name="views"></param>
/// <param name="dimension"></param>
/// <returns></returns>
public static int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension)
{
List<int> dimensionsList = new ();
// PERF: If this proves a perf issue, consider caching a ref to this list in each item
List<View> viewsInGroup = views.Where (
v =>
{
return dimension switch
{
Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId,
Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
_ => false
};
})
.ToList ();
if (viewsInGroup.Count == 0)
{
return 0;
}
// PERF: We iterate over viewsInGroup multiple times here.
// Update the dimensionList with the sizes of the views
for (var index = 0; index < viewsInGroup.Count; index++)
{
View view = viewsInGroup [index];
PosAlign? posAlign = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign;
if (posAlign is { })
{
dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height);
}
}
// Align
return dimensionsList.Sum ();
}
/// <summary>
/// Gets the identifier of a set of views that should be aligned together. When only a single
/// set of views in a SuperView is aligned, setting <see cref="GroupId"/> is not needed because it defaults to 0.
/// </summary>
public int GroupId { get; init; }
/// <inheritdoc/>
public override string ToString () { return $"Align(alignment={Aligner.Alignment},modes={Aligner.AlignmentModes},groupId={GroupId})"; }
internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
{
if (_cachedLocation.HasValue && Aligner.ContainerSize == superviewDimension)
{
return _cachedLocation.Value;
}
if (us?.SuperView is null)
{
return 0;
}
AlignAndUpdateGroup (GroupId, us.SuperView.Subviews, dimension, superviewDimension);
if (_cachedLocation.HasValue)
{
return _cachedLocation.Value;
}
return 0;
}
internal override int GetAnchor (int width) { return _cachedLocation ?? 0 - width; }
/// <summary>
/// Aligns the views in <paramref name="views"/> that have the same group ID as <paramref name="groupId"/>.
/// Updates each view's cached _location.
@@ -71,30 +146,30 @@ public record PosAlign : Pos
// PERF: If this proves a perf issue, consider caching a ref to this list in each item
List<PosAlign?> posAligns = views.Select (
v =>
{
switch (dimension)
{
case Dimension.Width when v.X.Has (typeof (PosAlign), out var pos):
v =>
{
switch (dimension)
{
case Dimension.Width when v.X.Has (typeof (PosAlign), out Pos pos):
if (pos is PosAlign posAlignX && posAlignX.GroupId == groupId)
{
return posAlignX;
}
if (pos is PosAlign posAlignX && posAlignX.GroupId == groupId)
{
return posAlignX;
}
break;
case Dimension.Height when v.Y.Has (typeof (PosAlign), out var pos):
if (pos is PosAlign posAlignY && posAlignY.GroupId == groupId)
{
return posAlignY;
}
break;
case Dimension.Height when v.Y.Has (typeof (PosAlign), out Pos pos):
if (pos is PosAlign posAlignY && posAlignY.GroupId == groupId)
{
return posAlignY;
}
break;
}
break;
}
return null;
})
.ToList ();
return null;
})
.ToList ();
// PERF: We iterate over viewsInGroup multiple times here.
@@ -136,80 +211,4 @@ public record PosAlign : Pos
}
private void Aligner_PropertyChanged (object? sender, PropertyChangedEventArgs e) { _cachedLocation = null; }
/// <inheritdoc/>
public override string ToString () { return $"Align(alignment={Aligner.Alignment},modes={Aligner.AlignmentModes},groupId={GroupId})"; }
internal override int GetAnchor (int width) { return _cachedLocation ?? 0 - width; }
internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
{
if (_cachedLocation.HasValue && Aligner.ContainerSize == superviewDimension)
{
return _cachedLocation.Value;
}
if (us?.SuperView is null)
{
return 0;
}
AlignAndUpdateGroup (GroupId, us.SuperView.Subviews, dimension, superviewDimension);
if (_cachedLocation.HasValue)
{
return _cachedLocation.Value;
}
return 0;
}
// TODO: PosAlign.CalculateMinDimension is a hack. Need to figure out a better way of doing this.
/// <summary>
/// Returns the minimum size a group of views with the same <paramref name="groupId"/> can be.
/// </summary>
/// <param name="groupId"></param>
/// <param name="views"></param>
/// <param name="dimension"></param>
/// <returns></returns>
public static int CalculateMinDimension (int groupId, IList<View> views, Dimension dimension)
{
List<int> dimensionsList = new ();
// PERF: If this proves a perf issue, consider caching a ref to this list in each item
List<View> viewsInGroup = views.Where (
v =>
{
return dimension switch
{
Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId,
Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId,
_ => false
};
})
.ToList ();
if (viewsInGroup.Count == 0)
{
return 0;
}
// PERF: We iterate over viewsInGroup multiple times here.
// Update the dimensionList with the sizes of the views
for (var index = 0; index < viewsInGroup.Count; index++)
{
View view = viewsInGroup [index];
PosAlign? posAlign = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign;
if (posAlign is { })
{
dimensionsList.Add (dimension == Dimension.Width ? view.Frame.Width : view.Frame.Height);
}
}
// Align
return dimensionsList.Sum ();
}
}

View File

@@ -10,27 +10,27 @@ namespace Terminal.Gui;
/// methods on the <see cref="Pos"/> class to create <see cref="Pos"/> objects instead.
/// </para>
/// </remarks>
/// <param name="add">
/// <param name="Add">
/// Indicates whether the two positions are added or subtracted.
/// </param>
/// <param name="left">The left position.</param>
/// <param name="right">The right position.</param>
public record PosCombine (AddOrSubtract add, Pos left, Pos right) : Pos
/// <param name="Left">The left position.</param>
/// <param name="Right">The right position.</param>
public record PosCombine (AddOrSubtract Add, Pos Left, Pos Right) : Pos
{
/// <summary>
/// Gets whether the two positions are added or subtracted.
/// </summary>
public AddOrSubtract Add { get; } = add;
public AddOrSubtract Add { get; } = Add;
/// <summary>
/// Gets the left position.
/// </summary>
public new Pos Left { get; } = left;
public new Pos Left { get; } = Left;
/// <summary>
/// Gets the right position.
/// </summary>
public new Pos Right { get; } = right;
public new Pos Right { get; } = Right;
/// <inheritdoc/>
public override string ToString () { return $"Combine({Left}{(Add == AddOrSubtract.Add ? '+' : '-')}{Right})"; }

View File

@@ -7,16 +7,16 @@ namespace Terminal.Gui;
/// <remarks>
/// <para>
/// This is a low-level API that is typically used internally by the layout system. Use the various static
/// methods on the <see cref="Pos"/> class to create <see cref="Pos"/> objects instead.
/// methods on the <see cref="Gui.Pos"/> class to create <see cref="Gui.Pos"/> objects instead.
/// </para>
/// </remarks>
/// <param name="pos">The position.</param>
public record PosFunc (Func<int> pos) : Pos
/// <param name="Pos">The position.</param>
public record PosFunc (Func<int> Pos) : Pos
{
/// <summary>
/// Gets the function that computes the position.
/// </summary>
public new Func<int> Func { get; } = pos;
public new Func<int> Func { get; } = Pos;
/// <inheritdoc/>
public override string ToString () { return $"PosFunc({Func ()})"; }

View File

@@ -10,13 +10,13 @@ namespace Terminal.Gui;
/// methods on the <see cref="Pos"/> class to create <see cref="Pos"/> objects instead.
/// </para>
/// </remarks>
/// <param name="percent"></param>
public record PosPercent (int percent) : Pos
/// <param name="Percent"></param>
public record PosPercent (int Percent) : Pos
{
/// <summary>
/// Gets the percentage of the width or height of the SuperView.
/// </summary>
public new int Percent { get; } = percent;
public new int Percent { get; } = Percent;
/// <inheritdoc/>
public override string ToString () { return $"Percent({Percent})"; }

View File

@@ -10,19 +10,19 @@ namespace Terminal.Gui;
/// methods on the <see cref="Pos"/> class to create <see cref="Pos"/> objects instead.
/// </para>
/// </remarks>
/// <param name="view">The View the position is anchored to.</param>
/// <param name="side">The side of the View the position is anchored to.</param>
public record PosView (View? view, Side side) : Pos
/// <param name="View">The View the position is anchored to.</param>
/// <param name="Side">The side of the View the position is anchored to.</param>
public record PosView (View? View, Side Side) : Pos
{
/// <summary>
/// Gets the View the position is anchored to.
/// </summary>
public View? Target { get; } = view;
public View? Target { get; } = View;
/// <summary>
/// Gets the side of the View the position is anchored to.
/// </summary>
public Side Side { get; } = side;
public Side Side { get; } = Side;
/// <inheritdoc/>
public override string ToString ()