Browse Source

- Edited layout.md
- Added DimAuto Deep Dive

Tig 1 year ago
parent
commit
2fafc6929f
3 changed files with 101 additions and 15 deletions
  1. 4 5
      Terminal.Gui/View/Layout/PosDim.cs
  2. 79 0
      docfx/docs/dimauto.md
  3. 18 10
      docfx/docs/layout.md

+ 4 - 5
Terminal.Gui/View/Layout/PosDim.cs

@@ -593,7 +593,7 @@ public class Pos
 ///                 </term>
 ///                 <description>
 ///                     Creates a <see cref="Dim"/> object that automatically sizes the view to fit
-///                     the view's SubViews.
+///                     the view's Text, SubViews, or ContentArea.
 ///                 </description>
 ///             </item>
 ///             <item>
@@ -660,7 +660,7 @@ public class Dim
         Auto = Content | Text,
 
         /// <summary>
-        ///     The dimensions will be computed based on the View's content.
+        ///     The dimensions will be computed based on the View's non-Text content.
         /// <para>
         ///     If <see cref="View.ContentSize"/> is explicitly set (is not <see langword="null"/>) then <see cref="View.ContentSize"/>
         ///     will be used to determine the dimension.
@@ -712,12 +712,11 @@ public class Dim
 
 
     /// <summary>
-    ///     Creates a <see cref="Dim"/> object that automatically sizes the view to fit all of the view's SubViews and/or Text.
+    ///     Creates a <see cref="Dim"/> object that automatically sizes the view to fit all the view's SubViews and/or Text.
     /// </summary>
     /// <remarks>
     ///     <para>
-    ///         Tthe behavior of <see cref="DimAutoStyle.Content"/> is overridden and the size of the
-    ///         view will be based on ContentSize.
+    ///         See <see cref="DimAutoStyle"/>.
     ///     </para>
     /// </remarks>
     /// <example>

+ 79 - 0
docfx/docs/dimauto.md

@@ -0,0 +1,79 @@
+# Dim.Auto Deep Dive
+
+The `Dim.Auto` type is a type of `Dim` that automatically sizes the view based on its content. This is useful when you want to size a view based on the content it contains. That content can either be the `Text`, the `SubViews`, or something else defined by the view.
+
+Like all `Dim` types, `Dim.Auto` is used to set the `Width` or `Height` of a view. 
+
+The `DimAutoStyle` enum defines the different ways that `Dim.Auto` can be used to size a view. The `DimAutoStyle` enum has the following values:
+
+* `Text` - The view is sized based on the `Text` property and `TextFormatter` settings.
+* `Content` - The view is sized based on either the `ContentSize` or the `Subviews` property. If `ContentSize` is null, the view is sized based on the size of the subviews (the Subview with the largest relvant dimension plus location will dictate the size). If `ContentSize` is not null, the view is sized based on the `ContentSize` property.
+* `Auto` -  The view is sized based on both `Text` and `Content`, whichever is larger.
+
+## Using Dim.Auto
+
+To use `Dim.Auto`, set the `Width` or `Height` property of a view to `Dim.Auto (DimAutoStyle.Text)` or `Dim.Auto (DimAutoStyle.Content)`.
+
+For example, to create a `View` that is sized based on the `Text` property, you can do this:
+
+```cs
+View view = new ()
+{
+    Text = "Hello, World!",
+    Width = Dim.Auto (DimAutoStyle.Text),
+    Height = Dim.Auto (DimAutoStyle.Text),
+};
+```
+
+Note, the built-in `Label` view class does precisely this in its constructor.
+
+To create a `View` that is sized based on its `Subviews`, you can do this:
+
+```cs
+View view = new ()
+{
+    Width = Dim.Auto (DimAutoStyle.Content),
+    Height = Dim.Auto (DimAutoStyle.Content),
+};
+view.Add (new Label () { Text = "Hello, World!" });
+```
+
+In this example, the `View` will be sized based on the size of the `Label` that is added to it.
+
+## Limitations
+
+`Dim.Auto` is not always the best choice for sizing a view. For example, if you want a view to fill the entire width of the Superview, you should use `Dim.Fill ()` instead of `Dim.Auto (DimAutoStyle.Content)`.
+
+`Dim.Auto` is also not always the most efficient way to size a view. If you know the size of the content ahead of time, you can set the `Width` and `Height` properties to `Dim.Absolute (n)` instead of using `Dim.Auto`.
+
+> TODO: Verify accuracy of the following paragraphs
+
+Some `Pos` and `Dim` types are not compatible with `Dim.Auto`. For example, you cannot use `Dim.Auto (DimAutoStyle.Content)` with Subviews that use `Dim.Fill ()` or `Dim.Percent (n)` because the size of the Subview is not known until the layout is computed.
+
+`Pos` types that are relative to the size of the view, such as `Pos.Percent (n)` are not compatible with `Dim.Auto` because the size of the view is not known until the layout is computed. However, `Pos.Center ()` and `Pos.AnchorEnd ()` are compatible with `Dim.Auto` because they are relative to the size of the view's Superview.
+
+
+## Building Dim.Auto friendly View
+
+It is common to build View classes that have a natrual size based on their content. For example, the `Label` class is a view that is sized based on the `Text` property. Another example is `Slider` which is size based on the number of options it has, it's orientation, etc... 
+
+Developers using these views shouldn't need to know the details of how the view is sized, they should just be able to use the view and have it size itself correctly.
+
+For example, a vertical `Slider` with 3 options may be created like this:
+
+```cs
+List<object> options = new () { "Option 1", "Option 2", "Option 3" };
+Slider slider = new (options)
+{
+    Orientation = Orientation.Vertical,
+    Type = SliderType.Multiple,
+};
+view.Add (slider);
+```
+
+Note the developer does not need to specify the size of the `Slider`, it will size itself based on the number of options and the orientation. 
+
+Views like `Slider` do this by setting `Width` and `Height` to `Dim.Auto (DimAutoStyle.Content)` in the constructor and and setting the `ContentSize` property to the size that the view should be in the `LayoutStarted` event handler.
+
+Views that use `Text` for their content can just set `Width` and `Height` to `Dim.Auto (DimAutoStyle.Text)`.
+

