Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,9 @@ public string Name

- PRs must not introduce new compiler warnings (fix warnings in files you modify)
- Title format: `Fixes #issue. Terse description`
- Update `Examples/UICatalog` scenarios when adding user-visible features
- Update `Examples/UICatalog` scenarios when adding user-visible features

## Documentation Style

- In reference/how-to/API docs, write instructions as `To [goal], [imperative action].`
- Avoid `When/If you want/need to ...` unless describing a real condition.
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ dotnet test --project Tests/UnitTestsParallelizable --no-build --filter-method "
7. **Backing fields** - Place immediately before their property
8. **Early return / guard clauses (CRITICAL)** - ALWAYS prefer guard clauses over nested `if`/`else`. Invert the condition, return/continue early, keep happy path at lowest indentation. This applies to methods, lambdas, loops — everywhere. See [early-return.md](/.claude/rules/early-return.md) for detailed examples.
9. **One type per file** - Public and internal types each get their own file
10. **Docs instruction style** - In reference/how-to/API docs, write `To [goal], [imperative action].` Avoid `When/If you want/need to ...` unless describing a real condition.

## Detailed Coding Rules

Expand Down Expand Up @@ -518,6 +519,5 @@ See `.claude/cookbook/` for common UI patterns:






1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ See `Tests/README.md` for the full list of test projects (including `Integration
8. **Unused lambda params** - use `_`: `(_, _) => { }`
9. **Early return / guard clauses** - ALWAYS invert conditions and return/continue early. Never wrap the happy path in a conditional. Applies to methods, lambdas, and loops. See `.claude/rules/early-return.md`.
10. **One type per file** - Public and internal types each get their own file
11. **Docs instruction style** - In reference/how-to/API docs, write `To [goal], [imperative action].` Avoid `When/If you want/need to ...` unless describing a real condition.

## Testing

Expand Down
32 changes: 17 additions & 15 deletions Terminal.Gui/ViewBase/Layout/Dim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
namespace Terminal.Gui.ViewBase;

/// <summary>
/// Describes a declarative, responsive dimension for a <see cref="View"/>.
/// <see cref="Dim"/> is the type of <see cref="View.Width"/> and <see cref="View.Height"/>.
/// Integer values are implicitly convertible to an absolute <see cref="Dim"/>.
/// </summary>
/// <remarks>
/// <para>
/// A Dim object describes the dimensions of a <see cref="View"/>. Dim is the type of the
/// <see cref="View.Width"/> and <see cref="View.Height"/> properties of <see cref="View"/>.
/// To make a view's size respond to the available space, its content, or the size and position of other views
/// rather than using a fixed number of cells, use <see cref="Dim"/>.
/// </para>
/// <para>
/// Integer values are implicitly convertible to an absolute <see cref="Dim"/>. These objects are created using
/// the static methods described below. The <see cref="Dim"/> objects can be combined with the addition and
/// subtraction operators.
/// To define responsive sizing in Terminal.Gui, describe the relationship that should be maintained and let the
/// layout engine resolve the final <see cref="View.Frame"/> whenever layout runs.
/// </para>
/// </summary>
/// <remarks>
/// <para>
/// <list type="table">
/// <listheader>
Expand Down Expand Up @@ -109,8 +111,8 @@ public abstract record Dim : IEqualityOperators<Dim, Dim, bool>
/// <para>
/// SubViews that use <see cref="Dim.Fill()"/> do not contribute to the auto-sizing calculation unless
/// <see cref="DimFill.MinimumContentDim"/> is specified. Without it, a <see cref="DimFill"/> SubView will
/// receive a size of 0. Use <see cref="Dim.Fill(Dim, Dim?)"/> with a <c>minimumContentDim</c> to ensure
/// the SubView contributes a minimum size.
/// receive a size of 0. To ensure the SubView contributes a minimum size, use
/// <see cref="Dim.Fill(Dim, Dim?)"/> with a <c>minimumContentDim</c>.
/// </para>
/// </remarks>
/// <example>
Expand Down Expand Up @@ -141,9 +143,9 @@ public static Dim Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim? minimumCont
/// </para>
/// <para>
/// If the SuperView uses <see cref="Dim.Auto"/>, a <see cref="DimFill"/> SubView does <b>not</b>
/// contribute to the auto-sizing calculation and will receive a size of 0. Use
/// <see cref="Fill(Dim, Dim?)"/> with a <c>minimumContentDim</c> or <see cref="Fill(View)"/> with
/// a <c>to</c> parameter to ensure the SubView contributes to auto-sizing.
/// contribute to the auto-sizing calculation and will receive a size of 0. To make the SubView contribute to
/// auto-sizing, use <see cref="Fill(Dim, Dim?)"/> with a <c>minimumContentDim</c> or <see cref="Fill(View)"/>
/// with a <c>to</c> parameter.
/// See the <a href="../docs/dimauto.md">Dim.Auto Deep Dive</a> for details.
/// </para>
/// </remarks>
Expand All @@ -162,9 +164,9 @@ public static Dim Auto (DimAutoStyle style = DimAutoStyle.Auto, Dim? minimumCont
/// <remarks>
/// <para>
/// If the SuperView uses <see cref="Dim.Auto"/>, a <see cref="DimFill"/> SubView does <b>not</b>
/// contribute to the auto-sizing calculation and will receive a size of 0. Use
/// <see cref="Fill(Dim, Dim?)"/> with a <c>minimumContentDim</c> or <see cref="Fill(View)"/> with
/// a <c>to</c> parameter to ensure the SubView contributes to auto-sizing.
/// contribute to the auto-sizing calculation and will receive a size of 0. To make the SubView contribute to
/// auto-sizing, use <see cref="Fill(Dim, Dim?)"/> with a <c>minimumContentDim</c> or <see cref="Fill(View)"/>
/// with a <c>to</c> parameter.
/// See the <a href="../docs/dimauto.md">Dim.Auto Deep Dive</a> for details.
/// </para>
/// </remarks>
Expand Down
28 changes: 17 additions & 11 deletions Terminal.Gui/ViewBase/Layout/Pos.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
namespace Terminal.Gui.ViewBase;

/// <summary>
/// Describes the position of a <see cref="View"/> which can be an absolute value, a percentage, centered, or
/// relative to the ending dimension. Integer values are implicitly convertible to an absolute <see cref="Pos"/>. These
/// objects are created using the static methods Percent, AnchorEnd, and Center. The <see cref="Pos"/> objects can be
/// combined with the addition and subtraction operators.
/// Describes a declarative, responsive position for a <see cref="View"/>.
/// A <see cref="Pos"/> can be absolute, percentage-based, centered, anchored to an edge, or relative to another
/// <see cref="View"/>. Integer values are implicitly convertible to an absolute <see cref="Pos"/>.
/// </summary>
/// <remarks>
/// <para>Use the <see cref="Pos"/> objects on the X or Y properties of a view to control the position.</para>
/// <para>
/// These can be used to set the absolute position, when merely assigning an integer value (via the implicit
/// integer to <see cref="Pos"/> conversion), and they can be combined to produce more useful layouts, like:
/// Pos.Center - 3, which would shift the position of the <see cref="View"/> 3 characters to the left after
/// centering for example.
/// To describe where a view should be, relative to its <see cref="View.SuperView"/>, its available space, or its
/// sibling views, use <see cref="Pos"/> with <see cref="View.X"/> and <see cref="View.Y"/>.
/// </para>
/// <para>
/// Reference coordinates of another view by using the methods Left(View), Right(View), Bottom(View), Top(View).
/// The X(View) and Y(View) are aliases to Left(View) and Top(View) respectively.
/// To define responsive horizontal and vertical placement in Terminal.Gui, describe the relationship that should
/// be maintained and let the layout engine resolve the final <see cref="View.Frame"/> whenever layout runs.
/// </para>
/// <para>
/// <see cref="Pos"/> values can be combined to produce more useful layouts, such as
/// <c>Pos.Center () - 3</c>, which shifts the resolved position of the <see cref="View"/> 3 cells earlier on
/// the axis after centering.
/// </para>
/// <para>
/// To reference coordinates of another view, use <see cref="Left(View)"/>, <see cref="Right(View)"/>,
/// <see cref="Bottom(View)"/>, and <see cref="Top(View)"/>. <see cref="X(View)"/> and <see cref="Y(View)"/> are
/// aliases to <see cref="Left(View)"/> and <see cref="Top(View)"/> respectively.
/// </para>
/// <para>
/// <list type="table">
Expand Down
77 changes: 59 additions & 18 deletions Terminal.Gui/ViewBase/View.Layout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ public partial class View // Layout APIs

private Rectangle? _frame;

/// <summary>Gets or sets the absolute location and dimension of the view.</summary>
/// <summary>
/// Gets or sets the resolved location and dimension of the view.
/// </summary>
/// <value>
/// The rectangle describing absolute location and dimension of the view, in coordinates relative to the
/// <see cref="SuperView"/>'s Content, which is bound by <see cref="GetContentSize ()"/>.
Expand All @@ -28,6 +30,11 @@ public partial class View // Layout APIs
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// <see cref="Frame"/> is typically the output of Terminal.Gui's responsive layout system. To describe layout,
/// use <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and <see cref="Height"/>. To inspect the
/// resolved result, read <see cref="Frame"/> after layout has resolved those relationships.
/// </para>
/// <para>
/// Frame is relative to the <see cref="SuperView"/>'s Content, which is bound by <see cref="GetContentSize ()"/>
/// .
/// </para>
Expand Down Expand Up @@ -207,14 +214,20 @@ private void PosDimSet ()

private Pos _x = Pos.Absolute (0);

/// <summary>Gets or sets the X position for the view (the column).</summary>
/// <summary>
/// Gets or sets the declarative horizontal position for the view.
/// </summary>
/// <value>The <see cref="Pos"/> object representing the X position.</value>
/// <remarks>
/// <para>
/// See the View Layout Deep Dive for more information:
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// To express responsive relationships such as "center this view", "anchor it to the end", or "place it to
/// the right of another view", use <see cref="X"/> with <see cref="Pos"/>.
/// </para>
/// <para>
/// The position is relative to the <see cref="SuperView"/>'s Content, which is bound by
/// <see cref="GetContentSize ()"/>.
/// </para>
Expand All @@ -230,7 +243,7 @@ private void PosDimSet ()
/// <para>
/// Changing this property will cause <see cref="Frame"/> to be updated.
/// </para>
/// <para>The default value is <c>Pos.At (0)</c>.</para>
/// <para>The default value is <c>Pos.Absolute (0)</c>.</para>
/// </remarks>
public Pos X
{
Expand All @@ -252,14 +265,20 @@ public Pos X

private Pos _y = Pos.Absolute (0);

/// <summary>Gets or sets the Y position for the view (the row).</summary>
/// <summary>
/// Gets or sets the declarative vertical position for the view.
/// </summary>
/// <value>The <see cref="Pos"/> object representing the Y position.</value>
/// <remarks>
/// <para>
/// See the View Layout Deep Dive for more information:
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// To express responsive relationships such as "center this view", "anchor it to the bottom", or "place it
/// below another view", use <see cref="Y"/> with <see cref="Pos"/>.
/// </para>
/// <para>
/// The position is relative to the <see cref="SuperView"/>'s Content, which is bound by
/// <see cref="GetContentSize ()"/>.
/// </para>
Expand All @@ -275,7 +294,7 @@ public Pos X
/// <para>
/// Changing this property will cause <see cref="Frame"/> to be updated.
/// </para>
/// <para>The default value is <c>Pos.At (0)</c>.</para>
/// <para>The default value is <c>Pos.Absolute (0)</c>.</para>
/// </remarks>
public Pos Y
{
Expand All @@ -296,14 +315,20 @@ public Pos Y

private Dim _height = Dim.Absolute (0);

/// <summary>Gets or sets the height dimension of the view.</summary>
/// <summary>
/// Gets or sets the declarative height for the view.
/// </summary>
/// <value>The <see cref="Dim"/> object representing the height of the view (the number of rows).</value>
/// <remarks>
/// <para>
/// See the View Layout Deep Dive for more information:
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// To express responsive sizing such as filling remaining space, using a percentage of the available height,
/// or growing to fit content with <c>Dim.Auto ()</c>, use <see cref="Height"/> with <see cref="Dim"/>.
/// </para>
/// <para>
/// The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by
/// <see cref="GetContentSize ()"/> .
/// </para>
Expand Down Expand Up @@ -383,14 +408,20 @@ protected virtual void OnHeightChanged (ValueChangedEventArgs<Dim> args) { }

private Dim _width = Dim.Absolute (0);

/// <summary>Gets or sets the width dimension of the view.</summary>
/// <summary>
/// Gets or sets the declarative width for the view.
/// </summary>
/// <value>The <see cref="Dim"/> object representing the width of the view (the number of columns).</value>
/// <remarks>
/// <para>
/// See the View Layout Deep Dive for more information:
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// To express responsive sizing such as filling remaining space, using a percentage of the available width,
/// or growing to fit content with <c>Dim.Auto ()</c>, use <see cref="Width"/> with <see cref="Dim"/>.
/// </para>
/// <para>
/// The dimension is relative to the <see cref="SuperView"/>'s Content, which is bound by
/// <see cref="GetContentSize ()"/>
/// .
Expand Down Expand Up @@ -507,16 +538,20 @@ internal static bool Layout (IEnumerable<View> views, Size contentSize)
}

/// <summary>
/// Performs layout of the view and its subviews within the specified content size.
/// Resolves the view's declarative layout and then lays out its subviews within the specified content size.
/// </summary>
/// <remarks>
/// <para>
/// See the View Layout Deep Dive for more information:
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// This method is intended to be called by the layout engine to
/// prepare the view for layout and is exposed as a public API primarily for testing purposes.
/// This method turns responsive <see cref="Pos"/> and <see cref="Dim"/> expressions into an absolute
/// <see cref="Frame"/>, then recursively lays out SubViews.
/// </para>
/// <para>
/// This method is intended to be called by the layout engine to prepare the view for layout and is exposed as
/// a public API primarily for testing purposes.
/// </para>
/// </remarks>
/// <param name="contentSize"></param>
Expand All @@ -537,30 +572,36 @@ public bool Layout (Size contentSize)
}

/// <summary>
/// Performs layout of the view and its subviews using the content size of either the <see cref="SuperView"/> or
/// <see cref="IApplication.Screen"/>.
/// Resolves the view's declarative layout and then lays out its subviews using the content size of either the
/// <see cref="SuperView"/> or <see cref="IApplication.Screen"/>.
/// </summary>
/// <remarks>
/// <para>
/// See the View Layout Deep Dive for more information:
/// <see href="https://gui-cs.github.io/Terminal.Gui/docs/layout.html"/>
/// </para>
/// <para>
/// This method is intended to be called by the layout engine to
/// prepare the view for layout and is exposed as a public API primarily for testing purposes.
/// To force a responsive layout pass after changing <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, or
/// <see cref="Height"/>, call this overload.
/// </para>
/// <para>
/// This method is intended to be called by the layout engine to prepare the view for layout and is exposed as
/// a public API primarily for testing purposes.
/// </para>
/// </remarks>
/// <returns><see langword="false"/>If the view could not be laid out (typically because dependency was not ready). </returns>
public bool Layout () => Layout (GetContainerSize ());

/// <summary>
/// Sets the position and size of this view, relative to the SuperView's ContentSize (nominally the same as
/// <c>this.SuperView.GetContentSize ()</c>) based on the values of <see cref="X"/>, <see cref="Y"/>,
/// <see cref="Width"/>,
/// and <see cref="Height"/>.
/// Resolves this view's declarative layout into a concrete position and size, relative to the SuperView's
/// content size, based on <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and <see cref="Height"/>.
/// </summary>
/// <remarks>
/// <para>
/// This method is the core step that turns responsive <see cref="Pos"/> and <see cref="Dim"/> expressions
/// into the view's absolute <see cref="Frame"/>.
/// </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.
Expand Down
Loading
Loading