
    AHj              	      "   U d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	m
Z
mZmZmZmZmZmZmZmZ ddlmZ e
rddlmZ eeee   eeef   eeeeef   f   Zd	ed
<   	  edee      ZddZ G d de      Z G d de      Z G d de      Z G d de      Ze
s,ej@                  jC                  dd      dk(  r	 ddl"mZmZmZmZ  edd      Z$ded<   	  edddd      Z%ded<   	  edd      Z&ded<   	  edddd      Z'ded<   y# e#$ r Y Gw xY w)zd

Functions and classes to manage terminal geometry (anything involving coordinates or dimensions).
    )annotationsN)	lru_cache)
attrgetter
itemgetter)	TYPE_CHECKINGAny
CollectionLiteral
NamedTupleTupleTypeVarUnioncast)Final)	TypeAliasr   SpacingDimensionsTc                L    ||kD  r| |k  r|S | |kD  r|S | S | |k  r|S | |kD  r|S | S )a  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.

    Args:
        value: A value.
        minimum: Minimum value.
        maximum: Maximum value.

    Returns:
        New value that is not less than the minimum or greater than the maximum.
     )valueminimummaximums      H/root/tools/cai/cai_env/lib/python3.12/site-packages/textual/geometry.pyclampr   %   sH    "  7?N7?N7?N7?N    c                      e Zd ZU dZdZded<   	 dZded<   	 edd       Zedd       Z	edd       Z
dd	Zdd
ZddZddZddZddZddZddZy)Offsetar  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:
        ```python
        >>> 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)
        ```
    r   intxyc                    | dk(  S )zIs the offset at (0, 0)?r   r   r   selfs    r   	is_originzOffset.is_originb   s     v~r   c                H    | \  }}t        |dk  rdn||dk  rd      S |      S )z=This offset with `x` and `y` restricted to values above zero.r   r   r$   r   r    s      r   clampedzOffset.clampedg   s0     11q5aaa!e;;;;r   c                    | \  }}||fS )z2A tuple of x and y, in reverse order, i.e. (y, x).r   r(   s      r   	transposezOffset.transposem   s     1!tr   c                    | dk7  S )Nr"   r   r#   s    r   __bool__zOffset.__bool__s   s    v~r   c                f    t        |t              r| \  }}|\  }}t        ||z   ||z         S t        S N
isinstancetupler   NotImplementedr$   other_x_yr   r    s         r   __add__zOffset.__add__v   9    eU#FBDAq"q&"q&))r   c                f    t        |t              r| \  }}|\  }}t        ||z
  ||z
        S t        S r/   r0   r4   s         r   __sub__zOffset.__sub__}   r9   r   c                
   t        |t        t        f      r)| \  }}t        t        ||z        t        ||z              S t        |t              r/| \  }}t        t        ||d   z        t        ||d   z              S t
        S )Nr      )r1   floatr   r   r2   r3   )r$   r5   r   r    s       r   __mul__zOffset.__mul__   sv    eeS\*DAq#a%i.#a%i.99eU#DAq#a%(l+SU1X->??r   c                (    | \  }}t        | |       S r/   r'   r(   s      r   __neg__zOffset.__neg__   s    1qb1"~r   c                v    | \  }}|\  }}t        t        |||z
  |z  z         t        |||z
  |z  z               S )a!  Calculate a new offset on a line between this offset and a destination offset.

        Args:
            destination: Point where factor would be 1.0.
            factor: A value between 0 and 1.0.

        Returns:
            A new point on a line between self and destination.
        )r   r   )r$   destinationfactorx1y1x2y2s          r   blendzOffset.blend   sO     BBb2g''(b2g''(
 	
r   c                N    | \  }}|\  }}||z
  ||z
  z  ||z
  ||z
  z  z   dz  }|S )zGet the distance to another offset.

        Args:
            other: An offset.

        Returns:
            Distance to other offset.
        g      ?r   )r$   r5   rE   rF   rG   rH   distances          r   get_distance_tozOffset.get_distance_to   sD     BBGR0BGR3HHSPr   c           	     \    | \  }}t        t        |d|dz
        t        |d|dz
              S )zClamp the offset to fit within a rectangle of width x height.

        Args:
            width: Width to clamp.
            height: Height to clamp.

        Returns:
            A new offset.
        r   r=   )r   r   )r$   widthheightr   r    s        r   r   zOffset.clamp   s4     1eAq%!),eAq&1*.EFFr   NreturnboolrQ   r   rQ   tuple[int, int])r5   objectrQ   r   )rC   r   rD   r>   rQ   r   )r5   r   rQ   r>   )rN   r   rO   r   rQ   r   )__name__
