#nullable enable
namespace Terminal.Gui;
using System.Numerics;
///
///
/// A Dim object describes the dimensions of a . Dim is the type of the
/// and properties of .
///
///
/// Integer values are implicitly convertible to an absolute . These objects are created using
/// the static methods described below. The objects can be combined with the addition and
/// subtraction operators.
///
///
///
///
///
///
/// Dim Object Description
///
/// -
///
///
///
///
/// Creates a that is a fixed size.
///
///
/// -
///
///
///
///
/// Creates a object that automatically sizes the view to fit
/// the view's Text, SubViews, or ContentArea.
///
///
/// -
///
///
///
///
/// Creates a object that computes the dimension by executing the provided
/// function. The function will be called every time the dimension is needed.
///
///
/// -
///
///
///
///
/// Creates a object that is a percentage of the width or height of the
/// SuperView.
///
///
/// -
///
///
///
///
/// Creates a object that fills the dimension from the View's X position
/// to the end of the super view's width, leaving the specified number of columns for a margin.
///
///
/// -
///
///
///
///
/// Creates a object that tracks the Width of the specified
/// .
///
///
/// -
///
///
///
///
/// Creates a object that tracks the Height of the specified
/// .
///
///
///
///
///
///
public abstract record Dim : IEqualityOperators
{
#region static Dim creation methods
/// Creates an Absolute from the specified integer value.
/// The Absolute .
/// The value to convert to the .
public static Dim? Absolute (int size) { return new DimAbsolute (size); }
///
/// Creates a object that automatically sizes the view to fit all the view's Content, Subviews, and/or Text.
///
///
///
/// See .
///
///
///
/// This initializes a with two SubViews. The view will be automatically sized to fit the two
/// SubViews.
///
/// var button = new Button () { Text = "Click Me!", X = 1, Y = 1, Width = 10, Height = 1 };
/// var textField = new TextField { Text = "Type here", X = 1, Y = 2, Width = 20, Height = 1 };
/// var view = new Window () { Title = "MyWindow", X = 0, Y = 0, Width = Dim.Auto (), Height = Dim.Auto () };
/// view.Add (button, textField);
///
///
/// The object.
///
/// Specifies how will compute the dimension. The default is .
///
/// The minimum dimension the View's ContentSize will be constrained to.
/// The maximum dimension the View's ContentSize will be fit to.
public static Dim? Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim? minimumContentDim = null, Dim? maximumContentDim = null)
{
return new DimAuto (
MinimumContentDim: minimumContentDim,
MaximumContentDim: maximumContentDim,
Style: style);
}
///
/// Creates a object that fills the dimension, leaving no margin.
///
/// The Fill dimension.
public static Dim? Fill () { return new DimFill (0); }
///
/// Creates a object that fills the dimension, leaving the specified margin.
///
/// The Fill dimension.
/// Margin to use.
public static Dim? Fill (Dim margin) { return new DimFill (margin); }
///
/// Creates a function object that computes the dimension by executing the provided function.
/// The function will be called every time the dimension is needed.
///
/// The function to be executed.
/// The returned from the function.
public static Dim Func (Func function) { return new DimFunc (function); }
/// Creates a object that tracks the Height of the specified .
/// The height of the other .
/// The view that will be tracked.
public static Dim Height (View? view) { return new DimView (view, Dimension.Height); }
/// Creates a percentage object that is a percentage of the width or height of the SuperView.
/// The percent object.
/// A value between 0 and 100 representing the percentage.
/// the mode. Defaults to .
///
/// This initializes a that will be centered horizontally, is 50% of the way down, is 30% the
/// height,
/// and is 80% the width of the SuperView.
///
/// var textView = new TextField {
/// X = Pos.Center (),
/// Y = Pos.Percent (50),
/// Width = Dim.Percent (80),
/// Height = Dim.Percent (30),
/// };
///
///
public static Dim? Percent (int percent, DimPercentMode mode = DimPercentMode.ContentSize)
{
ArgumentOutOfRangeException.ThrowIfNegative (percent, nameof (percent));
return new DimPercent (percent, mode);
}
/// Creates a object that tracks the Width of the specified .
/// The width of the other .
/// The view that will be tracked.
public static Dim Width (View? view) { return new DimView (view, Dimension.Width); }
#endregion static Dim creation methods
///
/// Indicates whether the specified type is in the hierarchy of this Dim object.
///
/// A reference to this instance.
///
public bool Has (out T dim) where T : Dim
{
dim = (this as T)!;
return this switch
{
DimCombine combine => combine.Left.Has (out dim) || combine.Right.Has (out dim),
T => true,
_ => false
};
}
#region virtual methods
///
/// Gets a dimension that is anchored to a certain point in the layout.
/// This method is typically used internally by the layout system to determine the size of a View.
///
/// The width of the area where the View is being sized (Superview.GetContentSize ()).
///
/// An integer representing the calculated dimension. The way this dimension is calculated depends on the specific
/// 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.
///
internal abstract int GetAnchor (int size);
///
/// Calculates and returns the dimension of a object. It takes into account the location of the
/// , it's SuperView's ContentSize, and whether it should automatically adjust its size based on its
/// content.
///
///
/// The starting point from where the size calculation begins. It could be the left edge for width calculation or the
/// top edge for height calculation.
///
/// The size of the SuperView's content. It could be width or height.
/// The View that holds this Pos object.
/// Width or Height
///
/// The calculated size of the View. The way this size is calculated depends on the specific subclass of Dim that
/// is used.
///
internal virtual int Calculate (int location, int superviewContentSize, View us, Dimension dimension)
{
return Math.Clamp (GetAnchor (superviewContentSize - location), 0, short.MaxValue);
}
///
/// Diagnostics API to determine if this Dim object references other views.
///
///
internal virtual bool ReferencesOtherViews () { return false; }
#endregion virtual methods
#region operators
/// Adds a to a , yielding a new .
/// The first to add.
/// The second to add.
/// The that is the sum of the values of left and right.
public static Dim operator + (Dim left, Dim right)
{
if (left is DimAbsolute && right is DimAbsolute)
{
return new DimAbsolute (left.GetAnchor (0) + right.GetAnchor (0));
}
var newDim = new DimCombine (AddOrSubtract.Add, left, right);
(left as DimView)?.Target?.SetNeedsLayout ();
return newDim;
}
/// Creates an Absolute from the specified integer value.
/// The Absolute .
/// The value to convert to the pos.
public static implicit operator Dim (int n) { return new DimAbsolute (n); }
///
/// Subtracts a from a , yielding a new
/// .
///
/// The to subtract from (the minuend).
/// The to subtract (the subtrahend).
/// The that is the left minus right.
public static Dim operator - (Dim left, Dim right)
{
if (left is DimAbsolute && right is DimAbsolute)
{
return new DimAbsolute (left.GetAnchor (0) - right.GetAnchor (0));
}
var newDim = new DimCombine (AddOrSubtract.Subtract, left, right);
(left as DimView)?.Target?.SetNeedsLayout ();
return newDim;
}
#endregion operators
}