Skip to content

Geometry

Functions and classes to manage terminal geometry (anything involving coordinates or dimensions).

NULL_OFFSET module-attribute

NULL_OFFSET: Final = Offset(0, 0)

An offset constant for (0, 0).

NULL_REGION module-attribute

NULL_REGION: Final = Region(0, 0, 0, 0)

A Region constant for a null region (at the origin, with both width and height set to zero).

NULL_SPACING module-attribute

NULL_SPACING: Final = Spacing(0, 0, 0, 0)

A Spacing constant for no space.

SpacingDimensions module-attribute

SpacingDimensions: TypeAlias = Union[
    int,
    Tuple[int],
    Tuple[int, int],
    Tuple[int, int, int, int],
]

The valid ways in which you can specify spacing.

Offset class

Bases: NamedTuple

A cell offset defined by x and y coordinates.

Offsets are typically relative to the top left of the terminal or other container.

Textual prefers the names x and y, but you could consider x to be the column and y to be the row.

Offsets support addition, subtraction, multiplication, and negation.

Example
>>> from textual.geometry import Offset
>>> offset = Offset(3, 2)
>>> offset
Offset(x=3, y=2)
>>> offset += Offset(10, 0)
>>> offset
Offset(x=13, y=2)
>>> -offset
Offset(x=-13, y=-2)

clamped property

clamped: Offset

This offset with x and y restricted to values above zero.

is_origin property

is_origin: bool

Is the offset at (0, 0)?

x class-attribute instance-attribute

x: int = 0

Offset in the x-axis (horizontal)

y class-attribute instance-attribute

y: int = 0

Offset in the y-axis (vertical)

blend method

def blend(self, destination, factor):

Calculate a new offset on a line between this offset and a destination offset.

Parameters
Name Type Description Default
destination Offset

Point where factor would be 1.0.

required
factor float

A value between 0 and 1.0.

required
Returns
Type Description
Offset

A new point on a line between self and destination.

get_distance_to method

def get_distance_to(self, other):

Get the distance to another offset.

Parameters
Name Type Description Default
other Offset

An offset.

required
Returns
Type Description
float

Distance to other offset.

Region class

Bases: NamedTuple

Defines a rectangular region.

A Region consists of a coordinate (x and y) and dimensions (width and height).

  (x, y)
    ┌────────────────────┐ ▲
    │                    │ │
    │                    │ │
    │                    │ height
    │                    │ │
    │                    │ │
    └────────────────────┘ ▼
    ◀─────── width ──────▶
Example
>>> from textual.geometry import Region
>>> region = Region(4, 5, 20, 10)
>>> region
Region(x=4, y=5, width=20, height=10)
>>> region.area
200
>>> region.size
Size(width=20, height=10)
>>> region.offset
Offset(x=4, y=5)
>>> region.contains(1, 2)
False
>>> region.contains(10, 8)
True

area property

area: int

The area under the region.

bottom property

bottom: int

Maximum Y value (non inclusive).

bottom_left property

bottom_left: Offset

Bottom left offset of the region.

Returns
Type Description
Offset

An offset.

bottom_right property

bottom_right: Offset

Bottom right offset of the region.

Returns
Type Description
Offset

An offset.

center property

center: tuple[float, float]

The center of the region.

Note, that this does not return an Offset, because the center may not be an integer coordinate.

Returns
Type Description
tuple[float, float]

Tuple of floats.

column_range property

column_range: range

A range object for X coordinates.

column_span property

column_span: tuple[int, int]

A pair of integers for the start and end columns (x coordinates) in this region.

The end value is exclusive.

corners property

corners: tuple[int, int, int, int]

The top left and bottom right coordinates as a tuple of four integers.

height class-attribute instance-attribute

height: int = 0

The height of the region.

line_range property

line_range: range

A range object for Y coordinates.

line_span property

line_span: tuple[int, int]

A pair of integers for the start and end lines (y coordinates) in this region.

The end value is exclusive.

offset property

offset: Offset

The top left corner of the region.

Returns
Type Description
Offset

An offset.

reset_offset property

reset_offset: Region

An region of the same size at (0, 0).

Returns
Type Description
Region

A region at the origin.

right property

right: int

Maximum X value (non inclusive).

size property

size: Size

Get the size of the region.

top_right property

