mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Merge pull request #3410 from tig/v2_481-AnchorEnd
Fixes #481. Adds `Pos.AnchorEnd ()` (no param) to automatically account for the view's dimension.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
namespace Terminal.Gui;
|
||||
using static Terminal.Gui.Dialog;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the position of a <see cref="View"/> which can be an absolute value, a percentage, centered, or
|
||||
@@ -43,7 +45,7 @@
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>
|
||||
/// <see cref="Pos.Anchor(int)"/>
|
||||
/// <see cref="Pos.AnchorEnd()"/>
|
||||
/// </term>
|
||||
/// <description>
|
||||
/// Creates a <see cref="Pos"/> object that is anchored to the end (right side or bottom) of
|
||||
@@ -125,20 +127,36 @@
|
||||
public class Pos
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Pos"/> object that is anchored to the end (right side or bottom) of the dimension, useful
|
||||
/// to flush the layout from the right or bottom.
|
||||
/// Creates a <see cref="Pos"/> object that is anchored to the end (right side or
|
||||
/// bottom) of the SuperView, minus the respective dimension of the View. This is equivalent to using
|
||||
/// <see cref="Pos.AnchorEnd(int)"/>,
|
||||
/// with an offset equivalent to the View's respective dimension.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Pos"/> object anchored to the end (the bottom or the right side) minus the View's dimension.</returns>
|
||||
/// <example>
|
||||
/// This sample shows how align a <see cref="Button"/> to the bottom-right the SuperView.
|
||||
/// <code>
|
||||
/// anchorButton.X = Pos.AnchorEnd ();
|
||||
/// anchorButton.Y = Pos.AnchorEnd ();
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static Pos AnchorEnd () { return new PosAnchorEnd (); }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Pos"/> object that is anchored to the end (right side or bottom) of the SuperView,
|
||||
/// useful to flush the layout from the right or bottom. See also <see cref="Pos.AnchorEnd()"/>, which uses the view
|
||||
/// dimension to ensure the view is fully visible.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Pos"/> object anchored to the end (the bottom or the right side).</returns>
|
||||
/// <param name="offset">The view will be shifted left or up by the amount specified.</param>
|
||||
/// <example>
|
||||
/// This sample shows how align a <see cref="Button"/> to the bottom-right of a <see cref="View"/>.
|
||||
/// This sample shows how align a 10 column wide <see cref="Button"/> to the bottom-right the SuperView.
|
||||
/// <code>
|
||||
/// // See Issue #502
|
||||
/// anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
|
||||
/// anchorButton.Y = Pos.AnchorEnd (1);
|
||||
/// anchorButton.X = Pos.AnchorEnd (10);
|
||||
/// anchorButton.Y = 1
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static Pos AnchorEnd (int offset = 0)
|
||||
public static Pos AnchorEnd (int offset)
|
||||
{
|
||||
if (offset < 0)
|
||||
{
|
||||
@@ -153,25 +171,17 @@ public class Pos
|
||||
/// <param name="n">The value to convert to the <see cref="Pos"/>.</param>
|
||||
public static Pos At (int n) { return new PosAbsolute (n); }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Pos"/> object that tracks the Bottom (Y+Height) coordinate of the specified
|
||||
/// <see cref="View"/>
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Bottom (View view) { return new PosView (view, 3); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that can be used to center the <see cref="View"/>.</summary>
|
||||
/// <returns>The center Pos.</returns>
|
||||
/// <example>
|
||||
/// This creates a <see cref="TextField"/>that is centered horizontally, is 50% of the way down, is 30% the height, and
|
||||
/// This creates a <see cref="TextView"/> centered horizontally, is 50% of the way down, is 30% the height, and
|
||||
/// is 80% the width of the <see cref="View"/> it added to.
|
||||
/// <code>
|
||||
/// var textView = new TextView () {
|
||||
/// X = Pos.Center (),
|
||||
/// Y = Pos.Percent (50),
|
||||
/// Width = Dim.Percent (80),
|
||||
/// Height = Dim.Percent (30),
|
||||
/// X = Pos.Center (),
|
||||
/// Y = Pos.Percent (50),
|
||||
/// Width = Dim.Percent (80),
|
||||
/// Height = Dim.Percent (30),
|
||||
/// };
|
||||
/// </code>
|
||||
/// </example>
|
||||
@@ -197,11 +207,6 @@ public class Pos
|
||||
/// <returns>A hash code for the current object.</returns>
|
||||
public override int GetHashCode () { return Anchor (0).GetHashCode (); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Left (View view) { return new PosView (view, 0); }
|
||||
|
||||
/// <summary>Adds a <see cref="Terminal.Gui.Pos"/> to a <see cref="Terminal.Gui.Pos"/>, yielding a new <see cref="Pos"/>.</summary>
|
||||
/// <param name="left">The first <see cref="Terminal.Gui.Pos"/> to add.</param>
|
||||
/// <param name="right">The second <see cref="Terminal.Gui.Pos"/> to add.</param>
|
||||
@@ -214,7 +219,11 @@ public class Pos
|
||||
}
|
||||
|
||||
var newPos = new PosCombine (true, left, right);
|
||||
SetPosCombine (left, newPos);
|
||||
|
||||
if (left is PosView view)
|
||||
{
|
||||
view.Target.SetNeedsLayout ();
|
||||
}
|
||||
|
||||
return newPos;
|
||||
}
|
||||
@@ -239,75 +248,109 @@ public class Pos
|
||||
}
|
||||
|
||||
var newPos = new PosCombine (false, left, right);
|
||||
SetPosCombine (left, newPos);
|
||||
|
||||
if (left is PosView view)
|
||||
{
|
||||
view.Target.SetNeedsLayout ();
|
||||
}
|
||||
|
||||
return newPos;
|
||||
}
|
||||
|
||||
/// <summary>Creates a percentage <see cref="Pos"/> object</summary>
|
||||
/// <returns>The percent <see cref="Pos"/> object.</returns>
|
||||
/// <param name="n">A value between 0 and 100 representing the percentage.</param>
|
||||
/// <param name="percent">A value between 0 and 100 representing the percentage.</param>
|
||||
/// <example>
|
||||
/// This creates a <see cref="TextField"/>that is centered horizontally, is 50% of the way down, is 30% the height, and
|
||||
/// This creates a <see cref="TextField"/> centered horizontally, is 50% of the way down, is 30% the height, and
|
||||
/// is 80% the width of the <see cref="View"/> it added to.
|
||||
/// <code>
|
||||
/// var textView = new TextView () {
|
||||
/// X = Pos.Center (),
|
||||
/// Y = Pos.Percent (50),
|
||||
/// Width = Dim.Percent (80),
|
||||
/// Height = Dim.Percent (30),
|
||||
/// var textView = new TextField {
|
||||
/// X = Pos.Center (),
|
||||
/// Y = Pos.Percent (50),
|
||||
/// Width = Dim.Percent (80),
|
||||
/// Height = Dim.Percent (30),
|
||||
/// };
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static Pos Percent (float n)
|
||||
public static Pos Percent (float percent)
|
||||
{
|
||||
if (n is < 0 or > 100)
|
||||
if (percent is < 0 or > 100)
|
||||
{
|
||||
throw new ArgumentException ("Percent value must be between 0 and 100");
|
||||
throw new ArgumentException ("Percent value must be between 0 and 100.");
|
||||
}
|
||||
|
||||
return new PosFactor (n / 100);
|
||||
return new PosFactor (percent / 100);
|
||||
}
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Top (View view) { return new PosView (view, Side.Top); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Y (View view) { return new PosView (view, Side.Top); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Left (View view) { return new PosView (view, Side.Left); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos X (View view) { return new PosView (view, Side.Left); }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Pos"/> object that tracks the Bottom (Y+Height) coordinate of the specified
|
||||
/// <see cref="View"/>
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Bottom (View view) { return new PosView (view, Side.Bottom); }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="Pos"/> object that tracks the Right (X+Width) coordinate of the specified
|
||||
/// <see cref="View"/>.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Right (View view) { return new PosView (view, 2); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Top (View view) { return new PosView (view, 1); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Left (X) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos X (View view) { return new PosView (view, 0); }
|
||||
|
||||
/// <summary>Creates a <see cref="Pos"/> object that tracks the Top (Y) position of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The <see cref="Pos"/> that depends on the other view.</returns>
|
||||
/// <param name="view">The <see cref="View"/> that will be tracked.</param>
|
||||
public static Pos Y (View view) { return new PosView (view, 1); }
|
||||
public static Pos Right (View view) { return new PosView (view, Side.Right); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a position that is anchored to a certain point in the layout. This method is typically used
|
||||
/// internally by the layout system to determine where a View should be positioned.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the area where the View is being positioned (Superview.ContentSize).</param>
|
||||
/// <returns>
|
||||
/// An integer representing the calculated position. The way this position is calculated depends on the specific
|
||||
/// subclass of Pos that is used. For example, PosAbsolute returns a fixed position, PosAnchorEnd returns a
|
||||
/// position that is anchored to the end of the layout, and so on.
|
||||
/// </returns>
|
||||
internal virtual int Anchor (int width) { return 0; }
|
||||
|
||||
private static void SetPosCombine (Pos left, PosCombine newPos)
|
||||
{
|
||||
var view = left as PosView;
|
||||
/// <summary>
|
||||
/// Calculates and returns the position of a <see cref="View"/> object. It takes into account the dimension of the
|
||||
/// superview and the dimension of the view itself.
|
||||
/// </summary>
|
||||
/// <param name="superviewDimension">
|
||||
/// The dimension of the superview. This could be the width for x-coordinate calculation or the
|
||||
/// height for y-coordinate calculation.
|
||||
/// </param>
|
||||
/// <param name="dim">The dimension of the View. It could be the current width or height.</param>
|
||||
/// <param name="autosize">Obsolete; to be deprecated.</param>
|
||||
/// <param name="autoSize">Obsolete; to be deprecated.</param>
|
||||
/// <returns>
|
||||
/// The calculated position of the View. The way this position is calculated depends on the specific subclass of Pos
|
||||
/// that
|
||||
/// is used.
|
||||
/// </returns>
|
||||
internal virtual int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize) { return Anchor (superviewDimension); }
|
||||
|
||||
if (view is { })
|
||||
{
|
||||
view.Target.SetNeedsLayout ();
|
||||
}
|
||||
}
|
||||
|
||||
internal class PosAbsolute : Pos
|
||||
internal class PosAbsolute (int n) : Pos
|
||||
{
|
||||
private readonly int _n;
|
||||
public PosAbsolute (int n) { _n = n; }
|
||||
private readonly int _n = n;
|
||||
public override bool Equals (object other) { return other is PosAbsolute abs && abs._n == _n; }
|
||||
public override int GetHashCode () { return _n.GetHashCode (); }
|
||||
public override string ToString () { return $"Absolute({_n})"; }
|
||||
@@ -317,30 +360,58 @@ public class Pos
|
||||
internal class PosAnchorEnd : Pos
|
||||
{
|
||||
private readonly int _offset;
|
||||
public PosAnchorEnd () { UseDimForOffset = true; }
|
||||
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 (); }
|
||||
public override string ToString () { return $"AnchorEnd({_offset})"; }
|
||||
internal override int Anchor (int width) { return width - _offset; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the offset is the width of the view, if false, the offset is the offset value.
|
||||
/// </summary>
|
||||
internal bool UseDimForOffset { get; set; }
|
||||
|
||||
public override string ToString () { return UseDimForOffset ? "AnchorEnd()" : $"AnchorEnd({_offset})"; }
|
||||
|
||||
internal override int Anchor (int width)
|
||||
{
|
||||
if (UseDimForOffset)
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
return width - _offset;
|
||||
}
|
||||
|
||||
internal override int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize)
|
||||
{
|
||||
int newLocation = Anchor (superviewDimension);
|
||||
|
||||
if (UseDimForOffset)
|
||||
{
|
||||
newLocation -= dim.Anchor (superviewDimension);
|
||||
}
|
||||
|
||||
return newLocation;
|
||||
}
|
||||
}
|
||||
|
||||
internal class PosCenter : Pos
|
||||
{
|
||||
public override string ToString () { return "Center"; }
|
||||
internal override int Anchor (int width) { return width / 2; }
|
||||
|
||||
internal override int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize)
|
||||
{
|
||||
int newDimension = Math.Max (dim.Calculate (0, superviewDimension, autosize, autoSize), 0);
|
||||
|
||||
return Anchor (superviewDimension - newDimension);
|
||||
}
|
||||
}
|
||||
|
||||
internal class PosCombine : Pos
|
||||
internal class PosCombine (bool add, Pos left, Pos right) : Pos
|
||||
{
|
||||
internal bool _add;
|
||||
internal Pos _left, _right;
|
||||
|
||||
public PosCombine (bool add, Pos left, Pos right)
|
||||
{
|
||||
_left = left;
|
||||
_right = right;
|
||||
_add = add;
|
||||
}
|
||||
internal bool _add = add;
|
||||
internal Pos _left = left, _right = right;
|
||||
|
||||
public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; }
|
||||
|
||||
@@ -356,12 +427,25 @@ public class Pos
|
||||
|
||||
return la - ra;
|
||||
}
|
||||
|
||||
internal override int Calculate (int superviewDimension, Dim dim, int autosize, bool autoSize)
|
||||
{
|
||||
int newDimension = dim.Calculate (0, superviewDimension, autosize, autoSize);
|
||||
int left = _left.Calculate (superviewDimension, dim, autosize, autoSize);
|
||||
int right = _right.Calculate (superviewDimension, dim, autosize, autoSize);
|
||||
|
||||
if (_add)
|
||||
{
|
||||
return left + right;
|
||||
}
|
||||
|
||||
return left - right;
|
||||
}
|
||||
}
|
||||
|
||||
internal class PosFactor : Pos
|
||||
internal class PosFactor (float factor) : Pos
|
||||
{
|
||||
private readonly float _factor;
|
||||
public PosFactor (float n) { _factor = n; }
|
||||
private readonly float _factor = factor;
|
||||
public override bool Equals (object other) { return other is PosFactor f && f._factor == _factor; }
|
||||
public override int GetHashCode () { return _factor.GetHashCode (); }
|
||||
public override string ToString () { return $"Factor({_factor})"; }
|
||||
@@ -369,78 +453,77 @@ public class Pos
|
||||
}
|
||||
|
||||
// Helper class to provide dynamic value by the execution of a function that returns an integer.
|
||||
internal class PosFunc : Pos
|
||||
internal class PosFunc (Func<int> n) : Pos
|
||||
{
|
||||
private readonly Func<int> _function;
|
||||
public PosFunc (Func<int> n) { _function = n; }
|
||||
private readonly Func<int> _function = n;
|
||||
public override bool Equals (object other) { return other is PosFunc f && f._function () == _function (); }
|
||||
public override int GetHashCode () { return _function.GetHashCode (); }
|
||||
public override string ToString () { return $"PosFunc({_function ()})"; }
|
||||
internal override int Anchor (int width) { return _function (); }
|
||||
}
|
||||
|
||||
internal class PosView : Pos
|
||||
/// <summary>
|
||||
/// Describes which side of the view to use for the position.
|
||||
/// </summary>
|
||||
public enum Side
|
||||
{
|
||||
public readonly View Target;
|
||||
/// <summary>
|
||||
/// The left (X) side of the view.
|
||||
/// </summary>
|
||||
Left = 0,
|
||||
|
||||
private readonly int side;
|
||||
/// <summary>
|
||||
/// The top (Y) side of the view.
|
||||
/// </summary>
|
||||
Top = 1,
|
||||
|
||||
public PosView (View view, int side)
|
||||
{
|
||||
Target = view;
|
||||
this.side = side;
|
||||
}
|
||||
/// <summary>
|
||||
/// The right (X + Width) side of the view.
|
||||
/// </summary>
|
||||
Right = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The bottom (Y + Height) side of the view.
|
||||
/// </summary>
|
||||
Bottom = 3
|
||||
}
|
||||
|
||||
internal class PosView (View view, Side side) : Pos
|
||||
{
|
||||
public readonly View Target = view;
|
||||
|
||||
public override bool Equals (object other) { return other is PosView abs && abs.Target == Target; }
|
||||
public override int GetHashCode () { return Target.GetHashCode (); }
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
string tside;
|
||||
|
||||
switch (side)
|
||||
string sideString = side switch
|
||||
{
|
||||
case 0:
|
||||
tside = "x";
|
||||
Side.Left => "left",
|
||||
Side.Top => "top",
|
||||
Side.Right => "right",
|
||||
Side.Bottom => "bottom",
|
||||
_ => "unknown"
|
||||
};
|
||||
|
||||
break;
|
||||
case 1:
|
||||
tside = "y";
|
||||
|
||||
break;
|
||||
case 2:
|
||||
tside = "right";
|
||||
|
||||
break;
|
||||
case 3:
|
||||
tside = "bottom";
|
||||
|
||||
break;
|
||||
default:
|
||||
tside = "unknown";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (Target is null)
|
||||
if (Target == null)
|
||||
{
|
||||
throw new NullReferenceException (nameof (Target));
|
||||
}
|
||||
|
||||
return $"View(side={tside},target={Target})";
|
||||
return $"View(side={sideString},target={Target})";
|
||||
}
|
||||
|
||||
internal override int Anchor (int width)
|
||||
{
|
||||
switch (side)
|
||||
return side switch
|
||||
{
|
||||
case 0: return Target.Frame.X;
|
||||
case 1: return Target.Frame.Y;
|
||||
case 2: return Target.Frame.Right;
|
||||
case 3: return Target.Frame.Bottom;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
Side.Left => Target.Frame.X,
|
||||
Side.Top => Target.Frame.Y,
|
||||
Side.Right => Target.Frame.Right,
|
||||
Side.Bottom => Target.Frame.Bottom,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -486,8 +569,8 @@ public class Pos
|
||||
/// <see cref="Dim.Fill(int)"/>
|
||||
/// </term>
|
||||
/// <description>
|
||||
/// Creates a <see cref="Dim"/> object that fills the dimension, leaving the specified number
|
||||
/// of columns for a margin.
|
||||
/// Creates a <see cref="Dim"/> 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.
|
||||
/// </description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
@@ -545,11 +628,11 @@ public class Dim
|
||||
/// <summary>Creates a <see cref="Dim"/> object that tracks the Height of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The height <see cref="Dim"/> of the other <see cref="View"/>.</returns>
|
||||
/// <param name="view">The view that will be tracked.</param>
|
||||
public static Dim Height (View view) { return new DimView (view, 0); }
|
||||
public static Dim Height (View view) { return new DimView (view, Dimension.Height); }
|
||||
|
||||
/// <summary>Adds a <see cref="Terminal.Gui.Dim"/> to a <see cref="Terminal.Gui.Dim"/>, yielding a new <see cref="Dim"/>.</summary>
|
||||
/// <param name="left">The first <see cref="Terminal.Gui.Dim"/> to add.</param>
|
||||
/// <param name="right">The second <see cref="Terminal.Gui.Dim"/> to add.</param>
|
||||
/// <summary>Adds a <see cref="Dim"/> to a <see cref="Dim"/>, yielding a new <see cref="Dim"/>.</summary>
|
||||
/// <param name="left">The first <see cref="Dim"/> to add.</param>
|
||||
/// <param name="right">The second <see cref="Dim"/> to add.</param>
|
||||
/// <returns>The <see cref="Dim"/> that is the sum of the values of <c>left</c> and <c>right</c>.</returns>
|
||||
public static Dim operator + (Dim left, Dim right)
|
||||
{
|
||||
@@ -559,7 +642,7 @@ public class Dim
|
||||
}
|
||||
|
||||
var newDim = new DimCombine (true, left, right);
|
||||
SetDimCombine (left, newDim);
|
||||
(left as DimView)?.Target.SetNeedsLayout ();
|
||||
|
||||
return newDim;
|
||||
}
|
||||
@@ -570,11 +653,11 @@ public class Dim
|
||||
public static implicit operator Dim (int n) { return new DimAbsolute (n); }
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts a <see cref="Terminal.Gui.Dim"/> from a <see cref="Terminal.Gui.Dim"/>, yielding a new
|
||||
/// Subtracts a <see cref="Dim"/> from a <see cref="Dim"/>, yielding a new
|
||||
/// <see cref="Dim"/>.
|
||||
/// </summary>
|
||||
/// <param name="left">The <see cref="Terminal.Gui.Dim"/> to subtract from (the minuend).</param>
|
||||
/// <param name="right">The <see cref="Terminal.Gui.Dim"/> to subtract (the subtrahend).</param>
|
||||
/// <param name="left">The <see cref="Dim"/> to subtract from (the minuend).</param>
|
||||
/// <param name="right">The <see cref="Dim"/> to subtract (the subtrahend).</param>
|
||||
/// <returns>The <see cref="Dim"/> that is the <c>left</c> minus <c>right</c>.</returns>
|
||||
public static Dim operator - (Dim left, Dim right)
|
||||
{
|
||||
@@ -584,38 +667,40 @@ public class Dim
|
||||
}
|
||||
|
||||
var newDim = new DimCombine (false, left, right);
|
||||
SetDimCombine (left, newDim);
|
||||
(left as DimView)?.Target.SetNeedsLayout ();
|
||||
|
||||
return newDim;
|
||||
}
|
||||
|
||||
/// <summary>Creates a percentage <see cref="Dim"/> object that is a percentage of the width or height of the SuperView.</summary>
|
||||
/// <returns>The percent <see cref="Dim"/> object.</returns>
|
||||
/// <param name="n">A value between 0 and 100 representing the percentage.</param>
|
||||
/// <param name="r">
|
||||
/// If <c>true</c> the Percent is computed based on the remaining space after the X/Y anchor positions. If
|
||||
/// <c>false</c> is computed based on the whole original space.
|
||||
/// <param name="percent">A value between 0 and 100 representing the percentage.</param>
|
||||
/// <param name="usePosition">
|
||||
/// If <see langword="true"/> the dimension is computed using the View's position (<see cref="View.X"/> or
|
||||
/// <see cref="View.Y"/>).
|
||||
/// If <see langword="false"/> the dimension is computed using the View's <see cref="View.ContentSize"/>.
|
||||
/// </param>
|
||||
/// <example>
|
||||
/// This initializes a <see cref="TextField"/>that is centered horizontally, is 50% of the way down, is 30% the height,
|
||||
/// and is 80% the width of the <see cref="View"/> it added to.
|
||||
/// This initializes a <see cref="TextField"/> that will be centered horizontally, is 50% of the way down, is 30% the
|
||||
/// height,
|
||||
/// and is 80% the width of the SuperView.
|
||||
/// <code>
|
||||
/// var textView = new TextView () {
|
||||
/// X = Pos.Center (),
|
||||
/// Y = Pos.Percent (50),
|
||||
/// Width = Dim.Percent (80),
|
||||
/// Height = Dim.Percent (30),
|
||||
/// var textView = new TextField {
|
||||
/// X = Pos.Center (),
|
||||
/// Y = Pos.Percent (50),
|
||||
/// Width = Dim.Percent (80),
|
||||
/// Height = Dim.Percent (30),
|
||||
/// };
|
||||
/// </code>
|
||||
/// </example>
|
||||
public static Dim Percent (float n, bool r = false)
|
||||
public static Dim Percent (float percent, bool usePosition = false)
|
||||
{
|
||||
if (n is < 0 or > 100)
|
||||
if (percent is < 0 or > 100)
|
||||
{
|
||||
throw new ArgumentException ("Percent value must be between 0 and 100");
|
||||
}
|
||||
|
||||
return new DimFactor (n / 100, r);
|
||||
return new DimFactor (percent / 100, usePosition);
|
||||
}
|
||||
|
||||
/// <summary>Creates an Absolute <see cref="Dim"/> from the specified integer value.</summary>
|
||||
@@ -626,34 +711,63 @@ public class Dim
|
||||
/// <summary>Creates a <see cref="Dim"/> object that tracks the Width of the specified <see cref="View"/>.</summary>
|
||||
/// <returns>The width <see cref="Dim"/> of the other <see cref="View"/>.</returns>
|
||||
/// <param name="view">The view that will be tracked.</param>
|
||||
public static Dim Width (View view) { return new DimView (view, 1); }
|
||||
public static Dim Width (View view) { return new DimView (view, Dimension.Width); }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the area where the View is being sized (Superview.ContentSize).</param>
|
||||
/// <returns>
|
||||
/// 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.
|
||||
/// </returns>
|
||||
internal virtual int Anchor (int width) { return 0; }
|
||||
|
||||
// BUGBUG: newPos is never used.
|
||||
private static void SetDimCombine (Dim left, DimCombine newPos) { (left as DimView)?.Target.SetNeedsLayout (); }
|
||||
|
||||
internal class DimAbsolute : Dim
|
||||
/// <summary>
|
||||
/// Calculates and returns the dimension of a <see cref="View"/> object. It takes into account the location of the
|
||||
/// <see cref="View"/>, its current size, and whether it should automatically adjust its size based on its content.
|
||||
/// </summary>
|
||||
/// <param name="location">
|
||||
/// 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.
|
||||
/// </param>
|
||||
/// <param name="dimension">The current size of the View. It could be the current width or height.</param>
|
||||
/// <param name="autosize">Obsolete; To be deprecated.</param>
|
||||
/// <param name="autoSize">Obsolete; To be deprecated.</param>
|
||||
/// <returns>
|
||||
/// The calculated size of the View. The way this size is calculated depends on the specific subclass of Dim that
|
||||
/// is used.
|
||||
/// </returns>
|
||||
internal virtual int Calculate (int location, int dimension, int autosize, bool autoSize)
|
||||
{
|
||||
private readonly int _n;
|
||||
public DimAbsolute (int n) { _n = n; }
|
||||
int newDimension = Math.Max (Anchor (dimension - location), 0);
|
||||
|
||||
return autoSize && autosize > newDimension ? autosize : newDimension;
|
||||
}
|
||||
|
||||
internal class DimAbsolute (int n) : Dim
|
||||
{
|
||||
private readonly int _n = n;
|
||||
public override bool Equals (object other) { return other is DimAbsolute abs && abs._n == _n; }
|
||||
public override int GetHashCode () { return _n.GetHashCode (); }
|
||||
public override string ToString () { return $"Absolute({_n})"; }
|
||||
internal override int Anchor (int width) { return _n; }
|
||||
|
||||
internal override int Calculate (int location, int dimension, int autosize, bool autoSize)
|
||||
{
|
||||
// DimAbsolute.Anchor (int width) ignores width and returns n
|
||||
int newDimension = Math.Max (Anchor (0), 0);
|
||||
|
||||
return autoSize && autosize > newDimension ? autosize : newDimension;
|
||||
}
|
||||
}
|
||||
|
||||
internal class DimCombine : Dim
|
||||
internal class DimCombine (bool add, Dim left, Dim right) : Dim
|
||||
{
|
||||
internal bool _add;
|
||||
internal Dim _left, _right;
|
||||
|
||||
public DimCombine (bool add, Dim left, Dim right)
|
||||
{
|
||||
_left = left;
|
||||
_right = right;
|
||||
_add = add;
|
||||
}
|
||||
internal bool _add = add;
|
||||
internal Dim _left = left, _right = right;
|
||||
|
||||
public override string ToString () { return $"Combine({_left}{(_add ? '+' : '-')}{_right})"; }
|
||||
|
||||
@@ -669,30 +783,49 @@ public class Dim
|
||||
|
||||
return la - ra;
|
||||
}
|
||||
|
||||
internal override int Calculate (int location, int dimension, int autosize, bool autoSize)
|
||||
{
|
||||
int leftNewDim = _left.Calculate (location, dimension, autosize, autoSize);
|
||||
int rightNewDim = _right.Calculate (location, dimension, autosize, autoSize);
|
||||
|
||||
int newDimension;
|
||||
|
||||
if (_add)
|
||||
{
|
||||
newDimension = leftNewDim + rightNewDim;
|
||||
}
|
||||
else
|
||||
{
|
||||
newDimension = Math.Max (0, leftNewDim - rightNewDim);
|
||||
}
|
||||
|
||||
return autoSize && autosize > newDimension ? autosize : newDimension;
|
||||
}
|
||||
}
|
||||
|
||||
internal class DimFactor : Dim
|
||||
internal class DimFactor (float factor, bool remaining = false) : Dim
|
||||
{
|
||||
private readonly float _factor;
|
||||
private readonly bool _remaining;
|
||||
|
||||
public DimFactor (float n, bool r = false)
|
||||
{
|
||||
_factor = n;
|
||||
_remaining = r;
|
||||
}
|
||||
private readonly float _factor = factor;
|
||||
private readonly bool _remaining = remaining;
|
||||
|
||||
public override bool Equals (object other) { return other is DimFactor f && f._factor == _factor && f._remaining == _remaining; }
|
||||
public override int GetHashCode () { return _factor.GetHashCode (); }
|
||||
public bool IsFromRemaining () { return _remaining; }
|
||||
public override string ToString () { return $"Factor({_factor},{_remaining})"; }
|
||||
internal override int Anchor (int width) { return (int)(width * _factor); }
|
||||
|
||||
internal override int Calculate (int location, int dimension, int autosize, bool autoSize)
|
||||
{
|
||||
int newDimension = _remaining ? Math.Max (Anchor (dimension - location), 0) : Anchor (dimension);
|
||||
|
||||
return autoSize && autosize > newDimension ? autosize : newDimension;
|
||||
}
|
||||
}
|
||||
|
||||
internal class DimFill : Dim
|
||||
internal class DimFill (int margin) : Dim
|
||||
{
|
||||
private readonly int _margin;
|
||||
public DimFill (int margin) { _margin = margin; }
|
||||
private readonly int _margin = margin;
|
||||
public override bool Equals (object other) { return other is DimFill fill && fill._margin == _margin; }
|
||||
public override int GetHashCode () { return _margin.GetHashCode (); }
|
||||
public override string ToString () { return $"Fill({_margin})"; }
|
||||
@@ -700,21 +833,36 @@ public class Dim
|
||||
}
|
||||
|
||||
// Helper class to provide dynamic value by the execution of a function that returns an integer.
|
||||
internal class DimFunc : Dim
|
||||
internal class DimFunc (Func<int> n) : Dim
|
||||
{
|
||||
private readonly Func<int> _function;
|
||||
public DimFunc (Func<int> n) { _function = n; }
|
||||
private readonly Func<int> _function = n;
|
||||
public override bool Equals (object other) { return other is DimFunc f && f._function () == _function (); }
|
||||
public override int GetHashCode () { return _function.GetHashCode (); }
|
||||
public override string ToString () { return $"DimFunc({_function ()})"; }
|
||||
internal override int Anchor (int width) { return _function (); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum Dimension
|
||||
{
|
||||
/// <summary>
|
||||
/// The height dimension.
|
||||
/// </summary>
|
||||
Height = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The width dimension.
|
||||
/// </summary>
|
||||
Width = 1
|
||||
}
|
||||
|
||||
internal class DimView : Dim
|
||||
{
|
||||
private readonly int _side;
|
||||
private readonly Dimension _side;
|
||||
|
||||
public DimView (View view, int side)
|
||||
internal DimView (View view, Dimension side)
|
||||
{
|
||||
Target = view;
|
||||
_side = side;
|
||||
@@ -726,29 +874,29 @@ public class Dim
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
if (Target is null)
|
||||
if (Target == null)
|
||||
{
|
||||
throw new NullReferenceException ();
|
||||
}
|
||||
|
||||
string tside = _side switch
|
||||
{
|
||||
0 => "Height",
|
||||
1 => "Width",
|
||||
_ => "unknown"
|
||||
};
|
||||
string sideString = _side switch
|
||||
{
|
||||
Dimension.Height => "Height",
|
||||
Dimension.Width => "Width",
|
||||
_ => "unknown"
|
||||
};
|
||||
|
||||
return $"View({tside},{Target})";
|
||||
return $"View({sideString},{Target})";
|
||||
}
|
||||
|
||||
internal override int Anchor (int width)
|
||||
{
|
||||
return _side switch
|
||||
{
|
||||
0 => Target.Frame.Height,
|
||||
1 => Target.Frame.Width,
|
||||
_ => 0
|
||||
};
|
||||
{
|
||||
Dimension.Height => Target.Frame.Height,
|
||||
Dimension.Width => Target.Frame.Width,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
@@ -88,11 +87,13 @@ public partial class View
|
||||
|
||||
private void SetFrame (Rectangle frame)
|
||||
{
|
||||
Rectangle oldViewport = Rectangle.Empty;
|
||||
var oldViewport = Rectangle.Empty;
|
||||
|
||||
if (IsInitialized)
|
||||
{
|
||||
oldViewport = Viewport;
|
||||
}
|
||||
|
||||
// This is the only place where _frame should be set directly. Use Frame = or SetFrame instead.
|
||||
_frame = frame;
|
||||
|
||||
@@ -113,7 +114,7 @@ public partial class View
|
||||
// Adornments don't have SuperViews; use Adornment.FrameToScreen override
|
||||
// which will give us the screen coordinates of the parent
|
||||
|
||||
var parentScreen = adornment.FrameToScreen ();
|
||||
Rectangle parentScreen = adornment.FrameToScreen ();
|
||||
|
||||
// Now add our Frame location
|
||||
parentScreen.Offset (screen.X, screen.Y);
|
||||
@@ -142,7 +143,7 @@ public partial class View
|
||||
{
|
||||
if (SuperView is null)
|
||||
{
|
||||
return new Point (x - Frame.X, y - Frame.Y);
|
||||
return new (x - Frame.X, y - Frame.Y);
|
||||
}
|
||||
|
||||
Point superViewViewportOffset = SuperView.GetViewportOffsetFromFrame ();
|
||||
@@ -242,7 +243,8 @@ public partial class View
|
||||
/// <value>The <see cref="Dim"/> object representing the height of the view (the number of rows).</value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>.
|
||||
/// The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>
|
||||
/// .
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If set to a relative value (e.g. <see cref="Dim.Fill(int)"/>) the value is indeterminate until the view has
|
||||
@@ -283,8 +285,8 @@ public partial class View
|
||||
if (IsAdded && AutoSize && !isValidNewAutoSize)
|
||||
{
|
||||
Debug.WriteLine (
|
||||
@$"Must set AutoSize to false before setting the {nameof (Height)}."
|
||||
);
|
||||
@$"Must set AutoSize to false before setting the {nameof (Height)}."
|
||||
);
|
||||
AutoSize = false;
|
||||
}
|
||||
|
||||
@@ -299,7 +301,8 @@ public partial class View
|
||||
/// <value>The <see cref="Dim"/> object representing the width of the view (the number of columns).</value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>.
|
||||
/// The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="ContentSize"/>
|
||||
/// .
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If set to a relative value (e.g. <see cref="Dim.Fill(int)"/>) the value is indeterminate until the view has
|
||||
@@ -330,7 +333,7 @@ public partial class View
|
||||
|
||||
if (AutoSize)
|
||||
{
|
||||
Debug.WriteLine($@"Must set AutoSize to false before setting {nameof(Width)}.");
|
||||
Debug.WriteLine ($@"Must set AutoSize to false before setting {nameof (Width)}.");
|
||||
AutoSize = false;
|
||||
}
|
||||
|
||||
@@ -338,7 +341,7 @@ public partial class View
|
||||
|
||||
if (IsAdded && AutoSize && !isValidNewAutoSize)
|
||||
{
|
||||
Debug.WriteLine($@"Must set AutoSize to false before setting {nameof(Width)}.");
|
||||
Debug.WriteLine ($@"Must set AutoSize to false before setting {nameof (Width)}.");
|
||||
AutoSize = false;
|
||||
}
|
||||
|
||||
@@ -656,6 +659,7 @@ public partial class View
|
||||
int startOffsetY = y - (start.Frame.Y + viewportOffset.Y);
|
||||
|
||||
View? subview = null;
|
||||
|
||||
for (int i = start.InternalSubviews.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (start.InternalSubviews [i].Visible
|
||||
@@ -750,8 +754,8 @@ public partial class View
|
||||
}
|
||||
|
||||
//System.Diagnostics.Debug.WriteLine ($"nx:{nx}, rWidth:{rWidth}");
|
||||
bool menuVisible = false;
|
||||
bool statusVisible = false;
|
||||
var menuVisible = false;
|
||||
var statusVisible = false;
|
||||
|
||||
if (viewToMove?.SuperView is null || viewToMove == Application.Top || viewToMove?.SuperView == Application.Top)
|
||||
{
|
||||
@@ -907,6 +911,7 @@ public partial class View
|
||||
|
||||
OnLayoutComplete (new (ContentSize));
|
||||
}
|
||||
|
||||
private void LayoutSubview (View v, Size contentSize)
|
||||
{
|
||||
v.SetRelativeLayout (contentSize);
|
||||
@@ -964,6 +969,7 @@ public partial class View
|
||||
SetNeedsLayout ();
|
||||
}
|
||||
}
|
||||
|
||||
internal bool LayoutNeeded { get; private set; } = true;
|
||||
|
||||
/// <summary>
|
||||
@@ -995,11 +1001,11 @@ public partial class View
|
||||
/// <see cref="Height"/>).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, or <see cref="Height"/> are
|
||||
/// absolute, they will be updated to reflect the new size and position of the view. Otherwise, they
|
||||
/// are left unchanged.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, or <see cref="Height"/> are
|
||||
/// absolute, they will be updated to reflect the new size and position of the view. Otherwise, they
|
||||
/// are left unchanged.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="superviewContentSize">
|
||||
/// The size of the SuperView's content (nominally the same as <c>this.SuperView.ContentSize</c>).
|
||||
@@ -1011,175 +1017,25 @@ public partial class View
|
||||
Debug.Assert (_width is { });
|
||||
Debug.Assert (_height is { });
|
||||
|
||||
int newX, newW, newY, newH;
|
||||
var autosize = Size.Empty;
|
||||
var autoSize = Size.Empty;
|
||||
|
||||
if (AutoSize)
|
||||
{
|
||||
// Note this is global to this function and used as such within the local functions defined
|
||||
// below. In v2 AutoSize will be re-factored to not need to be dealt with in this function.
|
||||
autosize = GetAutoSize ();
|
||||
autoSize = GetAutoSize ();
|
||||
}
|
||||
|
||||
// TODO: Since GetNewLocationAndDimension does not depend on View, it can be moved into PosDim.cs
|
||||
// TODO: to make architecture more clean. Do this after DimAuto is implemented and the
|
||||
// TODO: View.AutoSize stuff is removed.
|
||||
int newX = _x.Calculate (superviewContentSize.Width, _width, autoSize.Width, AutoSize);
|
||||
int newW = _width.Calculate (newX, superviewContentSize.Width, autoSize.Width, AutoSize);
|
||||
int newY = _y.Calculate (superviewContentSize.Height, _height, autoSize.Height, AutoSize);
|
||||
int newH = _height.Calculate (newY, superviewContentSize.Height, autoSize.Height, AutoSize);
|
||||
|
||||
// Returns the new dimension (width or height) and location (x or y) for the View given
|
||||
// the superview's Viewport
|
||||
// the current Pos (View.X or View.Y)
|
||||
// the current Dim (View.Width or View.Height)
|
||||
// This method is called recursively if pos is Pos.PosCombine
|
||||
(int newLocation, int newDimension) GetNewLocationAndDimension (
|
||||
bool width,
|
||||
Size superviewContentSize,
|
||||
Pos pos,
|
||||
Dim dim,
|
||||
int autosizeDimension
|
||||
)
|
||||
{
|
||||
// Gets the new dimension (width or height, dependent on `width`) of the given Dim given:
|
||||
// location: the current location (x or y)
|
||||
// dimension: the new dimension (width or height) (if relevant for Dim type)
|
||||
// autosize: the size to use if autosize = true
|
||||
// This method is recursive if d is Dim.DimCombine
|
||||
int GetNewDimension (Dim d, int location, int dimension, int autosize)
|
||||
{
|
||||
int newDimension;
|
||||
Rectangle newFrame = new (newX, newY, newW, newH);
|
||||
|
||||
switch (d)
|
||||
{
|
||||
case Dim.DimCombine combine:
|
||||
// TODO: Move combine logic into DimCombine?
|
||||
int leftNewDim = GetNewDimension (combine._left, location, dimension, autosize);
|
||||
int rightNewDim = GetNewDimension (combine._right, location, dimension, autosize);
|
||||
|
||||
if (combine._add)
|
||||
{
|
||||
newDimension = leftNewDim + rightNewDim;
|
||||
}
|
||||
else
|
||||
{
|
||||
newDimension = leftNewDim - rightNewDim;
|
||||
}
|
||||
|
||||
newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
|
||||
|
||||
break;
|
||||
|
||||
case Dim.DimFactor factor when !factor.IsFromRemaining ():
|
||||
newDimension = d.Anchor (dimension);
|
||||
newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
|
||||
|
||||
break;
|
||||
|
||||
case Dim.DimAbsolute:
|
||||
// DimAbsolute.Anchor (int width) ignores width and returns n
|
||||
newDimension = Math.Max (d.Anchor (0), 0);
|
||||
|
||||
// BUGBUG: AutoSize does two things: makes text fit AND changes the view's dimensions
|
||||
newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
|
||||
|
||||
break;
|
||||
|
||||
case Dim.DimFill:
|
||||
default:
|
||||
newDimension = Math.Max (d.Anchor (dimension - location), 0);
|
||||
newDimension = AutoSize && autosize > newDimension ? autosize : newDimension;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return newDimension;
|
||||
}
|
||||
|
||||
int newDimension, newLocation;
|
||||
int superviewDimension = width ? superviewContentSize.Width : superviewContentSize.Height;
|
||||
|
||||
// Determine new location
|
||||
switch (pos)
|
||||
{
|
||||
case Pos.PosCenter posCenter:
|
||||
// For Center, the dimension is dependent on location, but we need to force getting the dimension first
|
||||
// using a location of 0
|
||||
newDimension = Math.Max (GetNewDimension (dim, 0, superviewDimension, autosizeDimension), 0);
|
||||
newLocation = posCenter.Anchor (superviewDimension - newDimension);
|
||||
|
||||
newDimension = Math.Max (
|
||||
GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension),
|
||||
0
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case Pos.PosCombine combine:
|
||||
// TODO: Move combine logic into PosCombine?
|
||||
int left, right;
|
||||
|
||||
(left, newDimension) = GetNewLocationAndDimension (
|
||||
width,
|
||||
superviewContentSize,
|
||||
combine._left,
|
||||
dim,
|
||||
autosizeDimension
|
||||
);
|
||||
|
||||
(right, newDimension) = GetNewLocationAndDimension (
|
||||
width,
|
||||
superviewContentSize,
|
||||
combine._right,
|
||||
dim,
|
||||
autosizeDimension
|
||||
);
|
||||
|
||||
if (combine._add)
|
||||
{
|
||||
newLocation = left + right;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLocation = left - right;
|
||||
}
|
||||
|
||||
newDimension = Math.Max (
|
||||
GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension),
|
||||
0
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case Pos.PosAnchorEnd:
|
||||
case Pos.PosAbsolute:
|
||||
case Pos.PosFactor:
|
||||
case Pos.PosFunc:
|
||||
case Pos.PosView:
|
||||
default:
|
||||
newLocation = pos?.Anchor (superviewDimension) ?? 0;
|
||||
|
||||
newDimension = Math.Max (
|
||||
GetNewDimension (dim, newLocation, superviewDimension, autosizeDimension),
|
||||
0
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return (newLocation, newDimension);
|
||||
}
|
||||
|
||||
// horizontal/width
|
||||
(newX, newW) = GetNewLocationAndDimension (true, superviewContentSize, _x, _width, autosize.Width);
|
||||
|
||||
// vertical/height
|
||||
(newY, newH) = GetNewLocationAndDimension (false, superviewContentSize, _y, _height, autosize.Height);
|
||||
|
||||
Rectangle r = new (newX, newY, newW, newH);
|
||||
|
||||
if (Frame != r)
|
||||
if (Frame != newFrame)
|
||||
{
|
||||
// Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
|
||||
// the view LayoutStyle.Absolute.
|
||||
SetFrame (r);
|
||||
SetFrame (newFrame);
|
||||
|
||||
if (_x is Pos.PosAbsolute)
|
||||
{
|
||||
@@ -1207,18 +1063,18 @@ public partial class View
|
||||
|
||||
if (AutoSize)
|
||||
{
|
||||
if (autosize.Width == 0 || autosize.Height == 0)
|
||||
if (autoSize.Width == 0 || autoSize.Height == 0)
|
||||
{
|
||||
// Set the frame. Do NOT use `Frame` as it overwrites X, Y, Width, and Height, making
|
||||
// the view LayoutStyle.Absolute.
|
||||
SetFrame (_frame with { Size = autosize });
|
||||
SetFrame (_frame with { Size = autoSize });
|
||||
|
||||
if (autosize.Width == 0)
|
||||
if (autoSize.Width == 0)
|
||||
{
|
||||
_width = 0;
|
||||
}
|
||||
|
||||
if (autosize.Height == 0)
|
||||
if (autoSize.Height == 0)
|
||||
{
|
||||
_height = 0;
|
||||
}
|
||||
@@ -1432,4 +1288,4 @@ public partial class View
|
||||
public bool ValidatePosDim { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class Adornments : Scenario
|
||||
app.Add (window);
|
||||
|
||||
var tf1 = new TextField { Width = 10, Text = "TextField" };
|
||||
var color = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (11) };
|
||||
var color = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd () };
|
||||
color.BorderStyle = LineStyle.RoundedDotted;
|
||||
|
||||
color.ColorChanged += (s, e) =>
|
||||
@@ -68,15 +68,16 @@ public class Adornments : Scenario
|
||||
};
|
||||
label.Border.Thickness = new (1, 3, 1, 1);
|
||||
|
||||
var btnButtonInWindow = new Button { X = Pos.AnchorEnd (10), Y = Pos.AnchorEnd (1), Text = "Button" };
|
||||
var btnButtonInWindow = new Button { X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Text = "Button" };
|
||||
|
||||
var tv = new Label
|
||||
var labelAnchorEnd = new Label
|
||||
{
|
||||
AutoSize = false,
|
||||
Y = Pos.AnchorEnd (3),
|
||||
Width = 25,
|
||||
Height = Dim.Fill (),
|
||||
Text = "Label\nY=AnchorEnd(3),Height=Dim.Fill()"
|
||||
Y = Pos.AnchorEnd (),
|
||||
Width = 40,
|
||||
Height = Dim.Percent(20),
|
||||
Text = "Label\nY=AnchorEnd(),Height=Dim.Percent(10)",
|
||||
ColorScheme = Colors.ColorSchemes ["Error"]
|
||||
};
|
||||
|
||||
window.Margin.Data = "Margin";
|
||||
@@ -94,7 +95,7 @@ public class Adornments : Scenario
|
||||
|
||||
};
|
||||
longLabel.TextFormatter.WordWrap = true;
|
||||
window.Add (tf1, color, button, label, btnButtonInWindow, tv, longLabel);
|
||||
window.Add (tf1, color, button, label, btnButtonInWindow, labelAnchorEnd, longLabel);
|
||||
|
||||
editor.Initialized += (s, e) => { editor.ViewToEdit = window; };
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ public class AllViewsTester : Scenario
|
||||
};
|
||||
_settingsPane.Add (_computedCheckBox);
|
||||
|
||||
string [] radioItems = { "_Percent(x)", "_AnchorEnd(x)", "_Center", "A_t(x)" };
|
||||
string [] radioItems = { "_Percent(x)", "_AnchorEnd", "_Center", "A_t(x)" };
|
||||
|
||||
_locationFrame = new FrameView
|
||||
{
|
||||
@@ -179,7 +179,7 @@ public class AllViewsTester : Scenario
|
||||
|
||||
_locationFrame.Add (_xRadioGroup);
|
||||
|
||||
radioItems = new [] { "P_ercent(y)", "A_nchorEnd(y)", "C_enter", "At(_y)" };
|
||||
radioItems = new [] { "P_ercent(y)", "A_nchorEnd", "C_enter", "At(_y)" };
|
||||
label = new Label { X = Pos.Right (_xRadioGroup) + 1, Y = 0, Text = "Y:" };
|
||||
_locationFrame.Add (label);
|
||||
_yText = new TextField { X = Pos.Right (label) + 1, Y = 0, Width = 4, Text = $"{_yVal}" };
|
||||
@@ -388,7 +388,7 @@ public class AllViewsTester : Scenario
|
||||
view.X = _xRadioGroup.SelectedItem switch
|
||||
{
|
||||
0 => Pos.Percent (_xVal),
|
||||
1 => Pos.AnchorEnd (_xVal),
|
||||
1 => Pos.AnchorEnd (),
|
||||
2 => Pos.Center (),
|
||||
3 => Pos.At (_xVal),
|
||||
_ => view.X
|
||||
@@ -397,7 +397,7 @@ public class AllViewsTester : Scenario
|
||||
view.Y = _yRadioGroup.SelectedItem switch
|
||||
{
|
||||
0 => Pos.Percent (_yVal),
|
||||
1 => Pos.AnchorEnd (_yVal),
|
||||
1 => Pos.AnchorEnd (),
|
||||
2 => Pos.Center (),
|
||||
3 => Pos.At (_yVal),
|
||||
_ => view.Y
|
||||
|
||||
@@ -34,12 +34,12 @@ public class Animation : Scenario
|
||||
|
||||
win.Add (imageView);
|
||||
|
||||
var lbl = new Label { Y = Pos.AnchorEnd (2), Text = "Image by Wikiscient" };
|
||||
var lbl = new Label { Y = Pos.AnchorEnd (), Text = "Image by Wikiscient" };
|
||||
win.Add (lbl);
|
||||
|
||||
var lbl2 = new Label
|
||||
{
|
||||
Y = Pos.AnchorEnd (1), Text = "https://commons.wikimedia.org/wiki/File:Spinning_globe.gif"
|
||||
X = Pos.AnchorEnd(), Y = Pos.AnchorEnd (), Text = "https://commons.wikimedia.org/wiki/File:Spinning_globe.gif"
|
||||
};
|
||||
win.Add (lbl2);
|
||||
|
||||
|
||||
@@ -8,8 +8,15 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Text and Formatting")]
|
||||
public class BasicColors : Scenario
|
||||
{
|
||||
public override void Setup ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
|
||||
};
|
||||
|
||||
var vx = 30;
|
||||
var x = 30;
|
||||
var y = 14;
|
||||
@@ -31,7 +38,7 @@ public class BasicColors : Scenario
|
||||
Text = bg.ToString (),
|
||||
TextDirection = TextDirection.TopBottom_LeftRight
|
||||
};
|
||||
Win.Add (vl);
|
||||
app.Add (vl);
|
||||
|
||||
var hl = new Label
|
||||
{
|
||||
@@ -44,7 +51,7 @@ public class BasicColors : Scenario
|
||||
ColorScheme = new ColorScheme { Normal = attr },
|
||||
Text = bg.ToString ()
|
||||
};
|
||||
Win.Add (hl);
|
||||
app.Add (hl);
|
||||
vx++;
|
||||
|
||||
foreach (ColorName fg in colors)
|
||||
@@ -56,7 +63,7 @@ public class BasicColors : Scenario
|
||||
{
|
||||
ColorScheme = new ColorScheme { Normal = c }, X = x, Y = y, Text = t [^1].ToString ()
|
||||
};
|
||||
Win.Add (l);
|
||||
app.Add (l);
|
||||
x++;
|
||||
}
|
||||
|
||||
@@ -64,24 +71,24 @@ public class BasicColors : Scenario
|
||||
y++;
|
||||
}
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (36), Text = "Mouse over to get the Attribute:" }
|
||||
);
|
||||
Win.Add (new Label { X = Pos.AnchorEnd (35), Y = 2, Text = "Foreground:" });
|
||||
app.Add (new Label { X = Pos.AnchorEnd (35), Y = 2, Text = "Foreground:" });
|
||||
|
||||
var lblForeground = new Label { X = Pos.AnchorEnd (23), Y = 2 };
|
||||
Win.Add (lblForeground);
|
||||
app.Add (lblForeground);
|
||||
|
||||
var viewForeground = new View { X = Pos.AnchorEnd (2), Y = 2, ColorScheme = new ColorScheme (), Text = " " };
|
||||
Win.Add (viewForeground);
|
||||
app.Add (viewForeground);
|
||||
|
||||
Win.Add (new Label { X = Pos.AnchorEnd (35), Y = 4, Text = "Background:" });
|
||||
app.Add (new Label { X = Pos.AnchorEnd (35), Y = 4, Text = "Background:" });
|
||||
|
||||
var lblBackground = new Label { X = Pos.AnchorEnd (23), Y = 4 };
|
||||
Win.Add (lblBackground);
|
||||
app.Add (lblBackground);
|
||||
|
||||
var viewBackground = new View { X = Pos.AnchorEnd (2), Y = 4, ColorScheme = new ColorScheme (), Text = " " };
|
||||
Win.Add (viewBackground);
|
||||
app.Add (viewBackground);
|
||||
|
||||
Application.MouseEvent += (s, e) =>
|
||||
{
|
||||
@@ -103,5 +110,8 @@ public class BasicColors : Scenario
|
||||
new ColorScheme (viewBackground.ColorScheme) { Normal = new Attribute (back, back) };
|
||||
}
|
||||
};
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public class Buttons : Scenario
|
||||
|
||||
// This is the default button (IsDefault = true); if user presses ENTER in the TextField
|
||||
// the scenario will quit
|
||||
var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), IsDefault = true, Text = "_Quit" };
|
||||
var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (), IsDefault = true, Text = "_Quit" };
|
||||
defaultButton.Accept += (s, e) => Application.RequestStop ();
|
||||
main.Add (defaultButton);
|
||||
|
||||
@@ -459,7 +459,7 @@ public class Buttons : Scenario
|
||||
_up = new ()
|
||||
{
|
||||
AutoSize = false,
|
||||
X = Pos.AnchorEnd (1),
|
||||
X = Pos.AnchorEnd (),
|
||||
Y = Pos.Top (_number),
|
||||
Height = 1,
|
||||
Width = 1,
|
||||
|
||||
@@ -24,42 +24,45 @@ public class ColorPickers : Scenario
|
||||
private ColorPicker foregroundColorPicker;
|
||||
|
||||
/// <summary>Setup the scenario.</summary>
|
||||
public override void Setup ()
|
||||
public override void Main ()
|
||||
{
|
||||
// Scenario Window's.
|
||||
Win.Title = GetName ();
|
||||
Application.Init ();
|
||||
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
|
||||
};
|
||||
|
||||
// Foreground ColorPicker.
|
||||
foregroundColorPicker = new ColorPicker { Title = "Foreground Color", BorderStyle = LineStyle.Single };
|
||||
foregroundColorPicker.ColorChanged += ForegroundColor_ColorChanged;
|
||||
Win.Add (foregroundColorPicker);
|
||||
app.Add (foregroundColorPicker);
|
||||
|
||||
_foregroundColorLabel = new Label
|
||||
{
|
||||
X = Pos.Left (foregroundColorPicker), Y = Pos.Bottom (foregroundColorPicker) + 1
|
||||
};
|
||||
Win.Add (_foregroundColorLabel);
|
||||
app.Add (_foregroundColorLabel);
|
||||
|
||||
// Background ColorPicker.
|
||||
backgroundColorPicker = new ColorPicker
|
||||
{
|
||||
Title = "Background Color",
|
||||
// TODO: Replace with Pos.AnchorEnd () when #2900 is done
|
||||
X = Pos.AnchorEnd ((8 * 4) + 2), // 8 box * 4 width + 2 for border
|
||||
X = Pos.AnchorEnd (),
|
||||
BoxHeight = 1,
|
||||
BoxWidth = 4,
|
||||
BorderStyle = LineStyle.Single
|
||||
BorderStyle = LineStyle.Single,
|
||||
};
|
||||
|
||||
//backgroundColorPicker.X = Pos.AnchorEnd () - (Pos.Right (backgroundColorPicker) - Pos.Left (backgroundColorPicker));
|
||||
backgroundColorPicker.ColorChanged += BackgroundColor_ColorChanged;
|
||||
Win.Add (backgroundColorPicker);
|
||||
_backgroundColorLabel = new Label ();
|
||||
app.Add (backgroundColorPicker);
|
||||
_backgroundColorLabel = new Label ()
|
||||
{
|
||||
X = Pos.AnchorEnd (),
|
||||
Y = Pos.Bottom (backgroundColorPicker) + 1
|
||||
};
|
||||
|
||||
_backgroundColorLabel.X =
|
||||
Pos.AnchorEnd () - (Pos.Right (_backgroundColorLabel) - Pos.Left (_backgroundColorLabel));
|
||||
_backgroundColorLabel.Y = Pos.Bottom (backgroundColorPicker) + 1;
|
||||
Win.Add (_backgroundColorLabel);
|
||||
app.Add (_backgroundColorLabel);
|
||||
|
||||
// Demo Label.
|
||||
_demoView = new View
|
||||
@@ -74,12 +77,15 @@ public class ColorPickers : Scenario
|
||||
Height = 5,
|
||||
Width = 20
|
||||
};
|
||||
Win.Add (_demoView);
|
||||
app.Add (_demoView);
|
||||
|
||||
// Set default colors.
|
||||
foregroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Foreground.GetClosestNamedColor ();
|
||||
backgroundColorPicker.SelectedColor = _demoView.SuperView.ColorScheme.Normal.Background.GetClosestNamedColor ();
|
||||
Win.Initialized += (s, e) => Win.LayoutSubviews ();
|
||||
app.Initialized += (s, e) => app.LayoutSubviews ();
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
|
||||
/// <summary>Fired when background color is changed.</summary>
|
||||
|
||||
@@ -13,17 +13,15 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Layout")]
|
||||
public class ComputedLayout : Scenario
|
||||
{
|
||||
public override void Init ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
ConfigurationManager.Themes.Theme = Theme;
|
||||
ConfigurationManager.Apply ();
|
||||
Top = new ();
|
||||
Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
|
||||
}
|
||||
|
||||
public override void Setup ()
|
||||
{
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
|
||||
};
|
||||
|
||||
// Demonstrate using Dim to create a horizontal ruler that always measures the parent window's width
|
||||
const string rule = "|123456789";
|
||||
|
||||
@@ -38,7 +36,7 @@ public class ComputedLayout : Scenario
|
||||
Text = rule
|
||||
};
|
||||
|
||||
Top.Add (horizontalRuler);
|
||||
app.Add (horizontalRuler);
|
||||
|
||||
// Demonstrate using Dim to create a vertical ruler that always measures the parent window's height
|
||||
const string vrule = "|\n1\n2\n3\n4\n5\n6\n7\n8\n9\n";
|
||||
@@ -54,7 +52,7 @@ public class ComputedLayout : Scenario
|
||||
Text = vrule
|
||||
};
|
||||
|
||||
Top.LayoutComplete += (s, a) =>
|
||||
app.LayoutComplete += (s, a) =>
|
||||
{
|
||||
horizontalRuler.Text =
|
||||
rule.Repeat ((int)Math.Ceiling (horizontalRuler.Viewport.Width / (double)rule.Length)) [
|
||||
@@ -65,15 +63,15 @@ public class ComputedLayout : Scenario
|
||||
[..(verticalRuler.Viewport.Height * 2)];
|
||||
};
|
||||
|
||||
Top.Add (verticalRuler);
|
||||
app.Add (verticalRuler);
|
||||
|
||||
// Demonstrate At - Using Pos.At to locate a view in an absolute location
|
||||
var atButton = new Button { Text = "At(2,1)", X = Pos.At (2), Y = Pos.At (1) };
|
||||
Top.Add (atButton);
|
||||
app.Add (atButton);
|
||||
|
||||
// Throw in a literal absolute - Should function identically to above
|
||||
var absoluteButton = new Button { Text = "X = 30, Y = 1", X = 30, Y = 1 };
|
||||
Top.Add (absoluteButton);
|
||||
app.Add (absoluteButton);
|
||||
|
||||
// Demonstrate using Dim to create a window that fills the parent with a margin
|
||||
var margin = 10;
|
||||
@@ -84,7 +82,7 @@ public class ComputedLayout : Scenario
|
||||
subWin.Title =
|
||||
$"{subWin.GetType ().Name} {{X={subWin.X},Y={subWin.Y},Width={subWin.Width},Height={subWin.Height}}}";
|
||||
};
|
||||
Top.Add (subWin);
|
||||
app.Add (subWin);
|
||||
|
||||
var i = 1;
|
||||
var txt = "Resize the terminal to see computed layout in action.";
|
||||
@@ -209,7 +207,7 @@ public class ComputedLayout : Scenario
|
||||
}
|
||||
);
|
||||
frameView.Add (labelList.ToArray ());
|
||||
Top.Add (frameView);
|
||||
app.Add (frameView);
|
||||
|
||||
frameView = new FrameView
|
||||
{
|
||||
@@ -223,7 +221,7 @@ public class ComputedLayout : Scenario
|
||||
fv.Title =
|
||||
$"{frameView.GetType ().Name} {{X={fv.X},Y={fv.Y},Width={fv.Width},Height={fv.Height}}}";
|
||||
};
|
||||
Top.Add (frameView);
|
||||
app.Add (frameView);
|
||||
|
||||
// Demonstrate Dim & Pos using percentages - a TextField that is 30% height and 80% wide
|
||||
var textView = new TextView
|
||||
@@ -237,7 +235,7 @@ public class ComputedLayout : Scenario
|
||||
|
||||
textView.Text =
|
||||
"This TextView should horizontally & vertically centered and \n10% of the screeen height, and 80% of its width.";
|
||||
Top.Add (textView);
|
||||
app.Add (textView);
|
||||
|
||||
var oddballButton = new Button
|
||||
{
|
||||
@@ -245,7 +243,7 @@ public class ComputedLayout : Scenario
|
||||
X = Pos.Center (),
|
||||
Y = Pos.Bottom (textView) + 1
|
||||
};
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
#region Issue2358
|
||||
|
||||
@@ -253,19 +251,19 @@ public class ComputedLayout : Scenario
|
||||
// Until https://github.com/gui-cs/Terminal.Gui/issues/2358 is fixed these won't work right
|
||||
|
||||
oddballButton = new Button { Text = "Center + 0", X = Pos.Center () + 0, Y = Pos.Bottom (oddballButton) };
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
oddballButton = new Button { Text = "Center + 1", X = Pos.Center () + 1, Y = Pos.Bottom (oddballButton) };
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
oddballButton = new Button { Text = "0 + Center", X = 0 + Pos.Center (), Y = Pos.Bottom (oddballButton) };
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
oddballButton = new Button { Text = "1 + Center", X = 1 + Pos.Center (), Y = Pos.Bottom (oddballButton) };
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
oddballButton = new Button { Text = "Center - 1", X = Pos.Center () - 1, Y = Pos.Bottom (oddballButton) };
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
|
||||
// The `- Pos.Percent(5)` is there so at least something is visible
|
||||
@@ -275,7 +273,7 @@ public class ComputedLayout : Scenario
|
||||
X = Pos.Center () + Pos.Center () - Pos.Percent (50),
|
||||
Y = Pos.Bottom (oddballButton)
|
||||
};
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
|
||||
// The `- Pos.Percent(5)` is there so at least something is visible
|
||||
@@ -285,7 +283,7 @@ public class ComputedLayout : Scenario
|
||||
X = Pos.Percent (50) + Pos.Center () - Pos.Percent (50),
|
||||
Y = Pos.Bottom (oddballButton)
|
||||
};
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
// This demonstrates nonsense: it the same as using Pos.AnchorEnd (100/2=50 + 100/2=50 = 100 - 50)
|
||||
// The `- Pos.Percent(5)` is there so at least something is visible
|
||||
@@ -295,7 +293,7 @@ public class ComputedLayout : Scenario
|
||||
X = Pos.Center () + Pos.Percent (50) - Pos.Percent (50),
|
||||
Y = Pos.Bottom (oddballButton)
|
||||
};
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -306,29 +304,29 @@ public class ComputedLayout : Scenario
|
||||
X = Pos.Center () + Pos.Center () - Pos.Percent (50),
|
||||
Y = Pos.Bottom (oddballButton)
|
||||
};
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
// This demonstrates combining Percents)
|
||||
oddballButton = new Button
|
||||
{
|
||||
Text = "Percent(40) + Percent(10)", X = Pos.Percent (40) + Pos.Percent (10), Y = Pos.Bottom (oddballButton)
|
||||
};
|
||||
Top.Add (oddballButton);
|
||||
app.Add (oddballButton);
|
||||
|
||||
// Demonstrate AnchorEnd - Button is anchored to bottom/right
|
||||
var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd () - 1 };
|
||||
anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
|
||||
var anchorButton = new Button { Text = "Button using AnchorEnd", Y = Pos.AnchorEnd ()};
|
||||
anchorButton.X = Pos.AnchorEnd ();
|
||||
|
||||
anchorButton.Accept += (s, e) =>
|
||||
{
|
||||
// This demonstrates how to have a dynamically sized button
|
||||
// Each time the button is clicked the button's text gets longer
|
||||
// The call to Top.LayoutSubviews causes the Computed layout to
|
||||
// The call to app.LayoutSubviews causes the Computed layout to
|
||||
// get updated.
|
||||
anchorButton.Text += "!";
|
||||
Top.LayoutSubviews ();
|
||||
app.LayoutSubviews ();
|
||||
};
|
||||
Top.Add (anchorButton);
|
||||
app.Add (anchorButton);
|
||||
|
||||
// Demonstrate AnchorEnd(n)
|
||||
// This is intentionally convoluted to illustrate potential bugs.
|
||||
@@ -342,7 +340,7 @@ public class ComputedLayout : Scenario
|
||||
X = 5,
|
||||
Y = Pos.AnchorEnd (2)
|
||||
};
|
||||
Top.Add (anchorEndLabel1);
|
||||
app.Add (anchorEndLabel1);
|
||||
|
||||
// Demonstrate DimCombine (via AnchorEnd(n) - 1)
|
||||
// This is intentionally convoluted to illustrate potential bugs.
|
||||
@@ -357,22 +355,22 @@ public class ComputedLayout : Scenario
|
||||
X = 5,
|
||||
Y = Pos.AnchorEnd (2) - 1 // Pos.Combine
|
||||
};
|
||||
Top.Add (anchorEndLabel2);
|
||||
app.Add (anchorEndLabel2);
|
||||
|
||||
// Show positioning vertically using Pos.AnchorEnd via Pos.Combine
|
||||
var leftButton = new Button
|
||||
{
|
||||
Text = "Left", Y = Pos.AnchorEnd () - 1 // Pos.Combine
|
||||
Text = "Left", Y = Pos.AnchorEnd (0) - 1 // Pos.Combine
|
||||
};
|
||||
|
||||
leftButton.Accept += (s, e) =>
|
||||
{
|
||||
// This demonstrates how to have a dynamically sized button
|
||||
// Each time the button is clicked the button's text gets longer
|
||||
// The call to Top.LayoutSubviews causes the Computed layout to
|
||||
// The call to app.LayoutSubviews causes the Computed layout to
|
||||
// get updated.
|
||||
leftButton.Text += "!";
|
||||
Top.LayoutSubviews ();
|
||||
app.LayoutSubviews ();
|
||||
};
|
||||
|
||||
// show positioning vertically using Pos.AnchorEnd
|
||||
@@ -385,10 +383,10 @@ public class ComputedLayout : Scenario
|
||||
{
|
||||
// This demonstrates how to have a dynamically sized button
|
||||
// Each time the button is clicked the button's text gets longer
|
||||
// The call to Top.LayoutSubviews causes the Computed layout to
|
||||
// The call to app.LayoutSubviews causes the Computed layout to
|
||||
// get updated.
|
||||
centerButton.Text += "!";
|
||||
Top.LayoutSubviews ();
|
||||
app.LayoutSubviews ();
|
||||
};
|
||||
|
||||
// show positioning vertically using another window and Pos.Bottom
|
||||
@@ -398,18 +396,21 @@ public class ComputedLayout : Scenario
|
||||
{
|
||||
// This demonstrates how to have a dynamically sized button
|
||||
// Each time the button is clicked the button's text gets longer
|
||||
// The call to Top.LayoutSubviews causes the Computed layout to
|
||||
// The call to app.LayoutSubviews causes the Computed layout to
|
||||
// get updated.
|
||||
rightButton.Text += "!";
|
||||
Top.LayoutSubviews ();
|
||||
app.LayoutSubviews ();
|
||||
};
|
||||
|
||||
// Center three buttons with 5 spaces between them
|
||||
leftButton.X = Pos.Left (centerButton) - (Pos.Right (leftButton) - Pos.Left (leftButton)) - 5;
|
||||
rightButton.X = Pos.Right (centerButton) + 5;
|
||||
|
||||
Top.Add (leftButton);
|
||||
Top.Add (centerButton);
|
||||
Top.Add (rightButton);
|
||||
app.Add (leftButton);
|
||||
app.Add (centerButton);
|
||||
app.Add (rightButton);
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ public class ContentScrolling : Scenario
|
||||
// Add demo views to show that things work correctly
|
||||
var textField = new TextField { X = 20, Y = 7, Width = 15, Text = "Test TextField" };
|
||||
|
||||
var colorPicker = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (11), Y = 10 };
|
||||
var colorPicker = new ColorPicker { Title = "BG", BoxHeight = 1, BoxWidth = 1, X = Pos.AnchorEnd (), Y = 10 };
|
||||
colorPicker.BorderStyle = LineStyle.RoundedDotted;
|
||||
|
||||
colorPicker.ColorChanged += (s, e) =>
|
||||
@@ -358,18 +358,9 @@ public class ContentScrolling : Scenario
|
||||
charMap.Accept += (s, e) =>
|
||||
MessageBox.Query (20, 7, "Hi", $"Am I a {view.GetType ().Name}?", "Yes", "No");
|
||||
|
||||
var buttonAnchoredRight = new Button
|
||||
var buttonAnchored = new Button
|
||||
{
|
||||
X = Pos.AnchorEnd (10), Y = 0, Text = "Button"
|
||||
};
|
||||
|
||||
var labelAnchoredBottomLeft = new Label
|
||||
{
|
||||
AutoSize = false,
|
||||
Y = Pos.AnchorEnd (3),
|
||||
Width = 25,
|
||||
Height = Dim.Fill (),
|
||||
Text = "Label\nY=AnchorEnd(3),Height=Dim.Fill()"
|
||||
X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Text = "Bottom Right"
|
||||
};
|
||||
|
||||
view.Margin.Data = "Margin";
|
||||
@@ -380,7 +371,7 @@ public class ContentScrolling : Scenario
|
||||
|
||||
view.Padding.Data = "Padding";
|
||||
|
||||
view.Add (buttonAnchoredRight, textField, colorPicker, charMap, textView, labelAnchoredBottomLeft);
|
||||
view.Add (buttonAnchored, textField, colorPicker, charMap, textView);
|
||||
|
||||
var longLabel = new Label
|
||||
{
|
||||
|
||||
@@ -604,7 +604,7 @@ public class DynamicMenuBar : Scenario
|
||||
|
||||
var _btnRemoveMenuBar = new Button { Y = 1, Text = "Remove a MenuBar" };
|
||||
|
||||
_btnRemoveMenuBar.X = Pos.AnchorEnd () - (Pos.Right (_btnRemoveMenuBar) - Pos.Left (_btnRemoveMenuBar));
|
||||
_btnRemoveMenuBar.X = Pos.AnchorEnd (0) - (Pos.Right (_btnRemoveMenuBar) - Pos.Left (_btnRemoveMenuBar));
|
||||
_frmMenu.Add (_btnRemoveMenuBar);
|
||||
|
||||
var _btnPrevious = new Button
|
||||
@@ -614,7 +614,7 @@ public class DynamicMenuBar : Scenario
|
||||
_frmMenu.Add (_btnPrevious);
|
||||
|
||||
var _btnAdd = new Button { Y = Pos.Top (_btnPrevious) + 2, Text = " Add " };
|
||||
_btnAdd.X = Pos.AnchorEnd () - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd));
|
||||
_btnAdd.X = Pos.AnchorEnd ();
|
||||
_frmMenu.Add (_btnAdd);
|
||||
|
||||
var _btnNext = new Button { X = Pos.X (_btnAdd), Y = Pos.Top (_btnPrevious), Text = ">" };
|
||||
|
||||
@@ -371,11 +371,11 @@ public class DynamicStatusBar : Scenario
|
||||
|
||||
var _btnRemoveStatusBar = new Button { Y = 1, Text = "Remove a StatusBar" };
|
||||
|
||||
_btnRemoveStatusBar.X = Pos.AnchorEnd () - (Pos.Right (_btnRemoveStatusBar) - Pos.Left (_btnRemoveStatusBar));
|
||||
_btnRemoveStatusBar.X = Pos.AnchorEnd ();
|
||||
_frmStatusBar.Add (_btnRemoveStatusBar);
|
||||
|
||||
var _btnAdd = new Button { Y = Pos.Top (_btnRemoveStatusBar) + 2, Text = " Add " };
|
||||
_btnAdd.X = Pos.AnchorEnd () - (Pos.Right (_btnAdd) - Pos.Left (_btnAdd));
|
||||
_btnAdd.X = Pos.AnchorEnd (0);
|
||||
_frmStatusBar.Add (_btnAdd);
|
||||
|
||||
_lstItems = new ListView
|
||||
|
||||
@@ -4,108 +4,102 @@ namespace UICatalog.Scenarios;
|
||||
|
||||
[ScenarioMetadata ("HotKeys", "Demonstrates how HotKeys work.")]
|
||||
[ScenarioCategory ("Controls")]
|
||||
[ScenarioCategory("Mouse and Keyboard")]
|
||||
[ScenarioCategory ("Mouse and Keyboard")]
|
||||
public class HotKeys : Scenario
|
||||
{
|
||||
public override void Init ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
ConfigurationManager.Themes.Theme = Theme;
|
||||
ConfigurationManager.Apply ();
|
||||
Top = new ();
|
||||
Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
|
||||
Top.BorderStyle = LineStyle.RoundedDotted;
|
||||
Top.Title = $"{Application.QuitKey} to _Quit - Scenario: {GetName ()}";
|
||||
}
|
||||
|
||||
public override void Run ()
|
||||
{
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
|
||||
};
|
||||
|
||||
var textViewLabel = new Label { Text = "_TextView:", X = 0, Y = 0 };
|
||||
Top.Add (textViewLabel);
|
||||
|
||||
var textField = new TextField (){ X = Pos.Right (textViewLabel) + 1, Y = 0, Width = 10 };
|
||||
Top.Add (textField);
|
||||
app.Add (textViewLabel);
|
||||
|
||||
var textField = new TextField { X = Pos.Right (textViewLabel) + 1, Y = 0, Width = 10 };
|
||||
app.Add (textField);
|
||||
|
||||
var viewLabel = new Label { Text = "_View:", X = 0, Y = Pos.Bottom (textField) + 1 };
|
||||
Top.Add (viewLabel);
|
||||
app.Add (viewLabel);
|
||||
|
||||
var view = new View () {
|
||||
Title = "View (_focusable)",
|
||||
Text = "Text renders _Underscore",
|
||||
var view = new View
|
||||
{
|
||||
Title = "View (_focusable)",
|
||||
Text = "Text renders _Underscore",
|
||||
CanFocus = true,
|
||||
X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (view);
|
||||
app.Add (view);
|
||||
|
||||
viewLabel = new Label { Text = "Vi_ew:", X = 0, Y = Pos.Bottom (view) + 1 };
|
||||
Top.Add (viewLabel);
|
||||
viewLabel = new() { Text = "Vi_ew:", X = 0, Y = Pos.Bottom (view) + 1 };
|
||||
app.Add (viewLabel);
|
||||
|
||||
view = new View ()
|
||||
view = new()
|
||||
{
|
||||
Title = "View (n_ot focusable)",
|
||||
Text = "Text renders _Underscore",
|
||||
X = Pos.Right (viewLabel) + 1, Y = Pos.Top (viewLabel), Width = 30, Height = 3,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (view);
|
||||
app.Add (view);
|
||||
|
||||
var labelWithFrameLabel = new Label { Text = "_Label with Frame:", X = 0, Y = Pos.Bottom (view) + 1 };
|
||||
Top.Add (labelWithFrameLabel);
|
||||
app.Add (labelWithFrameLabel);
|
||||
|
||||
var labelWithFrameFocusable = new Label ()
|
||||
var labelWithFrameFocusable = new Label
|
||||
{
|
||||
AutoSize = false,
|
||||
Title = "Label _with Frame (focusable)",
|
||||
CanFocus = true,
|
||||
X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (labelWithFrameFocusable);
|
||||
app.Add (labelWithFrameFocusable);
|
||||
|
||||
labelWithFrameLabel = new Label { Text = "L_abel with Frame:", X = 0, Y = Pos.Bottom (labelWithFrameFocusable) + 1 };
|
||||
Top.Add (labelWithFrameLabel);
|
||||
labelWithFrameLabel = new() { Text = "L_abel with Frame:", X = 0, Y = Pos.Bottom (labelWithFrameFocusable) + 1 };
|
||||
app.Add (labelWithFrameLabel);
|
||||
|
||||
var labelWithFrame = new Label ()
|
||||
var labelWithFrame = new Label
|
||||
{
|
||||
AutoSize = false,
|
||||
Title = "Label with Frame (_not focusable)",
|
||||
X = Pos.Right (labelWithFrameLabel) + 1, Y = Pos.Top (labelWithFrameLabel), Width = 40, Height = 3,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (labelWithFrame);
|
||||
app.Add (labelWithFrame);
|
||||
|
||||
|
||||
var buttonWithFrameLabel = new Label { Text = "_Button with Frame:", X = 0, Y = Pos.Bottom (labelWithFrame) + 1 };
|
||||
Top.Add (buttonWithFrameLabel);
|
||||
app.Add (buttonWithFrameLabel);
|
||||
|
||||
var buttonWithFrameFocusable = new Button ()
|
||||
var buttonWithFrameFocusable = new Button
|
||||
{
|
||||
AutoSize = false,
|
||||
Title = "B_utton with Frame (focusable)",
|
||||
CanFocus = true,
|
||||
X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (buttonWithFrameFocusable);
|
||||
app.Add (buttonWithFrameFocusable);
|
||||
|
||||
buttonWithFrameLabel = new Label { Text = "Butt_on with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrameFocusable) + 1 };
|
||||
Top.Add (buttonWithFrameLabel);
|
||||
buttonWithFrameLabel = new() { Text = "Butt_on with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrameFocusable) + 1 };
|
||||
app.Add (buttonWithFrameLabel);
|
||||
|
||||
var buttonWithFrame = new Button ()
|
||||
var buttonWithFrame = new Button
|
||||
{
|
||||
AutoSize = false,
|
||||
Title = "Button with Frame (not focusab_le)",
|
||||
X = Pos.Right (buttonWithFrameLabel) + 1, Y = Pos.Top (buttonWithFrameLabel), Width = 40, Height = 3,
|
||||
CanFocus = false,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (buttonWithFrame);
|
||||
|
||||
|
||||
app.Add (buttonWithFrame);
|
||||
|
||||
var checkboxWithFrameLabel = new Label { Text = "_Checkbox with Frame:", X = 0, Y = Pos.Bottom (buttonWithFrame) + 1 };
|
||||
Top.Add (checkboxWithFrameLabel);
|
||||
app.Add (checkboxWithFrameLabel);
|
||||
|
||||
var checkboxWithFrameFocusable = new CheckBox
|
||||
{
|
||||
@@ -113,12 +107,12 @@ public class HotKeys : Scenario
|
||||
Title = "C_heckbox with Frame (focusable)",
|
||||
CanFocus = true,
|
||||
X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (checkboxWithFrameFocusable);
|
||||
app.Add (checkboxWithFrameFocusable);
|
||||
|
||||
checkboxWithFrameLabel = new Label { Text = "Checkb_ox with Frame:", X = 0, Y = Pos.Bottom (checkboxWithFrameFocusable) + 1 };
|
||||
Top.Add (checkboxWithFrameLabel);
|
||||
checkboxWithFrameLabel = new() { Text = "Checkb_ox with Frame:", X = 0, Y = Pos.Bottom (checkboxWithFrameFocusable) + 1 };
|
||||
app.Add (checkboxWithFrameLabel);
|
||||
|
||||
var checkboxWithFrame = new CheckBox
|
||||
{
|
||||
@@ -126,14 +120,14 @@ public class HotKeys : Scenario
|
||||
Title = "Checkbox with Frame (not focusable)",
|
||||
X = Pos.Right (checkboxWithFrameLabel) + 1, Y = Pos.Top (checkboxWithFrameLabel), Width = 40, Height = 3,
|
||||
CanFocus = false,
|
||||
BorderStyle = LineStyle.Dashed,
|
||||
BorderStyle = LineStyle.Dashed
|
||||
};
|
||||
Top.Add (checkboxWithFrame);
|
||||
app.Add (checkboxWithFrame);
|
||||
|
||||
var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (), Text = "_Press me!" };
|
||||
app.Add (button);
|
||||
|
||||
var button = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), Text = "_Press me!" };
|
||||
Top.Add (button);
|
||||
|
||||
Application.Run (Top);
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,14 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Proof of Concept")]
|
||||
public class LineCanvasExperiment : Scenario
|
||||
{
|
||||
public override void Init ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
Top = new ();
|
||||
}
|
||||
|
||||
/// <summary>Setup the scenario.</summary>
|
||||
public override void Setup ()
|
||||
{
|
||||
//var menu = new MenuBar (new MenuBarItem [] {
|
||||
//new MenuBarItem ("_File", new MenuItem [] {
|
||||
// new MenuItem ("_Quit", "", () => Application.RequestStop()),
|
||||
//}) });
|
||||
|
||||
//Top.Add (menu);
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
|
||||
};
|
||||
|
||||
var frame1 = new FrameView
|
||||
{
|
||||
@@ -37,7 +30,7 @@ public class LineCanvasExperiment : Scenario
|
||||
|
||||
//View.Diagnostics ^= DiagnosticFlags.FrameRuler;
|
||||
|
||||
Top.Add (frame1);
|
||||
app.Add (frame1);
|
||||
|
||||
var win1 = new Window
|
||||
{
|
||||
@@ -52,7 +45,7 @@ public class LineCanvasExperiment : Scenario
|
||||
BorderStyle = LineStyle.Heavy,
|
||||
SuperViewRendersLineCanvas = true
|
||||
};
|
||||
win1.Padding.Thickness = new Thickness (1);
|
||||
win1.Padding.Thickness = new (1);
|
||||
|
||||
frame1.Add (win1);
|
||||
|
||||
@@ -140,9 +133,12 @@ public class LineCanvasExperiment : Scenario
|
||||
SuperViewRendersLineCanvas = true
|
||||
};
|
||||
marginWindow.Margin.ColorScheme = Colors.ColorSchemes ["Dialog"];
|
||||
marginWindow.Margin.Thickness = new Thickness (1);
|
||||
marginWindow.Border.Thickness = new Thickness (1, 2, 1, 1);
|
||||
marginWindow.Margin.Thickness = new (1);
|
||||
marginWindow.Border.Thickness = new (1, 2, 1, 1);
|
||||
|
||||
frame1.Add (marginWindow);
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,10 +122,10 @@ public class Scrolling : Scenario
|
||||
);
|
||||
|
||||
// Demonstrate AnchorEnd - Button is anchored to bottom/right
|
||||
var anchorButton = new Button { Y = Pos.AnchorEnd () - 1, Text = "Bottom Right" };
|
||||
var anchorButton = new Button { Y = Pos.AnchorEnd (0) - 1, Text = "Bottom Right" };
|
||||
|
||||
// TODO: Use Pos.Width instead of (Right-Left) when implemented (#502)
|
||||
anchorButton.X = Pos.AnchorEnd () - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
|
||||
anchorButton.X = Pos.AnchorEnd (0) - (Pos.Right (anchorButton) - Pos.Left (anchorButton));
|
||||
|
||||
anchorButton.Accept += (s, e) =>
|
||||
{
|
||||
|
||||
@@ -10,14 +10,21 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Text and Formatting")]
|
||||
public class TextAlignmentsAndDirections : Scenario
|
||||
{
|
||||
public override void Setup ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
|
||||
};
|
||||
|
||||
// string txt = ".\n...\n.....\nHELLO\n.....\n...\n.";
|
||||
// string txt = "┌──┴──┐\n┤HELLO├\n└──┬──┘";
|
||||
var txt = "HELLO WORLD";
|
||||
|
||||
var color1 = new ColorScheme { Normal = new Attribute (Color.Black, Color.Gray) };
|
||||
var color2 = new ColorScheme { Normal = new Attribute (Color.Black, Color.DarkGray) };
|
||||
var color1 = new ColorScheme { Normal = new (Color.Black, Color.Gray) };
|
||||
var color2 = new ColorScheme { Normal = new (Color.Black, Color.DarkGray) };
|
||||
|
||||
List<Label> txts = new (); // single line
|
||||
List<Label> mtxts = new (); // multi line
|
||||
@@ -125,14 +132,14 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
txts.Add (txtLabelHR);
|
||||
txts.Add (txtLabelHJ);
|
||||
|
||||
Win.Add (labelHL);
|
||||
Win.Add (txtLabelHL);
|
||||
Win.Add (labelHC);
|
||||
Win.Add (txtLabelHC);
|
||||
Win.Add (labelHR);
|
||||
Win.Add (txtLabelHR);
|
||||
Win.Add (labelHJ);
|
||||
Win.Add (txtLabelHJ);
|
||||
app.Add (labelHL);
|
||||
app.Add (txtLabelHL);
|
||||
app.Add (labelHC);
|
||||
app.Add (txtLabelHC);
|
||||
app.Add (labelHR);
|
||||
app.Add (txtLabelHR);
|
||||
app.Add (labelHJ);
|
||||
app.Add (txtLabelHJ);
|
||||
|
||||
// Vertical Single-Line
|
||||
|
||||
@@ -245,14 +252,14 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
txts.Add (txtLabelVB);
|
||||
txts.Add (txtLabelVJ);
|
||||
|
||||
Win.Add (labelVT);
|
||||
Win.Add (txtLabelVT);
|
||||
Win.Add (labelVM);
|
||||
Win.Add (txtLabelVM);
|
||||
Win.Add (labelVB);
|
||||
Win.Add (txtLabelVB);
|
||||
Win.Add (labelVJ);
|
||||
Win.Add (txtLabelVJ);
|
||||
app.Add (labelVT);
|
||||
app.Add (txtLabelVT);
|
||||
app.Add (labelVM);
|
||||
app.Add (txtLabelVM);
|
||||
app.Add (labelVB);
|
||||
app.Add (txtLabelVB);
|
||||
app.Add (labelVJ);
|
||||
app.Add (txtLabelVJ);
|
||||
|
||||
// Multi-Line
|
||||
|
||||
@@ -410,7 +417,7 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
container.Add (txtLabelBC);
|
||||
container.Add (txtLabelBR);
|
||||
|
||||
Win.Add (container);
|
||||
app.Add (container);
|
||||
|
||||
// Edit Text
|
||||
|
||||
@@ -437,7 +444,7 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
}
|
||||
};
|
||||
|
||||
Win.KeyUp += (s, m) =>
|
||||
app.KeyUp += (s, m) =>
|
||||
{
|
||||
foreach (Label v in txts)
|
||||
{
|
||||
@@ -452,7 +459,7 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
|
||||
editText.SetFocus ();
|
||||
|
||||
Win.Add (editText);
|
||||
app.Add (editText);
|
||||
|
||||
// JUSTIFY CHECKBOX
|
||||
|
||||
@@ -494,7 +501,7 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
}
|
||||
};
|
||||
|
||||
Win.Add (justifyCheckbox);
|
||||
app.Add (justifyCheckbox);
|
||||
|
||||
// Direction Options
|
||||
|
||||
@@ -518,6 +525,9 @@ public class TextAlignmentsAndDirections : Scenario
|
||||
}
|
||||
};
|
||||
|
||||
Win.Add (directionOptions);
|
||||
app.Add (directionOptions);
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,15 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Colors")]
|
||||
public class TrueColors : Scenario
|
||||
{
|
||||
public override void Setup ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
|
||||
};
|
||||
|
||||
var x = 2;
|
||||
var y = 1;
|
||||
|
||||
@@ -18,7 +25,7 @@ public class TrueColors : Scenario
|
||||
{
|
||||
X = x, Y = y++, Text = $"Current driver is {Application.Driver.GetType ().Name}"
|
||||
};
|
||||
Win.Add (lblDriverName);
|
||||
app.Add (lblDriverName);
|
||||
y++;
|
||||
|
||||
var cbSupportsTrueColor = new CheckBox
|
||||
@@ -29,7 +36,7 @@ public class TrueColors : Scenario
|
||||
CanFocus = false,
|
||||
Text = "Driver supports true color "
|
||||
};
|
||||
Win.Add (cbSupportsTrueColor);
|
||||
app.Add (cbSupportsTrueColor);
|
||||
|
||||
var cbUseTrueColor = new CheckBox
|
||||
{
|
||||
@@ -40,53 +47,53 @@ public class TrueColors : Scenario
|
||||
Text = "Force 16 colors"
|
||||
};
|
||||
cbUseTrueColor.Toggled += (_, evt) => { Application.Force16Colors = evt.NewValue ?? false; };
|
||||
Win.Add (cbUseTrueColor);
|
||||
app.Add (cbUseTrueColor);
|
||||
|
||||
y += 2;
|
||||
SetupGradient ("Red gradient", x, ref y, i => new Color (i, 0));
|
||||
SetupGradient ("Green gradient", x, ref y, i => new Color (0, i));
|
||||
SetupGradient ("Blue gradient", x, ref y, i => new Color (0, 0, i));
|
||||
SetupGradient ("Yellow gradient", x, ref y, i => new Color (i, i));
|
||||
SetupGradient ("Magenta gradient", x, ref y, i => new Color (i, 0, i));
|
||||
SetupGradient ("Cyan gradient", x, ref y, i => new Color (0, i, i));
|
||||
SetupGradient ("Gray gradient", x, ref y, i => new Color (i, i, i));
|
||||
SetupGradient ("Red gradient", x, ref y, i => new (i, 0));
|
||||
SetupGradient ("Green gradient", x, ref y, i => new (0, i));
|
||||
SetupGradient ("Blue gradient", x, ref y, i => new (0, 0, i));
|
||||
SetupGradient ("Yellow gradient", x, ref y, i => new (i, i));
|
||||
SetupGradient ("Magenta gradient", x, ref y, i => new (i, 0, i));
|
||||
SetupGradient ("Cyan gradient", x, ref y, i => new (0, i, i));
|
||||
SetupGradient ("Gray gradient", x, ref y, i => new (i, i, i));
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (44), Y = 2, Text = "Mouse over to get the gradient view color:" }
|
||||
);
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (44), Y = 4, Text = "Red:" }
|
||||
);
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (44), Y = 5, Text = "Green:" }
|
||||
);
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (44), Y = 6, Text = "Blue:" }
|
||||
);
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (44), Y = 8, Text = "Darker:" }
|
||||
);
|
||||
|
||||
Win.Add (
|
||||
app.Add (
|
||||
new Label { X = Pos.AnchorEnd (44), Y = 9, Text = "Lighter:" }
|
||||
);
|
||||
|
||||
var lblRed = new Label { X = Pos.AnchorEnd (32), Y = 4, Text = "na" };
|
||||
Win.Add (lblRed);
|
||||
app.Add (lblRed);
|
||||
var lblGreen = new Label { X = Pos.AnchorEnd (32), Y = 5, Text = "na" };
|
||||
Win.Add (lblGreen);
|
||||
app.Add (lblGreen);
|
||||
var lblBlue = new Label { X = Pos.AnchorEnd (32), Y = 6, Text = "na" };
|
||||
Win.Add (lblBlue);
|
||||
app.Add (lblBlue);
|
||||
|
||||
var lblDarker = new Label { X = Pos.AnchorEnd (32), Y = 8, Text = " " };
|
||||
Win.Add (lblDarker);
|
||||
app.Add (lblDarker);
|
||||
|
||||
var lblLighter = new Label { X = Pos.AnchorEnd (32), Y = 9, Text = " " };
|
||||
Win.Add (lblLighter);
|
||||
app.Add (lblLighter);
|
||||
|
||||
Application.MouseEvent += (s, e) =>
|
||||
{
|
||||
@@ -94,16 +101,17 @@ public class TrueColors : Scenario
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Flags == MouseFlags.Button1Clicked)
|
||||
{
|
||||
Attribute normal = e.View.GetNormalColor ();
|
||||
|
||||
lblLighter.ColorScheme = new ColorScheme(e.View.ColorScheme)
|
||||
|
||||
lblLighter.ColorScheme = new (e.View.ColorScheme)
|
||||
{
|
||||
Normal = new Attribute (
|
||||
normal.Foreground,
|
||||
normal.Background.GetHighlightColor ()
|
||||
)
|
||||
Normal = new (
|
||||
normal.Foreground,
|
||||
normal.Background.GetHighlightColor ()
|
||||
)
|
||||
};
|
||||
}
|
||||
else
|
||||
@@ -114,31 +122,35 @@ public class TrueColors : Scenario
|
||||
lblBlue.Text = normal.Foreground.B.ToString ();
|
||||
}
|
||||
};
|
||||
}
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
|
||||
private void SetupGradient (string name, int x, ref int y, Func<int, Color> colorFunc)
|
||||
{
|
||||
var gradient = new Label { X = x, Y = y++, Text = name };
|
||||
Win.Add (gradient);
|
||||
return;
|
||||
|
||||
for (int dx = x, i = 0; i <= 256; i += 4)
|
||||
void SetupGradient (string name, int x, ref int y, Func<int, Color> colorFunc)
|
||||
{
|
||||
var l = new Label
|
||||
{
|
||||
X = dx++,
|
||||
Y = y,
|
||||
ColorScheme = new ColorScheme
|
||||
{
|
||||
Normal = new Attribute (
|
||||
colorFunc (Math.Clamp (i, 0, 255)),
|
||||
colorFunc (Math.Clamp (i, 0, 255))
|
||||
)
|
||||
},
|
||||
Text = " "
|
||||
};
|
||||
Win.Add (l);
|
||||
}
|
||||
var gradient = new Label { X = x, Y = y++, Text = name };
|
||||
app.Add (gradient);
|
||||
|
||||
y += 2;
|
||||
for (int dx = x, i = 0; i <= 256; i += 4)
|
||||
{
|
||||
var l = new Label
|
||||
{
|
||||
X = dx++,
|
||||
Y = y,
|
||||
ColorScheme = new()
|
||||
{
|
||||
Normal = new (
|
||||
colorFunc (Math.Clamp (i, 0, 255)),
|
||||
colorFunc (Math.Clamp (i, 0, 255))
|
||||
)
|
||||
},
|
||||
Text = " "
|
||||
};
|
||||
app.Add (l);
|
||||
}
|
||||
|
||||
y += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,17 +9,15 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Proof of Concept")]
|
||||
public class ViewExperiments : Scenario
|
||||
{
|
||||
public override void Init ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
ConfigurationManager.Themes.Theme = Theme;
|
||||
ConfigurationManager.Apply ();
|
||||
Top = new ();
|
||||
Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
|
||||
}
|
||||
|
||||
public override void Setup ()
|
||||
{
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
|
||||
};
|
||||
|
||||
var containerLabel = new Label
|
||||
{
|
||||
X = 0,
|
||||
@@ -28,7 +26,7 @@ public class ViewExperiments : Scenario
|
||||
Width = Dim.Fill (),
|
||||
Height = 3
|
||||
};
|
||||
Top.Add (containerLabel);
|
||||
app.Add (containerLabel);
|
||||
|
||||
var view = new View
|
||||
{
|
||||
@@ -41,7 +39,7 @@ public class ViewExperiments : Scenario
|
||||
Id = "DaView"
|
||||
};
|
||||
|
||||
//Top.Add (view);
|
||||
//app.Add (view);
|
||||
|
||||
view.Margin.Thickness = new Thickness (2, 2, 2, 2);
|
||||
view.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
|
||||
@@ -199,8 +197,7 @@ public class ViewExperiments : Scenario
|
||||
};
|
||||
view.Add (edit);
|
||||
|
||||
edit = new TextField { Text = "AnchorEnd[Right];AnchorEnd (1)", Y = Pos.AnchorEnd (1), Width = 30, Height = 1 };
|
||||
edit.X = Pos.AnchorEnd () - (Pos.Right (edit) - Pos.Left (edit));
|
||||
edit = new TextField { Text = "AnchorEnd ();AnchorEnd ()", X = Pos.AnchorEnd(), Y = Pos.AnchorEnd (), Width = 30, Height = 1 };
|
||||
view.Add (edit);
|
||||
|
||||
edit = new TextField
|
||||
@@ -217,9 +214,9 @@ public class ViewExperiments : Scenario
|
||||
{
|
||||
containerLabel.Text =
|
||||
$"Container.Frame: {
|
||||
Top.Frame
|
||||
app.Frame
|
||||
} .Bounds: {
|
||||
Top.Viewport
|
||||
app.Viewport
|
||||
}\nView.Frame: {
|
||||
view.Frame
|
||||
} .Viewport: {
|
||||
@@ -244,11 +241,14 @@ public class ViewExperiments : Scenario
|
||||
ViewToEdit = view
|
||||
};
|
||||
|
||||
Top.Add (editor);
|
||||
app.Add (editor);
|
||||
view.X = 36;
|
||||
view.Y = 4;
|
||||
view.Width = Dim.Fill ();
|
||||
view.Height = Dim.Fill ();
|
||||
Top.Add (view);
|
||||
app.Add (view);
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,15 @@ namespace UICatalog.Scenarios;
|
||||
[ScenarioCategory ("Layout")]
|
||||
public class WindowsAndFrameViews : Scenario
|
||||
{
|
||||
public override void Setup ()
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
Window app = new ()
|
||||
{
|
||||
Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
|
||||
};
|
||||
|
||||
static int About ()
|
||||
{
|
||||
return MessageBox.Query (
|
||||
@@ -26,11 +33,7 @@ public class WindowsAndFrameViews : Scenario
|
||||
// list of Windows we create
|
||||
List<View> listWin = new ();
|
||||
|
||||
//Ignore the Win that UI Catalog created and create a new one
|
||||
Top.Remove (Win);
|
||||
Win?.Dispose ();
|
||||
|
||||
Win = new Window
|
||||
var win = new Window
|
||||
{
|
||||
Title = $"{listWin.Count} - Scenario: {GetName ()}",
|
||||
X = Pos.Center (),
|
||||
@@ -39,8 +42,8 @@ public class WindowsAndFrameViews : Scenario
|
||||
Height = 10,
|
||||
ColorScheme = Colors.ColorSchemes ["Dialog"]
|
||||
};
|
||||
Win.Padding.Thickness = new Thickness (padding);
|
||||
Win.Margin.Thickness = new Thickness (margin);
|
||||
win.Padding.Thickness = new (padding);
|
||||
win.Margin.Thickness = new (margin);
|
||||
|
||||
var paddingButton = new Button
|
||||
{
|
||||
@@ -50,21 +53,21 @@ public class WindowsAndFrameViews : Scenario
|
||||
Text = $"Padding of container is {padding}"
|
||||
};
|
||||
paddingButton.Accept += (s, e) => About ();
|
||||
Win.Add (paddingButton);
|
||||
win.Add (paddingButton);
|
||||
|
||||
Win.Add (
|
||||
win.Add (
|
||||
new Button
|
||||
{
|
||||
X = Pos.Center (),
|
||||
Y = Pos.AnchorEnd (1),
|
||||
Y = Pos.AnchorEnd (),
|
||||
ColorScheme = Colors.ColorSchemes ["Error"],
|
||||
Text = "Press ME! (Y = Pos.AnchorEnd(1))"
|
||||
}
|
||||
);
|
||||
Top.Add (Win);
|
||||
app.Add (win);
|
||||
|
||||
// add it to our list
|
||||
listWin.Add (Win);
|
||||
listWin.Add (win);
|
||||
|
||||
// create 3 more Windows in a loop, adding them Application.Top
|
||||
// Each with a
|
||||
@@ -75,9 +78,9 @@ public class WindowsAndFrameViews : Scenario
|
||||
//
|
||||
for (var pad = 0; pad < 3; pad++)
|
||||
{
|
||||
Window win = null;
|
||||
Window loopWin = null;
|
||||
|
||||
win = new Window
|
||||
loopWin = new()
|
||||
{
|
||||
Title = $"{listWin.Count} - Window Loop - padding = {pad}",
|
||||
X = margin,
|
||||
@@ -85,9 +88,9 @@ public class WindowsAndFrameViews : Scenario
|
||||
Width = Dim.Fill (margin),
|
||||
Height = contentHeight + pad * 2 + 2
|
||||
};
|
||||
win.Padding.Thickness = new Thickness (pad);
|
||||
loopWin.Padding.Thickness = new (pad);
|
||||
|
||||
win.ColorScheme = Colors.ColorSchemes ["Dialog"];
|
||||
loopWin.ColorScheme = Colors.ColorSchemes ["Dialog"];
|
||||
|
||||
var pressMeButton = new Button
|
||||
{
|
||||
@@ -95,8 +98,8 @@ public class WindowsAndFrameViews : Scenario
|
||||
};
|
||||
|
||||
pressMeButton.Accept += (s, e) =>
|
||||
MessageBox.ErrorQuery (win.Title, "Neat?", "Yes", "No");
|
||||
win.Add (pressMeButton);
|
||||
MessageBox.ErrorQuery (loopWin.Title, "Neat?", "Yes", "No");
|
||||
loopWin.Add (pressMeButton);
|
||||
|
||||
var subWin = new Window
|
||||
{
|
||||
@@ -110,9 +113,9 @@ public class WindowsAndFrameViews : Scenario
|
||||
};
|
||||
|
||||
subWin.Add (
|
||||
new TextField { Y = 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Edit me! " + win.Title }
|
||||
new TextField { Y = 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Edit me! " + loopWin.Title }
|
||||
);
|
||||
win.Add (subWin);
|
||||
loopWin.Add (subWin);
|
||||
|
||||
var frameView = new FrameView
|
||||
{
|
||||
@@ -128,27 +131,15 @@ public class WindowsAndFrameViews : Scenario
|
||||
frameView.Add (
|
||||
new TextField { Y = 1, Text = "Edit Me!" }
|
||||
);
|
||||
win.Add (frameView);
|
||||
loopWin.Add (frameView);
|
||||
|
||||
Top.Add (win);
|
||||
listWin.Add (win);
|
||||
app.Add (loopWin);
|
||||
listWin.Add (loopWin);
|
||||
}
|
||||
|
||||
// Add a FrameView (frame) to Application.Top
|
||||
// Position it at Bottom, using the list of Windows we created above.
|
||||
// Fill it with
|
||||
// a label
|
||||
// a SubWindow containing (subWinofFV)
|
||||
// a TextField
|
||||
// two checkboxes
|
||||
// a Sub FrameView containing (subFrameViewofFV)
|
||||
// a TextField
|
||||
// two CheckBoxes
|
||||
// a checkbox
|
||||
// a checkbox
|
||||
FrameView frame = null;
|
||||
|
||||
frame = new FrameView
|
||||
frame = new()
|
||||
{
|
||||
X = margin,
|
||||
Y = Pos.Bottom (listWin.Last ()) + margin / 2,
|
||||
@@ -199,22 +190,22 @@ public class WindowsAndFrameViews : Scenario
|
||||
|
||||
subFrameViewofFV.Add (new CheckBox { Y = 1, Text = "Check me" });
|
||||
|
||||
// BUGBUG: This checkbox is not shown even though frameViewFV has 3 rows in
|
||||
// its client area. #522
|
||||
subFrameViewofFV.Add (new CheckBox { Y = 2, Text = "Or, Check me" });
|
||||
|
||||
frame.Add (
|
||||
new CheckBox { X = 0, Y = Pos.AnchorEnd (1), Text = "Btn1 (Y = Pos.AnchorEnd (1))" }
|
||||
new CheckBox { X = 0, Y = Pos.AnchorEnd (), Text = "Btn1 (Y = Pos.AnchorEnd ())" }
|
||||
);
|
||||
var c = new CheckBox { Y = Pos.AnchorEnd (1), Text = "Btn2 (Y = Pos.AnchorEnd (1))" };
|
||||
c.X = Pos.AnchorEnd () - (Pos.Right (c) - Pos.Left (c));
|
||||
var c = new CheckBox { X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Text = "Btn2 (Y = Pos.AnchorEnd ())" };
|
||||
frame.Add (c);
|
||||
|
||||
frame.Add (subFrameViewofFV);
|
||||
|
||||
Top.Add (frame);
|
||||
app.Add (frame);
|
||||
listWin.Add (frame);
|
||||
|
||||
Top.ColorScheme = Colors.ColorSchemes ["Base"];
|
||||
app.ColorScheme = Colors.ColorSchemes ["Base"];
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
297
UnitTests/View/Layout/AnchorEndTests.cs
Normal file
297
UnitTests/View/Layout/AnchorEndTests.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
using Xunit.Abstractions;
|
||||
using static Terminal.Gui.Pos;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
public class AnchorEndTests (ITestOutputHelper output)
|
||||
{
|
||||
[Fact]
|
||||
public void PosAnchorEnd_Constructor ()
|
||||
{
|
||||
var posAnchorEnd = new PosAnchorEnd (10);
|
||||
Assert.NotNull (posAnchorEnd);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0, 0, true)]
|
||||
[InlineData (10, 10, true)]
|
||||
[InlineData (0, 10, false)]
|
||||
[InlineData (10, 1, false)]
|
||||
public void PosAnchorEnd_Equals (int offset1, int offset2, bool expectedEquals)
|
||||
{
|
||||
var posAnchorEnd1 = new PosAnchorEnd (offset1);
|
||||
var posAnchorEnd2 = new PosAnchorEnd (offset2);
|
||||
|
||||
Assert.Equal (expectedEquals, posAnchorEnd1.Equals (posAnchorEnd2));
|
||||
Assert.Equal (expectedEquals, posAnchorEnd2.Equals (posAnchorEnd1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PosAnchorEnd_GetHashCode ()
|
||||
{
|
||||
var posAnchorEnd = new PosAnchorEnd (10);
|
||||
var expectedHashCode = 10.GetHashCode ();
|
||||
|
||||
Assert.Equal (expectedHashCode, posAnchorEnd.GetHashCode ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PosAnchorEnd_ToString ()
|
||||
{
|
||||
var posAnchorEnd = new PosAnchorEnd (10);
|
||||
var expectedString = "AnchorEnd(10)";
|
||||
|
||||
Assert.Equal (expectedString, posAnchorEnd.ToString ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PosAnchorEnd_Anchor ()
|
||||
{
|
||||
var posAnchorEnd = new PosAnchorEnd (10);
|
||||
var width = 50;
|
||||
var expectedAnchor = width - 10;
|
||||
|
||||
Assert.Equal (expectedAnchor, posAnchorEnd.Anchor (width));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_CreatesCorrectInstance ()
|
||||
{
|
||||
var pos = Pos.AnchorEnd (10);
|
||||
Assert.IsType<PosAnchorEnd> (pos);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_Negative_Throws ()
|
||||
{
|
||||
Pos pos;
|
||||
int n = -1;
|
||||
Assert.Throws<ArgumentException> (() => pos = Pos.AnchorEnd (n));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0)]
|
||||
[InlineData (1)]
|
||||
public void AnchorEnd_SetsValue_Anchor_Is_Negative (int offset)
|
||||
{
|
||||
Pos pos = Pos.AnchorEnd (offset);
|
||||
Assert.Equal (offset, -pos.Anchor (0));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0, 0, 25)]
|
||||
[InlineData (0, 10, 25)]
|
||||
[InlineData (1, 10, 24)]
|
||||
[InlineData (10, 10, 15)]
|
||||
[InlineData (20, 10, 5)]
|
||||
[InlineData (25, 10, 0)]
|
||||
[InlineData (26, 10, -1)]
|
||||
public void AnchorEnd_With_Offset_PositionsViewOffsetFromRight (int offset, int width, int expectedXPosition)
|
||||
{
|
||||
// Arrange
|
||||
var superView = new View { Width = 25, Height = 25 };
|
||||
var view = new View
|
||||
{
|
||||
X = Pos.AnchorEnd (offset),
|
||||
Width = width,
|
||||
Height = 1
|
||||
};
|
||||
superView.Add (view);
|
||||
superView.BeginInit ();
|
||||
superView.EndInit ();
|
||||
|
||||
// Act
|
||||
superView.LayoutSubviews ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedXPosition, view.Frame.X);
|
||||
}
|
||||
|
||||
// UseDimForOffset tests
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_UseDimForOffset_CreatesCorrectInstance ()
|
||||
{
|
||||
var pos = Pos.AnchorEnd ();
|
||||
Assert.IsType<PosAnchorEnd> (pos);
|
||||
Assert.True (((PosAnchorEnd)pos).UseDimForOffset);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_UseDimForOffset_SetsValue_Anchor_Is_Negative ()
|
||||
{
|
||||
Pos pos = Pos.AnchorEnd ();
|
||||
Assert.Equal (-10, -pos.Anchor (10));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0, 25)]
|
||||
[InlineData (10, 15)]
|
||||
[InlineData (9, 16)]
|
||||
[InlineData (11, 14)]
|
||||
[InlineData (25, 0)]
|
||||
[InlineData (26, -1)]
|
||||
public void AnchorEnd_UseDimForOffset_PositionsViewOffsetByDim (int dim, int expectedXPosition)
|
||||
{
|
||||
// Arrange
|
||||
var superView = new View { Width = 25, Height = 25 };
|
||||
var view = new View
|
||||
{
|
||||
X = Pos.AnchorEnd (),
|
||||
Width = dim,
|
||||
Height = 1
|
||||
};
|
||||
superView.Add (view);
|
||||
superView.BeginInit ();
|
||||
superView.EndInit ();
|
||||
|
||||
// Act
|
||||
superView.LayoutSubviews ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedXPosition, view.Frame.X);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData (0, 25)]
|
||||
[InlineData (10, 23)]
|
||||
[InlineData (50, 13)]
|
||||
[InlineData (100, 0)]
|
||||
public void AnchorEnd_UseDimForOffset_DimPercent_PositionsViewOffsetByDim (int percent, int expectedXPosition)
|
||||
{
|
||||
// Arrange
|
||||
var superView = new View { Width = 25, Height = 25 };
|
||||
var view = new View
|
||||
{
|
||||
X = Pos.AnchorEnd (),
|
||||
Width = Dim.Percent ( percent),
|
||||
Height = 1
|
||||
};
|
||||
superView.Add (view);
|
||||
superView.BeginInit ();
|
||||
superView.EndInit ();
|
||||
|
||||
// Act
|
||||
superView.LayoutSubviews ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (expectedXPosition, view.Frame.X);
|
||||
}
|
||||
|
||||
// This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests.
|
||||
[Fact]
|
||||
[SetupFakeDriver]
|
||||
public void AnchorEnd_View_And_Button ()
|
||||
{
|
||||
((FakeDriver)Application.Driver).SetBufferSize (20, 5);
|
||||
|
||||
var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}";
|
||||
|
||||
var frame = new FrameView { Width = 18, Height = 3 };
|
||||
Assert.Equal (16, frame.Viewport.Width);
|
||||
|
||||
Button btn = null;
|
||||
|
||||
int Btn_Width () { return btn?.Viewport.Width ?? 0; }
|
||||
|
||||
btn = new () { Text = "Ok", X = Pos.AnchorEnd (0) - Pos.Function (Btn_Width) };
|
||||
|
||||
var view = new View
|
||||
{
|
||||
Text = "0123456789abcdefghij",
|
||||
|
||||
// Dim.Fill (1) fills remaining space minus 1 (16 - 1 = 15)
|
||||
// Dim.Function (Btn_Width) is 6
|
||||
// Width should be 15 - 6 = 9
|
||||
Width = Dim.Fill (1) - Dim.Function (Btn_Width),
|
||||
Height = 1
|
||||
};
|
||||
|
||||
frame.Add (btn, view);
|
||||
frame.BeginInit ();
|
||||
frame.EndInit ();
|
||||
frame.Draw ();
|
||||
|
||||
Assert.Equal (6, btn.Viewport.Width);
|
||||
Assert.Equal (10, btn.Frame.X); // frame.Viewport.Width (16) - btn.Frame.Width (6) = 10
|
||||
Assert.Equal (0, btn.Frame.Y);
|
||||
Assert.Equal (6, btn.Frame.Width);
|
||||
Assert.Equal (1, btn.Frame.Height);
|
||||
|
||||
Assert.Equal (9, view.Viewport.Width); // frame.Viewport.Width (16) - Dim.Fill (1) - Dim.Function (6) = 9
|
||||
Assert.Equal (0, view.Frame.X);
|
||||
Assert.Equal (0, view.Frame.Y);
|
||||
Assert.Equal (9, view.Frame.Width);
|
||||
Assert.Equal (1, view.Frame.Height);
|
||||
|
||||
var expected = $@"
|
||||
┌────────────────┐
|
||||
│012345678 {b}│
|
||||
└────────────────┘
|
||||
";
|
||||
_ = TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
|
||||
}
|
||||
|
||||
|
||||
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
|
||||
// TODO: A new test that calls SetRelativeLayout directly is needed.
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void AnchorEnd_Equal_Inside_Window ()
|
||||
{
|
||||
var viewWidth = 10;
|
||||
var viewHeight = 1;
|
||||
|
||||
var tv = new TextView
|
||||
{
|
||||
X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight
|
||||
};
|
||||
|
||||
var win = new Window ();
|
||||
|
||||
win.Add (tv);
|
||||
|
||||
Toplevel top = new ();
|
||||
top.Add (win);
|
||||
RunState rs = Application.Begin (top);
|
||||
|
||||
Assert.Equal (new (0, 0, 80, 25), top.Frame);
|
||||
Assert.Equal (new (0, 0, 80, 25), win.Frame);
|
||||
Assert.Equal (new (68, 22, 10, 1), tv.Frame);
|
||||
Application.End (rs);
|
||||
}
|
||||
|
||||
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
|
||||
// TODO: A new test that calls SetRelativeLayout directly is needed.
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel ()
|
||||
{
|
||||
var viewWidth = 10;
|
||||
var viewHeight = 1;
|
||||
|
||||
var tv = new TextView
|
||||
{
|
||||
X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight
|
||||
};
|
||||
|
||||
var win = new Window ();
|
||||
|
||||
win.Add (tv);
|
||||
|
||||
var menu = new MenuBar ();
|
||||
var status = new StatusBar ();
|
||||
Toplevel top = new ();
|
||||
top.Add (win, menu, status);
|
||||
RunState rs = Application.Begin (top);
|
||||
|
||||
Assert.Equal (new (0, 0, 80, 25), top.Frame);
|
||||
Assert.Equal (new (0, 0, 80, 1), menu.Frame);
|
||||
Assert.Equal (new (0, 24, 80, 1), status.Frame);
|
||||
Assert.Equal (new (0, 1, 80, 23), win.Frame);
|
||||
Assert.Equal (new (68, 20, 10, 1), tv.Frame);
|
||||
|
||||
Application.End (rs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Xunit.Abstractions;
|
||||
using static Terminal.Gui.Dim;
|
||||
|
||||
|
||||
// Alias Console to MockConsole so we don't accidentally use Console
|
||||
using Console = Terminal.Gui.FakeConsole;
|
||||
@@ -22,6 +24,57 @@ public class DimTests
|
||||
Thread.CurrentThread.CurrentUICulture = culture;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DimAbsolute_GetDimension_ReturnsCorrectValue ()
|
||||
{
|
||||
var dim = new DimAbsolute (10);
|
||||
var result = dim.Calculate (0, 100, 50, false);
|
||||
Assert.Equal (10, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DimCombine_GetDimension_ReturnsCorrectValue ()
|
||||
{
|
||||
var dim1 = new DimAbsolute (10);
|
||||
var dim2 = new DimAbsolute (20);
|
||||
var dim = dim1 + dim2;
|
||||
var result = dim.Calculate (0, 100, 50, false);
|
||||
Assert.Equal (30, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DimFactor_GetDimension_ReturnsCorrectValue ()
|
||||
{
|
||||
var dim = new DimFactor (0.5f);
|
||||
var result = dim.Calculate (0, 100, 50, false);
|
||||
Assert.Equal (50, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DimFill_GetDimension_ReturnsCorrectValue ()
|
||||
{
|
||||
var dim = Dim.Fill ();
|
||||
var result = dim.Calculate (0, 100, 50, false);
|
||||
Assert.Equal (100, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DimFunc_GetDimension_ReturnsCorrectValue ()
|
||||
{
|
||||
var dim = new DimFunc (() => 10);
|
||||
var result = dim.Calculate (0, 100, 50, false);
|
||||
Assert.Equal (10, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DimView_GetDimension_ReturnsCorrectValue ()
|
||||
{
|
||||
var view = new View { Width = 10 };
|
||||
var dim = new DimView (view, Dimension.Width);
|
||||
var result = dim.Calculate (0, 100, 50, false);
|
||||
Assert.Equal (10, result);
|
||||
}
|
||||
|
||||
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
|
||||
// A new test that does not depend on Application is needed.
|
||||
[Fact]
|
||||
@@ -508,9 +561,9 @@ public class DimTests
|
||||
Assert.Equal (20, dimCombine.Anchor (100));
|
||||
|
||||
var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
|
||||
var dimViewHeight = new Dim.DimView (view, 0);
|
||||
var dimViewHeight = new Dim.DimView (view, Dimension.Height);
|
||||
Assert.Equal (1, dimViewHeight.Anchor (0));
|
||||
var dimViewWidth = new Dim.DimView (view, 1);
|
||||
var dimViewWidth = new Dim.DimView (view, Dimension.Width);
|
||||
Assert.Equal (20, dimViewWidth.Anchor (0));
|
||||
|
||||
view.Dispose ();
|
||||
|
||||
@@ -1,165 +1,65 @@
|
||||
using Xunit.Abstractions;
|
||||
|
||||
// Alias Console to MockConsole so we don't accidentally use Console
|
||||
using static Terminal.Gui.Dim;
|
||||
using static Terminal.Gui.Pos;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
public class PosTests
|
||||
public class PosTests (ITestOutputHelper output)
|
||||
{
|
||||
private readonly ITestOutputHelper _output;
|
||||
public PosTests (ITestOutputHelper output) { _output = output; }
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_Equal ()
|
||||
public void PosAbsolute_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
var n1 = 0;
|
||||
var n2 = 0;
|
||||
|
||||
Pos pos1 = Pos.AnchorEnd (n1);
|
||||
Pos pos2 = Pos.AnchorEnd (n2);
|
||||
Assert.Equal (pos1, pos2);
|
||||
|
||||
// Test inequality
|
||||
n2 = 5;
|
||||
pos2 = Pos.AnchorEnd (n2);
|
||||
Assert.NotEqual (pos1, pos2);
|
||||
}
|
||||
|
||||
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
|
||||
// TODO: A new test that calls SetRelativeLayout directly is needed.
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void AnchorEnd_Equal_Inside_Window ()
|
||||
{
|
||||
var viewWidth = 10;
|
||||
var viewHeight = 1;
|
||||
|
||||
var tv = new TextView
|
||||
{
|
||||
X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight
|
||||
};
|
||||
|
||||
var win = new Window ();
|
||||
|
||||
win.Add (tv);
|
||||
|
||||
Toplevel top = new ();
|
||||
top.Add (win);
|
||||
RunState rs = Application.Begin (top);
|
||||
|
||||
Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame);
|
||||
Assert.Equal (new Rectangle (0, 0, 80, 25), win.Frame);
|
||||
Assert.Equal (new Rectangle (68, 22, 10, 1), tv.Frame);
|
||||
Application.End (rs);
|
||||
}
|
||||
|
||||
// TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
|
||||
// TODO: A new test that calls SetRelativeLayout directly is needed.
|
||||
[Fact]
|
||||
[AutoInitShutdown]
|
||||
public void AnchorEnd_Equal_Inside_Window_With_MenuBar_And_StatusBar_On_Toplevel ()
|
||||
{
|
||||
var viewWidth = 10;
|
||||
var viewHeight = 1;
|
||||
|
||||
var tv = new TextView
|
||||
{
|
||||
X = Pos.AnchorEnd (viewWidth), Y = Pos.AnchorEnd (viewHeight), Width = viewWidth, Height = viewHeight
|
||||
};
|
||||
|
||||
var win = new Window ();
|
||||
|
||||
win.Add (tv);
|
||||
|
||||
var menu = new MenuBar ();
|
||||
var status = new StatusBar ();
|
||||
Toplevel top = new ();
|
||||
top.Add (win, menu, status);
|
||||
RunState rs = Application.Begin (top);
|
||||
|
||||
Assert.Equal (new Rectangle (0, 0, 80, 25), top.Frame);
|
||||
Assert.Equal (new Rectangle (0, 0, 80, 1), menu.Frame);
|
||||
Assert.Equal (new Rectangle (0, 24, 80, 1), status.Frame);
|
||||
Assert.Equal (new Rectangle (0, 1, 80, 23), win.Frame);
|
||||
Assert.Equal (new Rectangle (68, 20, 10, 1), tv.Frame);
|
||||
|
||||
Application.End (rs);
|
||||
var posAbsolute = new PosAbsolute (5);
|
||||
var result = posAbsolute.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (5, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_Negative_Throws ()
|
||||
public void PosAnchorEnd_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
Pos pos;
|
||||
int n = -1;
|
||||
Assert.Throws<ArgumentException> (() => pos = Pos.AnchorEnd (n));
|
||||
var posAnchorEnd = new PosAnchorEnd (5);
|
||||
var result = posAnchorEnd.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (5, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnchorEnd_SetsValue ()
|
||||
public void PosCenter_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
var n = 0;
|
||||
Pos pos = Pos.AnchorEnd ();
|
||||
Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
|
||||
|
||||
n = 5;
|
||||
pos = Pos.AnchorEnd (n);
|
||||
Assert.Equal ($"AnchorEnd({n})", pos.ToString ());
|
||||
var posCenter = new PosCenter ();
|
||||
var result = posCenter.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (4, result);
|
||||
}
|
||||
|
||||
// This test used to be Dialog_In_Window_With_TextField_And_Button_AnchorEnd in DialogTests.
|
||||
[Fact]
|
||||
[SetupFakeDriver]
|
||||
public void AnchorEnd_View_And_Button ()
|
||||
public void PosCombine_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
((FakeDriver)Application.Driver).SetBufferSize (20, 5);
|
||||
var posCombine = new PosCombine (true, new PosAbsolute (5), new PosAbsolute (3));
|
||||
var result = posCombine.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (8, result);
|
||||
}
|
||||
|
||||
var b = $"{CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}";
|
||||
[Fact]
|
||||
public void PosFactor_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
var posFactor = new PosFactor (0.5f);
|
||||
var result = posFactor.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (5, result);
|
||||
}
|
||||
|
||||
var frame = new FrameView { Width = 18, Height = 3 };
|
||||
Assert.Equal (16, frame.Viewport.Width);
|
||||
[Fact]
|
||||
public void PosFunc_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
var posFunc = new PosFunc (() => 5);
|
||||
var result = posFunc.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (5, result);
|
||||
}
|
||||
|
||||
Button btn = null;
|
||||
|
||||
int Btn_Width () { return btn?.Viewport.Width ?? 0; }
|
||||
|
||||
btn = new Button { Text = "Ok", X = Pos.AnchorEnd () - Pos.Function (Btn_Width) };
|
||||
|
||||
var view = new View
|
||||
{
|
||||
Text = "0123456789abcdefghij",
|
||||
|
||||
// Dim.Fill (1) fills remaining space minus 1 (16 - 1 = 15)
|
||||
// Dim.Function (Btn_Width) is 6
|
||||
// Width should be 15 - 6 = 9
|
||||
Width = Dim.Fill (1) - Dim.Function (Btn_Width),
|
||||
Height = 1
|
||||
};
|
||||
|
||||
frame.Add (btn, view);
|
||||
frame.BeginInit ();
|
||||
frame.EndInit ();
|
||||
frame.Draw ();
|
||||
|
||||
Assert.Equal (6, btn.Viewport.Width);
|
||||
Assert.Equal (10, btn.Frame.X); // frame.Viewport.Width (16) - btn.Frame.Width (6) = 10
|
||||
Assert.Equal (0, btn.Frame.Y);
|
||||
Assert.Equal (6, btn.Frame.Width);
|
||||
Assert.Equal (1, btn.Frame.Height);
|
||||
|
||||
Assert.Equal (9, view.Viewport.Width); // frame.Viewport.Width (16) - Dim.Fill (1) - Dim.Function (6) = 9
|
||||
Assert.Equal (0, view.Frame.X);
|
||||
Assert.Equal (0, view.Frame.Y);
|
||||
Assert.Equal (9, view.Frame.Width);
|
||||
Assert.Equal (1, view.Frame.Height);
|
||||
|
||||
var expected = $@"
|
||||
┌────────────────┐
|
||||
│012345678 {
|
||||
b
|
||||
}│
|
||||
└────────────────┘
|
||||
";
|
||||
_ = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
|
||||
[Fact]
|
||||
public void PosView_GetLocation_ReturnsExpectedValue ()
|
||||
{
|
||||
var posView = new PosView (new View { Frame = new Rectangle (5, 5, 10, 10) }, 0);
|
||||
var result = posView.Calculate (10, new DimAbsolute (2), 1, false);
|
||||
Assert.Equal (5, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -201,28 +101,28 @@ public class PosTests
|
||||
Pos pos = Pos.Left (v);
|
||||
|
||||
Assert.Equal (
|
||||
$"View(side=x,target=View(V){v.Frame})",
|
||||
$"View(side=left,target=View(V){v.Frame})",
|
||||
pos.ToString ()
|
||||
);
|
||||
|
||||
pos = Pos.X (v);
|
||||
|
||||
Assert.Equal (
|
||||
$"View(side=x,target=View(V){v.Frame})",
|
||||
$"View(side=left,target=View(V){v.Frame})",
|
||||
pos.ToString ()
|
||||
);
|
||||
|
||||
pos = Pos.Top (v);
|
||||
|
||||
Assert.Equal (
|
||||
$"View(side=y,target=View(V){v.Frame})",
|
||||
$"View(side=top,target=View(V){v.Frame})",
|
||||
pos.ToString ()
|
||||
);
|
||||
|
||||
pos = Pos.Y (v);
|
||||
|
||||
Assert.Equal (
|
||||
$"View(side=y,target=View(V){v.Frame})",
|
||||
$"View(side=top,target=View(V){v.Frame})",
|
||||
pos.ToString ()
|
||||
);
|
||||
|
||||
@@ -291,19 +191,19 @@ public class PosTests
|
||||
Assert.Equal (posCombine._right, posAbsolute);
|
||||
Assert.Equal (20, posCombine.Anchor (100));
|
||||
|
||||
posCombine = new Pos.PosCombine (true, posAbsolute, posFactor);
|
||||
posCombine = new (true, posAbsolute, posFactor);
|
||||
Assert.Equal (posCombine._left, posAbsolute);
|
||||
Assert.Equal (posCombine._right, posFactor);
|
||||
Assert.Equal (20, posCombine.Anchor (100));
|
||||
|
||||
var view = new View { Frame = new Rectangle (20, 10, 20, 1) };
|
||||
var posViewX = new Pos.PosView (view, 0);
|
||||
var view = new View { Frame = new (20, 10, 20, 1) };
|
||||
var posViewX = new Pos.PosView (view, Pos.Side.Left);
|
||||
Assert.Equal (20, posViewX.Anchor (0));
|
||||
var posViewY = new Pos.PosView (view, 1);
|
||||
var posViewY = new Pos.PosView (view, Pos.Side.Top);
|
||||
Assert.Equal (10, posViewY.Anchor (0));
|
||||
var posRight = new Pos.PosView (view, 2);
|
||||
var posRight = new Pos.PosView (view, Pos.Side.Right);
|
||||
Assert.Equal (40, posRight.Anchor (0));
|
||||
var posViewBottom = new Pos.PosView (view, 3);
|
||||
var posViewBottom = new Pos.PosView (view, Pos.Side.Bottom);
|
||||
Assert.Equal (11, posViewBottom.Anchor (0));
|
||||
|
||||
view.Dispose ();
|
||||
@@ -339,6 +239,7 @@ public class PosTests
|
||||
Application.End (rs);
|
||||
|
||||
Application.Top.Dispose ();
|
||||
|
||||
// Shutdown must be called to safely clean up Application if Init has been called
|
||||
Application.Shutdown ();
|
||||
}
|
||||
@@ -513,6 +414,7 @@ public class PosTests
|
||||
Assert.Equal (20, count);
|
||||
|
||||
top.Dispose ();
|
||||
|
||||
// Shutdown must be called to safely clean up Application if Init has been called
|
||||
Application.Shutdown ();
|
||||
}
|
||||
@@ -582,6 +484,7 @@ public class PosTests
|
||||
Assert.Equal (0, count);
|
||||
|
||||
top.Dispose ();
|
||||
|
||||
// Shutdown must be called to safely clean up Application if Init has been called
|
||||
Application.Shutdown ();
|
||||
}
|
||||
@@ -619,7 +522,7 @@ public class PosTests
|
||||
var super = new View { Width = 10, Height = 10, Text = "super" };
|
||||
var view1 = new View { Width = 2, Height = 2, Text = "view1" };
|
||||
var view2 = new View { Width = 2, Height = 2, Text = "view2" };
|
||||
view2.X = Pos.AnchorEnd () - (Pos.Right (view2) - Pos.Left (view2));
|
||||
view2.X = Pos.AnchorEnd (0) - (Pos.Right (view2) - Pos.Left (view2));
|
||||
|
||||
super.Add (view1, view2);
|
||||
super.BeginInit ();
|
||||
@@ -627,9 +530,9 @@ public class PosTests
|
||||
|
||||
Exception exception = Record.Exception (super.LayoutSubviews);
|
||||
Assert.Null (exception);
|
||||
Assert.Equal (new Rectangle (0, 0, 10, 10), super.Frame);
|
||||
Assert.Equal (new Rectangle (0, 0, 2, 2), view1.Frame);
|
||||
Assert.Equal (new Rectangle (8, 0, 2, 2), view2.Frame);
|
||||
Assert.Equal (new (0, 0, 10, 10), super.Frame);
|
||||
Assert.Equal (new (0, 0, 2, 2), view1.Frame);
|
||||
Assert.Equal (new (8, 0, 2, 2), view2.Frame);
|
||||
|
||||
super.Dispose ();
|
||||
}
|
||||
@@ -714,21 +617,21 @@ public class PosTests
|
||||
Pos pos;
|
||||
|
||||
// Pos.Left
|
||||
side = "x";
|
||||
side = "left";
|
||||
testInt = 0;
|
||||
testRect = Rectangle.Empty;
|
||||
pos = Pos.Left (new View ());
|
||||
pos = Pos.Left (new ());
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
pos = Pos.Left (new View { Frame = testRect });
|
||||
pos = Pos.Left (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
testRect = new Rectangle (1, 2, 3, 4);
|
||||
pos = Pos.Left (new View { Frame = testRect });
|
||||
testRect = new (1, 2, 3, 4);
|
||||
pos = Pos.Left (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
// Pos.Left(win) + 0
|
||||
pos = Pos.Left (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Left (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -738,7 +641,7 @@ public class PosTests
|
||||
testInt = 1;
|
||||
|
||||
// Pos.Left(win) +1
|
||||
pos = Pos.Left (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Left (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -748,7 +651,7 @@ public class PosTests
|
||||
testInt = -1;
|
||||
|
||||
// Pos.Left(win) -1
|
||||
pos = Pos.Left (new View { Frame = testRect }) - testInt;
|
||||
pos = Pos.Left (new() { Frame = testRect }) - testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -756,21 +659,21 @@ public class PosTests
|
||||
);
|
||||
|
||||
// Pos.X
|
||||
side = "x";
|
||||
side = "left";
|
||||
testInt = 0;
|
||||
testRect = Rectangle.Empty;
|
||||
pos = Pos.X (new View ());
|
||||
pos = Pos.X (new ());
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
pos = Pos.X (new View { Frame = testRect });
|
||||
pos = Pos.X (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
testRect = new Rectangle (1, 2, 3, 4);
|
||||
pos = Pos.X (new View { Frame = testRect });
|
||||
testRect = new (1, 2, 3, 4);
|
||||
pos = Pos.X (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
// Pos.X(win) + 0
|
||||
pos = Pos.X (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.X (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -780,7 +683,7 @@ public class PosTests
|
||||
testInt = 1;
|
||||
|
||||
// Pos.X(win) +1
|
||||
pos = Pos.X (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.X (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -790,7 +693,7 @@ public class PosTests
|
||||
testInt = -1;
|
||||
|
||||
// Pos.X(win) -1
|
||||
pos = Pos.X (new View { Frame = testRect }) - testInt;
|
||||
pos = Pos.X (new() { Frame = testRect }) - testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -798,21 +701,21 @@ public class PosTests
|
||||
);
|
||||
|
||||
// Pos.Top
|
||||
side = "y";
|
||||
side = "top";
|
||||
testInt = 0;
|
||||
testRect = Rectangle.Empty;
|
||||
pos = Pos.Top (new View ());
|
||||
pos = Pos.Top (new ());
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
pos = Pos.Top (new View { Frame = testRect });
|
||||
pos = Pos.Top (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
testRect = new Rectangle (1, 2, 3, 4);
|
||||
pos = Pos.Top (new View { Frame = testRect });
|
||||
testRect = new (1, 2, 3, 4);
|
||||
pos = Pos.Top (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
// Pos.Top(win) + 0
|
||||
pos = Pos.Top (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Top (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -822,7 +725,7 @@ public class PosTests
|
||||
testInt = 1;
|
||||
|
||||
// Pos.Top(win) +1
|
||||
pos = Pos.Top (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Top (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -832,7 +735,7 @@ public class PosTests
|
||||
testInt = -1;
|
||||
|
||||
// Pos.Top(win) -1
|
||||
pos = Pos.Top (new View { Frame = testRect }) - testInt;
|
||||
pos = Pos.Top (new() { Frame = testRect }) - testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -840,21 +743,21 @@ public class PosTests
|
||||
);
|
||||
|
||||
// Pos.Y
|
||||
side = "y";
|
||||
side = "top";
|
||||
testInt = 0;
|
||||
testRect = Rectangle.Empty;
|
||||
pos = Pos.Y (new View ());
|
||||
pos = Pos.Y (new ());
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
pos = Pos.Y (new View { Frame = testRect });
|
||||
pos = Pos.Y (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
testRect = new Rectangle (1, 2, 3, 4);
|
||||
pos = Pos.Y (new View { Frame = testRect });
|
||||
testRect = new (1, 2, 3, 4);
|
||||
pos = Pos.Y (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
// Pos.Y(win) + 0
|
||||
pos = Pos.Y (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Y (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -864,7 +767,7 @@ public class PosTests
|
||||
testInt = 1;
|
||||
|
||||
// Pos.Y(win) +1
|
||||
pos = Pos.Y (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Y (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -874,7 +777,7 @@ public class PosTests
|
||||
testInt = -1;
|
||||
|
||||
// Pos.Y(win) -1
|
||||
pos = Pos.Y (new View { Frame = testRect }) - testInt;
|
||||
pos = Pos.Y (new() { Frame = testRect }) - testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -885,18 +788,18 @@ public class PosTests
|
||||
side = "bottom";
|
||||
testRect = Rectangle.Empty;
|
||||
testInt = 0;
|
||||
pos = Pos.Bottom (new View ());
|
||||
pos = Pos.Bottom (new ());
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
pos = Pos.Bottom (new View { Frame = testRect });
|
||||
pos = Pos.Bottom (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
testRect = new Rectangle (1, 2, 3, 4);
|
||||
pos = Pos.Bottom (new View { Frame = testRect });
|
||||
testRect = new (1, 2, 3, 4);
|
||||
pos = Pos.Bottom (new() { Frame = testRect });
|
||||
Assert.Equal ($"View(side={side},target=View(){testRect})", pos.ToString ());
|
||||
|
||||
// Pos.Bottom(win) + 0
|
||||
pos = Pos.Bottom (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Bottom (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -906,7 +809,7 @@ public class PosTests
|
||||
testInt = 1;
|
||||
|
||||
// Pos.Bottom(win) +1
|
||||
pos = Pos.Bottom (new View { Frame = testRect }) + testInt;
|
||||
pos = Pos.Bottom (new() { Frame = testRect }) + testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
@@ -916,7 +819,7 @@ public class PosTests
|
||||
testInt = -1;
|
||||
|
||||
// Pos.Bottom(win) -1
|
||||
pos = Pos.Bottom (new View { Frame = testRect }) - testInt;
|
||||
pos = Pos.Bottom (new() { Frame = testRect }) - testInt;
|
||||
|
||||
Assert.Equal (
|
||||
$"Combine(View(side={side},target=View(){testRect}){(testInt < 0 ? '-' : '+')}Absolute({testInt}))",
|
||||
|
||||
@@ -405,7 +405,7 @@ public class SetRelativeLayoutTests
|
||||
{
|
||||
var screen = new Size (30, 1);
|
||||
var view = new View { Text = "abc", AutoSize = true }; // BUGBUG: AutoSize or Width must be set
|
||||
view.X = Pos.AnchorEnd () - Pos.Function (GetViewWidth);
|
||||
view.X = Pos.AnchorEnd (0) - Pos.Function (GetViewWidth);
|
||||
|
||||
int GetViewWidth () { return view.Frame.Width; }
|
||||
|
||||
|
||||
@@ -164,8 +164,8 @@ public class ButtonTests (ITestOutputHelper output)
|
||||
var btn = new Button { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true };
|
||||
var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}";
|
||||
|
||||
btn.X = Pos.AnchorEnd () - Pos.Function (() => btn.TextFormatter.Text.GetColumns ());
|
||||
btn.X = Pos.AnchorEnd () - Pos.Function (() => btn.TextFormatter.Text.GetColumns ());
|
||||
btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ());
|
||||
btn.X = Pos.AnchorEnd (0) - Pos.Function (() => btn.TextFormatter.Text.GetColumns ());
|
||||
|
||||
var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
|
||||
win.Add (btn);
|
||||
|
||||
@@ -77,7 +77,7 @@ public class CheckBoxTests
|
||||
{
|
||||
var checkBox = new CheckBox { Y = Pos.Center (), Text = "C_heck this out 你" };
|
||||
|
||||
checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width);
|
||||
checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width);
|
||||
|
||||
var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" };
|
||||
win.Add (checkBox);
|
||||
@@ -121,7 +121,7 @@ public class CheckBoxTests
|
||||
{
|
||||
var checkBox = new CheckBox { Y = Pos.Center (), Text = "Check this out 你" };
|
||||
|
||||
checkBox.X = Pos.AnchorEnd () - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width);
|
||||
checkBox.X = Pos.AnchorEnd (0) - Pos.Function (() => checkBox.GetSizeNeededForTextWithoutHotKey ().Width);
|
||||
|
||||
var win = new Window { Width = Dim.Fill (), Height = Dim.Fill (), Title = "Test Demo 你" };
|
||||
win.Add (checkBox);
|
||||
|
||||
@@ -92,7 +92,7 @@ public class LabelTests
|
||||
public void AutoSize_Stays_True_AnchorEnd ()
|
||||
{
|
||||
var label = new Label { Y = Pos.Center (), Text = "Say Hello 你", AutoSize = true };
|
||||
label.X = Pos.AnchorEnd () - Pos.Function (() => label.TextFormatter.Text.GetColumns ());
|
||||
label.X = Pos.AnchorEnd (0) - Pos.Function (() => label.TextFormatter.Text.GetColumns ());
|
||||
|
||||
var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () };
|
||||
win.Add (label);
|
||||
|
||||
@@ -55,7 +55,7 @@ The [Pos](~/api/Terminal.Gui.Pos.yml) is the type of `View.X` and `View.Y` and s
|
||||
|
||||
* Absolute position, by passing an integer - `Pos.Absolute(n)`.
|
||||
* Percentage of the parent's view size - `Pos.Percent(percent)`.
|
||||
* Anchored from the end of the dimension - `Pos.AnchorEnd(margin)`.
|
||||
* Anchored from the end of the dimension - `Pos.AnchorEnd()`.
|
||||
* Centered, using `Pos.Center()`.
|
||||
* The `Pos.Left(otherView)`, `Pos.Top(otherView)`, `Pos.Bottom(otherView)`, `Pos.Right(otherView)` positions of another view.
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ The entire library has been reviewed and simplified. As a result, the API is mor
|
||||
* *Adornments* -
|
||||
* *Built-in Scrolling/Virtual Content Area* - In v1, to have a view a user could scroll required either a bespoke scrolling implementation, inheriting from `ScrollView`, or managing the complexity of `ScrollBarView` directly. In v2, the base-View class supports scrolling inherently. The area of a view visible to the user at a given moment was previously a rectangle called `Bounds`. `Bounds.Location` was always `Point.Empty`. In v2 the visible area is a rectangle called `Viewport` which is a protal into the Views content, which can be bigger (or smaller) than the area visible to the user. Causing a view to scroll is as simple as changing `View.Viewport.Location`. The View's content described by `View.ContentSize`. See [Layout](layout.md) for details.
|
||||
* *Computed Layout Improvements* -
|
||||
* *`Pos.AnchorEnd ()`* - New to v2 is `Pos.AnchorEnd ()` (with no parameters) which allows a view to be anchored to the right or bottom of the Superview.
|
||||
* *`Dim.Auto`* -
|
||||
* ...
|
||||
|
||||
|
||||
Reference in New Issue
Block a user