mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Stream layout
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,6 +29,7 @@ lib/
|
|||||||
lib64/
|
lib64/
|
||||||
parts/
|
parts/
|
||||||
sdist/
|
sdist/
|
||||||
|
dist/
|
||||||
var/
|
var/
|
||||||
wheels/
|
wheels/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ VALID_BORDER: Final = {
|
|||||||
"wide",
|
"wide",
|
||||||
}
|
}
|
||||||
VALID_EDGE: Final = {"top", "right", "bottom", "left", "none"}
|
VALID_EDGE: Final = {"top", "right", "bottom", "left", "none"}
|
||||||
VALID_LAYOUT: Final = {"vertical", "horizontal", "grid"}
|
VALID_LAYOUT: Final = {"vertical", "horizontal", "grid", "stream"}
|
||||||
|
|
||||||
VALID_BOX_SIZING: Final = {"border-box", "content-box"}
|
VALID_BOX_SIZING: Final = {"border-box", "content-box"}
|
||||||
VALID_OVERFLOW: Final = {"scroll", "hidden", "auto"}
|
VALID_OVERFLOW: Final = {"scroll", "hidden", "auto"}
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ class StylesBase:
|
|||||||
layout = LayoutProperty()
|
layout = LayoutProperty()
|
||||||
"""Set the layout of the widget, defining how it's children are laid out.
|
"""Set the layout of the widget, defining how it's children are laid out.
|
||||||
|
|
||||||
Valid values are "grid", "horizontal", and "vertical" or None to clear any layout
|
Valid values are "grid", "stream", "horizontal", or "vertical" or None to clear any layout
|
||||||
that was set at runtime.
|
that was set at runtime.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ from __future__ import annotations
|
|||||||
from textual.layout import Layout
|
from textual.layout import Layout
|
||||||
from textual.layouts.grid import GridLayout
|
from textual.layouts.grid import GridLayout
|
||||||
from textual.layouts.horizontal import HorizontalLayout
|
from textual.layouts.horizontal import HorizontalLayout
|
||||||
|
from textual.layouts.stream import StreamLayout
|
||||||
from textual.layouts.vertical import VerticalLayout
|
from textual.layouts.vertical import VerticalLayout
|
||||||
|
|
||||||
LAYOUT_MAP: dict[str, type[Layout]] = {
|
LAYOUT_MAP: dict[str, type[Layout]] = {
|
||||||
"horizontal": HorizontalLayout,
|
"horizontal": HorizontalLayout,
|
||||||
"grid": GridLayout,
|
"grid": GridLayout,
|
||||||
"vertical": VerticalLayout,
|
"vertical": VerticalLayout,
|
||||||
|
"stream": StreamLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
58
src/textual/layouts/stream.py
Normal file
58
src/textual/layouts/stream.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from textual.geometry import NULL_OFFSET, Region, Size
|
||||||
|
from textual.layout import ArrangeResult, Layout, WidgetPlacement
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
from textual.widget import Widget
|
||||||
|
|
||||||
|
|
||||||
|
class StreamLayout(Layout):
|
||||||
|
name = "stream"
|
||||||
|
|
||||||
|
def arrange(
|
||||||
|
self, parent: Widget, children: list[Widget], size: Size, greedy: bool = True
|
||||||
|
) -> ArrangeResult:
|
||||||
|
parent.pre_layout(self)
|
||||||
|
viewport = parent.app.size
|
||||||
|
|
||||||
|
placements: list[WidgetPlacement] = []
|
||||||
|
if not children:
|
||||||
|
return []
|
||||||
|
width = size.width
|
||||||
|
first_child_styles = children[0].styles
|
||||||
|
y = first_child_styles.margin.top
|
||||||
|
previous_margin = 0
|
||||||
|
null_offset = NULL_OFFSET
|
||||||
|
|
||||||
|
for widget in children:
|
||||||
|
styles = widget.styles
|
||||||
|
overlay = styles.overlay == "screen"
|
||||||
|
absolute = styles.has_rule("position") and styles.position == "absolute"
|
||||||
|
margin = styles.margin
|
||||||
|
top, right, bottom, left = margin
|
||||||
|
margin_width = left + right
|
||||||
|
y += max(top, previous_margin)
|
||||||
|
previous_margin = bottom
|
||||||
|
height = widget.get_content_height(size, viewport, width - margin_width)
|
||||||
|
height += styles.gutter.height
|
||||||
|
if (max_height := styles.max_height) is not None and max_height.is_cells:
|
||||||
|
height = min(height, int(max_height.value))
|
||||||
|
placements.append(
|
||||||
|
WidgetPlacement(
|
||||||
|
Region(left, y, width - margin_width, height),
|
||||||
|
null_offset,
|
||||||
|
margin,
|
||||||
|
widget,
|
||||||
|
0,
|
||||||
|
False,
|
||||||
|
overlay,
|
||||||
|
absolute,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
y += height
|
||||||
|
|
||||||
|
return placements
|
||||||
Reference in New Issue
Block a user