summaryrefslogtreecommitdiffstats
path: root/examples/fullscreen.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--examples/fullscreen.py185
1 files changed, 185 insertions, 0 deletions
diff --git a/examples/fullscreen.py b/examples/fullscreen.py
new file mode 100644
index 0000000..507eed1
--- /dev/null
+++ b/examples/fullscreen.py
@@ -0,0 +1,185 @@
+"""
+Demonstrates a Rich "application" using the Layout and Live classes.
+
+"""
+
+from datetime import datetime
+
+from rich import box
+from rich.align import Align
+from rich.console import Console, RenderGroup
+from rich.layout import Layout
+from rich.panel import Panel
+from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn
+from rich.syntax import Syntax
+from rich.table import Table
+from rich.text import Text
+
+console = Console()
+
+
+def make_layout() -> Layout:
+ """Define the layout."""
+ layout = Layout(name="root")
+
+ layout.split(
+ Layout(name="header", size=3),
+ Layout(name="main", ratio=1),
+ Layout(name="footer", size=7),
+ )
+ layout["main"].split(
+ Layout(name="side"),
+ Layout(name="body", ratio=2, minimum_size=60),
+ direction="horizontal",
+ )
+ layout["side"].split(Layout(name="box1"), Layout(name="box2"))
+ return layout
+
+
+def make_sponsor_message() -> Panel:
+ """Some example content."""
+ sponsor_message = Table.grid(padding=1)
+ sponsor_message.add_column(style="green", justify="right")
+ sponsor_message.add_column(no_wrap=True)
+ sponsor_message.add_row(
+ "Sponsor me",
+ "[u blue link=https://github.com/sponsors/willmcgugan]https://github.com/sponsors/willmcgugan",
+ )
+ sponsor_message.add_row(
+ "Buy me a :coffee:",
+ "[u blue link=https://ko-fi.com/willmcgugan]https://ko-fi.com/willmcgugan",
+ )
+ sponsor_message.add_row(
+ "Twitter",
+ "[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan",
+ )
+ sponsor_message.add_row(
+ "Blog", "[u blue link=https://www.willmcgugan.com]https://www.willmcgugan.com"
+ )
+
+ intro_message = Text.from_markup(
+ """Consider supporting my work via Github Sponsors (ask your company / organization), or buy me a coffee to say thanks. - Will McGugan"""
+ )
+
+ message = Table.grid(padding=1)
+ message.add_column()
+ message.add_column(no_wrap=True)
+ message.add_row(intro_message, sponsor_message)
+
+ message_panel = Panel(
+ Align.center(
+ RenderGroup(intro_message, "\n", Align.center(sponsor_message)),
+ vertical="middle",
+ ),
+ box=box.ROUNDED,
+ padding=(1, 2),
+ title="[b red]Thanks for trying out Rich!",
+ border_style="bright_blue",
+ )
+ return message_panel
+
+
+class Header:
+ """Display header with clock."""
+
+ def __rich__(self) -> Panel:
+ grid = Table.grid(expand=True)
+ grid.add_column(justify="center", ratio=1)
+ grid.add_column(justify="right")
+ grid.add_row(
+ "[b]Rich[/b] Layout application",
+ datetime.now().ctime().replace(":", "[blink]:[/]"),
+ )
+ return Panel(grid, style="white on blue")
+
+
+def make_syntax() -> Syntax:
+ code = """\
+def ratio_resolve(total: int, edges: List[Edge]) -> List[int]:
+ sizes = [(edge.size or None) for edge in edges]
+
+ # While any edges haven't been calculated
+ while any(size is None for size in sizes):
+ # Get flexible edges and index to map these back on to sizes list
+ flexible_edges = [
+ (index, edge)
+ for index, (size, edge) in enumerate(zip(sizes, edges))
+ if size is None
+ ]
+ # Remaining space in total
+ remaining = total - sum(size or 0 for size in sizes)
+ if remaining <= 0:
+ # No room for flexible edges
+ sizes[:] = [(size or 0) for size in sizes]
+ break
+ # Calculate number of characters in a ratio portion
+ portion = remaining / sum((edge.ratio or 1) for _, edge in flexible_edges)
+
+ # If any edges will be less than their minimum, replace size with the minimum
+ for index, edge in flexible_edges:
+ if portion * edge.ratio <= edge.minimum_size:
+ sizes[index] = edge.minimum_size
+ break
+ else:
+ # Distribute flexible space and compensate for rounding error
+ # Since edge sizes can only be integers we need to add the remainder
+ # to the following line
+ _modf = modf
+ remainder = 0.0
+ for index, edge in flexible_edges:
+ remainder, size = _modf(portion * edge.ratio + remainder)
+ sizes[index] = int(size)
+ break
+ # Sizes now contains integers only
+ return cast(List[int], sizes)
+ """
+ syntax = Syntax(code, "python", line_numbers=True)
+ return syntax
+
+
+job_progress = Progress(
+ "{task.description}",
+ SpinnerColumn(),
+ BarColumn(),
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
+)
+job_progress.add_task("[green]Cooking")
+job_progress.add_task("[magenta]Baking", total=200)
+job_progress.add_task("[cyan]Mixing", total=400)
+
+total = sum(task.total for task in job_progress.tasks)
+overall_progress = Progress()
+overall_task = overall_progress.add_task("All Jobs", total=int(total))
+
+progress_table = Table.grid(expand=True)
+progress_table.add_row(
+ Panel(
+ overall_progress,
+ title="Overall Progress",
+ border_style="green",
+ padding=(2, 2),
+ ),
+ Panel(job_progress, title="[b]Jobs", border_style="red", padding=(1, 2)),
+)
+
+
+layout = make_layout()
+layout["header"].update(Header())
+layout["body"].update(make_sponsor_message())
+layout["box2"].update(Panel(make_syntax(), border_style="green"))
+layout["box1"].update(Panel(layout.tree, border_style="red"))
+layout["footer"].update(progress_table)
+
+
+from rich.live import Live
+from time import sleep
+
+with Live(layout, refresh_per_second=10, screen=True):
+ while not overall_progress.finished:
+ sleep(0.1)
+ for job in job_progress.tasks:
+ if not job.finished:
+ job_progress.advance(job.id)
+
+ completed = sum(task.completed for task in job_progress.tasks)
+ overall_progress.update(overall_task, completed=completed)