+ 18 - 10
docfx/docs/layout.md

@@ -2,19 +2,28 @@
 
 Terminal.Gui provides a rich system for how `View` objects are laid out relative to each other. The layout system also defines how coordinates are specified.
 
-## Dealing with coordinates
+## Coordinates
 
-The coordinate systems in Terminal.Gui are:
 
-* `Screen` - Describes the dimensions and characteristics of the underlying terminal. Currently Terminal.Gui only supports applications that run "full-screen", meaning they fill the entire terminal when running. As the user resizes their terminal, the `Screen` changes size and the applicaiton will be resized to fit. *Screen-Relative* means an origin (`0, 0`) at the top-left corner of the terminal. `ConsoleDriver`s operate exclusively on *Screen-Relative* coordinates.
-* `Application` - The dimensions and characteristics of the application. Because only full-screen apps are currently supported, `Application` is effectively the same as `Screen` from a layout perspective. *Application-Relative* currently means an origin (`0, 0`) at the top-left corner of the terminal. `Applicaiton.Top` is a `View` with a top-left corner fixed at the *Application.Relative* coordinate of (`0, 0`) and is the size of `Screen`.
-* `View Frame` - A rectangle at a particular point, and of a particular size, within another `View`, referred to as the `Superview`. *Frame-Relative* means a coordinate is relative to the top-left corner of the View in question. `View.FrameToScreen ()` and `View.ScreenToFrame ()` are helper methods for translating a *Frame-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa.
-* `View Content/Content Area` - A rectangle, with an origin of (`0, 0`) and size (defined by `View.ContentSize`) where the View's content exists. *Content-Relative* means a coordinate is relative to the top-left corner of the content, which is always (`0,0`). `View.ContentToScreen ()` and `View.ScreenToContent ()` are helper methods for translating a *Content-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa.
-* `Viewport` - A *Content-Relative* rectangle representing the subset of the View's content that is visible to the user. If `View.ContentSize` is larger than the Viewport, scrolling is enabled. *Viewport-Relative* means a coordinate that is bound by (`0,0`) and the size of the inner-rectangle of the View's `Padding`. The View drawing primitives (e.g. `View.Move`) take *Viewport-Relative* coordinates; `Move (0, 0)` means the `Cell` in the top-left corner of the inner rectangle of `Padding`. `View.ViewportToScreen ()` and `View.ScreenToViewport ()` are helper methods for translating a *Viewport-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa. To convert a *Viewport-Relative* coordinate to a *Content-Relative* coordinate, simply subtract `Viewport.X` and/or `Viewport.Y` from the *Content-Relative* coordinate. To convert a *Viewport-Relative* coordinate to a *Frame-Relative* coordinate, subtract the point returned by `View.GetViewportOffsetFromFrame`.
+* **Screen-Relative** - Describes the dimensions and characteristics of the underlying terminal. Currently Terminal.Gui only supports applications that run "full-screen", meaning they fill the entire terminal when running. As the user resizes their terminal, the `Screen` changes size and the applicaiton will be resized to fit. *Screen-Relative* means an origin (`0, 0`) at the top-left corner of the terminal. `ConsoleDriver`s operate exclusively on *Screen-Relative* coordinates.
+* **Application.Relative** - The dimensions and characteristics of the application. Because only full-screen apps are currently supported, `Application` is effectively the same as `Screen` from a layout perspective. *Application-Relative* currently means an origin (`0, 0`) at the top-left corner of the terminal. `Applicaiton.Top` is a `View` with a top-left corner fixed at the *Application.Relative* coordinate of (`0, 0`) and is the size of `Screen`.
+* **Frame-Relative**  - The `Frame` property of a `View` is a rectangle that describes the current location and size of the view relative to the `Superview`'s content area. *Frame-Relative* means a coordinate is relative to the top-left corner of the View in question. `View.FrameToScreen ()` and `View.ScreenToFrame ()` are helper methods for translating a *Frame-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa.
+* **Content-Relative** - A rectangle, with an origin of (`0, 0`) and size (defined by `View.ContentSize`) where the View's content exists. *Content-Relative* means a coordinate is relative to the top-left corner of the content, which is always (`0,0`). `View.ContentToScreen ()` and `View.ScreenToContent ()` are helper methods for translating a *Content-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa.
+* **Viewport-Relative** - A *Content-Relative* rectangle representing the subset of the View's content that is visible to the user. If `View.ContentSize` is larger than the Viewport, scrolling is enabled. *Viewport-Relative* means a coordinate that is bound by (`0,0`) and the size of the inner-rectangle of the View's `Padding`. The View drawing primitives (e.g. `View.Move`) take *Viewport-Relative* coordinates; `Move (0, 0)` means the `Cell` in the top-left corner of the inner rectangle of `Padding`. `View.ViewportToScreen ()` and `View.ScreenToViewport ()` are helper methods for translating a *Viewport-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa. To convert a *Viewport-Relative* coordinate to a *Content-Relative* coordinate, simply subtract `Viewport.X` and/or `Viewport.Y` from the *Content-Relative* coordinate. To convert a *Viewport-Relative* coordinate to a *Frame-Relative* coordinate, subtract the point returned by `View.GetViewportOffsetFromFrame`.
+
+## The Frame
+
+The `Frame` property of a `View` is a rectangle that describes the current location and size of the view relative to the `Superview`'s content area. The `Frame`  has a `Location` and `Size`. The `Location` describes the top-left corner of the view relative to the `Superview`'s content area. The `Size` describes the width and height of the view. The `Frame` is used to determine where the view is drawn on the screen and is used to calculate the `Viewport` and `ContentSize`.
+
+## The Content Area
+
+ The content area is the area where the view's content is drawn. Content can be any combination of the `View.Text` property, `Subviews`, and other content drawn by the View. The `View.ContentSize` property defines the size of the content area of the view. *Content Area* refers to the rectangle with a location of `0,0` with a size of `ContentSize`.
+
+ `ContentSize` is `null` by default. If `ContentSize` is `null`, the content area is the size of the `Viewport`. If `ContentSize` is set, the content area is the size of `ContentSize`. If `ContentSize` is larger than the `Viewport`, scrolling is enabled. 
 
 ## The Viewport
 