top_right: Offset

Top right offset of the region.

Returns
Type Description
Offset

An offset.

width class-attribute instance-attribute

width: int = 0

The width of the region.

x class-attribute instance-attribute

x: int = 0

Offset in the x-axis (horizontal).

y class-attribute instance-attribute

y: int = 0

Offset in the y-axis (vertical).

at_offset method

def at_offset(self, offset):

Get a new Region with the same size at a given offset.

Parameters
Name Type Description Default
offset tuple[int, int]

An offset.

required
Returns
Type Description
Region

New Region with adjusted offset.

clip method

def clip(self, width, height):

Clip this region to fit within width, height.

Parameters
Name Type Description Default
width int

Width of bounds.

required
height int

Height of bounds.

required
Returns
Type Description
Region

Clipped region.

clip_size method

def clip_size(self, size):

Clip the size to fit within minimum values.

Parameters
Name Type Description Default
size tuple[int, int]

Maximum width and height.

required
Returns
Type Description
Region

No region, not bigger than size.

contains method

def contains(self, x, y):

Check if a point is in the region.

Parameters
Name Type Description Default
x int

X coordinate.

required
y int

Y coordinate.

required
Returns
Type Description
bool

True if the point is within the region.

contains_point method

def contains_point(self, point):

Check if a point is in the region.

Parameters
Name Type Description Default
point tuple[int, int]

A tuple of x and y coordinates.

required
Returns
Type Description
bool

True if the point is within the region.

contains_region cached

def contains_region(self, other):

Check if a region is entirely contained within this region.

Parameters
Name Type Description Default
other Region

A region.

required
Returns
Type Description
bool

True if the other region fits perfectly within this region.

crop_size method

def crop_size(self, size):

Get a region with the same offset, with a size no larger than size.

Parameters
Name Type Description Default
size tuple[int, int]

Maximum width and height (WIDTH, HEIGHT).

required
Returns
Type Description
Region

New region that could fit within size.

expand method

def expand(self, size):

Increase the size of the region by adding a border.

Parameters
Name Type Description Default
size tuple[int, int]

Additional width and height.

required
Returns
Type Description
Region

A new region.

from_corners classmethod

def from_corners(cls, x1, y1, x2, y2):

Construct a Region form the top left and bottom right corners.

Parameters
Name Type Description Default
x1 int

Top left x.

required
y1 int

Top left y.

required
x2 int

Bottom right x.

required
y2 int

Bottom right y.

required
Returns
Type Description
Region

A new region.

from_offset classmethod

def from_offset(cls, offset, size):

Create a region from offset and size.

Parameters
Name Type Description Default
offset tuple[int, int]

Offset (top left point).

required
size tuple[int, int]

Dimensions of region.

required
Returns
Type Description
Region

A region instance.

from_union classmethod

def from_union(cls, regions):

Create a Region from the union of other regions.

Parameters
Name Type Description Default
regions Collection[Region]

One or more regions.

required
Returns
Type Description
Region

A Region that encloses all other regions.

get_scroll_to_visible classmethod

def get_scroll_to_visible(
    cls, window_region, region, *, top=False
):

Calculate the smallest offset required to translate a window so that it contains another region.

This method is used to calculate the required offset to scroll something in to view.

Parameters
Name Type Description Default
window_region Region

The window region.

required
region Region

The region to move inside the window.

required
top bool

Get offset to top of window.

False
Returns
Type Description
Offset

An offset required to add to region to move it inside window_region.

grow cached

def grow(self, margin):

Grow a region by adding spacing.

Parameters
Name Type Description Default
margin tuple[int, int, int, int]

Grow space by (<top>, <right>, <bottom>, <left>).

required
Returns
Type Description
Region

New region.

inflect method

def inflect(self, x_axis=+1, y_axis=+1, margin=None):

Inflect a region around one or both axis.

The x_axis and y_axis parameters define which direction to move the region. A positive value will move the region right or down, a negative value will move the region left or up. A value of 0 will leave that axis unmodified.

╔══════════╗    │
║          ║
║   Self   ║    │
║          ║
╚══════════╝    │

─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─

                │    ┌──────────┐
                     │          │
                │    │  Result  │
                     │          │
                │    └──────────┘
Parameters
Name Type Description Default
x_axis int