__module____qualname____doc__r   __annotations__r    propertyr%   r)   r+   r-   r8   r;   r?   rA   rI   rL   r   r   r   r   r   r   F   s    , AsJ+AsJ)  < <
  

"Gr   r   c                      e Zd ZU dZdZded<   	 dZded<   	 ddZedd       Z	edd       Z
edd	       Zdd
ZddZddZddZddZddZddZddZy)SizeaJ  The dimensions (width and height) of a rectangular region.

    Example:
        ```python
        >>> 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)
        ```
    r   r   rN   rO   c                :    | j                   | j                  z  dk7  S )z!A Size is Falsy if it has area 0.r   rN   rO   r#   s    r   r-   zSize.__bool__   s    zzDKK'1,,r   c                4    | j                   | j                  z  S )z+The area occupied by a region of this size.r`   r#   s    r   areaz	Size.area        zzDKK''r   c                (    | \  }}t        dd||      S )z)A region of the same size, at the origin.r   Region)r$   rN   rO   s      r   regionzSize.region   s     vaE6**r   c                ,    t        | j                        S )z9A range object that covers values between 0 and `height`.)rangerO   r#   s    r   
line_rangezSize.line_range   s     T[[!!r   c                .    t        || j                        S )zGet a new Size with just the width changed.

        Args:
            width: New width.

        Returns:
            New Size instance.
        )r^   rO   )r$   rN   s     r   
with_widthzSize.with_width   s     E4;;''r   c                .    t        | j                  |      S )zGet a new Size with just the height changed.

        Args:
            height: New height.

        Returns:
            New Size instance.
        )r^   rN   )r$   rO   s     r   with_heightzSize.with_height   s     DJJ''r   c                    t        |t              r0| \  }}|\  }}t        t        d||z         t        d||z               S t        S Nr   r1   r2   r^   maxr3   r$   r5   rN   rO   width2height2s         r   r8   zSize.__add__   H    eU# ME6#OFGAuv~.Av7G0HIIr   c                    t        |t              r0| \  }}|\  }}t        t        d||z
        t        d||z
              S t        S rp   rq   rs   s         r   r;   zSize.__sub__  rv   r   c                P    | \  }}||cxkD  xr dk\  nc xr ||cxkD  xr dk\  S c S )zCheck if a point is in area defined by the size.

        Args:
            x: X coordinate.
            y: Y coordinate.

        Returns:
            True if the point is within the region.
        r   r   r$   r   r    rN   rO   s        r   containszSize.contains  s-     vq~A~1&1//1/1r   c                Z    |\  }}| \  }}||cxkD  xr dk\  nc xr ||cxkD  xr dk\  S c S )zCheck if a point is in the area defined by the size.

        Args:
            point: A tuple of x and y coordinates.

        Returns:
            True if the point is within the region.
        r   r   )r$   pointr   r    rN   rO   s         r   contains_pointzSize.contains_point  s6     1vq~A~1&1//1/1r   c                    	 |\  }}| \  }}||cxkD  xr dk\  nc xr ||cxkD  xr dk\  S c S # t         $ r t        d      w xY w)Nz<Dimensions.__contains__ requires an iterable of two integersr   )	Exception	TypeError)r$   r5   r   r    rN   rO   s         r   __contains__zSize.__contains__&  s^    	 DAq
 vq~A~1&1//1/1  	N 	s	   . Ac                N    |j                  | j                  | j                        S )zClamp an offset to fit within the width x height.

        Args:
            offset: An offset.

        Returns:
            A new offset that will fit inside the dimensions defined in the Size.
        )r   rN   rO   )r$   offsets     r   clamp_offsetzSize.clamp_offset2  s     ||DJJ44r   NrP   rQ   r   rQ   rf   rQ   ri   )rN   r   rQ   r^   )rO   r   rQ   r^   )r5   rV   rQ   r^   r   r   r    r   rQ   rR   r|   rU   rQ   rR   r5   r   rQ   rR   )r   r   rQ   r   )rW   rX   rY   rZ   rN   r[   rO   r-   r\   rb   rg   rj   rl   rn   r8   r;   rz   r}   r   r   r   r   r   r^   r^      s     E3NFCO- ( ( + +
 " "	(	(22
2	5r   r^   c                     e Zd ZU dZdZded<   	 dZded<   	 dZded<   	 dZded<   	 e	d:d       Z
e	d;d	       Ze	d<d
       Ze	dd	 	 	 	 	 	 	 d=d       Zd>dZed?d       Zed?d       Zed@d       Zed@d       Zed@d       ZedAd       ZedBd       ZedAd       ZedAd       ZedAd       ZedAd       ZedCd       ZedDd       ZedEd       ZedEd       ZedFd       ZdGdZ dGd Z!dHd!Z"dId"Z#dJd#Z$dJd$Z% e&d%&      dKd'       Z'dLd(Z(dMd)Z) e&d%&      dKd*       Z* e&d%&      dId+       Z+ e&d,&      dNd-       Z,dOd.Z- e&d,&      dPd/       Z. e&d,&      dPd0       Z/ e&d,&      dQd1       Z0 e&d,&      dQd2       Z1 e&d%&      dRd3       Z2 e&d%&      dSd4       Z3 e&d%&      dSd5       Z4	 dT	 	 	 	 	 	 	 dUd6Z5	 dV	 	 	 	 	 	 	 dWd8Z6	 	 	 	 	 	 	 	 	 	 dXd9Z7y7)Yrf   u  Defines a rectangular region.

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

    ```
      (x, y)
        ┌────────────────────┐ ▲
        │                    │ │
        │                    │ │
        │                    │ height
        │                    │ │
        │                    │ │
        └────────────────────┘ ▼
        ◀─────── width ──────▶
    ```

    Example:
        ```python
        >>> 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
        ```
    r   r   r   r    rN   rO   c                >   |st        d      t        |t        d            j                  }t	        |t        d            j                  }t        |t        d            j                  }t	        |t        d            j                  } | ||||z
  ||z
        S )zCreate a Region from the union of other regions.

        Args:
            regions: One or more regions.

        Returns:
            A Region that encloses all other regions.
        zAt least one region expectedr   keyrightr=   bottom)	