-The Viewport (`View.Viewport`) is a rectangle describing a sub-set of the View's content. It is a "portal" into the content. The `Viewport.Location` is relative to the top-left corner of the inner rectangle of `View.Padding`. If `Viewport.Size` is the same as `View.ContentSize`, `Viewport.Location` will be `0,0`. 
+The Viewport (`View.Viewport`) is a rectangle describing the portion of the *Content Area* that is currently visible to the user. It is a "portal" into the content. The `Viewport.Location` is relative to the top-left corner of the inner rectangle of `View.Padding`. If `Viewport.Size` is the same as `View.ContentSize`, `Viewport.Location` will be `0,0`. 
 
 To enable scrolling set `View.ContentSize` and then set `Viewport.Location` to positive values. Making `Viewport.Location` positive moves the Viewport down and to the right in the content. 
 
@@ -42,7 +51,6 @@ var label2 = new Label () {
     Width = Dim.Fill (),
     Height = Dim.Percent (50)
 };
-
 ```
 
 The `Frame` property is a rectangle that provides the current location and size of the view relative to the View's `Superview`'s Content area. 
@@ -84,7 +92,7 @@ The [Dim](~/api/Terminal.Gui.Dim.yml) is the type of `View.Width` and `View.Heig
 * Fill to the end of the Superview's Content Area - `Dim.Fill ()`.
 * Reference the Width or Height of another view - `Dim.Width (otherView)`, `Dim.Height (otherView)`.
 * An arbitrary function - `Dim.Function(fn)`
-* Automatic size based on the View's content (either Subviews or Text) - `Dim.Auto()`
+* Automatic size based on the View's content (either Subviews or Text) - `Dim.Auto()` - See the [DimAuto Deep Dive](dimauto.md) for more information.
 
 All `Dim` dimensions are relative to the Superview's content area.