diff --git a/Terminal.Gui/View/Layout/Dim.cs b/Terminal.Gui/View/Layout/Dim.cs
index a04b9798d..dc4b612a9 100644
--- a/Terminal.Gui/View/Layout/Dim.cs
+++ b/Terminal.Gui/View/Layout/Dim.cs
@@ -3,69 +3,6 @@ using System.Diagnostics;
namespace Terminal.Gui;
-///
-/// Specifies how will compute the dimension.
-///
-[Flags]
-public enum DimAutoStyle
-{
- ///
- /// The dimension will be computed using both the view's and
- /// (whichever is larger).
- ///
- Auto = Content | Text,
-
- ///
- /// The dimensions will be computed based on the View's non-Text content.
- ///
- /// If is explicitly set (is not ) then
- ///
- /// will be used to determine the dimension.
- ///
- ///
- /// Otherwise, the Subview in with the largest corresponding position plus dimension
- /// will determine the dimension.
- ///
- ///
- /// The corresponding dimension of the view's will be ignored.
- ///
- ///
- Content = 0,
-
- ///
- ///
- /// The corresponding dimension of the view's , formatted using the
- /// settings,
- /// will be used to determine the dimension.
- ///
- ///
- /// The corresponding dimensions of the will be ignored.
- ///
- ///
- Text = 1
-}
-
-///
-/// Indicates the dimension for operations.
-///
-public enum Dimension
-{
- ///
- /// No dimension specified.
- ///
- None = 0,
-
- ///
- /// The height dimension.
- ///
- Height = 1,
-
- ///
- /// The width dimension.
- ///
- Width = 2
-}
-
///
///
/// A Dim object describes the dimensions of a . Dim is the type of the
@@ -337,479 +274,4 @@ public abstract class Dim
#endregion operators
-}
-
-///
-/// Represents a dimension that is a fixed size.
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-///
-public class DimAbsolute (int size) : Dim
-{
- ///
- public override bool Equals (object? other) { return other is DimAbsolute abs && abs.Size == Size; }
-
- ///
- public override int GetHashCode () { return Size.GetHashCode (); }
-
- ///
- /// Gets the size of the dimension.
- ///
- public int Size { get; } = size;
-
- ///
- public override string ToString () { return $"Absolute({Size})"; }
-
- internal override int GetAnchor (int size) { return Size; }
-
- internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
- {
- return Math.Max (GetAnchor (0), 0);
- }
-}
-
-///
-/// Represents a dimension that automatically sizes the view to fit all the view's Content, SubViews, and/or Text.
-///
-///
-///
-/// See .
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-public class DimAuto () : Dim
-{
- private readonly Dim? _maximumContentDim;
-
- ///
- /// Gets the maximum dimension the View's ContentSize will be fit to. NOT CURRENTLY SUPPORTED.
- ///
- // ReSharper disable once ConvertToAutoProperty
- public required Dim? MaximumContentDim
- {
- get => _maximumContentDim;
- init => _maximumContentDim = value;
- }
-
- private readonly Dim? _minimumContentDim;
-
- ///
- /// Gets the minimum dimension the View's ContentSize will be constrained to.
- ///
- // ReSharper disable once ConvertToAutoProperty
- public required Dim? MinimumContentDim
- {
- get => _minimumContentDim;
- init => _minimumContentDim = value;
- }
-
- private readonly DimAutoStyle _style;
-
- ///
- /// Gets the style of the DimAuto.
- ///
- // ReSharper disable once ConvertToAutoProperty
- public required DimAutoStyle Style
- {
- get => _style;
- init => _style = value;
- }
-
- ///
- public override string ToString () { return $"Auto({Style},{MinimumContentDim},{MaximumContentDim})"; }
-
- internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
- {
- var textSize = 0;
- var subviewsSize = 0;
-
- int autoMin = MinimumContentDim?.GetAnchor (superviewContentSize) ?? 0;
-
- if (Style.HasFlag (DimAutoStyle.Text))
- {
- textSize = int.Max (autoMin, dimension == Dimension.Width ? us.TextFormatter.Size.Width : us.TextFormatter.Size.Height);
- }
-
- if (Style.HasFlag (DimAutoStyle.Content))
- {
- if (us._contentSize is { })
- {
- subviewsSize = dimension == Dimension.Width ? us.ContentSize.Width : us.ContentSize.Height;
- }
- else
- {
- // TODO: This whole body of code is a WIP (for https://github.com/gui-cs/Terminal.Gui/pull/3451).
- subviewsSize = 0;
-
- List subviews;
-
- if (dimension == Dimension.Width)
- {
- subviews = us.Subviews.Where (v => v.X is not PosAnchorEnd && v.Width is not DimFill).ToList ();
- }
- else
- {
- subviews = us.Subviews.Where (v => v.Y is not PosAnchorEnd && v.Height is not DimFill).ToList ();
- }
-
- for (var i = 0; i < subviews.Count; i++)
- {
- View v = subviews [i];
-
- int size = dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height;
-
- if (size > subviewsSize)
- {
- subviewsSize = size;
- }
- }
-
- if (dimension == Dimension.Width)
- {
- subviews = us.Subviews.Where (v => v.X is PosAnchorEnd).ToList ();
- }
- else
- {
- subviews = us.Subviews.Where (v => v.Y is PosAnchorEnd).ToList ();
- }
-
- int maxAnchorEnd = 0;
- for (var i = 0; i < subviews.Count; i++)
- {
- View v = subviews [i];
- maxAnchorEnd = dimension == Dimension.Width ? v.Frame.Width : v.Frame.Height;
- }
-
- subviewsSize += maxAnchorEnd;
-
-
- if (dimension == Dimension.Width)
- {
- subviews = us.Subviews.Where (v => v.Width is DimFill).ToList ();
- }
- else
- {
- subviews = us.Subviews.Where (v => v.Height is DimFill).ToList ();
- }
-
- for (var i = 0; i < subviews.Count; i++)
- {
- View v = subviews [i];
-
- if (dimension == Dimension.Width)
- {
- v.SetRelativeLayout (new Size (autoMin - subviewsSize, 0));
- }
- else
- {
- v.SetRelativeLayout (new Size (0, autoMin - subviewsSize));
- }
- }
-
- }
- }
-
- // All sizes here are content-relative; ignoring adornments.
- // We take the largest of text and content.
- int max = int.Max (textSize, subviewsSize);
-
- // And, if min: is set, it wins if larger
- max = int.Max (max, autoMin);
-
- // Factor in adornments
- Thickness thickness = us.GetAdornmentsThickness ();
-
- max += dimension switch
- {
- Dimension.Width => thickness.Horizontal,
- Dimension.Height => thickness.Vertical,
- Dimension.None => 0,
- _ => throw new ArgumentOutOfRangeException (nameof (dimension), dimension, null)
- };
-
- return int.Min (max, MaximumContentDim?.GetAnchor (superviewContentSize) ?? max);
- }
-
- internal override bool ReferencesOtherViews ()
- {
- // BUGBUG: This is not correct. _contentSize may be null.
- return false; //_style.HasFlag (DimAutoStyle.Content);
- }
-
- ///
- public override bool Equals (object? other)
- {
- if (other is not DimAuto auto)
- {
- return false;
- }
-
- return auto.MinimumContentDim == MinimumContentDim &&
- auto.MaximumContentDim == MaximumContentDim &&
- auto.Style == Style;
- }
-
- ///
- public override int GetHashCode ()
- {
- return HashCode.Combine (MinimumContentDim, MaximumContentDim, Style);
- }
-
-}
-
-///
-/// Represents a dimension that is a combination of two other dimensions.
-///
-///
-/// Indicates whether the two dimensions are added or subtracted.
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-/// The left dimension.
-/// The right dimension.
-public class DimCombine (AddOrSubtract add, Dim? left, Dim? right) : Dim
-{
- ///
- /// Gets whether the two dimensions are added or subtracted.
- ///
- public AddOrSubtract Add { get; } = add;
-
- ///
- /// Gets the left dimension.
- ///
- public Dim? Left { get; } = left;
-
- ///
- /// Gets the right dimension.
- ///
- public Dim? Right { get; } = right;
-
- ///
- public override string ToString () { return $"Combine({Left}{(Add == AddOrSubtract.Add ? '+' : '-')}{Right})"; }
-
- internal override int GetAnchor (int size)
- {
- int la = Left!.GetAnchor (size);
- int ra = Right!.GetAnchor (size);
-
- if (Add == AddOrSubtract.Add)
- {
- return la + ra;
- }
-
- return la - ra;
- }
-
- internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
- {
- int leftNewDim = Left!.Calculate (location, superviewContentSize, us, dimension);
- int rightNewDim = Right!.Calculate (location, superviewContentSize, us, dimension);
-
- int newDimension;
-
- if (Add == AddOrSubtract.Add)
- {
- newDimension = leftNewDim + rightNewDim;
- }
- else
- {
- newDimension = Math.Max (0, leftNewDim - rightNewDim);
- }
-
- return newDimension;
- }
-
- ///
- /// Diagnostics API to determine if this Dim object references other views.
- ///
- ///
- internal override bool ReferencesOtherViews ()
- {
- if (Left!.ReferencesOtherViews ())
- {
- return true;
- }
-
- if (Right!.ReferencesOtherViews ())
- {
- return true;
- }
-
- return false;
- }
-}
-
-///
-/// Represents a dimension that is a percentage of the width or height of the SuperView.
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-/// The percentage.
-///
-/// If the dimension is computed using the View's position ( or
-/// ).
-/// If the dimension is computed using the View's .
-///
-public class DimPercent (float percent, bool usePosition = false) : Dim
-{
- ///
- public override bool Equals (object? other) { return other is DimPercent f && f.Percent == Percent && f.UsePosition == UsePosition; }
-
- ///
- public override int GetHashCode () { return Percent.GetHashCode (); }
-
- ///
- /// Gets the percentage.
- ///
- public new float Percent { get; } = percent;
-
- ///
- ///
- ///
- public override string ToString () { return $"Percent({Percent},{UsePosition})"; }
-
- ///
- /// Gets whether the dimension is computed using the View's position or ContentSize.
- ///
- public bool UsePosition { get; } = usePosition;
-
- internal override int GetAnchor (int size) { return (int)(size * Percent); }
-
- internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
- {
- return UsePosition ? Math.Max (GetAnchor (superviewContentSize - location), 0) : GetAnchor (superviewContentSize);
- }
-}
-
-///
-/// Represents a dimension that fills the dimension, leaving the specified margin.
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-/// The margin to not fill.
-public class DimFill (int margin) : Dim
-{
- ///
- public override bool Equals (object? other) { return other is DimFill fill && fill.Margin == Margin; }
-
- ///
- public override int GetHashCode () { return Margin.GetHashCode (); }
-
- ///
- /// Gets the margin to not fill.
- ///
- public int Margin { get; } = margin;
-
- ///
- public override string ToString () { return $"Fill({Margin})"; }
-
- internal override int GetAnchor (int size) { return size - Margin; }
-}
-
-///
-/// Represents a function object that computes the dimension by executing the provided function.
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-public class DimFunc (Func dim) : Dim
-{
- ///
- public override bool Equals (object? other) { return other is DimFunc f && f.Func () == Func (); }
-
- ///
- /// Gets the function that computes the dimension.
- ///
- public new Func Func { get; } = dim;
-
- ///
- public override int GetHashCode () { return Func.GetHashCode (); }
-
- ///
- public override string ToString () { return $"DimFunc({Func ()})"; }
-
- internal override int GetAnchor (int size) { return Func (); }
-}
-
-///
-/// Represents a dimension that tracks the Height or Width of the specified View.
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-public class DimView : Dim
-{
- ///
- /// Initializes a new instance of the class.
- ///
- /// The view the dimension is anchored to.
- /// Indicates which dimension is tracked.
- public DimView (View view, Dimension dimension)
- {
- Target = view;
- Dimension = dimension;
- }
-
- ///
- /// Gets the indicated dimension of the View.
- ///
- public Dimension Dimension { get; }
-
- ///
- public override bool Equals (object? other) { return other is DimView abs && abs.Target == Target && abs.Dimension == Dimension; }
-
- ///
- public override int GetHashCode () { return Target.GetHashCode (); }
-
- ///
- /// Gets the View the dimension is anchored to.
- ///
- public View Target { get; init; }
-
- ///
- public override string ToString ()
- {
- if (Target == null)
- {
- throw new NullReferenceException ();
- }
-
- string dimString = Dimension switch
- {
- Dimension.Height => "Height",
- Dimension.Width => "Width",
- _ => "unknown"
- };
-
- return $"View({dimString},{Target})";
- }
-
- internal override int GetAnchor (int size)
- {
- return Dimension switch
- {
- Dimension.Height => Target.Frame.Height,
- Dimension.Width => Target.Frame.Width,
- _ => 0
- };
- }
-
- internal override bool ReferencesOtherViews () { return true; }
-}
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimAbsolute.cs b/Terminal.Gui/View/Layout/DimAbsolute.cs
new file mode 100644
index 000000000..72d4e12f7
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimAbsolute.cs
@@ -0,0 +1,36 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a dimension that is a fixed size.
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+///
+public class DimAbsolute (int size) : Dim
+{
+ ///
+ public override bool Equals (object? other) { return other is DimAbsolute abs && abs.Size == Size; }
+
+ ///
+ public override int GetHashCode () { return Size.GetHashCode (); }
+
+ ///
+ /// Gets the size of the dimension.
+ ///
+ public int Size { get; } = size;
+
+ ///
+ public override string ToString () { return $"Absolute({Size})"; }
+
+ internal override int GetAnchor (int size) { return Size; }
+
+ internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
+ {
+ return Math.Max (GetAnchor (0), 0);
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimAuto.cs b/Terminal.Gui/View/Layout/DimAuto.cs
new file mode 100644
index 000000000..6a569b01c
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimAuto.cs
@@ -0,0 +1,194 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a dimension that automatically sizes the view to fit all the view's Content, SubViews, and/or Text.
+///
+///
+///
+/// See .
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+public class DimAuto () : Dim
+{
+ private readonly Dim? _maximumContentDim;
+
+ ///
+ /// Gets the maximum dimension the View's ContentSize will be fit to. NOT CURRENTLY SUPPORTED.
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public required Dim? MaximumContentDim
+ {
+ get => _maximumContentDim;
+ init => _maximumContentDim = value;
+ }
+
+ private readonly Dim? _minimumContentDim;
+
+ ///
+ /// Gets the minimum dimension the View's ContentSize will be constrained to.
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public required Dim? MinimumContentDim
+ {
+ get => _minimumContentDim;
+ init => _minimumContentDim = value;
+ }
+
+ private readonly DimAutoStyle _style;
+
+ ///
+ /// Gets the style of the DimAuto.
+ ///
+ // ReSharper disable once ConvertToAutoProperty
+ public required DimAutoStyle Style
+ {
+ get => _style;
+ init => _style = value;
+ }
+
+ ///
+ public override string ToString () { return $"Auto({Style},{MinimumContentDim},{MaximumContentDim})"; }
+
+ internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
+ {
+ var textSize = 0;
+ var subviewsSize = 0;
+
+ int autoMin = MinimumContentDim?.GetAnchor (superviewContentSize) ?? 0;
+
+ if (Style.HasFlag (DimAutoStyle.Text))
+ {
+ textSize = int.Max (autoMin, dimension == Dimension.Width ? us.TextFormatter.Size.Width : us.TextFormatter.Size.Height);
+ }
+
+ if (Style.HasFlag (DimAutoStyle.Content))
+ {
+ if (us._contentSize is { })
+ {
+ subviewsSize = dimension == Dimension.Width ? us.ContentSize.Width : us.ContentSize.Height;
+ }
+ else
+ {
+ // TODO: This whole body of code is a WIP (for https://github.com/gui-cs/Terminal.Gui/pull/3451).
+ subviewsSize = 0;
+
+ List subviews;
+
+ if (dimension == Dimension.Width)
+ {
+ subviews = us.Subviews.Where (v => v.X is not PosAnchorEnd && v.Width is not DimFill).ToList ();
+ }
+ else
+ {
+ subviews = us.Subviews.Where (v => v.Y is not PosAnchorEnd && v.Height is not DimFill).ToList ();
+ }
+
+ for (var i = 0; i < subviews.Count; i++)
+ {
+ View v = subviews [i];
+
+ int size = dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height;
+
+ if (size > subviewsSize)
+ {
+ subviewsSize = size;
+ }
+ }
+
+ if (dimension == Dimension.Width)
+ {
+ subviews = us.Subviews.Where (v => v.X is PosAnchorEnd).ToList ();
+ }
+ else
+ {
+ subviews = us.Subviews.Where (v => v.Y is PosAnchorEnd).ToList ();
+ }
+
+ int maxAnchorEnd = 0;
+ for (var i = 0; i < subviews.Count; i++)
+ {
+ View v = subviews [i];
+ maxAnchorEnd = dimension == Dimension.Width ? v.Frame.Width : v.Frame.Height;
+ }
+
+ subviewsSize += maxAnchorEnd;
+
+
+ if (dimension == Dimension.Width)
+ {
+ subviews = us.Subviews.Where (v => v.Width is DimFill).ToList ();
+ }
+ else
+ {
+ subviews = us.Subviews.Where (v => v.Height is DimFill).ToList ();
+ }
+
+ for (var i = 0; i < subviews.Count; i++)
+ {
+ View v = subviews [i];
+
+ if (dimension == Dimension.Width)
+ {
+ v.SetRelativeLayout (new Size (autoMin - subviewsSize, 0));
+ }
+ else
+ {
+ v.SetRelativeLayout (new Size (0, autoMin - subviewsSize));
+ }
+ }
+
+ }
+ }
+
+ // All sizes here are content-relative; ignoring adornments.
+ // We take the largest of text and content.
+ int max = int.Max (textSize, subviewsSize);
+
+ // And, if min: is set, it wins if larger
+ max = int.Max (max, autoMin);
+
+ // Factor in adornments
+ Thickness thickness = us.GetAdornmentsThickness ();
+
+ max += dimension switch
+ {
+ Dimension.Width => thickness.Horizontal,
+ Dimension.Height => thickness.Vertical,
+ Dimension.None => 0,
+ _ => throw new ArgumentOutOfRangeException (nameof (dimension), dimension, null)
+ };
+
+ return int.Min (max, MaximumContentDim?.GetAnchor (superviewContentSize) ?? max);
+ }
+
+ internal override bool ReferencesOtherViews ()
+ {
+ // BUGBUG: This is not correct. _contentSize may be null.
+ return false; //_style.HasFlag (DimAutoStyle.Content);
+ }
+
+ ///
+ public override bool Equals (object? other)
+ {
+ if (other is not DimAuto auto)
+ {
+ return false;
+ }
+
+ return auto.MinimumContentDim == MinimumContentDim &&
+ auto.MaximumContentDim == MaximumContentDim &&
+ auto.Style == Style;
+ }
+
+ ///
+ public override int GetHashCode ()
+ {
+ return HashCode.Combine (MinimumContentDim, MaximumContentDim, Style);
+ }
+
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimAutoStyle.cs b/Terminal.Gui/View/Layout/DimAutoStyle.cs
new file mode 100644
index 000000000..271a53d8e
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimAutoStyle.cs
@@ -0,0 +1,43 @@
+namespace Terminal.Gui;
+
+///
+/// Specifies how will compute the dimension.
+///
+[Flags]
+public enum DimAutoStyle
+{
+ ///
+ /// The dimension will be computed using both the view's and
+ /// (whichever is larger).
+ ///
+ Auto = Content | Text,
+
+ ///
+ /// The dimensions will be computed based on the View's non-Text content.
+ ///
+ /// If is explicitly set (is not ) then
+ ///
+ /// will be used to determine the dimension.
+ ///
+ ///
+ /// Otherwise, the Subview in with the largest corresponding position plus dimension
+ /// will determine the dimension.
+ ///
+ ///
+ /// The corresponding dimension of the view's will be ignored.
+ ///
+ ///
+ Content = 0,
+
+ ///
+ ///
+ /// The corresponding dimension of the view's , formatted using the
+ /// settings,
+ /// will be used to determine the dimension.
+ ///
+ ///
+ /// The corresponding dimensions of the will be ignored.
+ ///
+ ///
+ Text = 1
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimCombine.cs b/Terminal.Gui/View/Layout/DimCombine.cs
new file mode 100644
index 000000000..d66352855
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimCombine.cs
@@ -0,0 +1,86 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a dimension that is a combination of two other dimensions.
+///
+///
+/// Indicates whether the two dimensions are added or subtracted.
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+/// The left dimension.
+/// The right dimension.
+public class DimCombine (AddOrSubtract add, Dim? left, Dim? right) : Dim
+{
+ ///
+ /// Gets whether the two dimensions are added or subtracted.
+ ///
+ public AddOrSubtract Add { get; } = add;
+
+ ///
+ /// Gets the left dimension.
+ ///
+ public Dim? Left { get; } = left;
+
+ ///
+ /// Gets the right dimension.
+ ///
+ public Dim? Right { get; } = right;
+
+ ///
+ public override string ToString () { return $"Combine({Left}{(Add == AddOrSubtract.Add ? '+' : '-')}{Right})"; }
+
+ internal override int GetAnchor (int size)
+ {
+ int la = Left!.GetAnchor (size);
+ int ra = Right!.GetAnchor (size);
+
+ if (Add == AddOrSubtract.Add)
+ {
+ return la + ra;
+ }
+
+ return la - ra;
+ }
+
+ internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
+ {
+ int leftNewDim = Left!.Calculate (location, superviewContentSize, us, dimension);
+ int rightNewDim = Right!.Calculate (location, superviewContentSize, us, dimension);
+
+ int newDimension;
+
+ if (Add == AddOrSubtract.Add)
+ {
+ newDimension = leftNewDim + rightNewDim;
+ }
+ else
+ {
+ newDimension = Math.Max (0, leftNewDim - rightNewDim);
+ }
+
+ return newDimension;
+ }
+
+ ///
+ /// Diagnostics API to determine if this Dim object references other views.
+ ///
+ ///
+ internal override bool ReferencesOtherViews ()
+ {
+ if (Left!.ReferencesOtherViews ())
+ {
+ return true;
+ }
+
+ if (Right!.ReferencesOtherViews ())
+ {
+ return true;
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimFill.cs b/Terminal.Gui/View/Layout/DimFill.cs
new file mode 100644
index 000000000..03cf6f3d2
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimFill.cs
@@ -0,0 +1,29 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a dimension that fills the dimension, leaving the specified margin.
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+/// The margin to not fill.
+public class DimFill (int margin) : Dim
+{
+ ///
+ public override bool Equals (object? other) { return other is DimFill fill && fill.Margin == Margin; }
+
+ ///
+ public override int GetHashCode () { return Margin.GetHashCode (); }
+
+ ///
+ /// Gets the margin to not fill.
+ ///
+ public int Margin { get; } = margin;
+
+ ///
+ public override string ToString () { return $"Fill({Margin})"; }
+
+ internal override int GetAnchor (int size) { return size - Margin; }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimFunc.cs b/Terminal.Gui/View/Layout/DimFunc.cs
new file mode 100644
index 000000000..c15e9fc8c
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimFunc.cs
@@ -0,0 +1,29 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a function object that computes the dimension by executing the provided function.
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+public class DimFunc (Func dim) : Dim
+{
+ ///
+ public override bool Equals (object? other) { return other is DimFunc f && f.Func () == Func (); }
+
+ ///
+ /// Gets the function that computes the dimension.
+ ///
+ public new Func Func { get; } = dim;
+
+ ///
+ public override int GetHashCode () { return Func.GetHashCode (); }
+
+ ///
+ public override string ToString () { return $"DimFunc({Func ()})"; }
+
+ internal override int GetAnchor (int size) { return Func (); }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimPercent.cs b/Terminal.Gui/View/Layout/DimPercent.cs
new file mode 100644
index 000000000..7e535d308
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimPercent.cs
@@ -0,0 +1,46 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a dimension that is a percentage of the width or height of the SuperView.
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+/// The percentage.
+///
+/// If the dimension is computed using the View's position ( or
+/// ).
+/// If the dimension is computed using the View's .
+///
+public class DimPercent (float percent, bool usePosition = false) : Dim
+{
+ ///
+ public override bool Equals (object? other) { return other is DimPercent f && f.Percent == Percent && f.UsePosition == UsePosition; }
+
+ ///
+ public override int GetHashCode () { return Percent.GetHashCode (); }
+
+ ///
+ /// Gets the percentage.
+ ///
+ public new float Percent { get; } = percent;
+
+ ///
+ ///
+ ///
+ public override string ToString () { return $"Percent({Percent},{UsePosition})"; }
+
+ ///
+ /// Gets whether the dimension is computed using the View's position or ContentSize.
+ ///
+ public bool UsePosition { get; } = usePosition;
+
+ internal override int GetAnchor (int size) { return (int)(size * Percent); }
+
+ internal override int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
+ {
+ return UsePosition ? Math.Max (GetAnchor (superviewContentSize - location), 0) : GetAnchor (superviewContentSize);
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/DimView.cs b/Terminal.Gui/View/Layout/DimView.cs
new file mode 100644
index 000000000..8e7c22b52
--- /dev/null
+++ b/Terminal.Gui/View/Layout/DimView.cs
@@ -0,0 +1,69 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a dimension that tracks the Height or Width of the specified View.
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+public class DimView : Dim
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The view the dimension is anchored to.
+ /// Indicates which dimension is tracked.
+ public DimView (View view, Dimension dimension)
+ {
+ Target = view;
+ Dimension = dimension;
+ }
+
+ ///
+ /// Gets the indicated dimension of the View.
+ ///
+ public Dimension Dimension { get; }
+
+ ///
+ public override bool Equals (object? other) { return other is DimView abs && abs.Target == Target && abs.Dimension == Dimension; }
+
+ ///
+ public override int GetHashCode () { return Target.GetHashCode (); }
+
+ ///
+ /// Gets the View the dimension is anchored to.
+ ///
+ public View Target { get; init; }
+
+ ///
+ public override string ToString ()
+ {
+ if (Target == null)
+ {
+ throw new NullReferenceException ();
+ }
+
+ string dimString = Dimension switch
+ {
+ Dimension.Height => "Height",
+ Dimension.Width => "Width",
+ _ => "unknown"
+ };
+
+ return $"View({dimString},{Target})";
+ }
+
+ internal override int GetAnchor (int size)
+ {
+ return Dimension switch
+ {
+ Dimension.Height => Target.Frame.Height,
+ Dimension.Width => Target.Frame.Width,
+ _ => 0
+ };
+ }
+
+ internal override bool ReferencesOtherViews () { return true; }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/Dimension.cs b/Terminal.Gui/View/Layout/Dimension.cs
new file mode 100644
index 000000000..65186b4ab
--- /dev/null
+++ b/Terminal.Gui/View/Layout/Dimension.cs
@@ -0,0 +1,22 @@
+namespace Terminal.Gui;
+
+///
+/// Indicates the dimension for operations.
+///
+public enum Dimension
+{
+ ///
+ /// No dimension specified.
+ ///
+ None = 0,
+
+ ///
+ /// The height dimension.
+ ///
+ Height = 1,
+
+ ///
+ /// The width dimension.
+ ///
+ Width = 2
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/LayoutStyle.cs b/Terminal.Gui/View/Layout/LayoutStyle.cs
new file mode 100644
index 000000000..36e55a4ec
--- /dev/null
+++ b/Terminal.Gui/View/Layout/LayoutStyle.cs
@@ -0,0 +1,35 @@
+namespace Terminal.Gui;
+
+///
+/// Indicates the LayoutStyle for the .
+///
+/// If Absolute, the , , , and
+/// objects are all absolute values and are not relative. The position and size of the
+/// view is described by .
+///
+///
+/// If Computed, one or more of the , , , or
+/// objects are relative to the and are computed at layout
+/// time.
+///
+///
+public enum LayoutStyle
+{
+ ///
+ /// Indicates the , , , and
+ /// objects are all absolute values and are not relative. The position and size of the view
+ /// is described by .
+ ///
+ Absolute,
+
+ ///
+ /// Indicates one or more of the , , , or
+ ///
+ /// objects are relative to the and are computed at layout time. The position and size of
+ /// the
+ /// view
+ /// will be computed based on these objects at layout time. will provide the absolute computed
+ /// values.
+ ///
+ Computed
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/Pos.cs b/Terminal.Gui/View/Layout/Pos.cs
index 1935e3c02..8db733431 100644
--- a/Terminal.Gui/View/Layout/Pos.cs
+++ b/Terminal.Gui/View/Layout/Pos.cs
@@ -1,31 +1,6 @@
+#nullable enable
namespace Terminal.Gui;
-///
-/// Indicates the side for operations.
-///
-public enum Side
-{
- ///
- /// The left (X) side of the view.
- ///
- Left = 0,
-
- ///
- /// The top (Y) side of the view.
- ///
- Top = 1,
-
- ///
- /// The right (X + Width) side of the view.
- ///
- Right = 2,
-
- ///
- /// The bottom (Y + Height) side of the view.
- ///
- Bottom = 3
-}
-
///
/// Describes the position of a which can be an absolute value, a percentage, centered, or
/// relative to the ending dimension. Integer values are implicitly convertible to an absolute . These
@@ -385,315 +360,4 @@ public abstract class Pos
#endregion operators
-}
-
-///
-/// Represents an absolute position in the layout. This is used to specify a fixed position in the layout.
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-///
-public class PosAbsolute (int position) : Pos
-{
- ///
- /// The position of the in the layout.
- ///
- public int Position { get; } = position;
-
- ///
- public override bool Equals (object other) { return other is PosAbsolute abs && abs.Position == Position; }
-
- ///
- public override int GetHashCode () { return Position.GetHashCode (); }
-
- ///
- public override string ToString () { return $"Absolute({Position})"; }
-
- internal override int GetAnchor (int size) { return Position; }
-}
-
-///
-/// Represents a position anchored to the end (right side or bottom).
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-public class PosAnchorEnd : Pos
-{
- ///
- /// Gets the offset of the position from the right/bottom.
- ///
- public int Offset { get; }
-
- ///
- /// Constructs a new position anchored to the end (right side or bottom) of the SuperView,
- /// minus the respective dimension of the View. This is equivalent to using ,
- /// with an offset equivalent to the View's respective dimension.
- ///
- public PosAnchorEnd () { UseDimForOffset = true; }
-
- ///
- /// Constructs a new position anchored to the end (right side or bottom) of the SuperView,
- ///
- ///
- public PosAnchorEnd (int offset) { Offset = offset; }
-
- ///
- public override bool Equals (object other) { return other is PosAnchorEnd anchorEnd && anchorEnd.Offset == Offset; }
-
- ///
- public override int GetHashCode () { return Offset.GetHashCode (); }
-
- ///
- /// If true, the offset is the width of the view, if false, the offset is the offset value.
- ///
- public bool UseDimForOffset { get; }
-
- ///
- public override string ToString () { return UseDimForOffset ? "AnchorEnd()" : $"AnchorEnd({Offset})"; }
-
- internal override int GetAnchor (int size)
- {
- if (UseDimForOffset)
- {
- return size;
- }
-
- return size - Offset;
- }
-
- internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
- {
- int newLocation = GetAnchor (superviewDimension);
-
- if (UseDimForOffset)
- {
- newLocation -= dim.GetAnchor (superviewDimension);
- }
-
- return newLocation;
- }
-}
-
-///
-/// Represents a position that is centered.
-///
-public class PosCenter : Pos
-{
- ///
- public override string ToString () { return "Center"; }
-
- internal override int GetAnchor (int size) { return size / 2; }
-
- internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
- {
- int newDimension = Math.Max (dim.Calculate (0, superviewDimension, us, dimension), 0);
-
- return GetAnchor (superviewDimension - newDimension);
- }
-}
-
-///
-/// Represents a position that is a combination of two other positions.
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-///
-/// Indicates whether the two positions are added or subtracted.
-///
-/// The left position.
-/// The right position.
-public class PosCombine (AddOrSubtract add, Pos left, Pos right) : Pos
-{
- ///
- /// Gets whether the two positions are added or subtracted.
- ///
- public AddOrSubtract Add { get; } = add;
-
- ///
- /// Gets the left position.
- ///
- public new Pos Left { get; } = left;
-
- ///
- /// Gets the right position.
- ///
- public new Pos Right { get; } = right;
-
- ///
- public override string ToString () { return $"Combine({Left}{(Add == AddOrSubtract.Add ? '+' : '-')}{Right})"; }
-
- internal override int GetAnchor (int size)
- {
- int la = Left.GetAnchor (size);
- int ra = Right.GetAnchor (size);
-
- if (Add == AddOrSubtract.Add)
- {
- return la + ra;
- }
-
- return la - ra;
- }
-
- internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
- {
- int left = Left.Calculate (superviewDimension, dim, us, dimension);
- int right = Right.Calculate (superviewDimension, dim, us, dimension);
-
- if (Add == AddOrSubtract.Add)
- {
- return left + right;
- }
-
- return left - right;
- }
-
- internal override bool ReferencesOtherViews ()
- {
- if (Left.ReferencesOtherViews ())
- {
- return true;
- }
-
- if (Right.ReferencesOtherViews ())
- {
- return true;
- }
-
- return false;
- }
-}
-
-///
-/// Represents a position that is a percentage of the width or height of the SuperView.
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-///
-public class PosPercent (float percent) : Pos
-{
- ///
- /// Gets the factor that represents the percentage of the width or height of the SuperView.
- ///
- public new float Percent { get; } = percent;
-
- ///
- public override bool Equals (object other) { return other is PosPercent f && f.Percent == Percent; }
-
- ///
- public override int GetHashCode () { return Percent.GetHashCode (); }
-
- ///
- public override string ToString () { return $"Percent({Percent})"; }
-
- internal override int GetAnchor (int size) { return (int)(size * Percent); }
-}
-
-///
-/// Represents a position that is computed by executing a function that returns an integer position.
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-/// The position.
-public class PosFunc (Func pos) : Pos
-{
- ///
- /// Gets the function that computes the position.
- ///
- public new Func Func { get; } = pos;
-
- ///
- public override bool Equals (object other) { return other is PosFunc f && f.Func () == Func (); }
-
- ///
- public override int GetHashCode () { return Func.GetHashCode (); }
-
- ///
- public override string ToString () { return $"PosFunc({Func ()})"; }
-
- internal override int GetAnchor (int size) { return Func (); }
-}
-
-///
-/// Represents a position that is anchored to the side of another view.
-///
-///
-///
-/// This is a low-level API that is typically used internally by the layout system. Use the various static
-/// methods on the class to create objects instead.
-///
-///
-/// The View the position is anchored to.
-/// The side of the View the position is anchored to.
-public class PosView (View view, Side side) : Pos
-{
- ///
- /// Gets the View the position is anchored to.
- ///
- public View Target { get; } = view;
-
- ///
- /// Gets the side of the View the position is anchored to.
- ///
- public Side Side { get; } = side;
-
- ///
- public override bool Equals (object other) { return other is PosView abs && abs.Target == Target && abs.Side == Side; }
-
- ///
- public override int GetHashCode () { return Target.GetHashCode (); }
-
- ///
- public override string ToString ()
- {
- string sideString = Side switch
- {
- Side.Left => "left",
- Side.Top => "top",
- Side.Right => "right",
- Side.Bottom => "bottom",
- _ => "unknown"
- };
-
- if (Target == null)
- {
- throw new NullReferenceException (nameof (Target));
- }
-
- return $"View(side={sideString},target={Target})";
- }
-
- internal override int GetAnchor (int size)
- {
- return Side switch
- {
- Side.Left => Target.Frame.X,
- Side.Top => Target.Frame.Y,
- Side.Right => Target.Frame.Right,
- Side.Bottom => Target.Frame.Bottom,
- _ => 0
- };
- }
-
- internal override bool ReferencesOtherViews () { return true; }
-}
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosAbsolute.cs b/Terminal.Gui/View/Layout/PosAbsolute.cs
new file mode 100644
index 000000000..44afdac97
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosAbsolute.cs
@@ -0,0 +1,31 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents an absolute position in the layout. This is used to specify a fixed position in the layout.
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+///
+public class PosAbsolute (int position) : Pos
+{
+ ///
+ /// The position of the in the layout.
+ ///
+ public int Position { get; } = position;
+
+ ///
+ public override bool Equals (object? other) { return other is PosAbsolute abs && abs.Position == Position; }
+
+ ///
+ public override int GetHashCode () { return Position.GetHashCode (); }
+
+ ///
+ public override string ToString () { return $"Absolute({Position})"; }
+
+ internal override int GetAnchor (int size) { return Position; }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosAnchorEnd.cs b/Terminal.Gui/View/Layout/PosAnchorEnd.cs
new file mode 100644
index 000000000..e4641c2b5
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosAnchorEnd.cs
@@ -0,0 +1,68 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a position anchored to the end (right side or bottom).
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+public class PosAnchorEnd : Pos
+{
+ ///
+ /// Gets the offset of the position from the right/bottom.
+ ///
+ public int Offset { get; }
+
+ ///
+ /// Constructs a new position anchored to the end (right side or bottom) of the SuperView,
+ /// minus the respective dimension of the View. This is equivalent to using ,
+ /// with an offset equivalent to the View's respective dimension.
+ ///
+ public PosAnchorEnd () { UseDimForOffset = true; }
+
+ ///
+ /// Constructs a new position anchored to the end (right side or bottom) of the SuperView,
+ ///
+ ///
+ public PosAnchorEnd (int offset) { Offset = offset; }
+
+ ///
+ public override bool Equals (object? other) { return other is PosAnchorEnd anchorEnd && anchorEnd.Offset == Offset; }
+
+ ///
+ public override int GetHashCode () { return Offset.GetHashCode (); }
+
+ ///
+ /// If true, the offset is the width of the view, if false, the offset is the offset value.
+ ///
+ public bool UseDimForOffset { get; }
+
+ ///
+ public override string ToString () { return UseDimForOffset ? "AnchorEnd()" : $"AnchorEnd({Offset})"; }
+
+ internal override int GetAnchor (int size)
+ {
+ if (UseDimForOffset)
+ {
+ return size;
+ }
+
+ return size - Offset;
+ }
+
+ internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
+ {
+ int newLocation = GetAnchor (superviewDimension);
+
+ if (UseDimForOffset)
+ {
+ newLocation -= dim.GetAnchor (superviewDimension);
+ }
+
+ return newLocation;
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosCenter.cs b/Terminal.Gui/View/Layout/PosCenter.cs
new file mode 100644
index 000000000..04c7958bb
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosCenter.cs
@@ -0,0 +1,20 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a position that is centered.
+///
+public class PosCenter : Pos
+{
+ ///
+ public override string ToString () { return "Center"; }
+
+ internal override int GetAnchor (int size) { return size / 2; }
+
+ internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
+ {
+ int newDimension = Math.Max (dim.Calculate (0, superviewDimension, us, dimension), 0);
+
+ return GetAnchor (superviewDimension - newDimension);
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosCombine.cs b/Terminal.Gui/View/Layout/PosCombine.cs
new file mode 100644
index 000000000..3f9666d9c
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosCombine.cs
@@ -0,0 +1,78 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a position that is a combination of two other positions.
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+///
+/// Indicates whether the two positions are added or subtracted.
+///
+/// The left position.
+/// The right position.
+public class PosCombine (AddOrSubtract add, Pos left, Pos right) : Pos
+{
+ ///
+ /// Gets whether the two positions are added or subtracted.
+ ///
+ public AddOrSubtract Add { get; } = add;
+
+ ///
+ /// Gets the left position.
+ ///
+ public new Pos Left { get; } = left;
+
+ ///
+ /// Gets the right position.
+ ///
+ public new Pos Right { get; } = right;
+
+ ///
+ public override string ToString () { return $"Combine({Left}{(Add == AddOrSubtract.Add ? '+' : '-')}{Right})"; }
+
+ internal override int GetAnchor (int size)
+ {
+ int la = Left.GetAnchor (size);
+ int ra = Right.GetAnchor (size);
+
+ if (Add == AddOrSubtract.Add)
+ {
+ return la + ra;
+ }
+
+ return la - ra;
+ }
+
+ internal override int Calculate (int superviewDimension, Dim dim, View us, Dimension dimension)
+ {
+ int left = Left.Calculate (superviewDimension, dim, us, dimension);
+ int right = Right.Calculate (superviewDimension, dim, us, dimension);
+
+ if (Add == AddOrSubtract.Add)
+ {
+ return left + right;
+ }
+
+ return left - right;
+ }
+
+ internal override bool ReferencesOtherViews ()
+ {
+ if (Left.ReferencesOtherViews ())
+ {
+ return true;
+ }
+
+ if (Right.ReferencesOtherViews ())
+ {
+ return true;
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosFunc.cs b/Terminal.Gui/View/Layout/PosFunc.cs
new file mode 100644
index 000000000..24344f9a8
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosFunc.cs
@@ -0,0 +1,31 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a position that is computed by executing a function that returns an integer position.
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+/// The position.
+public class PosFunc (Func pos) : Pos
+{
+ ///
+ /// Gets the function that computes the position.
+ ///
+ public new Func Func { get; } = pos;
+
+ ///
+ public override bool Equals (object? other) { return other is PosFunc f && f.Func () == Func (); }
+
+ ///
+ public override int GetHashCode () { return Func.GetHashCode (); }
+
+ ///
+ public override string ToString () { return $"PosFunc({Func ()})"; }
+
+ internal override int GetAnchor (int size) { return Func (); }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosPercent.cs b/Terminal.Gui/View/Layout/PosPercent.cs
new file mode 100644
index 000000000..09b6e179b
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosPercent.cs
@@ -0,0 +1,31 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a position that is a percentage of the width or height of the SuperView.
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+///
+public class PosPercent (float percent) : Pos
+{
+ ///
+ /// Gets the factor that represents the percentage of the width or height of the SuperView.
+ ///
+ public new float Percent { get; } = percent;
+
+ ///
+ public override bool Equals (object? other) { return other is PosPercent f && f.Percent == Percent; }
+
+ ///
+ public override int GetHashCode () { return Percent.GetHashCode (); }
+
+ ///
+ public override string ToString () { return $"Percent({Percent})"; }
+
+ internal override int GetAnchor (int size) { return (int)(size * Percent); }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/PosView.cs b/Terminal.Gui/View/Layout/PosView.cs
new file mode 100644
index 000000000..51802337d
--- /dev/null
+++ b/Terminal.Gui/View/Layout/PosView.cs
@@ -0,0 +1,66 @@
+#nullable enable
+namespace Terminal.Gui;
+
+///
+/// Represents a position that is anchored to the side of another view.
+///
+///
+///
+/// This is a low-level API that is typically used internally by the layout system. Use the various static
+/// methods on the class to create objects instead.
+///
+///
+/// The View the position is anchored to.
+/// The side of the View the position is anchored to.
+public class PosView (View view, Side side) : Pos
+{
+ ///
+ /// Gets the View the position is anchored to.
+ ///
+ public View Target { get; } = view;
+
+ ///
+ /// Gets the side of the View the position is anchored to.
+ ///
+ public Side Side { get; } = side;
+
+ ///
+ public override bool Equals (object? other) { return other is PosView abs && abs.Target == Target && abs.Side == Side; }
+
+ ///
+ public override int GetHashCode () { return Target.GetHashCode (); }
+
+ ///
+ public override string ToString ()
+ {
+ string sideString = Side switch
+ {
+ Side.Left => "left",
+ Side.Top => "top",
+ Side.Right => "right",
+ Side.Bottom => "bottom",
+ _ => "unknown"
+ };
+
+ if (Target == null)
+ {
+ throw new NullReferenceException (nameof (Target));
+ }
+
+ return $"View(side={sideString},target={Target})";
+ }
+
+ internal override int GetAnchor (int size)
+ {
+ return Side switch
+ {
+ Side.Left => Target.Frame.X,
+ Side.Top => Target.Frame.Y,
+ Side.Right => Target.Frame.Right,
+ Side.Bottom => Target.Frame.Bottom,
+ _ => 0
+ };
+ }
+
+ internal override bool ReferencesOtherViews () { return true; }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/Side.cs b/Terminal.Gui/View/Layout/Side.cs
new file mode 100644
index 000000000..6c03d5470
--- /dev/null
+++ b/Terminal.Gui/View/Layout/Side.cs
@@ -0,0 +1,27 @@
+namespace Terminal.Gui;
+
+///
+/// Indicates the side for operations.
+///
+public enum Side
+{
+ ///
+ /// The left (X) side of the view.
+ ///
+ Left = 0,
+
+ ///
+ /// The top (Y) side of the view.
+ ///
+ Top = 1,
+
+ ///
+ /// The right (X + Width) side of the view.
+ ///
+ Right = 2,
+
+ ///
+ /// The bottom (Y + Height) side of the view.
+ ///
+ Bottom = 3
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/View.cs
similarity index 96%
rename from Terminal.Gui/View/Layout/ViewLayout.cs
rename to Terminal.Gui/View/Layout/View.cs
index e0ca37eb4..dcb94b91e 100644
--- a/Terminal.Gui/View/Layout/ViewLayout.cs
+++ b/Terminal.Gui/View/Layout/View.cs
@@ -4,40 +4,6 @@ using Microsoft.CodeAnalysis;
namespace Terminal.Gui;
-///
-/// Indicates the LayoutStyle for the .
-///
-/// If Absolute, the , , , and
-/// objects are all absolute values and are not relative. The position and size of the
-/// view is described by .
-///
-///
-/// If Computed, one or more of the , , , or
-/// objects are relative to the and are computed at layout
-/// time.
-///
-///
-public enum LayoutStyle
-{
- ///
- /// Indicates the , , , and
- /// objects are all absolute values and are not relative. The position and size of the view
- /// is described by .
- ///
- Absolute,
-
- ///
- /// Indicates one or more of the , , , or
- ///
- /// objects are relative to the and are computed at layout time. The position and size of
- /// the
- /// view
- /// will be computed based on these objects at layout time. will provide the absolute computed
- /// values.
- ///
- Computed
-}
-
public partial class View
{
#region Frame