ValueErrorminr   r   rr   r   r   r    r   )clsregionsmin_xmax_xmin_ymax_ys         r   
from_unionzRegion.from_unionk  s     ;<<GA/11GG!45;;GA/11GH!56==5%>>r   c                $     | ||||z
  ||z
        S )zConstruct a Region form the top left and bottom right corners.

        Args:
            x1: Top left x.
            y1: Top left y.
            x2: Bottom right x.
            y2: Bottom right y.

        Returns:
            A new region.
        r   )r   rE   rF   rG   rH   s        r   from_cornerszRegion.from_corners}  s     2r27BG,,r   c                ,    |\  }}|\  }} | ||||      S )zCreate a region from offset and size.

        Args:
            offset: Offset (top left point).
            size: Dimensions of region.

        Returns:
            A region instance.
        r   )r   r   sizer   r    rN   rO   s          r   from_offsetzRegion.from_offset  s'     1v1a''r   F)topc                  ||v r|st         S |j                  \  }}}}|j                  |j                        }|j                  \  }}	}
}dx}}||cxkD  r|k\  rn n||
cxkD  r|k\  s'n t	        ||z
  |||j
                  z
  z
  t              }|r|	|z
  }n@||	cxkD  r|k\  rn n||cxkD  r|k\  s'n t	        |	|z
  |	||j                  z
  z
  t              }t        ||      S )a  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.

        Args:
            window_region: The window region.
            region: The region to move inside the window.
            top: Get offset to top of window.

        Returns:
            An offset required to add to region to move it inside window_region.
        r   r   )	NULL_OFFSETcorners	crop_sizer   r   rN   absrO   r   )r   window_regionrg   r   window_left
window_topwindow_rightwindow_bottomlefttop_r   r   delta_xdelta_ys                 r   get_scroll_to_visiblezRegion.get_scroll_to_visible  s    $ ]"3?L?T?T<Z}!!-"4"45$*NN!dE6' D/K/44 {"v||34G Z'G T/Z/5:5 z!56G
 gw''r   c                     | \  }}}}||z  dkD  S )z1A Region is considered False when it has no area.r   r   r$   _rN   rO   s       r   r-   zRegion.__bool__  s    "1eVv~!!r   c                L    | j                   | j                   | j                  z   fS )zA pair of integers for the start and end columns (x coordinates) in this region.

        The end value is *exclusive*.
        r   rN   r#   s    r   column_spanzRegion.column_span  s      +,,r   c                L    | j                   | j                   | j                  z   fS )z~A pair of integers for the start and end lines (y coordinates) in this region.

        The end value is *exclusive*.
        r    rO   r#   s    r   	line_spanzRegion.line_span  s      ,--r   c                4    | j                   | j                  z   S )z Maximum X value (non inclusive).r   r#   s    r   r   zRegion.right  s     vv