+1 to inflect in the positive direction, -1 to inflect in the negative direction.

+1
y_axis int

+1 to inflect in the positive direction, -1 to inflect in the negative direction.

+1
margin Spacing | None

Additional margin.

None
Returns
Type Description
Region

A new region.

intersection cached

def intersection(self, region):

Get the overlapping portion of the two regions.

Parameters
Name Type Description Default
region Region

A region that overlaps this region.

required
Returns
Type Description
Region

A new region that covers when the two regions overlap.

overlaps cached

def overlaps(self, other):

Check if another region overlaps this region.

Parameters
Name Type Description Default
other Region

A Region.

required
Returns
Type Description
bool

True if other region shares any cells with this region.

shrink cached

def shrink(self, margin):

Shrink a region by subtracting spacing.

Parameters
Name Type Description Default
margin tuple[int, int, int, int]

Shrink space by (<top>, <right>, <bottom>, <left>).

required
Returns
Type Description
Region

The new, smaller region.

split cached

def split(self, cut_x, cut_y):

Split a region in to 4 from given x and y offsets (cuts).

           cut_x ↓
        ┌────────┐ ┌───┐
        │        │ │   │
        │    0   │ │ 1 │
        │        │ │   │
cut_y → └────────┘ └───┘
        ┌────────┐ ┌───┐
        │    2   │ │ 3 │
        └────────┘ └───┘
Parameters
Name Type Description Default
cut_x int

Offset from self.x where the cut should be made. If negative, the cut is taken from the right edge.

required
cut_y int

Offset from self.y where the cut should be made. If negative, the cut is taken from the lower edge.

required
Returns
Type Description
tuple[Region, Region, Region, Region]

Four new regions which add up to the original (self).

split_horizontal cached

def split_horizontal(self, cut):

Split a region in to two, from a given y offset.

            ┌─────────┐
            │    0    │
            │         │
    cut →   └─────────┘
            ┌─────────┐
            │    1    │
            └─────────┘
Parameters
Name Type Description Default
cut int

An offset from self.y where the cut should be made. May be negative, for the offset to start from the lower edge.

required
Returns
Type Description
tuple[Region, Region]

Two regions, which add up to the original (self).

split_vertical cached

def split_vertical(self, cut):

Split a region in to two, from a given x offset.

         cut ↓
    ┌────────┐┌───┐
    │    0   ││ 1 │
    │        ││   │
    └────────┘└───┘
Parameters
Name Type Description Default
cut int

An offset from self.x where the cut should be made. If cut is negative, it is taken from the right edge.

required
Returns
Type Description
tuple[Region, Region]

Two regions, which add up to the original (self).

translate cached

def translate(self, offset):

Move the offset of the Region.

Parameters
Name Type Description Default
offset tuple[int, int]

Offset to add to region.

required
Returns
Type Description
Region

A new region shifted by (x, y)

translate_inside method

def translate_inside(self, container, x_axis=True, y_axis=True):

Translate this region, so it fits within a container.

This will ensure that there is as little overlap as possible. The top left of the returned region is guaranteed to be within the container.

┌──────────────────┐         ┌──────────────────┐
│    container     │         │    container     │
│                  │         │    ┌─────────────┤
│                  │   ──▶   │    │    return   │
│       ┌──────────┴──┐      │    │             │
│       │    self     │      │    │             │
└───────┤             │      └────┴─────────────┘
        │             │
        └─────────────┘
Parameters
Name Type Description Default
container Region

A container region.

required
x_axis bool

Allow translation of X axis.

True
y_axis bool

Allow translation of Y axis.

True
Returns
Type Description
Region

A new region with same dimensions that fits with inside container.

union cached

def union(self, region):

Get the smallest region that contains both regions.

Parameters
Name Type Description Default
region Region

Another region.

required
Returns
Type Description
Region

An optimally sized region to cover both regions.

Size class

Bases: NamedTuple

The dimensions (width and height) of a rectangular region.

Example
>>> from textual.geometry import Size
>>> size = Size(2, 3)
>>> size
Size(width=2, height=3)
>>> size.area
6
>>> size + Size(10, 20)
Size(width=12, height=23)

area property

area: int

The area occupied by a region of this size.

height class-attribute instance-attribute

height: int = 0

The height in cells.

line_range property

line_range: range

