diff --git a/docs/examples/guide/widgets/fizzbuzz.css b/docs/examples/guide/widgets/fizzbuzz01.css similarity index 62% rename from docs/examples/guide/widgets/fizzbuzz.css rename to docs/examples/guide/widgets/fizzbuzz01.css index db6100c65..0893c4dbe 100644 --- a/docs/examples/guide/widgets/fizzbuzz.css +++ b/docs/examples/guide/widgets/fizzbuzz01.css @@ -5,5 +5,6 @@ Screen { FizzBuzz { width: auto; height: auto; - background: $panel; + background: $primary; + color: $text; } diff --git a/docs/examples/guide/widgets/fizzbuzz.py b/docs/examples/guide/widgets/fizzbuzz01.py similarity index 95% rename from docs/examples/guide/widgets/fizzbuzz.py rename to docs/examples/guide/widgets/fizzbuzz01.py index fe70e4b85..129abdd07 100644 --- a/docs/examples/guide/widgets/fizzbuzz.py +++ b/docs/examples/guide/widgets/fizzbuzz01.py @@ -19,7 +19,7 @@ class FizzBuzz(Static): class FizzBuzzApp(App): - CSS_PATH = "fizzbuzz.css" + CSS_PATH = "fizzbuzz01.css" def compose(self) -> ComposeResult: yield FizzBuzz() diff --git a/docs/examples/guide/widgets/fizzbuzz02.css b/docs/examples/guide/widgets/fizzbuzz02.css new file mode 100644 index 000000000..d5c2e0c28 --- /dev/null +++ b/docs/examples/guide/widgets/fizzbuzz02.css @@ -0,0 +1,10 @@ +Screen { + layout: center; +} + +FizzBuzz { + width: auto; + height: auto; + background: $primary; + color: $text; +} diff --git a/docs/examples/guide/widgets/fizzbuzz02.py b/docs/examples/guide/widgets/fizzbuzz02.py new file mode 100644 index 000000000..58618aba5 --- /dev/null +++ b/docs/examples/guide/widgets/fizzbuzz02.py @@ -0,0 +1,35 @@ +from rich.table import Table + +from textual.app import App, ComposeResult +from textual.geometry import Size +from textual.widgets import Static + + +class FizzBuzz(Static): + def on_mount(self) -> None: + table = Table("Number", "Fizz?", "Buzz?", expand=True) + for n in range(1, 16): + fizz = not n % 3 + buzz = not n % 5 + table.add_row( + str(n), + "fizz" if fizz else "", + "buzz" if buzz else "", + ) + self.update(table) + + def get_content_width(self, container: Size, viewport: Size) -> int: + """Force content width size.""" + return 50 + + +class FizzBuzzApp(App): + CSS_PATH = "fizzbuzz02.css" + + def compose(self) -> ComposeResult: + yield FizzBuzz() + + +if __name__ == "__main__": + app = FizzBuzzApp() + app.run() diff --git a/docs/guide/widgets.md b/docs/guide/widgets.md index acc852dba..2a4c11fbc 100644 --- a/docs/guide/widgets.md +++ b/docs/guide/widgets.md @@ -150,34 +150,54 @@ Lets make a widget that uses a Rich table for its content. The following app is This app will "play" fizz buzz by displaying a table of the first 15 numbers and columns for fizz and buzz. -=== "fizzbuzz.py" +=== "fizzbuzz01.py" - ```python title="fizzbuzz.py" hl_lines="18" - --8<-- "docs/examples/guide/widgets/fizzbuzz.py" + ```python title="fizzbuzz01.py" hl_lines="18" + --8<-- "docs/examples/guide/widgets/fizzbuzz01.py" ``` -=== "fizzbuzz.css" +=== "fizzbuzz01.css" - ```sass title="fizzbuzz.css" hl_lines="32-35" - --8<-- "docs/examples/guide/widgets/fizzbuzz.css" + ```sass title="fizzbuzz01.css" hl_lines="32-35" + --8<-- "docs/examples/guide/widgets/fizzbuzz01.css" ``` === "Output" - ```{.textual path="docs/examples/guide/widgets/fizzbuzz.py"} + ```{.textual path="docs/examples/guide/widgets/fizzbuzz01.py"} ``` ## Content size -If you use a rich renderable as content, Textual can auto-detect the dimensions of the output which will become the content area of the widget. +Textual will auto-detect the dimensions of the content area from rich renderables if width or height is set to `auto`. You can override auto dimensions by implementing [get_content_width()][textual.widget.Widget.get_content_width] or [get_content_height()][textual.widget.Widget.get_content_height]. + +Let's modify the default width for the fizzbuzz example. By default, the table will be just wide enough to fix the columns. Let's force it to be 50 characters wide. + + +=== "fizzbuzz02.py" + + ```python title="fizzbuzz02.py" hl_lines="10 21-23" + --8<-- "docs/examples/guide/widgets/fizzbuzz02.py" + ``` + +=== "fizzbuzz02.css" + + ```sass title="fizzbuzz02.css" + --8<-- "docs/examples/guide/widgets/fizzbuzz02.css" + ``` + +=== "Output" + + ```{.textual path="docs/examples/guide/widgets/fizzbuzz02.py"} + ``` + +Note that we've added `expand=True` to tell the Table to expand beyond the optimal width, so that it fills the 50 characters returned by `get_content_width`. + ## Compound widgets +TODO: Explanation of compound widgets ## Line API -TODO: Widgets docs - -- Content size -- Compound widgets -- Line API +TODO: Explanation of line API diff --git a/src/textual/_compositor.py b/src/textual/_compositor.py index 7fe963692..074154056 100644 --- a/src/textual/_compositor.py +++ b/src/textual/_compositor.py @@ -14,8 +14,7 @@ without having to render the entire screen. from __future__ import annotations from itertools import chain -from functools import reduce -from operator import itemgetter, __or__ +from operator import itemgetter import sys from typing import Callable, cast, Iterator, Iterable, NamedTuple, TYPE_CHECKING @@ -776,4 +775,3 @@ class Compositor: add_region(update_region) self._dirty_regions.update(regions) - self._link_map = None diff --git a/src/textual/widget.py b/src/textual/widget.py index 10ac54551..0f89fab12 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -365,9 +365,7 @@ class Widget(DOMNode): return box_model def get_content_width(self, container: Size, viewport: Size) -> int: - """Gets the width of the content area. - - May be overridden in a subclass. + """Called by textual to get the width of the content area. May be overridden in a subclass. Args: container (Size): Size of the container (immediate parent) widget. @@ -397,9 +395,7 @@ class Widget(DOMNode): return width def get_content_height(self, container: Size, viewport: Size, width: int) -> int: - """Gets the height (number of lines) in the content area. - - May be overridden in a subclass. + """Called by Textual to get the height of the content area. May be overridden in a subclass. Args: container (Size): Size of the container (immediate parent) widget.