""r   c                4    | j                   | j                  z   S )z Maximum Y value (non inclusive).r   r#   s    r   r   zRegion.bottom  s     vv##r   c                4    | j                   | j                  z  S )zThe area under the region.r`   r#   s    r   rb   zRegion.area  rc   r   c                    t        | dd  S )zTThe top left corner of the region.

        Returns:
            An offset.
        N   r'   r#   s    r   r   zRegion.offset  s     tBQx  r   c                0    | \  }}}}||dz  z   ||dz  z   fS )zThe center of the region.

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

        Returns:
            Tuple of floats.
        g       @r   ry   s        r   centerzRegion.center  s.     #1eVECKVc\!122r   c                .    | \  }}}}t        |||z         S )zSBottom left offset of the region.

        Returns:
            An offset.
        r'   )r$   r   r    _widthrO   s        r   bottom_leftzRegion.bottom_left
  s#      $1ffaV$$r   c                .    | \  }}}}t        ||z   |      S )zQTop right offset of the region.

        Returns:
            An offset.
        r'   )r$   r   r    rN   _heights        r   	top_rightzRegion.top_right  s#      $1eWa%i##r   c                4    | \  }}}}t        ||z   ||z         S )zTBottom right offset of the region.

        Returns:
            An offset.
        r'   ry   s        r   bottom_rightzRegion.bottom_right  s'     #1eVa%iV,,r   c                @    | \  }}}}t        ||z   dz
  ||z   dz
        S )z9Bottom right corner of the region, within its boundaries.r=   r'   ry   s        r   bottom_right_inclusivezRegion.bottom_right_inclusive(  s/     #1eVa%i!mQZ!^44r   c                    t        | dd  S )zGet the size of the region.r   N)r^   r#   s    r   r   zRegion.size.  s     T!"Xr   c                (    | \  }}}}||||z   ||z   fS )zFThe top left and bottom right coordinates as a tuple of four integers.r   ry   s        r   r   zRegion.corners3  s)     #1eV!QYF
**r   c                \    t        | j                  | j                  | j                  z         S )z!A range object for X coordinates.)ri   r   rN   r#   s    r   column_rangezRegion.column_range9  s"     TVVTVVdjj011r   c                \    t        | j                  | j                  | j                  z         S )z!A range object for Y coordinates.)ri   r    rO   r#   s    r   rj   zRegion.line_range>  s"     TVVTVVdkk122r   c                ,    | \  }}}}t        dd||      S )zdAn region of the same size at (0, 0).

        Returns:
            A region at the origin.
        r   re   r   s       r   reset_offsetzRegion.reset_offsetC  s#     #1eVaE6**r   c                n    t        |t              r |\  }}| \  }}}}t        ||z   ||z   ||      S t        S r/   r1   r2   rf   r3   r$   r5   oxoyr   r    rN   rO   s           r   r8   zRegion.__add__M  B    eU#FB"&Aq%!b&!b&%88r   c                n    t        |t              r |\  }}| \  }}}}t        ||z
  ||z
  ||      S t        S r/   r   r   s           r   r;   zRegion.__sub__T  r   r   c                    t        |j                  | j                  z
  | j                  |j                  z
  | j                  |j                  z
  |j                  | j                  z
        S )zGet spacing between two regions.

        Args:
            region: Another region.

        Returns:
            Spacing that if subtracted from `self` produces `region`.
        )Spacingr    r   r   r   )r$   rg   s     r   get_spacing_betweenzRegion.get_spacing_between[  sQ     HHtvvJJ%KK&--'HHtvv	
 	
r   c                6    |\  }}| \  }}}}t        ||||      S )zGet a new Region with the same size at a given offset.

        Args:
            offset: An offset.

        Returns:
            New Region with adjusted offset.
        re   )r$   r   r   r    r6   r7   rN   rO   s           r   	at_offsetzRegion.at_offsetk  s,     1 $BvaE6**r   c           	     ^    | \  }}}}|\  }}t        ||t        ||      t        ||            S )zGet a region with the same offset, with a size no larger than `size`.

        Args:
            size: Maximum width and height (WIDTH, HEIGHT).

        Returns:
            New region that could fit within `size`.
        )rf   r   )r$   r   r   r    width1height1rt   ru   s           r   r   zRegion.crop_sizex  s:     !%1fgaC/Wg1FGGr   c                Z    |\  }}| \  }}}}t        ||z
  ||z
  ||dz  z   ||dz  z         S )zIncrease the size of the region by adding a border.

        Args:
            size: Additional width and height.

        Returns:
            A new region.
        r   re   )r$   r   expand_widthexpand_heightr   r    rN   rO   s           r   expandzRegion.expand  sS     '+#m"1eVL1$$]Q&&	
 	
r   i   )maxsizec                
   | j                   \  }}}}|j                   \  }}}}	||cxkD  xr |k\  nc xs ||cxkD  xr |kD  nc xs ||k  xr ||k\  xr0 ||cxkD  xr |k\  nc xs ||	cxkD  xr |kD  nc xs ||k  xr |	|k\  S )zCheck if another region overlaps this region.

        Args:
            other: A Region.

        Returns:
            True if other region shares any cells with this region.
        r   )