A range object that covers values between 0 and height.

region property

region: Region

A region of the same size, at the origin.

width class-attribute instance-attribute

width: int = 0

The width in cells.

contains method

def contains(self, x, y):

Check if a point is in area defined by the size.

Parameters
Name Type Description Default
x int

X coordinate.

required
y int

Y coordinate.

required
Returns
Type Description
bool

True if the point is within the region.

contains_point method

def contains_point(self, point):

Check if a point is in the area defined by the size.

Parameters
Name Type Description Default
point tuple[int, int]

A tuple of x and y coordinates.

required
Returns
Type Description
bool

True if the point is within the region.

Spacing class

Bases: NamedTuple

The spacing around a renderable, such as padding and border.

Spacing is defined by four integers for the space at the top, right, bottom, and left of a region.

┌ ─ ─ ─ ─ ─ ─ ─▲─ ─ ─ ─ ─ ─ ─ ─ ┐
               │ top
│        ┏━━━━━▼━━━━━━┓         │
 ◀──────▶┃            ┃◀───────▶
│  left  ┃            ┃ right   │
         ┃            ┃
│        ┗━━━━━▲━━━━━━┛         │
               │ bottom
└ ─ ─ ─ ─ ─ ─ ─▼─ ─ ─ ─ ─ ─ ─ ─ ┘
Example
>>> from textual.geometry import Region, Spacing
>>> region = Region(2, 3, 20, 10)
>>> spacing = Spacing(1, 2, 3, 4)
>>> region.grow(spacing)
Region(x=-2, y=2, width=26, height=14)
>>> region.shrink(spacing)
Region(x=6, y=4, width=14, height=6)
>>> spacing.css
'1 2 3 4'

bottom class-attribute instance-attribute

bottom: int = 0

Space from the bottom of a region.

bottom_right property

bottom_right: tuple[int, int]

A pair of integers for the right, and bottom space.

css property

css: str

A string containing the spacing in CSS format.

For example: "1" or "2 4" or "4 2 8 2".

height property

height: int

Total space in the y axis.

left class-attribute instance-attribute

left: int = 0

Space from the left of a region.

right class-attribute instance-attribute

right: int = 0

Space from the right of a region.

top class-attribute instance-attribute

top: int = 0

Space from the top of a region.

top_left property

top_left: tuple[int, int]

A pair of integers for the left, and top space.

totals property

totals: tuple[int, int]

A pair of integers for the total horizontal and vertical space.

width property

width: int

Total space in the x axis.

all classmethod

def all(cls, amount):

Construct a Spacing with a given amount of spacing on all edges.

Parameters
Name Type Description Default
amount int

The magnitude of spacing to apply to all edges

required
Returns
Type Description
Spacing

Spacing(amount, amount, amount, amount)

grow_maximum method

def grow_maximum(self, other):

Grow spacing with a maximum.

Parameters
Name Type Description Default
other Spacing

Spacing object.

required
Returns
Type Description
Spacing

New spacing where the values are maximum of the two values.

horizontal classmethod

def horizontal(cls, amount):

Construct a Spacing with a given amount of spacing on horizontal edges, and no vertical spacing.

Parameters
Name Type Description Default
amount int

The magnitude of spacing to apply to horizontal edges

required
Returns
Type Description
Spacing

Spacing(0, amount, 0, amount)

unpack classmethod

def unpack(cls, pad):

Unpack padding specified in CSS style.

Parameters
Name Type Description Default
pad SpacingDimensions

An integer, or tuple of 1, 2, or 4 integers.

required
Raises
Type Description
ValueError

If pad is an invalid value.

Returns
Type Description
Spacing

New Spacing object.

vertical classmethod

def vertical(cls, amount):

Construct a Spacing with a given amount of spacing on vertical edges, and no horizontal spacing.

Parameters
Name Type Description Default
amount int

The magnitude of spacing to apply to vertical edges

required
Returns
Type Description
Spacing

Spacing(amount, 0, amount, 0)

clamp function

def clamp(value, minimum, maximum):

Adjust a value so it is not less than a minimum and not greater than a maximum value.

Parameters
Name Type Description Default
value T

A value.

required
minimum T

Minimum value.

required
maximum T

Maximum value.

required
Returns
Type Description
T

New value that is not less than the minimum or greater than the maximum.