Skip to content

Commit 5f89d81

Browse files
committed
move Extrema object
1 parent 3cc4440 commit 5f89d81

File tree

4 files changed

+79
-73
lines changed

4 files changed

+79
-73
lines changed

src/textual/_extrema.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from fractions import Fraction
2+
from typing import NamedTuple
3+
4+
5+
class Extrema(NamedTuple):
6+
"""Specifies minimum and maximum dimensions."""
7+
8+
min_width: Fraction | None = None
9+
max_width: Fraction | None = None
10+
min_height: Fraction | None = None
11+
max_height: Fraction | None = None
12+
13+
def apply_width(self, width: Fraction) -> Fraction:
14+
"""Apply width extrema.
15+
16+
Args:
17+
width: Width value.
18+
19+
Returns:
20+
Width, clamped between minimum and maximum.
21+
22+
"""
23+
min_width, max_width = self[:2]
24+
if min_width is not None:
25+
width = max(width, min_width)
26+
if max_width is not None:
27+
width = min(width, max_width)
28+
return width
29+
30+
def apply_height(self, height: Fraction) -> Fraction:
31+
"""Apply height extrema.
32+
33+
Args:
34+
height: Height value.
35+
36+
Returns:
37+
Height, clamped between minimum and maximum.
38+
39+
"""
40+
min_height, max_height = self[2:]
41+
if min_height is not None:
42+
height = max(height, min_height)
43+
if max_height is not None:
44+
height = min(height, max_height)
45+
return height

src/textual/geometry.py

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from __future__ import annotations
77