r$   r5   r   r    rG   rH   r   r   ox2oy2s
             r   overlapszRegion.overlaps  s     ||1b" ==BSbAJ2<a<JR!V5Ir	 
"\\FrC|!|Fa1EC2I	
r   c                `    | \  }}}}||z   |cxkD  xr |k\  nc xr ||z   |cxkD  xr |k\  S c S )zCheck if a point is in the region.

        Args:
            x: X coordinate.
            y: Y coordinate.

        Returns:
            True if the point is within the region.
        r   )r$   r   r    self_xself_yrN   rO   s          r   rz   zRegion.contains  s?     )-%v,f,Q6F?Q3P&3PQ3PQr   c                    | j                   \  }}}}	 |\  }}||cxkD  xr |k\  nc xr ||cxkD  xr |k\  S c S # t        $ r t        d|      w xY w)zCheck if a point is in the region.

        Args:
            point: A tuple of x and y coordinates.

        Returns:
            True if the point is within the region.
        z)a tuple of two integers is required, not )r   r   r   )r$   r|   rE   rF   rG   rH   r   r   s           r   r}   zRegion.contains_point  sl     BB	SFB R22BMrM2M2  	SGyQRR	Ss	   : Ac                    | j                   \  }}}}|j                   \  }}}}	||cxk\  xr |k\  nc xr4 ||cxk\  xr |k\  nc xr" ||cxk\  xr |k\  nc xr ||	cxk\  xr |k\  S c S )zCheck if a region is entirely contained within this region.

        Args:
            other: A region.

        Returns:
            True if the other region fits perfectly within this region.
        r   )
r$   r5   rE   rF   rG   rH   r   r   r   r   s
             r   contains_regionzRegion.contains_region  ss     BB ==BS2^^ "rR"sb" sb		
 !		
r   c                B    | \  }}}}|\  }}t        ||z   ||z   ||      S )zMove the offset of the Region.

        Args:
            offset: Offset to add to region.

        Returns:
            A new region shifted by (x, y).
        re   )r$   r   r   r   rN   rO   offset_xoffset_ys           r   	translatezRegion.translate  s7     )-%v#(fx'():E6JJr   i   c                    t        |t              r| j                  |      S 	 | j                  |      S # t        $ r Y yw xY w)z#Check if a point is in this region.F)r1   rf   r   r}   r   )r$   r5   s     r   r   zRegion.__contains__  sG     eV$''..**511 s   4 	A A c           
         | j                   \  }}}}t        }t        j                   ||d|       ||d|       ||d|       ||d|            }|S )zClip this region to fit within width, height.

        Args:
            width: Width of bounds.
            height: Height of bounds.

        Returns:
            Clipped region.
        r   )r   r   rf   r   )	r$   rN   rO   rE   rF   rG   rH   _clamp
new_regions	            r   clipzRegion.clip  sb     BB((2q% 2q&!2q% 2q&!	

 r   c           
         t        |      s| S |\  }}}}| \  }}}}	t        ||z
  ||z
  t        d||z   |z         t        d|	|z   |z               S )zGrow a region by adding spacing.

        Args:
            margin: Grow space by `(<top>, <right>, <bottom>, <left>)`.

        Returns:
            New region.
        r   r   r    rN   rO   anyrf   rr   
r$   marginr   r   r   r   r   r    rN   rO   s
             r   growzRegion.grow  sm     6{K#) UFD"1eV$h#ga-.q&3,/0	
 	
r   c                    t        |      s| S |\  }}}}| \  }}}}	t        ||z   ||z   t        d|||z   z
        t        d|	||z   z
              S )zShrink a region by subtracting spacing.

        Args:
            margin: Shrink space by `(<top>, <right>, <bottom>, <left>)`.

        Returns:
            The new, smaller region.
        r   r   r   r   s
             r   shrinkzRegion.shrink  sm     6{K#) UFD"1eV$h#ga$,/0q&C&L12	
 	
r   c                    | \  }}}}|\  }}}}	||z   }
||z   }||z   }||	z   }||kD  r|n||k  r|n|}||kD  r|n||k  r|n|}|
|kD  r|n|
|k  r|n|
}||kD  r|n||k  r|n|}t        ||||z
  ||z
        S )zGet the overlapping portion of the two regions.

        Args:
            region: A region that overlaps this region.

        Returns:
            A new region that covers when the two regions overlap.
        re   )r$   rg   rE   rF   w1h1cx1cy1w2h2rG   rH   cx2cy2rx1ry1rx2ry2s                     r   intersectionzRegion.intersection1  s     BB!S"b"W"WBhBh#Xc28C#Xc28C#Xc28C#Xc28Cc3c	3955r   c           	         | j                   \  }}}}|j                   \  }}}}	| j                  t        ||      t        ||      t        ||      t        ||	            }
|
S )zGet the smallest region that contains both regions.

        Args:
            region: Another region.

        Returns:
            An optimally sized region to cover both regions.
        )r   r   r   rr   )r$   rg   rE   rF   rG   rH   ox1oy1r   r   union_regions              r   unionzRegion.unionJ  s`     BB#^^S#s((CL#b#,Bc"cl
 r   c           
         | \  }}}}|dk  r||z   }|dk  r||z   }t         } |||||       |||z   |||z
  |       ||||z   |||z
         |||z   ||z   ||z
  ||z
        fS )u  Split a region into 4 from given x and y offsets (cuts).

        ```
                   cut_x ↓
                ┌────────┐ ┌───┐
                │        │ │   │
                │    0   │ │ 1 │
                │        │ │   │
        cut_y → └────────┘ └───┘
                ┌────────┐ ┌───┐
                │    2   │ │ 3 │
                └────────┘ └───┘
        ```

        Args:
            cut_x: Offset from self.x where the cut should be made. If negative, the cut
                is taken from the right edge.
            cut_y: Offset from self.y where the cut should be made. If negative, the cut
                is taken from the lower edge.

        Returns:
            Four new regions which add up to the original (self).
        r   re   )r$   cut_xcut_yr   r    rN   rO   _Regions           r   splitzRegion.split\  s    4 #1eV19EME19UNEAq%'AIq%%-7Aq5y%%8AIq5y%%-%H	
 	
