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/
|
||||
parts/
|
||||
sdist/
|
||||
dist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
|
||||
@@ -28,7 +28,7 @@ VALID_BORDER: Final = {
|
||||
"wide",
|
||||
}
|
||||
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_OVERFLOW: Final = {"scroll", "hidden", "auto"}
|
||||
|
||||
@@ -284,7 +284,7 @@ class StylesBase:
|
||||
layout = LayoutProperty()
|
||||
"""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.
|
||||
|
||||
Raises:
|
||||
|
||||
@@ -3,12 +3,14 @@ from __future__ import annotations
|
||||
from textual.layout import Layout
|
||||
from textual.layouts.grid import GridLayout
|
||||
from textual.layouts.horizontal import HorizontalLayout
|
||||
from textual.layouts.stream import StreamLayout
|
||||
from textual.layouts.vertical import VerticalLayout
|
||||
|
||||
LAYOUT_MAP: dict[str, type[Layout]] = {
|
||||
"horizontal": HorizontalLayout,
|
||||
"grid": GridLayout,
|
||||
"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