Skip to content

textual.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_SIZE module-attribute

NULL_SIZE: Final = Size(0, 0)

A Size constant for a null size (with zero area).

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

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)?

transpose property

transpose: tuple[int, int]

A tuple of x and y, in reverse order, i.e. (y, x).

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

blend(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.

clamp

clamp(width, height)

Clamp the offset to fit within a rectangle of width x height.

Parameters:

Name Type Description Default
width int

Width to clamp.

required
height int

Height to clamp.

required

Returns:

Type Description
Offset

A new offset.

get_distance_to

get_distance_to(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

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.

bottom_right_inclusive property

bottom_right_inclusive: Offset

Bottom right corner of the region, within its boundaries.

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

at_offset(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

clip(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.

constrain

constrain(constrain_x, constrain_y, margin, container)

Constrain a region to fit within a container, using different methods per axis.

Parameters:

Name Type Description Default
constrain_x Literal['none', 'inside', 'inflect']

Constrain method for the X-axis.

required
constrain_y Literal['none', 'inside', 'inflect']

Constrain method for the Y-axis.

required
margin Spacing

Margin to maintain around region.

required
container Region

Container to constrain to.

required

Returns:

Type Description
Region

New widget, that fits inside the container (if possible).

contains

contains(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

contains_point(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

contains_region(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

crop_size(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

expand(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

from_corners(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

from_offset(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

from_union(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

get_scroll_to_visible(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 into 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.

get_spacing_between

get_spacing_between(region)

Get spacing between two regions.

Parameters:

Name Type Description Default
region Region

Another region.

required

Returns:

Type Description
Spacing

Spacing that if subtracted from self produces region.

grow cached

grow(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

inflect(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.

If a margin is provided, it will add space between the resulting region.

Note that if margin is specified it overlaps, so the space will be the maximum of two edges, and not the total.

╔══════════╗    │
║          ║
║   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

intersection(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

overlaps(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

shrink(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

split(cut_x, cut_y)

Split a region into 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

split_horizontal(cut)

Split a region into 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

split_vertical(cut)

Split a region into 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

translate(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

translate_inside(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

union(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

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.

clamp_offset

clamp_offset(offset)

Clamp an offset to fit within the width x height.

Parameters:

Name Type Description Default
offset Offset

An offset.

required

Returns:

Type Description
Offset

A new offset that will fit inside the dimensions defined in the Size.

contains

contains(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

contains_point(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.

with_height

with_height(height)

Get a new Size with just the height changed.

Parameters:

Name Type Description Default
height int

New height.

required

Returns:

Type Description
Size

New Size instance.

with_width

with_width(width)

Get a new Size with just the width changed.

Parameters:

Name Type Description Default
width int

New width.

required

Returns:

Type Description
Size

New Size instance.

Spacing

Bases: NamedTuple

Stores spacing around a widget, 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.

max_height property

max_height: int

The space between regions in the Y direction if margins overlap, i.e. max(self.top, self.bottom).

max_width property

max_width: int

The space between regions in the X direction if margins overlap, i.e. max(self.left, self.right).

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

all(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

grow_maximum(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

horizontal(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

unpack(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

vertical(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

clamp(value, minimum, maximum)

Restrict a value to a given range.

If value is less than the minimum, return the minimum. If value is greater than the maximum, return the maximum. Otherwise, return value.

The minimum and maximum arguments values may be given in reverse order.

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.