r   c                h    | \  }}}}|dk  r||z   }t        ||||      t        ||z   |||z
  |      fS )u  Split a region into two, from a given x offset.

        ```
                 cut ↓
            ┌────────┐┌───┐
            │    0   ││ 1 │
            │        ││   │
            └────────┘└───┘
        ```

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

        Returns:
            Two regions, which add up to the original (self).
        r   re   r$   cutr   r    rN   rO   s         r   split_verticalzRegion.split_vertical  sR    ( #1eV7#+C 1af%1s7Aus{F3
 	
r   c                h    | \  }}}}|dk  r||z   }t        ||||      t        |||z   |||z
        fS )u  Split a region into two, from a given y offset.

        ```
                    ┌─────────┐
                    │    0    │
                    │         │
            cut →   └─────────┘
                    ┌─────────┐
                    │    1    │
                    └─────────┘
        ```

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

        Returns:
            Two regions, which add up to the original (self).
        r   re   r  s         r   split_horizontalzRegion.split_horizontal  sR    * #1eV73,C 1a$1a#gufsl3
 	
r   c           
         |\  }}}}| \  }}	}
}t        |rt        t        |||z   |
z
        |      n||r"t        t        |	||z   |z
        |      |
|      S |	|
|      S )u  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     │      │    │             │
        └───────┤             │      └────┴─────────────┘
                │             │
                └─────────────┘
        ```


        Args:
            container: A container region.
            x_axis: Allow translation of X axis.
            y_axis: Allow translation of Y axis.

        Returns:
            A new region with same dimensions that fits with inside container.
        )rf   rr   r   )r$   	containerx_axisy_axisrE   rF   r   r   rG   rH   rt   ru   s               r   translate_insidezRegion.translate_inside  s    : #,B"&B6<CBVf,-r2"8>CBWw./4	
 	
DF	
 	
r   Nc                    |t         n|}| \  }}}}|r|||j                  z   |z  z  }|r|||j                  z   |z  z  }t        ||||      S )u  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  │
                        │          │
                        └──────────┘
        ```

        Args:
            x_axis: +1 to inflect in the positive direction, -1 to inflect in the negative direction.
            y_axis: +1 to inflect in the positive direction, -1 to inflect in the negative direction.
            margin: Additional margin.

        Returns:
            A new region.
        )NULL_SPACING	max_width
max_heightrf   )	r$   r!  r"  r   inflect_marginr   r    rN   rO   s	            r   inflectzRegion.inflect  si    H *0V"1eV%.222f<<A&>444>>AaE6**r   c           	        | j                  |      }| }	 	 	 	 	 	 	 	 	 	 dd}|dk(  s|dk(  r|j                  |dk(  r4 ||j                  |j                  |j                  |j                         nd|dk(  r4 ||j                  |j
                  |j                  |j
                         nd|      }|j                  |j                  |      |dk7  |dk7        }|S )a  Constrain a region to fit within a container, using different methods per axis.

        Args:
            constrain_x: Constrain method for the X-axis.
            constrain_y: Constrain method for the Y-axis.
            margin: Margin to maintain around region.
            container: Container to constrain to.

        Returns:
            New widget, that fits inside the container (if possible).
        c                &    | |k\  r||k  ry| |k  ryy)as  Compare a span with a container

            Args:
                span_start: Start of the span.
                span_end: end of the span.
                container_start: Start of the container.
                container_end: End of the container.

            Returns:
                0 if the span fits, -1 if it is less that the container, otherwise +1
            r   r=   r   )