8-
from fractions import Fraction
98
from functools import lru_cache
109
from operator import attrgetter, itemgetter
1110
from typing import (
@@ -187,52 +186,6 @@ def clamp(self, width: int, height: int) -> Offset:
187186
return Offset(clamp(x, 0, width - 1), clamp(y, 0, height - 1))
188187

189188

190-
class Extrema(NamedTuple):
191-
"""Specifies minimum and maximum dimensions."""
192-
193-
min_width: int | None = None
194-
max_width: int | None = None
195-
min_height: int | None = None
196-
max_height: int | None = None
197-
198-
@property
199-
def fractions(
200-
self,
201-
) -> tuple[Fraction | None, Fraction | None, Fraction | None, Fraction | None]:
202-
min_width, max_width, min_height, max_height = self
203-
return (
204-
None if min_width is None else Fraction(min_width),
205-
None if max_width is None else Fraction(max_width),
206-
None if min_height is None else Fraction(min_height),
207-
None if max_height is None else Fraction(max_height),
208-
)
209-
210-
def apply_width(self, width: int) -> int:
211-
"""Apply width extrema."""
212-
min_width, max_width = self[:2]
213-
if min_width is not None:
214-
width = max(width, min_width)
215-
if max_width is not None:
216-
width = min(width, max_width)
217-
return width
218-
219-
def apply_height(self, height: int) -> int:
220-
"""Apply height extrema."""
221-
min_height, max_height = self[2:]
222-
if min_height is not None:
223-
height = max(height, min_height)
224-
if max_height is not None:
225-
height = min(height, max_height)
226-
return height
227-
228-
def apply(self, width: int, height: int) -> Size:
229-
"""Apply extrema to width and height."""
230-
return Size(
231-
self.apply_width(width),
232-
self.apply_height(height),
233-
)
234-
235-
236189
class Size(NamedTuple):
237190
"""The dimensions (width and height) of a rectangular region.
238191

src/textual/layout.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,11 @@ def get_content_height(
264264
):
265265
# An exception for containers with all dynamic height widgets
266266
arrangement = widget._arrange(
267-
Size(width, widget.extrema.apply_height(container.height))
267+
Size(width, widget._extrema.apply_height(container.height))
268268
)
269269
else:
270270
arrangement = widget._arrange(
271-
Size(width, widget.extrema.min_height or 0)
271+
Size(width, widget._extrema.min_height or 0)
272272
)
273273
height = arrangement.total_region.height
274274
else:

src/textual/widget.py

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
from textual._debug import get_caller_file_and_line
5555
from textual._dispatch_key import dispatch_key
5656
from textual._easing import DEFAULT_SCROLL_EASING
57+
from textual._extrema import Extrema
5758
from textual._styles_cache import StylesCache
5859
from textual._types import AnimationLevel
5960
from textual.actions import SkipAction
@@ -71,7 +72,6 @@
7172
NULL_REGION,
7273
NULL_SIZE,
7374
NULL_SPACING,
74-
Extrema,
7575
Offset,
7676
Region,
7777
Size,
@@ -505,7 +505,8 @@ def __init__(
505505
"""Time of last scroll."""
506506
self._user_scroll_interrupt: bool = False
507507
"""Has the user interrupted a scroll to end?"""
508-
self.extrema = Extrema()
508+
self._extrema = Extrema()
509+
"""Optional minimum and maximum values for width and height."""
509510

510511
@property
511512
def is_mounted(self) -> bool:
@@ -1530,10 +1531,10 @@ def _get_box_model(
15301531
# Container minus padding and border
15311532
content_container = container - gutter.totals
15321533

1533-
extrema = self.extrema = self._resolve_extrema(
1534+
extrema = self._extrema = self._resolve_extrema(
15341535
container, viewport, width_fraction, height_fraction
15351536
)
1536-
min_width, max_width, min_height, max_height = extrema.fractions
1537+
min_width, max_width, min_height, max_height = extrema
15371538

15381539
if styles.width is None:
15391540
# No width specified, fill available space
@@ -2192,47 +2193,54 @@ def _resolve_extrema(
21922193
width_fraction: Fraction,
21932194
height_fraction: Fraction,
21942195
) -> Extrema:
2196+
"""Resolve minimum and maximum values.
21952197
2196-
min_width: int | None = None
2197-
max_width: int | None = None
2198-
min_height: int | None = None
2199-
max_height: int | None = None
2198+
Args:
2199+
container: Size of outer widget.
2200+
viewport: Viewport size.
2201+
width_fraction: Size of 1fr width.
2202+
height_fraction: Size of 1fr height.
2203+
2204+
Returns:
2205+
Extrema object.
2206+
"""
2207+
2208+
min_width: Fraction | None = None
2209+
max_width: Fraction | None = None
2210+
min_height: Fraction | None = None
2211+
max_height: Fraction | None = None
22002212

22012213
styles = self.styles
22022214
margin = styles.margin
22032215
is_border_box = styles.box_sizing == "border-box"
22042216
gutter = styles.gutter
22052217

22062218
if styles.min_width is not None:
2207-
min_width = int(
2208-
styles.min_width.resolve(
2209-
container - margin.totals, viewport, width_fraction
2210-
)
2219+
min_width = styles.min_width.resolve(
2220+
container - margin.totals, viewport, width_fraction
22112221
)
2222+
22122223
if is_border_box:
22132224
min_width -= gutter.width
22142225
if styles.max_width is not None:
2215-
max_width = int(
2216-
styles.max_width.resolve(
2217-
container - margin.totals, viewport, width_fraction
2218-
)
2226+
max_width = styles.max_width.resolve(
2227+
container - margin.totals, viewport, width_fraction
22192228
)
2229+
22202230
if is_border_box:
22212231
max_width -= gutter.width
22222232
if styles.min_height is not None:
2223-
min_height = int(
2224-
styles.min_height.resolve(
2225-
container - margin.totals, viewport, height_fraction
2226-
)
2233+
min_height = styles.min_height.resolve(
2234+
container - margin.totals, viewport, height_fraction
22272235
)
2236+
22282237
if is_border_box:
22292238
min_height -= gutter.height
22302239
if styles.max_height is not None:
2231-
max_height = int(
2232-
styles.max_height.resolve(
2233-
container - margin.totals, viewport, height_fraction
2234-
)
2240+
max_height = styles.max_height.resolve(
2241+
container - margin.totals, viewport, height_fraction
22352242
)
2243+
22362244
if is_border_box:
22372245
max_height -= gutter.height
22382246

0 commit comments

Comments
 (0)