Implement a Progress Bar widget. (#2333)

* First prototype of PB.

* Repurpose UnderlineBar.

* Factor out 'Bar' widget.

* Revert "Factor out 'Bar' widget."

This reverts commit 0bb4871adf.

* Add Bar widget.

* Cap progress at 100%.

* Add skeleton for the ETA label.

[skip ci]

* Add ETA display.

* Improve docstrings.

* Directly compute percentage.

* Watch percentage changes directly.

[skip ci]

* Documentation.

* Make reactive percentage private.

Instead, we create a public read-only percentage property.

* Update griffe to fix documentation issue.

Related issues: #1572, https://github.com/mkdocstrings/griffe/issues/128.
Related PRs: https://github.com/mkdocstrings/griffe/pull/135.

* Add example and docs.

* Address review feedback.

[skip ci]

* More documentation.

* Add tests.

* Changelog.

* More tests.

* Fix/fake tests.

* Final tweaks.
This commit is contained in:
Rodrigo Girão Serrão
2023-04-26 15:25:39 +01:00
committed by GitHub
parent ee0d407067
commit 4148b1d450
20 changed files with 2242 additions and 262 deletions

View File

@@ -4,7 +4,7 @@ from rich.console import Console, ConsoleOptions
from rich.text import Text
from tests.utilities.render import render
from textual.renderables.underline_bar import UnderlineBar
from textual.renderables.bar import Bar
MAGENTA = "\x1b[35m"
GREY = "\x1b[38;5;59m"
@@ -14,22 +14,22 @@ RED = "\x1b[31m"
def test_no_highlight():
bar = UnderlineBar(width=6)
bar = Bar(width=6)
assert render(bar) == f"{GREY}━━━━━━{STOP}"
def test_highlight_from_zero():
bar = UnderlineBar(highlight_range=(0, 2.5), width=6)
bar = Bar(highlight_range=(0, 2.5), width=6)
assert render(bar) == (f"{MAGENTA}━━{STOP}{MAGENTA}{STOP}{GREY}━━━{STOP}")
def test_highlight_from_zero_point_five():
bar = UnderlineBar(highlight_range=(0.5, 2), width=6)
bar = Bar(highlight_range=(0.5, 2), width=6)
assert render(bar) == (f"{MAGENTA}╺━{STOP}{GREY}{STOP}{GREY}━━━{STOP}")
def test_highlight_middle():
bar = UnderlineBar(highlight_range=(2, 4), width=6)
bar = Bar(highlight_range=(2, 4), width=6)
assert render(bar) == (
f"{GREY}{STOP}"
f"{GREY}{STOP}"
@@ -40,14 +40,14 @@ def test_highlight_middle():
def test_highlight_half_start():
bar = UnderlineBar(highlight_range=(2.5, 4), width=6)
bar = Bar(highlight_range=(2.5, 4), width=6)
assert render(bar) == (
f"{GREY}━━{STOP}" f"{MAGENTA}╺━{STOP}" f"{GREY}{STOP}" f"{GREY}{STOP}"
)
def test_highlight_half_end():
bar = UnderlineBar(highlight_range=(2, 4.5), width=6)
bar = Bar(highlight_range=(2, 4.5), width=6)
assert render(bar) == (
f"{GREY}{STOP}"
f"{GREY}{STOP}"
@@ -58,46 +58,46 @@ def test_highlight_half_end():
def test_highlight_half_start_and_half_end():
bar = UnderlineBar(highlight_range=(2.5, 4.5), width=6)
bar = Bar(highlight_range=(2.5, 4.5), width=6)
assert render(bar) == (
f"{GREY}━━{STOP}" f"{MAGENTA}╺━{STOP}" f"{MAGENTA}{STOP}" f"{GREY}{STOP}"
)
def test_highlight_to_near_end():
bar = UnderlineBar(highlight_range=(3, 5.5), width=6)
bar = Bar(highlight_range=(3, 5.5), width=6)
assert render(bar) == (
f"{GREY}━━{STOP}" f"{GREY}{STOP}" f"{MAGENTA}━━{STOP}" f"{MAGENTA}{STOP}"
)
def test_highlight_to_end():
bar = UnderlineBar(highlight_range=(3, 6), width=6)
bar = Bar(highlight_range=(3, 6), width=6)
assert render(bar) == (f"{GREY}━━{STOP}{GREY}{STOP}{MAGENTA}━━━{STOP}")
def test_highlight_out_of_bounds_start():
bar = UnderlineBar(highlight_range=(-2, 3), width=6)
bar = Bar(highlight_range=(-2, 3), width=6)
assert render(bar) == (f"{MAGENTA}━━━{STOP}{GREY}{STOP}{GREY}━━{STOP}")
def test_highlight_out_of_bounds_end():
bar = UnderlineBar(highlight_range=(3, 9), width=6)
bar = Bar(highlight_range=(3, 9), width=6)
assert render(bar) == (f"{GREY}━━{STOP}{GREY}{STOP}{MAGENTA}━━━{STOP}")
def test_highlight_full_range_out_of_bounds_end():
bar = UnderlineBar(highlight_range=(9, 10), width=6)
bar = Bar(highlight_range=(9, 10), width=6)
assert render(bar) == f"{GREY}━━━━━━{STOP}"
def test_highlight_full_range_out_of_bounds_start():
bar = UnderlineBar(highlight_range=(-5, -2), width=6)
bar = Bar(highlight_range=(-5, -2), width=6)
assert render(bar) == f"{GREY}━━━━━━{STOP}"
def test_custom_styles():
bar = UnderlineBar(
bar = Bar(
highlight_range=(2, 4), highlight_style="red", background_style="green", width=6
)
assert render(bar) == (
@@ -110,7 +110,7 @@ def test_custom_styles():
def test_clickable_ranges():
bar = UnderlineBar(
bar = Bar(
highlight_range=(0, 1), width=6, clickable_ranges={"foo": (0, 2), "bar": (4, 5)}
)