span_startspan_endcontainer_startcontainer_ends       r   compare_spanz&Region.constrain.<locals>.compare_span&  s$     _,]1JO+r   r)  r   none)
r-  r   r.  r   r/  r   r0  r   rQ   r   )r   r)  r   r   r    r   r#  r   )r$   constrain_xconstrain_yr   r   margin_regionrg   r1  s           r   	constrainzRegion.constrain  s   $ 		&)		'*	=@	QT		* )#{i'?^^ #i/ "%%++!!	   #i/ "%%,,!!((	  +F6 ((V$6!6!
 r   )r   zCollection[Region]rQ   rf   )
rE   r   rF   r   rG   r   rH   r   rQ   rf   )r   rU   r   rU   rQ   rf   )r   rf   rg   rf   r   rR   rQ   r   rP   rT   r   rS   )rQ   ztuple[float, float])rQ   r^   )rQ   tuple[int, int, int, int]r   r   )r5   rV   rQ   rf   )rg   rf   rQ   r   )r   rU   rQ   rf   )r   rU   rQ   rf   )r5   rf   rQ   rR   r   r   r   )rN   r   rO   r   rQ   rf   )r   r7  rQ   rf   )rg   rf   rQ   rf   )r  r   r  r   rQ   z%tuple[Region, Region, Region, Region])r  r   rQ   ztuple[Region, Region])TT)r   rf   r!  rR   r"  rR   rQ   rf   )r=   r=   N)r!  r   r"  r   r   zSpacing | NonerQ   rf   )
r3  $Literal['none', 'inside', 'inflect']r4  r8  r   r   r   rf   rQ   rf   )8rW   rX   rY   rZ   r   r[   r    rN   rO   classmethodr   r   r   r   r-   r\   r   r   r   r   rb   r   r   r   r   r   r   r   r   r   rj   r   r8   r;   r   r   r   r   r   r   rz   r}   r   r   r   r   r   r   r  r  r  r  r  r#  r)  r6  r   r   r   rf   rf   >  s   !F AsJ,AsJ*E3N"FCO#? ?" - - ( ( CH3("3(,23(<@3(	3( 3(j"
 - - . . # # $ $ ( ( ! ! 	3 	3 % % $ $ - - 5 5
   + +
 2 2 3 3 + +
 +H
$ t
 
 R3  t
 
$ tK K t * t
 
( t
 
( t6 60 t " t%
 %
N t
 
8 t
 
< FJ$
$
)-$
>B$
	$
N LP*+*+(+*+:H*+	*+XL9L :L 	L
 L 
Lr   rf   c                  J   e Zd ZU dZdZded<   	 dZded<   	 dZded<   	 dZded<   	 ddZ	e
dd	       Ze
dd
       Ze
dd       Ze
dd       Ze
dd       Ze
dd       Ze
dd       Ze
dd       Zedd       Zedd       Zedd       Zedd       ZddZddZd dZy)!r   u.  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:
        ```python
        >>> 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'
        ```
    r   r   r   r   r   r   c                    | dk7  S )N)r   r   r   r   r   r#   s    r   r-   zSpacing.__bool__  s    |##r   c                4    | j                   | j                  z   S )zTotal space in the x axis.)r   r   r#   s    r   rN   zSpacing.width  s     yy4::%%r   c                4    | j                   | j                  z   S )zTotal space in the y axis.)r   r   r#   s    r   rO   zSpacing.height  s     xx$++%%r   c                "    | \  }}}}||kD  r|S |S )zcThe space between regions in the X direction if margins overlap, i.e. `max(self.left, self.right)`.r   )r$   _topr   _bottomr   s        r   r&  zSpacing.max_width  s#     &*"eWde|t..r   c                "    | \  }}}}||kD  r|S |S )zcThe space between regions in the Y direction if margins overlap, i.e. `max(self.top, self.bottom)`.r   )r$   r   _rightr   _lefts        r   r'  zSpacing.max_height  s#     &*"VVUFls..r   c                2    | j                   | j                  fS )z/A pair of integers for the left, and top space.)r   r   r#   s    r   top_leftzSpacing.top_left  s     		488$$r   c                2    | j                   | j                  fS )z3A pair of integers for the right, and bottom space.)r   r   r#   s    r   r   zSpacing.bottom_right  s     

