Layout
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.
See View Deep Dive, Arrangement Deep Dive, Scrolling Deep Dive, and Drawing Deep Dive for more.
Lexicon & Taxonomy
| Term | Meaning |
|---|---|
| Adornment | The Thicknesses that separate the Frame from the Viewport. There are three Adornments: Margin, Padding, and Border. Adornments are not part of the View's content and are not clipped by the View's ClipArea. |
| Application-Relative | The dimensions and characteristics of the application. Because only full-screen apps are currently supported, @Terminal.Gui.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. @Terminal.Gui.Application.Top is a View with a top-left corner fixed at the Application.Relative coordinate of (0, 0) and is the size of Screen. |
| Border | The Adornment that resides in the inside of the Margin. The Border is where a visual border (drawn using line-drawing glyphs) and the @Terminal.Gui.View.Title are drawn, and where the user can interact with the mouse/keyboard to adjust the Views' Arrangement. |
| Content Area | Describes the View's total content. The location of the content is always (0, 0) and the size is set by @Terminal.Gui.View.SetContentSize* and defaults to the size of the Viewport. If the content size is larger than the Viewport, scrolling is enabled. |
| Content-Relative | A rectangle, with an origin of (0, 0) and size, defined by @Terminal.Gui.View.GetContentSize*, 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). @Terminal.Gui.View.ContentToScreen* and @Terminal.Gui.View.ScreenToContent* are helper methods for translating coordinates. |
| Frame | A Rectangle that defines the location and size of the @Terminal.Gui.View. The coordinates are relative to the SuperView of the View (or, in the case of Application.Top, the console size). Controlled by @Terminal.Gui.View.X, @Terminal.Gui.View.Y, @Terminal.Gui.View.Width, and @Terminal.Gui.View.Height. |
| Frame-Relative | The @Terminal.Gui.View.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. @Terminal.Gui.View.FrameToScreen* and @Terminal.Gui.View.ScreenToFrame* are helper methods for translating coordinates. |
| Margin | The outermost Adornment. The outside of the margin is a rectangle the same size as the Frame. By default Margin is {0,0,0,0}. When made thicker, Margins are visually transparent and transparent to mouse events by default. |
| Overlapped/Overlapping | Refers to a form Layout where SubViews of a View are visually arranged such that their Frames overlap. In Overlap view arrangements there is a Z-axis (Z-order) in addition to the X and Y dimension. |
| Padding | The Adornment resides in the inside of the Border and outside of the Viewport. Padding is {0, 0, 0, 0} by default. Padding is not part of the View's content and is not clipped by the View's Clip. When enabled, scroll bars reside within Padding. |
| 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. Screen-Relative means an origin (0, 0) at the top-left corner of the terminal. @Terminal.Gui.ConsoleDriver implementations operate exclusively on Screen-Relative coordinates. |
| Thickness | A smart record struct describing a rectangle where each of the four sides can have a width. Valid width values are >= 0. The inner area of a Thickness is the sum of the widths of the four sides minus the size of the rectangle. |
| Tiled/Tiling | Refer to a form of Views that are visually arranged such that they abut each other and do not overlap. In a Tiled view arrangement, Z-ordering only comes into play when a developer intentionally causes views to be aligned such that they overlap. |
| Viewport | The Rectangle that describes the portion of the View's Content Area that is currently visible to the user. If size of the Content Area is larger than the Viewport, scrolling is enabled and the Viewport location determines which portion of the content is visible. |
| Viewport-Relative | A Content-Relative rectangle representing the subset of the View's content that is visible to the user: @Terminal.Gui.View.Viewport. 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. |
Arrangement Modes
See Arrangement Deep Dive for more.
Composition
View Composition Diagram
classDiagram
class View {
+Frame: Rectangle
+Margin: Adornment - outermost
+Border: Adornment - border lines and Title
+Padding: Adornment - innermost - Scrollbars
+Viewport: Rectangle describing portal into ContentArea
+ContentArea: Rectangle with Location always 0,0
+GetContentSize(): Size
+SetContentSize(Size)
}
class Adornment {
+Thickness: Thickness
}
class Thickness {
+Top: int
+Right: int
+Bottom: int
+Left: int
}
class Rectangle {
+Location: Point
+Size: Size
}
View --> Adornment : has
Adornment --> Thickness : has
View --> Rectangle : has
note for View "Frame defines location and size relative to SuperView"
note for Adornment "Separates Frame from Viewport"
note for Rectangle "Defines location and size"
The diagram above shows the structure of a View's composition:
- Frame: The outermost rectangle defining the View's location and size
- Margin: Separates the View from other SubViews
- Border: Contains visual border and title
- Padding: Offsets the Viewport from the Border
- Viewport: The visible portion of the Content Area
- Content Area: Where the View's content is drawn (shown larger than Viewport to illustrate scrolling)
Each layer is defined by a Thickness that specifies the width of each side (top, right, bottom, left). The Content Area is shown as a separate container that the Viewport "looks into" - this illustrates how scrolling works. In this example, the Viewport is positioned at (5,5) relative to the Content Area, showing how scrolling works.
The Content Area
Content Area refers to the rectangle with a location of 0,0 with the size returned by @Terminal.Gui.View.GetContentSize*.
The content area is the area where the view's content is drawn. Content can be any combination of the @Terminal.Gui.View.Text property, SubViews, and other content drawn by the View. The @Terminal.Gui.View.GetContentSize* method gets the size of the content area of the view.
The Content Area size tracks the size of the @Terminal.Gui.View.Viewport by default. If the content size is set via @Terminal.Gui.View.SetContentSize*, the content area is the provided size. If the content size is larger than the @Terminal.Gui.View.Viewport, scrolling is enabled.
The Viewport
The @Terminal.Gui.View.Viewport is a rectangle describing the portion of the Content Area that is 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.GetContentSize(), Viewport.Location will be 0,0.
To enable scrolling call View.SetContentSize() and then set Viewport.Location to positive values. Making Viewport.Location positive moves the Viewport down and to the right in the content.
See the Scrolling Deep Dive for details on how to enable scrolling.
Viewport Settings
The @Terminal.Gui.View.ViewportSettings property controls how the Viewport is constrained using ViewportSettingsFlags. By default, ViewportSettings is None, which provides sensible constraints for typical scrolling scenarios.
Default Behavior (No Flags Set)
With no flags set, the Viewport is constrained as follows:
- No negative scrolling:
Viewport.XandViewport.Ycannot go below0. The user cannot scroll above or to the left of the content origin. - Content fills the viewport: The Viewport is clamped so that
Viewport.X + Viewport.Width <= ContentSize.WidthandViewport.Y + Viewport.Height <= ContentSize.Height. This prevents blank space from appearing when scrolling - the content always fills the visible area. - Last row/column always visible: Even if trying to scroll past the end of content, at least the last row and last column remain visible.
Flag Categories
The flags are organized into categories:
Negative Location Flags - Allow scrolling before the content origin (0,0):
AllowNegativeX- PermitsViewport.X < 0(scroll left of content)AllowNegativeY- PermitsViewport.Y < 0(scroll above content)AllowNegativeLocation- Combines both X and Y
Greater Than Content Flags - Allow scrolling past the last row/column:
AllowXGreaterThanContentWidth- PermitsViewport.X >= ContentSize.WidthAllowYGreaterThanContentHeight- PermitsViewport.Y >= ContentSize.HeightAllowLocationGreaterThanContentSize- Combines both X and Y
Blank Space Flags - Allow blank space to appear when scrolling:
AllowXPlusWidthGreaterThanContentWidth- PermitsViewport.X + Viewport.Width > ContentSize.Width(blank space on right)AllowYPlusHeightGreaterThanContentHeight- PermitsViewport.Y + Viewport.Height > ContentSize.Height(blank space on bottom)AllowLocationPlusSizeGreaterThanContentSize- Combines both X and Y
Conditional Negative Flags - Allow negative scrolling only when viewport is larger than content:
AllowNegativeXWhenWidthGreaterThanContentWidth- Useful for centering content smaller than the viewAllowNegativeYWhenHeightGreaterThanContentHeight- Useful for centering content smaller than the viewAllowNegativeLocationWhenSizeGreaterThanContentSize- Combines both X and Y
Drawing Flags - Control clipping and clearing behavior:
ClipContentOnly- Clips drawing to the visible content area instead of the entire ViewportClearContentOnly- Clears only the visible content area (requiresClipContentOnly)Transparent- The view does not clear its background when drawingTransparentMouse- Mouse events pass through areas not occupied by SubViews
Layout Engine
Terminal.Gui provides a rich system for how views are laid out relative to each other. The position of a view is set by setting the X and Y properties, which are of time @Terminal.Gui.Pos. The size is set via Width and Height, which are of type @Terminal.Gui.Dim.
var label1 = new Label () { X = 1, Y = 2, Width = 3, Height = 4, Title = "Absolute")
var label2 = new Label () {
Title = "Computed",
X = Pos.Right (otherView),
Y = Pos.Center (),
Width = Dim.Fill (),
Height = Dim.Percent (50)
};
@Terminal.Gui.Pos
@Terminal.Gui.Pos is the type of View.X and View.Y and supports the following sub-types:
- Absolute position, by passing an integer - @Terminal.Gui.Pos.Absolute*.
- Percentage of the parent's view size - @Terminal.Gui.Pos.Percent(System.Int32)
- Anchored from the end of the dimension - @Terminal.Gui.Pos.AnchorEnd(System.Int32)
- Centered, using @Terminal.Gui.Pos.Center*
- The @Terminal.Gui.Pos.Left*, @Terminal.Gui.Pos.Right*, @Terminal.Gui.Pos.Top*, and @Terminal.Gui.Pos.Bottom* tracks the position of another view.
- Aligned (left, right, center, etc...) with other views - @Terminal.Gui.Pos.Align*
- An arbitrary function - @Terminal.Gui.Pos.Func*
All Pos coordinates are relative to the SuperView's content area.
Pos values can be combined using addition or subtraction:
// Set the X coordinate to 10 characters left from the center
view.X = Pos.Center () - 10;
view.Y = Pos.Percent (20);
anotherView.X = AnchorEnd (10);
anotherView.Width = 9;
myView.X = Pos.X (view);
myView.Y = Pos.Bottom (anotherView) + 5;
@Terminal.Gui.Dim
@Terminal.Gui.Dim is the type of View.Width and View.Height and supports the following sub-types:
- Automatic size based on the View's content (either SubViews or Text) - @Terminal.Gui.Dim.Auto* - See Dim.Auto Deep Dive.
- Absolute size, by passing an integer - @Terminal.Gui.Dim.Absolute(System.Int32).
- Percentage of the SuperView's Content Area - @Terminal.Gui.Dim.Percent(System.Int32).
- Fill to the end of the SuperView's Content Area - @Terminal.Gui.Dim.Fill*. Note:
Dim.Filldoes not contribute to a SuperView's @Terminal.Gui.Dim.Auto sizing unlessminimumContentDimis specified. See Dim.Auto Deep Dive for details. - Reference the Width or Height of another view - @Terminal.Gui.Dim.Width(Terminal.Gui.View), @Terminal.Gui.Dim.Height(Terminal.Gui.View).
- An arbitrary function - @Terminal.Gui.Dim.Func(System.Func{System.Int32}).
All Dim dimensions are relative to the SuperView's content area.
Like, Pos, objects of type Dim can be combined using addition or subtraction, like this:
// Set the Width to be 10 characters less than filling
// the remaining portion of the screen
view.Width = Dim.Fill () - 10;
view.Height = Dim.Percent(20) - 1;
anotherView.Height = Dim.Height (view) + 1;
classDiagram
class View ["View — location and size relative to SuperView"]
class Frame ["Frame — Rectangle"]
class Viewport ["Viewport — visible portion of Content Area"]
class Margin ["Margin — where Shadows live"]
class Border ["Border — Title and Arrangement controls"]
class Padding ["Padding — where ScrollBars live"]
class Adornment
class Thickness ["Thickness — each side has a width"]
View --> Frame
View --> Viewport
View --> Margin : has
View --> Border : has
View --> Padding : has
Margin --|> Adornment
Border --|> Adornment
Padding --|> Adornment
Adornment --> Thickness : has