mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
96
sandbox/will/fr.py
Normal file
96
sandbox/will/fr.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.containers import Horizontal, Vertical
|
||||||
|
from textual.widgets import Static
|
||||||
|
|
||||||
|
|
||||||
|
class StaticText(Static):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Header(Static):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Footer(Static):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FrApp(App):
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
Screen {
|
||||||
|
layout: horizontal;
|
||||||
|
align: center middle;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertical {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Header {
|
||||||
|
background: $boost;
|
||||||
|
|
||||||
|
content-align: center middle;
|
||||||
|
text-align: center;
|
||||||
|
color: $text;
|
||||||
|
height: 3;
|
||||||
|
border: tall $warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
Horizontal {
|
||||||
|
height: 1fr;
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Footer {
|
||||||
|
background: $boost;
|
||||||
|
|
||||||
|
content-align: center middle;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
color: $text;
|
||||||
|
height: 6;
|
||||||
|
border: tall $warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticText {
|
||||||
|
background: $boost;
|
||||||
|
height: 8;
|
||||||
|
content-align: center middle;
|
||||||
|
text-align: center;
|
||||||
|
color: $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
#foo {
|
||||||
|
width: 10;
|
||||||
|
border: tall $primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bar {
|
||||||
|
width: 1fr;
|
||||||
|
border: tall $error;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#baz {
|
||||||
|
width: 20;
|
||||||
|
border: tall $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Vertical(
|
||||||
|
Header("HEADER"),
|
||||||
|
Horizontal(
|
||||||
|
StaticText("foo", id="foo"),
|
||||||
|
StaticText("bar", id="bar"),
|
||||||
|
StaticText("baz", id="baz"),
|
||||||
|
),
|
||||||
|
Footer("FOOTER"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = FrApp()
|
||||||
|
app.run()
|
||||||
@@ -60,10 +60,9 @@ def arrange(
|
|||||||
for dock_widget in dock_widgets:
|
for dock_widget in dock_widgets:
|
||||||
edge = dock_widget.styles.dock
|
edge = dock_widget.styles.dock
|
||||||
|
|
||||||
fraction_unit = Fraction(
|
box_model = dock_widget._get_box_model(
|
||||||
size.height if edge in ("top", "bottom") else size.width
|
size, viewport, Fraction(size.width), Fraction(size.height)
|
||||||
)
|
)
|
||||||
box_model = dock_widget._get_box_model(size, viewport, fraction_unit)
|
|
||||||
widget_width_fraction, widget_height_fraction, margin = box_model
|
widget_width_fraction, widget_height_fraction, margin = box_model
|
||||||
|
|
||||||
widget_width = int(widget_width_fraction) + margin.width
|
widget_width = int(widget_width_fraction) + margin.width
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sys
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from itertools import accumulate
|
from itertools import accumulate
|
||||||
from typing import cast, Sequence
|
from typing import cast, Sequence, TYPE_CHECKING
|
||||||
|
|
||||||
|
from .box_model import BoxModel
|
||||||
from .css.scalar import Scalar
|
from .css.scalar import Scalar
|
||||||
from .geometry import Size
|
from .geometry import Size
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .widget import Widget
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
from typing import Literal
|
||||||
|
else:
|
||||||
|
from typing_extensions import Literal
|
||||||
|
|
||||||
|
|
||||||
def resolve(
|
def resolve(
|
||||||
dimensions: Sequence[Scalar],
|
dimensions: Sequence[Scalar],
|
||||||
@@ -71,3 +82,79 @@ def resolve(
|
|||||||
]
|
]
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_box_models(
|
||||||
|
dimensions: list[Scalar | None],
|
||||||
|
widgets: list[Widget],
|
||||||
|
size: Size,
|
||||||
|
parent_size: Size,
|
||||||
|
dimension: Literal["width", "height"] = "width",
|
||||||
|
) -> list[BoxModel]:
|
||||||
|
"""Resolve box models for a list of dimensions
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dimensions (list[Scalar | None]): A list of Scalars or Nones for each dimension.
|
||||||
|
widgets (list[Widget]): Widgets in resolve.
|
||||||
|
size (Size): size of container.
|
||||||
|
parent_size (Size): Size of parent.
|
||||||
|
dimensions (Literal["width", "height"]): Which dimension to resolve.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[BoxModel]: List of resolved box models.
|
||||||
|
"""
|
||||||
|
|
||||||
|
fraction_width = Fraction(size.width)
|
||||||
|
fraction_height = Fraction(size.height)
|
||||||
|
box_models: list[BoxModel | None] = [
|
||||||
|
(
|
||||||
|
None
|
||||||
|
if dimension is not None and dimension.is_fraction
|
||||||
|
else widget._get_box_model(
|
||||||
|
size, parent_size, fraction_width, fraction_height
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for (dimension, widget) in zip(dimensions, widgets)
|
||||||
|
]
|
||||||
|
|
||||||
|
if dimension == "width":
|
||||||
|
total_remaining = sum(
|
||||||
|
box_model.width for box_model in box_models if box_model is not None
|
||||||
|
)
|
||||||
|
remaining_space = max(0, size.width - total_remaining)
|
||||||
|
else:
|
||||||
|
total_remaining = sum(
|
||||||
|
box_model.height for box_model in box_models if box_model is not None
|
||||||
|
)
|
||||||
|
remaining_space = max(0, size.height - total_remaining)
|
||||||
|
|
||||||
|
fraction_unit = Fraction(
|
||||||
|
remaining_space,
|
||||||
|
int(
|
||||||
|
sum(
|
||||||
|
dimension.value
|
||||||
|
for dimension in dimensions
|
||||||
|
if dimension and dimension.is_fraction
|
||||||
|
)
|
||||||
|
)
|
||||||
|
or 1,
|
||||||
|
)
|
||||||
|
if dimension == "width":
|
||||||
|
width_fraction = fraction_unit
|
||||||
|
height_fraction = Fraction(size.height)
|
||||||
|
else:
|
||||||
|
width_fraction = Fraction(size.width)
|
||||||
|
height_fraction = fraction_unit
|
||||||
|
|
||||||
|
box_models = [
|
||||||
|
box_model
|
||||||
|
or widget._get_box_model(
|
||||||
|
size,
|
||||||
|
parent_size,
|
||||||
|
width_fraction,
|
||||||
|
height_fraction,
|
||||||
|
)
|
||||||
|
for widget, box_model in zip(widgets, box_models)
|
||||||
|
]
|
||||||
|
|
||||||
|
return cast("list[BoxModel]", box_models)
|
||||||
|
|||||||
@@ -1271,7 +1271,12 @@ class App(Generic[ReturnType], DOMNode):
|
|||||||
self.set_timer(screenshot_timer, on_screenshot, name="screenshot timer")
|
self.set_timer(screenshot_timer, on_screenshot, name="screenshot timer")
|
||||||
|
|
||||||
async def _on_compose(self) -> None:
|
async def _on_compose(self) -> None:
|
||||||
widgets = list(self.compose())
|
try:
|
||||||
|
widgets = list(self.compose())
|
||||||
|
except TypeError as error:
|
||||||
|
raise TypeError(
|
||||||
|
f"{self!r} compose() returned an invalid response; {error}"
|
||||||
|
) from None
|
||||||
await self.mount_all(widgets)
|
await self.mount_all(widgets)
|
||||||
|
|
||||||
def _on_idle(self) -> None:
|
def _on_idle(self) -> None:
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ def get_box_model(
|
|||||||
styles: StylesBase,
|
styles: StylesBase,
|
||||||
container: Size,
|
container: Size,
|
||||||
viewport: Size,
|
viewport: Size,
|
||||||
fraction_unit: Fraction,
|
width_fraction: Fraction,
|
||||||
|
height_fraction: Fraction,
|
||||||
get_content_width: Callable[[Size, Size], int],
|
get_content_width: Callable[[Size, Size], int],
|
||||||
get_content_height: Callable[[Size, Size, int], int],
|
get_content_height: Callable[[Size, Size, int], int],
|
||||||
) -> BoxModel:
|
) -> BoxModel:
|
||||||
@@ -30,6 +31,8 @@ def get_box_model(
|
|||||||
styles (StylesBase): Styles object.
|
styles (StylesBase): Styles object.
|
||||||
container (Size): The size of the widget container.
|
container (Size): The size of the widget container.
|
||||||
viewport (Size): The viewport size.
|
viewport (Size): The viewport size.
|
||||||
|
width_fraction (Fraction): A fraction used for 1 `fr` unit on the width dimension.
|
||||||
|
height_fraction (Fraction):A fraction used for 1 `fr` unit on the height dimension.
|
||||||
get_auto_width (Callable): A callable which accepts container size and parent size and returns a width.
|
get_auto_width (Callable): A callable which accepts container size and parent size and returns a width.
|
||||||
get_auto_height (Callable): A callable which accepts container size and parent size and returns a height.
|
get_auto_height (Callable): A callable which accepts container size and parent size and returns a height.
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ def get_box_model(
|
|||||||
# An explicit width
|
# An explicit width
|
||||||
styles_width = styles.width
|
styles_width = styles.width
|
||||||
content_width = styles_width.resolve_dimension(
|
content_width = styles_width.resolve_dimension(
|
||||||
sizing_container - styles.margin.totals, viewport, fraction_unit
|
sizing_container - styles.margin.totals, viewport, width_fraction
|
||||||
)
|
)
|
||||||
if is_border_box and styles_width.excludes_border:
|
if is_border_box and styles_width.excludes_border:
|
||||||
content_width -= gutter.width
|
content_width -= gutter.width
|
||||||
@@ -71,14 +74,14 @@ def get_box_model(
|
|||||||
if styles.min_width is not None:
|
if styles.min_width is not None:
|
||||||
# Restrict to minimum width, if set
|
# Restrict to minimum width, if set
|
||||||
min_width = styles.min_width.resolve_dimension(
|
min_width = styles.min_width.resolve_dimension(
|
||||||
content_container, viewport, fraction_unit
|
content_container, viewport, width_fraction
|
||||||
)
|
)
|
||||||
content_width = max(content_width, min_width)
|
content_width = max(content_width, min_width)
|
||||||
|
|
||||||
if styles.max_width is not None:
|
if styles.max_width is not None:
|
||||||
# Restrict to maximum width, if set
|
# Restrict to maximum width, if set
|
||||||
max_width = styles.max_width.resolve_dimension(
|
max_width = styles.max_width.resolve_dimension(
|
||||||
content_container, viewport, fraction_unit
|
content_container, viewport, width_fraction
|
||||||
)
|
)
|
||||||
if is_border_box:
|
if is_border_box:
|
||||||
max_width -= gutter.width
|
max_width -= gutter.width
|
||||||
@@ -98,7 +101,7 @@ def get_box_model(
|
|||||||
styles_height = styles.height
|
styles_height = styles.height
|
||||||
# Explicit height set
|
# Explicit height set
|
||||||
content_height = styles_height.resolve_dimension(
|
content_height = styles_height.resolve_dimension(
|
||||||
sizing_container - styles.margin.totals, viewport, fraction_unit
|
sizing_container - styles.margin.totals, viewport, height_fraction
|
||||||
)
|
)
|
||||||
if is_border_box and styles_height.excludes_border:
|
if is_border_box and styles_height.excludes_border:
|
||||||
content_height -= gutter.height
|
content_height -= gutter.height
|
||||||
@@ -106,14 +109,14 @@ def get_box_model(
|
|||||||
if styles.min_height is not None:
|
if styles.min_height is not None:
|
||||||
# Restrict to minimum height, if set
|
# Restrict to minimum height, if set
|
||||||
min_height = styles.min_height.resolve_dimension(
|
min_height = styles.min_height.resolve_dimension(
|
||||||
content_container, viewport, fraction_unit
|
content_container, viewport, height_fraction
|
||||||
)
|
)
|
||||||
content_height = max(content_height, min_height)
|
content_height = max(content_height, min_height)
|
||||||
|
|
||||||
if styles.max_height is not None:
|
if styles.max_height is not None:
|
||||||
# Restrict maximum height, if set
|
# Restrict maximum height, if set
|
||||||
max_height = styles.max_height.resolve_dimension(
|
max_height = styles.max_height.resolve_dimension(
|
||||||
content_container, viewport, fraction_unit
|
content_container, viewport, height_fraction
|
||||||
)
|
)
|
||||||
content_height = min(content_height, max_height)
|
content_height = min(content_height, max_height)
|
||||||
|
|
||||||
|
|||||||
@@ -145,9 +145,7 @@ class GridLayout(Layout):
|
|||||||
y2, cell_height = rows[min(max_row, row + row_span)]
|
y2, cell_height = rows[min(max_row, row + row_span)]
|
||||||
cell_size = Size(cell_width + x2 - x, cell_height + y2 - y)
|
cell_size = Size(cell_width + x2 - x, cell_height + y2 - y)
|
||||||
width, height, margin = widget._get_box_model(
|
width, height, margin = widget._get_box_model(
|
||||||
cell_size,
|
cell_size, viewport, fraction_unit, fraction_unit
|
||||||
viewport,
|
|
||||||
fraction_unit,
|
|
||||||
)
|
)
|
||||||
region = (
|
region = (
|
||||||
Region(x, y, int(width + margin.width), int(height + margin.height))
|
Region(x, y, int(width + margin.width), int(height + margin.height))
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from typing import cast
|
|
||||||
|
|
||||||
from textual.geometry import Size, Region
|
from .._resolve import resolve_box_models
|
||||||
from textual._layout import ArrangeResult, Layout, WidgetPlacement
|
from ..geometry import Size, Region
|
||||||
|
from .._layout import ArrangeResult, Layout, WidgetPlacement
|
||||||
from textual.widget import Widget
|
from ..widget import Widget
|
||||||
|
|
||||||
|
|
||||||
class HorizontalLayout(Layout):
|
class HorizontalLayout(Layout):
|
||||||
@@ -22,20 +21,16 @@ class HorizontalLayout(Layout):
|
|||||||
|
|
||||||
placements: list[WidgetPlacement] = []
|
placements: list[WidgetPlacement] = []
|
||||||
add_placement = placements.append
|
add_placement = placements.append
|
||||||
|
|
||||||
x = max_height = Fraction(0)
|
x = max_height = Fraction(0)
|
||||||
parent_size = parent.outer_size
|
parent_size = parent.outer_size
|
||||||
|
|
||||||
styles = [child.styles for child in children if child.styles.width is not None]
|
box_models = resolve_box_models(
|
||||||
total_fraction = sum(
|
[child.styles.width for child in children],
|
||||||
[int(style.width.value) for style in styles if style.width.is_fraction]
|
children,
|
||||||
|
size,
|
||||||
|
parent_size,
|
||||||
|
dimension="width",
|
||||||
)
|
)
|
||||||
fraction_unit = Fraction(size.width, total_fraction or 1)
|
|
||||||
|
|
||||||
box_models = [
|
|
||||||
widget._get_box_model(size, parent_size, fraction_unit)
|
|
||||||
for widget in cast("list[Widget]", children)
|
|
||||||
]
|
|
||||||
|
|
||||||
margins = [
|
margins = [
|
||||||
max((box1.margin.right, box2.margin.left))
|
max((box1.margin.right, box2.margin.left))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from .._resolve import resolve_box_models
|
||||||
from ..geometry import Region, Size
|
from ..geometry import Region, Size
|
||||||
from .._layout import ArrangeResult, Layout, WidgetPlacement
|
from .._layout import ArrangeResult, Layout, WidgetPlacement
|
||||||
|
|
||||||
@@ -21,19 +22,15 @@ class VerticalLayout(Layout):
|
|||||||
|
|
||||||
placements: list[WidgetPlacement] = []
|
placements: list[WidgetPlacement] = []
|
||||||
add_placement = placements.append
|
add_placement = placements.append
|
||||||
|
|
||||||
parent_size = parent.outer_size
|
parent_size = parent.outer_size
|
||||||
|
|
||||||
styles = [child.styles for child in children if child.styles.height is not None]
|
box_models = resolve_box_models(
|
||||||
total_fraction = sum(
|
[child.styles.height for child in children],
|
||||||
[int(style.height.value) for style in styles if style.height.is_fraction]
|
children,
|
||||||
|
size,
|
||||||
|
parent_size,
|
||||||
|
dimension="height",
|
||||||
)
|
)
|
||||||
fraction_unit = Fraction(size.height, total_fraction or 1)
|
|
||||||
|
|
||||||
box_models = [
|
|
||||||
widget._get_box_model(size, parent_size, fraction_unit)
|
|
||||||
for widget in children
|
|
||||||
]
|
|
||||||
|
|
||||||
margins = [
|
margins = [
|
||||||
max((box1.margin.bottom, box2.margin.top))
|
max((box1.margin.bottom, box2.margin.top))
|
||||||
|
|||||||
@@ -425,14 +425,19 @@ class Widget(DOMNode):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _get_box_model(
|
def _get_box_model(
|
||||||
self, container: Size, viewport: Size, fraction_unit: Fraction
|
self,
|
||||||
|
container: Size,
|
||||||
|
viewport: Size,
|
||||||
|
width_fraction: Fraction,
|
||||||
|
height_fraction: Fraction,
|
||||||
) -> BoxModel:
|
) -> BoxModel:
|
||||||
"""Process the box model for this widget.
|
"""Process the box model for this widget.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
container (Size): The size of the container widget (with a layout)
|
container (Size): The size of the container widget (with a layout)
|
||||||
viewport (Size): The viewport size.
|
viewport (Size): The viewport size.
|
||||||
fraction_unit (Fraction): The unit used for `fr` units.
|
width_fraction (Fraction): A fraction used for 1 `fr` unit on the width dimension.
|
||||||
|
height_fraction (Fraction):A fraction used for 1 `fr` unit on the height dimension.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
BoxModel: The size and margin for this widget.
|
BoxModel: The size and margin for this widget.
|
||||||
@@ -441,7 +446,8 @@ class Widget(DOMNode):
|
|||||||
self.styles,
|
self.styles,
|
||||||
container,
|
container,
|
||||||
viewport,
|
viewport,
|
||||||
fraction_unit,
|
width_fraction,
|
||||||
|
height_fraction,
|
||||||
self.get_content_width,
|
self.get_content_width,
|
||||||
self.get_content_height,
|
self.get_content_height,
|
||||||
)
|
)
|
||||||
@@ -1946,8 +1952,13 @@ class Widget(DOMNode):
|
|||||||
async def handle_key(self, event: events.Key) -> bool:
|
async def handle_key(self, event: events.Key) -> bool:
|
||||||
return await self.dispatch_key(event)
|
return await self.dispatch_key(event)
|
||||||
|
|
||||||
async def _on_compose(self, event: events.Compose) -> None:
|
async def _on_compose(self) -> None:
|
||||||
widgets = list(self.compose())
|
try:
|
||||||
|
widgets = list(self.compose())
|
||||||
|
except TypeError as error:
|
||||||
|
raise TypeError(
|
||||||
|
f"{self!r} compose() returned an invalid response; {error}"
|
||||||
|
) from None
|
||||||
await self.mount(*widgets)
|
await self.mount(*widgets)
|
||||||
|
|
||||||
def _on_mount(self, event: events.Mount) -> None:
|
def _on_mount(self, event: events.Mount) -> None:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -85,6 +85,10 @@ def test_header_render(snap_compare):
|
|||||||
assert snap_compare("docs/examples/widgets/header.py")
|
assert snap_compare("docs/examples/widgets/header.py")
|
||||||
|
|
||||||
|
|
||||||
|
def test_fr_units(snap_compare):
|
||||||
|
assert snap_compare("tests/snapshots/fr_units.py")
|
||||||
|
|
||||||
|
|
||||||
# --- CSS properties ---
|
# --- CSS properties ---
|
||||||
# We have a canonical example for each CSS property that is shown in their docs.
|
# We have a canonical example for each CSS property that is shown in their docs.
|
||||||
# If any of these change, something has likely broken, so snapshot each of them.
|
# If any of these change, something has likely broken, so snapshot each of them.
|
||||||
|
|||||||
55
tests/snapshots/fr_units.py
Normal file
55
tests/snapshots/fr_units.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.containers import Horizontal, Vertical
|
||||||
|
from textual.widgets import Static
|
||||||
|
|
||||||
|
|
||||||
|
class StaticText(Static):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FRApp(App):
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
StaticText {
|
||||||
|
height: 1fr;
|
||||||
|
background: $boost;
|
||||||
|
border: heavy white;
|
||||||
|
}
|
||||||
|
#foo {
|
||||||
|
width: 10;
|
||||||
|
}
|
||||||
|
#bar {
|
||||||
|
width: 1fr;
|
||||||
|
}
|
||||||
|
#baz {
|
||||||
|
width: 8;
|
||||||
|
}
|
||||||
|
#header {
|
||||||
|
height: 1fr
|
||||||
|
}
|
||||||
|
|
||||||
|
Horizontal {
|
||||||
|
height: 2fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
height: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Vertical(
|
||||||
|
StaticText("HEADER", id="header"),
|
||||||
|
Horizontal(
|
||||||
|
StaticText("foo", id="foo"),
|
||||||
|
StaticText("bar", id="bar"),
|
||||||
|
StaticText("baz", id="baz"),
|
||||||
|
),
|
||||||
|
StaticText("FOOTER", id="footer"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = FRApp()
|
||||||
|
app.run()
|
||||||
@@ -26,7 +26,7 @@ def test_content_box():
|
|||||||
assert False, "must not be called"
|
assert False, "must not be called"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
# Size should be inclusive of padding / border
|
# Size should be inclusive of padding / border
|
||||||
assert box_model == BoxModel(Fraction(10), Fraction(8), Spacing(0, 0, 0, 0))
|
assert box_model == BoxModel(Fraction(10), Fraction(8), Spacing(0, 0, 0, 0))
|
||||||
@@ -35,7 +35,7 @@ def test_content_box():
|
|||||||
styles.box_sizing = "content-box"
|
styles.box_sizing = "content-box"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
# width and height have added padding / border to accommodate content
|
# width and height have added padding / border to accommodate content
|
||||||
assert box_model == BoxModel(Fraction(14), Fraction(12), Spacing(0, 0, 0, 0))
|
assert box_model == BoxModel(Fraction(14), Fraction(12), Spacing(0, 0, 0, 0))
|
||||||
@@ -53,7 +53,7 @@ def test_width():
|
|||||||
return 10
|
return 10
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(60), Fraction(20), Spacing(0, 0, 0, 0))
|
assert box_model == BoxModel(Fraction(60), Fraction(20), Spacing(0, 0, 0, 0))
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ def test_width():
|
|||||||
styles.margin = (1, 2, 3, 4)
|
styles.margin = (1, 2, 3, 4)
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ def test_width():
|
|||||||
styles.width = "auto"
|
styles.width = "auto"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
# Setting width to auto should call get_auto_width
|
# Setting width to auto should call get_auto_width
|
||||||
assert box_model == BoxModel(Fraction(10), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(10), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
@@ -78,7 +78,7 @@ def test_width():
|
|||||||
styles.width = "100vw"
|
styles.width = "100vw"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(80), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(80), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ def test_width():
|
|||||||
styles.width = "100%"
|
styles.width = "100%"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ def test_width():
|
|||||||
styles.max_width = "50%"
|
styles.max_width = "50%"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(30), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(30), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ def test_height():
|
|||||||
return 10
|
return 10
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(60), Fraction(20), Spacing(0, 0, 0, 0))
|
assert box_model == BoxModel(Fraction(60), Fraction(20), Spacing(0, 0, 0, 0))
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ def test_height():
|
|||||||
styles.margin = (1, 2, 3, 4)
|
styles.margin = (1, 2, 3, 4)
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ def test_height():
|
|||||||
styles.height = "100vh"
|
styles.height = "100vh"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(54), Fraction(24), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(54), Fraction(24), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ def test_height():
|
|||||||
styles.height = "100%"
|
styles.height = "100%"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ def test_height():
|
|||||||
styles.margin = 2
|
styles.margin = 2
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(56), Fraction(10), Spacing(2, 2, 2, 2))
|
assert box_model == BoxModel(Fraction(56), Fraction(10), Spacing(2, 2, 2, 2))
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ def test_height():
|
|||||||
styles.max_height = "50%"
|
styles.max_height = "50%"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(60, 20), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(54), Fraction(10), Spacing(1, 2, 3, 4))
|
assert box_model == BoxModel(Fraction(54), Fraction(10), Spacing(1, 2, 3, 4))
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ def test_max():
|
|||||||
assert False, "must not be called"
|
assert False, "must not be called"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(40, 30), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(40, 30), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))
|
assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))
|
||||||
|
|
||||||
@@ -194,6 +194,6 @@ def test_min():
|
|||||||
assert False, "must not be called"
|
assert False, "must not be called"
|
||||||
|
|
||||||
box_model = get_box_model(
|
box_model = get_box_model(
|
||||||
styles, Size(40, 30), Size(80, 24), one, get_auto_width, get_auto_height
|
styles, Size(40, 30), Size(80, 24), one, one, get_auto_width, get_auto_height
|
||||||
)
|
)
|
||||||
assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))
|
assert box_model == BoxModel(Fraction(40), Fraction(30), Spacing(0, 0, 0, 0))
|
||||||
|
|||||||
Reference in New Issue
Block a user