DKK((r   c                $    | \  }}}}||z   ||z   fS )z?A pair of integers for the total horizontal and vertical space.r   r$   r   r   r   r   s        r   totalszSpacing.totals  s%     $( UFDucFl++r   c                t    | \  }}}}||cxk(  r|cxk(  r|k(  r| S  ||f||fk(  r| d| S | d| d| d| S )zhA string containing the spacing in CSS format.

        For example: "1" or "2 4" or "4 2 8 2".
         r   rH  s        r   csszSpacing.css  sn     $( UFD%)6)T)UO *<FD>)U!E7##U!E7!F81TF33r   c                n   t        |t              r | ||||      S t        |      }|dk(  r|d   } | ||||      S |dk(  r+t        t        t        t        f   |      \  }} | ||||      S |dk(  r7t        t        t        t        t        t        f   |      \  }}}}	 | ||||	      S t        d| d      )zUnpack padding specified in CSS style.

        Args:
            pad: An integer, or tuple of 1, 2, or 4 integers.

        Raises:
            ValueError: If `pad` is an invalid value.

        Returns:
            New Spacing object.
        r=   r   r      z41, 2 or 4 integers required for spacing properties; z given)r1   r   lenr   r   r   )
r   padpad_len_padpad_top	pad_rightr   r   r   r   s
             r   unpackzSpacing.unpack  s     c3sCc**c(a<q6DtT4..a<!%eCHos!;GYw	7I>>a<'+E#sC2D,Es'K$CsE6400B7)6R
 	
r   c                    t        |d|d      S )a  Construct a Spacing with a given amount of spacing on vertical edges,
        and no horizontal spacing.

        Args:
            amount: The magnitude of spacing to apply to vertical edges.

        Returns:
            `Spacing(amount, 0, amount, 0)`
        r   r   r   amounts     r   verticalzSpacing.vertical  s     vq&!,,r   c                    t        d|d|      S )a	  Construct a Spacing with a given amount of spacing on horizontal edges,
        and no vertical spacing.

        Args:
            amount: The magnitude of spacing to apply to horizontal edges.

        Returns:
            `Spacing(0, amount, 0, amount)`
        r   rW  rX  s     r   
horizontalzSpacing.horizontal  s     q&!V,,r   c                    t        ||||      S )zConstruct a Spacing with a given amount of spacing on all edges.

        Args:
            amount: The magnitude of spacing to apply to all edges.

        Returns:
            `Spacing(amount, amount, amount, amount)`
        rW  rX  s     r   allzSpacing.all  s     vvvv66r   c                ~    t        |t              r(| \  }}}}|\  }}}}	t        ||z   ||z   ||z   ||	z         S t        S r/   r1   r2   r   r3   
r$   r5   top1right1bottom1left1top2right2bottom2left2s
             r   r8   zSpacing.__add__  W    eU#+/(D&'5+0(D&'5tVf_g.?  r   c                ~    t        |t              r(| \  }}}}|\  }}}}	t        ||z
  ||z
  ||z
  ||	z
        S t        S r/   r`  ra  s
             r   r;   zSpacing.__sub__  rj  r   c           	         | \  }}}}|\  }}}}	t        t        ||      t        ||      t        ||      t        ||	            S )zGrow spacing with a maximum.

        Args:
            other: Spacing object.

        Returns:
            New spacing where the values are maximum of the two values.
        )r   rr   )
r$   r5   r   r   r   r   	other_topother_rightother_bottom
other_lefts
             r   grow_maximumzSpacing.grow_maximum  sU     $( UFD;@8	;jY{#%j!	
 	
r   NrP   r   rT   )rQ   str)rP  r   rQ   r   )rY  r   rQ   r   )r5   rV   rQ   r   )r5   r   rQ   r   )rW   rX   rY   rZ   r   r[   r   r   r   r-   r\   rN   rO   r&  r'  rE  r   rI  rL  r9  rU  rZ  r\  r^  r8   r;   rq  r   r   r   r   r   `  s=   < CL)E3N+FCO,D#M*$ & & & & / /
 / /
 % % ) ) , ,
 4 4 
 
8 
- 
- 
- 
- 	7 	7
r   r   TEXTUAL_SPEEDUPS1)r   rf   r^   r   r   r   NULL_REGION	NULL_SIZEr%  )r   r   r   r   r   r   rQ   r   )(rZ   
__future__r   os	functoolsr   operatorr   r   typingr   r   r	   r
   r   r   r   r   r   typing_extensionsr   r   r   r   r[   r>   r   r   r   r^   rf   r   environgettextual_speedupsImportErrorr   ru  rv  r%  r   r   r   <module>r     sV  
 # 	  +
 
 
 $+  %sU38_eCc3,>&??  9  7CeBuGZ uGp}5: }5@_Z _DD
j D
N (:C@CGBB
 Aq\U ! ?Aq!Q'U ' }1:	5  PaAq)e ) B  s   :D DD