mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
optimized line rendering and updated render_lines API
This commit is contained in:
84
poetry.lock
generated
84
poetry.lock
generated
@@ -345,7 +345,7 @@ mkdocs = ">=1.1"
|
||||
|
||||
[[package]]
|
||||
name = "mkdocs-material"
|
||||
version = "8.3.3"
|
||||
version = "8.3.5"
|
||||
description = "Documentation that simply works"
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -391,7 +391,7 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "mkdocstrings-python"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
description = "A Python handler for mkdocstrings."
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -658,16 +658,21 @@ version = "12.4.4"
|
||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.3,<4.0.0"
|
||||
python-versions = "^3.6.3"
|
||||
develop = true
|
||||
|
||||
[package.dependencies]
|
||||
commonmark = ">=0.9.0,<0.10.0"
|
||||
pygments = ">=2.6.0,<3.0.0"
|
||||
typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""}
|
||||
commonmark = "^0.9.0"
|
||||
pygments = "^2.6.0"
|
||||
typing-extensions = {version = ">=4.0.0, <5.0", markers = "python_version < \"3.9\""}
|
||||
|
||||
[package.extras]
|
||||
jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
|
||||
|
||||
[package.source]
|
||||
type = "directory"
|
||||
url = "../rich"
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
@@ -740,7 +745,7 @@ testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)",
|
||||
|
||||
[[package]]
|
||||
name = "watchdog"
|
||||
version = "2.1.8"
|
||||
version = "2.1.9"
|
||||
description = "Filesystem events monitoring"
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -777,7 +782,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "378a60041202d505cba26ea7084886fe1b01090a0035253b100593b559aed090"
|
||||
content-hash = "4aeef009c7c1f6a34d0dd1c3c16647b53a339f5963dcbe31eef43bb9dac270ab"
|
||||
|
||||
[metadata.files]
|
||||
aiohttp = [
|
||||
@@ -1122,8 +1127,8 @@ mkdocs-autorefs = [
|
||||
{file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"},
|
||||
]
|
||||
mkdocs-material = [
|
||||
{file = "mkdocs-material-8.3.3.tar.gz", hash = "sha256:3dd30af894f6d5da3d8a2f8ffc04c90c4d0f1be013e654ec45f608373c131542"},
|
||||
{file = "mkdocs_material-8.3.3-py2.py3-none-any.whl", hash = "sha256:4f9564af58f9c96f25c263cb705a40a82c833cb10c2626d6db6ddadedaa5b6c3"},
|
||||
{file = "mkdocs-material-8.3.5.tar.gz", hash = "sha256:0d7ae82b28fa57a2ad9a4eeb5fd01704cb8fe963eb20c56a68afdd735e52b432"},
|
||||
{file = "mkdocs_material-8.3.5-py2.py3-none-any.whl", hash = "sha256:9190aef365bd6ed43b27f47d1de956d9e67b61f4b9edb444563337ef717cacd3"},
|
||||
]
|
||||
mkdocs-material-extensions = [
|
||||
{file = "mkdocs-material-extensions-1.0.3.tar.gz", hash = "sha256:bfd24dfdef7b41c312ede42648f9eb83476ea168ec163b613f9abd12bbfddba2"},
|
||||
@@ -1134,8 +1139,8 @@ mkdocstrings = [
|
||||
{file = "mkdocstrings-0.19.0.tar.gz", hash = "sha256:efa34a67bad11229d532d89f6836a8a215937548623b64f3698a1df62e01cc3e"},
|
||||
]
|
||||
mkdocstrings-python = [
|
||||
{file = "mkdocstrings-python-0.7.0.tar.gz", hash = "sha256:e54c67890e8bb7dc4604360c8ef5dd214b23b6924de7706f461e3c998d4ea061"},
|
||||
{file = "mkdocstrings_python-0.7.0-py3-none-any.whl", hash = "sha256:6964bd92f106766e771ac6cd5bc02643a960602b4d921b95362e31d491e9a6db"},
|
||||
{file = "mkdocstrings-python-0.7.1.tar.gz", hash = "sha256:c334b382dca202dfa37071c182418a6df5818356a95d54362a2b24822ca3af71"},
|
||||
{file = "mkdocstrings_python-0.7.1-py3-none-any.whl", hash = "sha256:a22060bfa374697678e9af4e62b020d990dad2711c98f7a9fac5c0345bef93c7"},
|
||||
]
|
||||
msgpack = [
|
||||
{file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"},
|
||||
@@ -1381,10 +1386,7 @@ pyyaml-env-tag = [
|
||||
{file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
|
||||
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
||||
]
|
||||
rich = [
|
||||
{file = "rich-12.4.4-py3-none-any.whl", hash = "sha256:d2bbd99c320a2532ac71ff6a3164867884357da3e3301f0240090c5d2fdac7ec"},
|
||||
{file = "rich-12.4.4.tar.gz", hash = "sha256:4c586de507202505346f3e32d1363eb9ed6932f0c2f63184dea88983ff4971e2"},
|
||||
]
|
||||
rich = []
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
@@ -1474,31 +1476,31 @@ virtualenv = [
|
||||
{file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"},
|
||||
]
|
||||
watchdog = [
|
||||
{file = "watchdog-2.1.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:676263bee67b165f16b05abc52acc7a94feac5b5ab2449b491f1a97638a79277"},
|
||||
{file = "watchdog-2.1.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:aa68d2d9a89d686fae99d28a6edf3b18595e78f5adf4f5c18fbfda549ac0f20c"},
|
||||
{file = "watchdog-2.1.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e2e51c53666850c3ecffe9d265fc5d7351db644de17b15e9c685dd3cdcd6f97"},
|
||||
{file = "watchdog-2.1.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7721ac736170b191c50806f43357407138c6748e4eb3e69b071397f7f7aaeedd"},
|
||||
{file = "watchdog-2.1.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ce7376aed3da5fd777483fe5ebc8475a440c6d18f23998024f832134b2938e7b"},
|
||||
{file = "watchdog-2.1.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f9ee4c6bf3a1b2ed6be90a2d78f3f4bbd8105b6390c04a86eb48ed67bbfa0b0b"},
|
||||
{file = "watchdog-2.1.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:68dbe75e0fa1ba4d73ab3f8e67b21770fbed0651d32ce515cd38919a26873266"},
|
||||
{file = "watchdog-2.1.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0c520009b8cce79099237d810aaa19bc920941c268578436b62013b2f0102320"},
|
||||
{file = "watchdog-2.1.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efcc8cbc1b43902571b3dce7ef53003f5b97fe4f275fe0489565fc6e2ebe3314"},
|
||||
{file = "watchdog-2.1.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:746e4c197ec1083581bb1f64d07d1136accf03437badb5ff8fcb862565c193b2"},
|
||||
{file = "watchdog-2.1.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ae17b6be788fb8e4d8753d8d599de948f0275a232416e16436363c682c6f850"},
|
||||
{file = "watchdog-2.1.8-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ddde157dc1447d8130cb5b8df102fad845916fe4335e3d3c3f44c16565becbb7"},
|
||||
{file = "watchdog-2.1.8-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4978db33fc0934c92013ee163a9db158ec216099b69fce5aec790aba704da412"},
|
||||
{file = "watchdog-2.1.8-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b962de4d7d92ff78fb2dbc6a0cb292a679dea879a0eb5568911484d56545b153"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_aarch64.whl", hash = "sha256:1e5d0fdfaa265c29dc12621913a76ae99656cf7587d03950dfeb3595e5a26102"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_armv7l.whl", hash = "sha256:036ed15f7cd656351bf4e17244447be0a09a61aaa92014332d50719fc5973bc0"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_i686.whl", hash = "sha256:2962628a8777650703e8f6f2593065884c602df7bae95759b2df267bd89b2ef5"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_ppc64.whl", hash = "sha256:156ec3a94695ea68cfb83454b98754af6e276031ba1ae7ae724dc6bf8973b92a"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:47598fe6713fc1fee86b1ca85c9cbe77e9b72d002d6adeab9c3b608f8a5ead10"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_s390x.whl", hash = "sha256:fed4de6e45a4f16e4046ea00917b4fe1700b97244e5d114f594b4a1b9de6bed8"},
|
||||
{file = "watchdog-2.1.8-py3-none-manylinux2014_x86_64.whl", hash = "sha256:24dedcc3ce75e150f2a1d704661f6879764461a481ba15a57dc80543de46021c"},
|
||||
{file = "watchdog-2.1.8-py3-none-win32.whl", hash = "sha256:6ddf67bc9f413791072e3afb466e46cc72c6799ba73dea18439b412e8f2e3257"},
|
||||
{file = "watchdog-2.1.8-py3-none-win_amd64.whl", hash = "sha256:88ef3e8640ef0a64b7ad7394b0f23384f58ac19dd759da7eaa9bc04b2898943f"},
|
||||
{file = "watchdog-2.1.8-py3-none-win_ia64.whl", hash = "sha256:0fb60c7d31474b21acba54079ce9ff0136411183e9a591369417cddb1d7d00d7"},
|
||||
{file = "watchdog-2.1.8.tar.gz", hash = "sha256:6d03149126864abd32715d4e9267d2754cede25a69052901399356ad3bc5ecff"},
|
||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"},
|
||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"},
|
||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"},
|
||||
{file = "watchdog-2.1.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591"},
|
||||
{file = "watchdog-2.1.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33"},
|
||||
{file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846"},
|
||||
{file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3"},
|
||||
{file = "watchdog-2.1.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654"},
|
||||
{file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39"},
|
||||
{file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7"},
|
||||
{file = "watchdog-2.1.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd"},
|
||||
{file = "watchdog-2.1.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3"},
|
||||
{file = "watchdog-2.1.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d"},
|
||||
{file = "watchdog-2.1.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_armv7l.whl", hash = "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_i686.whl", hash = "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64.whl", hash = "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_s390x.whl", hash = "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6"},
|
||||
{file = "watchdog-2.1.9-py3-none-win32.whl", hash = "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1"},
|
||||
{file = "watchdog-2.1.9-py3-none-win_amd64.whl", hash = "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c"},
|
||||
{file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"},
|
||||
{file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"},
|
||||
]
|
||||
yarl = [
|
||||
{file = "yarl-1.7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95"},
|
||||
|
||||
@@ -22,8 +22,8 @@ textual = "textual.cli.cli:run"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.7"
|
||||
rich = "^12.4.3"
|
||||
#rich = {path="../rich", develop=true}
|
||||
#rich = "^12.4.3"
|
||||
rich = {path="../rich", develop=true}
|
||||
click = "8.1.2"
|
||||
importlib-metadata = "^4.11.3"
|
||||
typing-extensions = { version = "^4.0.0", python = "<3.8" }
|
||||
|
||||
@@ -174,3 +174,6 @@ if __name__ == "__main__":
|
||||
from textual.css.scalar import Scalar
|
||||
|
||||
print(Scalar.resolve_dimension.cache_info())
|
||||
|
||||
from rich.style import Style
|
||||
print(Style.__add__.cache_info())
|
||||
|
||||
@@ -21,10 +21,14 @@ class TableApp(App):
|
||||
|
||||
def on_mount(self):
|
||||
self.bind("d", "toggle_dark")
|
||||
self.bind("z", "toggle_zebra")
|
||||
|
||||
def action_toggle_dark(self) -> None:
|
||||
self.app.dark = not self.app.dark
|
||||
|
||||
def action_toggle_zebra(self) -> None:
|
||||
self.table.zebra_stripes = not self.table.zebra_stripes
|
||||
|
||||
|
||||
app = TableApp()
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -445,7 +445,8 @@ class Compositor:
|
||||
x -= region.x
|
||||
y -= region.y
|
||||
|
||||
lines = widget.render_lines((y, y + 1), (0, region.width))
|
||||
# lines = widget.render_lines((y, y + 1), (0, region.width))
|
||||
lines = widget.render_lines(Region(0, y, region.width, 1))
|
||||
|
||||
if not lines:
|
||||
return Style.null()
|
||||
@@ -546,8 +547,7 @@ class Compositor:
|
||||
continue
|
||||
if region in clip:
|
||||
yield region, clip, widget.render_lines(
|
||||
(0, region.height),
|
||||
(0, region.width),
|
||||
Region(0, 0, region.width, region.height)
|
||||
)
|
||||
elif overlaps(clip, region):
|
||||
clipped_region = intersection(region, clip)
|
||||
@@ -556,10 +556,8 @@ class Compositor:
|
||||
new_x, new_y, new_width, new_height = clipped_region
|
||||
delta_x = new_x - region.x
|
||||
delta_y = new_y - region.y
|
||||
crop_x = delta_x + new_width
|
||||
lines = widget.render_lines(
|
||||
(delta_y, delta_y + new_height),
|
||||
(delta_x, crop_x),
|
||||
Region(delta_x, delta_y, new_width, new_height)
|
||||
)
|
||||
yield region, clip, lines
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ class App(Generic[ReturnType], DOMNode):
|
||||
|
||||
self.console = Console(
|
||||
file=(open(os.devnull, "wt") if self.is_headless else sys.__stdout__),
|
||||
markup=True,
|
||||
markup=False,
|
||||
highlight=False,
|
||||
emoji=False,
|
||||
)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from rich.console import RenderableType
|
||||
from rich.segment import Segment
|
||||
from rich.style import Style
|
||||
|
||||
|
||||
from .geometry import Size
|
||||
from ._types import Lines
|
||||
from .widget import Widget
|
||||
|
||||
|
||||
|
||||
@@ -877,21 +877,26 @@ class Widget(DOMNode):
|
||||
self._dirty_regions.clear()
|
||||
|
||||
def _crop_lines(self, lines: Lines, x1, x2) -> Lines:
|
||||
if (x1, x2) != (0, self.size.width):
|
||||
lines = [line_crop(line, x1, x2, self.size.width) for line in lines]
|
||||
width = self.size.width
|
||||
if (x1, x2) != (0, width):
|
||||
lines = [line_crop(line, x1, x2, width) for line in lines]
|
||||
return lines
|
||||
|
||||
def render_lines(
|
||||
self, line_range: tuple[int, int], column_range: tuple[int, int]
|
||||
) -> Lines:
|
||||
"""Get segment lines to render the widget."""
|
||||
def render_lines(self, crop: Region) -> Lines:
|
||||
"""Render the widget in to lines.
|
||||
|
||||
Args:
|
||||
crop (Region): Region within visible area to.
|
||||
|
||||
Returns:
|
||||
Lines: A list of list of segments
|
||||
"""
|
||||
if self._dirty_regions:
|
||||
self._render_lines()
|
||||
|
||||
y1, y2 = line_range
|
||||
x1, y1, x2, y2 = crop.corners
|
||||
lines = self._render_cache.lines[y1:y2]
|
||||
if column_range is not None:
|
||||
lines = self._crop_lines(lines, *column_range)
|
||||
lines = self._crop_lines(lines, x1, x2)
|
||||
return lines
|
||||
|
||||
def get_style_at(self, x: int, y: int) -> Style:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from typing import ClassVar, Generic, TypeVar, cast
|
||||
|
||||
from rich.console import RenderableType
|
||||
from rich.padding import Padding
|
||||
from rich.segment import Segment
|
||||
from rich.style import Style
|
||||
@@ -11,8 +12,9 @@ from rich.text import Text, TextType
|
||||
from .._lru_cache import LRUCache
|
||||
from .._segment_tools import line_crop
|
||||
from .._types import Lines
|
||||
from ..geometry import Size
|
||||
from ..geometry import Region, Size
|
||||
from ..reactive import Reactive
|
||||
from .._profile import timer
|
||||
from ..scroll_view import ScrollView
|
||||
from ..widget import Widget
|
||||
|
||||
@@ -27,6 +29,13 @@ class Column:
|
||||
index: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class Row:
|
||||
index: int
|
||||
height: int = 1
|
||||
cell_renderables: list[RenderableType] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Cell:
|
||||
value: object
|
||||
@@ -62,6 +71,10 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
background: $primary 10%;
|
||||
}
|
||||
|
||||
.-dark-mode DataTable > .datatable--even-row {
|
||||
background: $primary 15%;
|
||||
}
|
||||
|
||||
DataTable > .datatable--highlight {
|
||||
background: $secondary;
|
||||
color: $text-secondary;
|
||||
@@ -84,16 +97,19 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
) -> None:
|
||||
super().__init__(name=name, id=id, classes=classes)
|
||||
self.columns: list[Column] = []
|
||||
self.rows: dict[int, Row] = {}
|
||||
self.data: dict[int, list[CellType]] = {}
|
||||
self.row_count = 0
|
||||
|
||||
self._cells: dict[int, list[Cell]] = {}
|
||||
self.line_contents: list[str] = []
|
||||
|
||||
self._cells: dict[int, list[Cell]] = {}
|
||||
self._cell_render_cache: dict[tuple[int, int], Lines] = LRUCache(10000)
|
||||
|
||||
show_header = Reactive(True)
|
||||
fixed_rows = Reactive(1)
|
||||
fixed_columns = Reactive(1)
|
||||
zebra_stripes = Reactive(False)
|
||||
|
||||
def _update_dimensions(self) -> None:
|
||||
max_width = sum(column.width for column in self.columns)
|
||||
@@ -105,8 +121,17 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
self._update_dimensions()
|
||||
self.refresh()
|
||||
|
||||
def add_row(self, *cells: CellType) -> None:
|
||||
self.data[self.row_count] = list(cells)
|
||||
def add_row(self, *cells: CellType, height: int = 1) -> None:
|
||||
row_index = self.row_count
|
||||
self.data[row_index] = list(cells)
|
||||
self.rows[row_index] = Row(
|
||||
row_index,
|
||||
height=height,
|
||||
cell_renderables=[
|
||||
Text.from_markup(cell) if isinstance(cell, str) else cell
|
||||
for cell in cells
|
||||
],
|
||||
)
|
||||
self.row_count += 1
|
||||
self._update_dimensions()
|
||||
self.refresh()
|
||||
@@ -122,7 +147,7 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
if data is None:
|
||||
return [Text() for column in self.columns]
|
||||
else:
|
||||
return data
|
||||
return self.rows[data_offset].cell_renderables
|
||||
|
||||
def _render_cell(self, y: int, column: Column) -> Lines:
|
||||
|
||||
@@ -151,6 +176,8 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
rendered_width += column.width
|
||||
cell_segments.append(lines[0])
|
||||
|
||||
base_style = self.rich_style
|
||||
|
||||
fixed_style = self.component_styles[
|
||||
"datatable--fixed"
|
||||
].node.rich_style + Style.from_meta({"fixed": True})
|
||||
@@ -165,37 +192,31 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
|
||||
line: list[Segment] = sum(cell_segments, start=[])
|
||||
|
||||
row_style = Style()
|
||||
row_style = base_style
|
||||
if y == 0:
|
||||
segments = fixed + line_crop(line, x1 + fixed_width, x2, width)
|
||||
line = Segment.adjust_line_length(segments, width)
|
||||
else:
|
||||
component_row_style = (
|
||||
"datatable--odd-row" if y % 2 else "datatable--even-row"
|
||||
)
|
||||
|
||||
row_style += self.component_styles[component_row_style].node.rich_style
|
||||
if self.zebra_stripes:
|
||||
component_row_style = (
|
||||
"datatable--odd-row" if y % 2 else "datatable--even-row"
|
||||
)
|
||||
row_style = self.component_styles[component_row_style].node.rich_style
|
||||
|
||||
line = list(Segment.apply_style(line, row_style))
|
||||
segments = fixed + line_crop(line, x1 + fixed_width, x2, width)
|
||||
line = Segment.adjust_line_length(segments, width)
|
||||
line = Segment.adjust_line_length(segments, width, style=base_style)
|
||||
|
||||
if y == 0 and self.show_header:
|
||||
line = list(Segment.apply_style(line, header_style))
|
||||
|
||||
return line
|
||||
|
||||
def render_lines(
|
||||
self, line_range: tuple[int, int], column_range: tuple[int, int]
|
||||
) -> Lines:
|
||||
scroll_x, scroll_y = self.scroll_offset
|
||||
y1, y2 = line_range
|
||||
y1 += scroll_y
|
||||
y2 += scroll_y
|
||||
@timer("render_lines")
|
||||
def render_lines(self, crop: Region) -> Lines:
|
||||
|
||||
x1, x2 = column_range
|
||||
x1 += scroll_x
|
||||
x2 += scroll_x
|
||||
scroll_x, scroll_y = self.scroll_offset
|
||||
x1, y1, x2, y2 = crop.translate(scroll_x, scroll_y).corners
|
||||
|
||||
fixed_lines = [self._render_line(y, x1, x2) for y in range(0, self.fixed_rows)]
|
||||
lines = [self._render_line(y, x1, x2) for y in range(y1, y2)]
|
||||
@@ -204,10 +225,6 @@ class DataTable(ScrollView, Generic[CellType]):
|
||||
if y - scroll_y == 0:
|
||||
lines[0] = fixed_line
|
||||
|
||||
(base_background, base_color), (background, color) = self.colors
|
||||
style = Style.from_color(color.rich_color, background.rich_color)
|
||||
lines = [list(Segment.apply_style(line, style)) for line in lines]
|
||||
|
||||
return lines
|
||||
|
||||
def on_mouse_move(self, event):
|
||||
|
||||
Reference in New Issue
Block a user