mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Checkbox polishing + fix auto-width in Horizontal layout (#942)
* checkbox widget * fixes * Checkbox additions, fix content width in horizontal layout * Update docs, add tests for checkbox * Remove some test code * Small renaming of test class Co-authored-by: Will McGugan <willmcgugan@gmail.com>
This commit is contained in:
28
docs/examples/widgets/checkbox.css
Normal file
28
docs/examples/widgets/checkbox.css
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Screen {
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox {
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
height: 3;
|
||||||
|
content-align: center middle;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-design {
|
||||||
|
background: darkslategrey;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-design > .checkbox--switch {
|
||||||
|
color: dodgerblue;
|
||||||
|
background: darkslateblue;
|
||||||
|
}
|
||||||
33
docs/examples/widgets/checkbox.py
Normal file
33
docs/examples/widgets/checkbox.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.containers import Horizontal
|
||||||
|
from textual.widgets import Checkbox, Static
|
||||||
|
|
||||||
|
|
||||||
|
class CheckboxApp(App):
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Static("[b]Example checkboxes\n", classes="label")
|
||||||
|
yield Horizontal(
|
||||||
|
Static("off: ", classes="label"), Checkbox(), classes="container"
|
||||||
|
)
|
||||||
|
yield Horizontal(
|
||||||
|
Static("on: ", classes="label"),
|
||||||
|
Checkbox(value=True),
|
||||||
|
classes="container",
|
||||||
|
)
|
||||||
|
|
||||||
|
focused_checkbox = Checkbox()
|
||||||
|
focused_checkbox.focus()
|
||||||
|
yield Horizontal(
|
||||||
|
Static("focused: ", classes="label"), focused_checkbox, classes="container"
|
||||||
|
)
|
||||||
|
|
||||||
|
yield Horizontal(
|
||||||
|
Static("custom: ", classes="label"),
|
||||||
|
Checkbox(id="custom-design"),
|
||||||
|
classes="container",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = CheckboxApp(css_path="checkbox.css")
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
1
docs/reference/checkbox.md
Normal file
1
docs/reference/checkbox.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
::: textual.widgets.Checkbox
|
||||||
57
docs/widgets/checkbox.md
Normal file
57
docs/widgets/checkbox.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Checkbox
|
||||||
|
|
||||||
|
A simple checkbox widget which stores a boolean value.
|
||||||
|
|
||||||
|
- [x] Focusable
|
||||||
|
- [ ] Container
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The example below shows checkboxes in various states.
|
||||||
|
|
||||||
|
=== "Output"
|
||||||
|
|
||||||
|
```{.textual path="docs/examples/widgets/checkbox.py"}
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "checkbox.py"
|
||||||
|
|
||||||
|
```python
|
||||||
|
--8<-- "docs/examples/widgets/checkbox.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
=== "checkbox.css"
|
||||||
|
|
||||||
|
```css
|
||||||
|
--8<-- "docs/examples/widgets/checkbox.css"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reactive Attributes
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
|---------|--------|---------|------------------------------------|
|
||||||
|
| `value` | `bool` | `False` | The default value of the checkbox. |
|
||||||
|
|
||||||
|
## Messages
|
||||||
|
|
||||||
|
### Pressed
|
||||||
|
|
||||||
|
The `Checkbox.Changed` message is sent when the checkbox is toggled.
|
||||||
|
|
||||||
|
- [x] Bubbles
|
||||||
|
|
||||||
|
#### Attributes
|
||||||
|
|
||||||
|
| attribute | type | purpose |
|
||||||
|
|-----------|--------|--------------------------------|
|
||||||
|
| `value` | `bool` | The new value of the checkbox. |
|
||||||
|
|
||||||
|
## Additional Notes
|
||||||
|
|
||||||
|
- To remove the spacing around a checkbox, set `border: none;` and `padding: 0;`.
|
||||||
|
- The `.checkbox--switch` component class can be used to change the color and background of the switch.
|
||||||
|
- When focused, the ++enter++ or ++space++ keys can be used to toggle the checkbox.
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Checkbox](../reference/checkbox.md) code reference
|
||||||
@@ -54,7 +54,7 @@ The `Input.Submitted` message is sent when you press ++enter++ with the text fie
|
|||||||
#### Attributes
|
#### Attributes
|
||||||
|
|
||||||
| attribute | type | purpose |
|
| attribute | type | purpose |
|
||||||
| --------- | ----- | -------------------------------- |
|
|-----------|-------|----------------------------------|
|
||||||
| `value` | `str` | The new value in the text input. |
|
| `value` | `str` | The new value in the text input. |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ edit_uri: edit/css/docs/
|
|||||||
nav:
|
nav:
|
||||||
- Introduction:
|
- Introduction:
|
||||||
- "index.md"
|
- "index.md"
|
||||||
- "getting_started.md"
|
- "getting_started.md"
|
||||||
- "tutorial.md"
|
- "tutorial.md"
|
||||||
- Guide:
|
- Guide:
|
||||||
- "guide/index.md"
|
- "guide/index.md"
|
||||||
@@ -92,6 +92,7 @@ nav:
|
|||||||
- Widgets:
|
- Widgets:
|
||||||
- "widgets/index.md"
|
- "widgets/index.md"
|
||||||
- "widgets/button.md"
|
- "widgets/button.md"
|
||||||
|
- "widgets/checkbox.md"
|
||||||
- "widgets/data_table.md"
|
- "widgets/data_table.md"
|
||||||
- "widgets/footer.md"
|
- "widgets/footer.md"
|
||||||
- "widgets/header.md"
|
- "widgets/header.md"
|
||||||
|
|||||||
28
sandbox/darren/check.css
Normal file
28
sandbox/darren/check.css
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Screen {
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Container {
|
||||||
|
width: 50;
|
||||||
|
height: 15;
|
||||||
|
background: $boost;
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox {
|
||||||
|
}
|
||||||
|
|
||||||
|
#check {
|
||||||
|
background: red;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#check > .checkbox--switch {
|
||||||
|
color: red;
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#check:focus {
|
||||||
|
tint: magenta 60%;
|
||||||
|
}
|
||||||
24
sandbox/darren/check.py
Normal file
24
sandbox/darren/check.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
|
||||||
|
from textual.containers import Container
|
||||||
|
from textual.widgets import Checkbox, Footer
|
||||||
|
|
||||||
|
|
||||||
|
class CheckboxApp(App):
|
||||||
|
BINDINGS = [("s", "switch", "Press switch"), ("d", "toggle_dark", "Dark mode")]
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Footer()
|
||||||
|
yield Container(Checkbox(id="check", animate=True))
|
||||||
|
|
||||||
|
def action_switch(self) -> None:
|
||||||
|
checkbox = self.query_one(Checkbox)
|
||||||
|
checkbox.toggle()
|
||||||
|
|
||||||
|
def key_f(self):
|
||||||
|
print(self.app.focused)
|
||||||
|
|
||||||
|
|
||||||
|
app = CheckboxApp(css_path="check.css")
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
10
sandbox/will/check.css
Normal file
10
sandbox/will/check.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Screen {
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Container {
|
||||||
|
width: 50;
|
||||||
|
height: 15;
|
||||||
|
background: $boost;
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
21
sandbox/will/check.py
Normal file
21
sandbox/will/check.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
|
||||||
|
from textual.containers import Container
|
||||||
|
from textual.widgets import Checkbox, Footer
|
||||||
|
|
||||||
|
|
||||||
|
class CheckboxApp(App):
|
||||||
|
BINDINGS = [("s", "switch", "Press switch"), ("d", "toggle_dark", "Dark mode")]
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Footer()
|
||||||
|
yield Container(Checkbox())
|
||||||
|
|
||||||
|
def action_switch(self) -> None:
|
||||||
|
checkbox = self.query_one(Checkbox)
|
||||||
|
checkbox.value = not checkbox.value
|
||||||
|
|
||||||
|
|
||||||
|
app = CheckboxApp(css_path="check.css")
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
@@ -65,17 +65,18 @@ class Layout(ABC):
|
|||||||
int: Width of the content.
|
int: Width of the content.
|
||||||
"""
|
"""
|
||||||
width: int | None = None
|
width: int | None = None
|
||||||
widget_gutter = widget.gutter.width
|
gutter_width = widget.gutter.width
|
||||||
for child in widget.displayed_children:
|
for child in widget.displayed_children:
|
||||||
if not child.is_container:
|
if not child.is_container:
|
||||||
child_width = (
|
child_width = (
|
||||||
child.get_content_width(container, viewport)
|
child.get_content_width(container, viewport)
|
||||||
+ widget_gutter
|
+ gutter_width
|
||||||
+ child.gutter.width
|
+ child.gutter.width
|
||||||
)
|
)
|
||||||
width = child_width if width is None else max(width, child_width)
|
width = child_width if width is None else max(width, child_width)
|
||||||
if width is None:
|
if width is None:
|
||||||
width = container.width
|
width = container.width
|
||||||
|
|
||||||
return width
|
return width
|
||||||
|
|
||||||
def get_content_height(
|
def get_content_height(
|
||||||
|
|||||||
@@ -64,3 +64,33 @@ class HorizontalLayout(Layout):
|
|||||||
x = next_x + margin
|
x = next_x + margin
|
||||||
|
|
||||||
return placements, set(displayed_children)
|
return placements, set(displayed_children)
|
||||||
|
|
||||||
|
def get_content_width(self, widget: Widget, container: Size, viewport: Size) -> int:
|
||||||
|
"""Get the width of the content. In Horizontal layout, the content width of
|
||||||
|
a widget is the sum of the widths of its children.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
widget (Widget): The container widget.
|
||||||
|
container (Size): The container size.
|
||||||
|
viewport (Size): The viewport size.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Width of the content.
|
||||||
|
"""
|
||||||
|
width: int | None = None
|
||||||
|
gutter_width = widget.gutter.width
|
||||||
|
for child in widget.displayed_children:
|
||||||
|
if not child.is_container:
|
||||||
|
child_width = (
|
||||||
|
child.get_content_width(container, viewport)
|
||||||
|
+ gutter_width
|
||||||
|
+ child.gutter.width
|
||||||
|
)
|
||||||
|
if width is None:
|
||||||
|
width = child_width
|
||||||
|
else:
|
||||||
|
width += child_width
|
||||||
|
if width is None:
|
||||||
|
width = container.width
|
||||||
|
|
||||||
|
return width
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ if typing.TYPE_CHECKING:
|
|||||||
# `__init__.pyi` file in this same folder - otherwise text editors and type checkers won't be able to "see" them.
|
# `__init__.pyi` file in this same folder - otherwise text editors and type checkers won't be able to "see" them.
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Button",
|
"Button",
|
||||||
|
"Checkbox",
|
||||||
"DataTable",
|
"DataTable",
|
||||||
"DirectoryTree",
|
"DirectoryTree",
|
||||||
"Footer",
|
"Footer",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# This stub file must re-export every classes exposed in the __init__.py's `__all__` list:
|
# This stub file must re-export every classes exposed in the __init__.py's `__all__` list:
|
||||||
from ._button import Button as Button
|
from ._button import Button as Button
|
||||||
from ._data_table import DataTable as DataTable
|
from ._data_table import DataTable as DataTable
|
||||||
|
from ._checkbox import Checkbox as Checkbox
|
||||||
from ._directory_tree import DirectoryTree as DirectoryTree
|
from ._directory_tree import DirectoryTree as DirectoryTree
|
||||||
from ._footer import Footer as Footer
|
from ._footer import Footer as Footer
|
||||||
from ._header import Header as Header
|
from ._header import Header as Header
|
||||||
|
|||||||
126
src/textual/widgets/_checkbox.py
Normal file
126
src/textual/widgets/_checkbox.py
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
|
from rich.console import RenderableType
|
||||||
|
|
||||||
|
from ..binding import Binding
|
||||||
|
from ..geometry import Size
|
||||||
|
from ..message import Message
|
||||||
|
from ..reactive import reactive
|
||||||
|
from ..widget import Widget
|
||||||
|
from ..scrollbar import ScrollBarRender
|
||||||
|
|
||||||
|
|
||||||
|
class Checkbox(Widget, can_focus=True):
|
||||||
|
"""A checkbox widget. Represents a boolean value. Can be toggled by clicking
|
||||||
|
on it or by pressing the enter key or space bar while it has focus.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value (bool, optional): The initial value of the checkbox. Defaults to False.
|
||||||
|
animate (bool, optional): True if the checkbox should animate when toggled. Defaults to True.
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
|
||||||
|
Checkbox {
|
||||||
|
border: tall transparent;
|
||||||
|
background: $panel;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
padding: 0 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox > .checkbox--switch {
|
||||||
|
background: $panel-darken-2;
|
||||||
|
color: $panel-lighten-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox:hover {
|
||||||
|
border: tall $background;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox:focus {
|
||||||
|
border: tall $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox.-on {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox.-on > .checkbox--switch {
|
||||||
|
color: $success;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
BINDINGS = [
|
||||||
|
Binding("enter,space", "toggle", "toggle", show=False),
|
||||||
|
]
|
||||||
|
|
||||||
|
COMPONENT_CLASSES: ClassVar[set[str]] = {
|
||||||
|
"checkbox--switch",
|
||||||
|
}
|
||||||
|
|
||||||
|
value = reactive(False, init=False)
|
||||||
|
slider_pos = reactive(0.0)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
value: bool = None,
|
||||||
|
*,
|
||||||
|
animate: bool = True,
|
||||||
|
name: str | None = None,
|
||||||
|
id: str | None = None,
|
||||||
|
classes: str | None = None,
|
||||||
|
):
|
||||||
|
super().__init__(name=name, id=id, classes=classes)
|
||||||
|
if value:
|
||||||
|
self.slider_pos = 1.0
|
||||||
|
self._reactive_value = value
|
||||||
|
self._should_animate = animate
|
||||||
|
|
||||||
|
def watch_value(self, value: bool) -> None:
|
||||||
|
target_slider_pos = 1.0 if value else 0.0
|
||||||
|
if self._should_animate:
|
||||||
|
self.animate("slider_pos", target_slider_pos, duration=0.3)
|
||||||
|
else:
|
||||||
|
self.slider_pos = target_slider_pos
|
||||||
|
self.emit_no_wait(self.Changed(self, self.value))
|
||||||
|
|
||||||
|
def watch_slider_pos(self, slider_pos: float) -> None:
|
||||||
|
self.set_class(slider_pos == 1, "-on")
|
||||||
|
|
||||||
|
def render(self) -> RenderableType:
|
||||||
|
style = self.get_component_rich_style("checkbox--switch")
|
||||||
|
return ScrollBarRender(
|
||||||
|
virtual_size=100,
|
||||||
|
window_size=50,
|
||||||
|
position=self.slider_pos * 50,
|
||||||
|
style=style,
|
||||||
|
vertical=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_content_width(self, container: Size, viewport: Size) -> int:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
def get_content_height(self, container: Size, viewport: Size, width: int) -> int:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def on_click(self) -> None:
|
||||||
|
self.toggle()
|
||||||
|
|
||||||
|
def action_toggle(self) -> None:
|
||||||
|
self.toggle()
|
||||||
|
|
||||||
|
def toggle(self) -> None:
|
||||||
|
"""Toggle the checkbox value. As a result of the value changing,
|
||||||
|
a Checkbox.Changed message will be emitted."""
|
||||||
|
self.value = not self.value
|
||||||
|
|
||||||
|
class Changed(Message, bubble=True):
|
||||||
|
"""Checkbox was toggled."""
|
||||||
|
|
||||||
|
def __init__(self, sender: Checkbox, value: bool) -> None:
|
||||||
|
super().__init__(sender)
|
||||||
|
self.value = value
|
||||||
|
self.input = sender
|
||||||
@@ -85,7 +85,7 @@ class Input(Widget, can_focus=True):
|
|||||||
Binding("home", "home", "home", show=False),
|
Binding("home", "home", "home", show=False),
|
||||||
Binding("end", "end", "end", show=False),
|
Binding("end", "end", "end", show=False),
|
||||||
Binding("ctrl+d", "delete_right", "delete right", show=False),
|
Binding("ctrl+d", "delete_right", "delete right", show=False),
|
||||||
Binding("enter", "submit", "Submit", show=False),
|
Binding("enter", "submit", "submit", show=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
COMPONENT_CLASSES = {"input--cursor", "input--placeholder"}
|
COMPONENT_CLASSES = {"input--cursor", "input--placeholder"}
|
||||||
@@ -180,22 +180,6 @@ class Input(Widget, can_focus=True):
|
|||||||
return placeholder
|
return placeholder
|
||||||
return _InputRenderable(self, self._cursor_visible)
|
return _InputRenderable(self, self._cursor_visible)
|
||||||
|
|
||||||
class Changed(Message, bubble=True):
|
|
||||||
"""Value was changed."""
|
|
||||||
|
|
||||||
def __init__(self, sender: Input, value: str) -> None:
|
|
||||||
super().__init__(sender)
|
|
||||||
self.value = value
|
|
||||||
self.input = sender
|
|
||||||
|
|
||||||
class Submitted(Message, bubble=True):
|
|
||||||
"""Value was updated via enter key or blur."""
|
|
||||||
|
|
||||||
def __init__(self, sender: Input, value: str) -> None:
|
|
||||||
super().__init__(sender)
|
|
||||||
self.value = value
|
|
||||||
self.input = sender
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _value(self) -> Text:
|
def _value(self) -> Text:
|
||||||
"""Value rendered as text."""
|
"""Value rendered as text."""
|
||||||
@@ -323,3 +307,19 @@ class Input(Widget, can_focus=True):
|
|||||||
|
|
||||||
async def action_submit(self) -> None:
|
async def action_submit(self) -> None:
|
||||||
await self.emit(self.Submitted(self, self.value))
|
await self.emit(self.Submitted(self, self.value))
|
||||||
|
|
||||||
|
class Changed(Message, bubble=True):
|
||||||
|
"""Value was changed."""
|
||||||
|
|
||||||
|
def __init__(self, sender: Input, value: str) -> None:
|
||||||
|
super().__init__(sender)
|
||||||
|
self.value = value
|
||||||
|
self.input = sender
|
||||||
|
|
||||||
|
class Submitted(Message, bubble=True):
|
||||||
|
"""Value was updated via enter key or blur."""
|
||||||
|
|
||||||
|
def __init__(self, sender: Input, value: str) -> None:
|
||||||
|
super().__init__(sender)
|
||||||
|
self.value = value
|
||||||
|
self.input = sender
|
||||||
|
|||||||
46
tests/layouts/test_horizontal.py
Normal file
46
tests/layouts/test_horizontal.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
from textual.geometry import Size
|
||||||
|
from textual.layouts.horizontal import HorizontalLayout
|
||||||
|
from textual.widget import Widget
|
||||||
|
|
||||||
|
|
||||||
|
class SizedWidget(Widget):
|
||||||
|
"""Simple Widget wrapped allowing you to modify the return values for
|
||||||
|
get_content_width and get_content_height via the constructor."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*children: Widget,
|
||||||
|
content_width: int = 10,
|
||||||
|
content_height: int = 5,
|
||||||
|
):
|
||||||
|
super().__init__(*children)
|
||||||
|
self.content_width = content_width
|
||||||
|
self.content_height = content_height
|
||||||
|
|
||||||
|
def get_content_width(self, container: Size, viewport: Size) -> int:
|
||||||
|
return self.content_width
|
||||||
|
|
||||||
|
def get_content_height(self, container: Size, viewport: Size, width: int) -> int:
|
||||||
|
return self.content_height
|
||||||
|
|
||||||
|
|
||||||
|
CHILDREN = [
|
||||||
|
SizedWidget(content_width=10, content_height=5),
|
||||||
|
SizedWidget(content_width=4, content_height=2),
|
||||||
|
SizedWidget(content_width=12, content_height=3),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_get_content_width():
|
||||||
|
parent = Widget(*CHILDREN)
|
||||||
|
layout = HorizontalLayout()
|
||||||
|
width = layout.get_content_width(widget=parent, container=Size(), viewport=Size())
|
||||||
|
assert width == sum(child.content_width for child in CHILDREN)
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_get_content_width_no_children():
|
||||||
|
parent = Widget()
|
||||||
|
layout = HorizontalLayout()
|
||||||
|
container_size = Size(24, 24)
|
||||||
|
width = layout.get_content_width(widget=parent, container=container_size, viewport=Size())
|
||||||
|
assert width == container_size.width
|
||||||
File diff suppressed because one or more lines are too long
@@ -24,3 +24,9 @@ def test_vertical_layout(snap_compare):
|
|||||||
|
|
||||||
def test_dock_layout_sidebar(snap_compare):
|
def test_dock_layout_sidebar(snap_compare):
|
||||||
assert snap_compare("docs/examples/guide/layout/dock_layout2_sidebar.py")
|
assert snap_compare("docs/examples/guide/layout/dock_layout2_sidebar.py")
|
||||||
|
|
||||||
|
|
||||||
|
def test_checkboxes(snap_compare):
|
||||||
|
"""Tests checkboxes but also acts a regression test for using
|
||||||
|
width: auto in a Horizontal layout context."""
|
||||||
|
assert snap_compare("docs/examples/widgets/checkbox.py")
|
||||||
|
|||||||
Reference in New Issue
Block a user