mathy/pi_finder/ui/views.py
2025-11-05 12:20:31 +01:00

96 lines
2.9 KiB
Python

from __future__ import annotations
import curses
from typing import Optional
from .colors import UIColors
class HeaderView:
"""Top panel with live metrics."""
def __init__(self, height: int, width: int, y: int, x: int) -> None:
self.win = curses.newwin(height, width, y, x)
def render(
self,
iteration: int,
digits: int,
elapsed: float,
rate: float,
last_digit: Optional[str],
computing: bool,
) -> None:
self.win.erase()
style = UIColors.style(UIColors.HEADER, bold=True)
metric_style = UIColors.style(UIColors.METRIC, bold=True)
status_style = UIColors.style(UIColors.STATUS)
lines = [
" π Stream Dashboard ",
f" Iteration: {iteration:,}",
f" Digits: {digits:,}",
f" Elapsed: {elapsed:8.2f}s • Rate: {rate:8.2f} digits/s",
]
status = " Generating…" if computing else " Idle"
digit_line = f" Last digit: {last_digit if last_digit is not None else ''}"
try:
self.win.addstr(0, 0, lines[0], style)
self.win.addstr(1, 0, lines[1], metric_style)
self.win.addstr(2, 0, lines[2], metric_style)
self.win.addstr(3, 0, lines[3], metric_style)
self.win.addstr(4, 0, digit_line, metric_style)
self.win.addstr(5, 0, status, status_style)
width = max(1, self.win.getmaxyx()[1] - 1)
self.win.addstr(6, 0, "" * width, UIColors.style(UIColors.SEPARATOR))
except curses.error:
pass
self.win.noutrefresh()
class DigitsView:
"""Scrollable window for the π digits."""
def __init__(self, height: int, width: int, y: int, x: int) -> None:
self.win = curses.newwin(height, width, y, x)
def render(self, digits_text: str, scroll: int) -> int:
self.win.erase()
max_y, max_x = self.win.getmaxyx()
if max_y <= 0 or max_x <= 0:
self.win.noutrefresh()
return 0
cols = max(1, max_x - 1)
chunks = [digits_text[i : i + cols] for i in range(0, len(digits_text), cols)] or ["0"]
max_scroll = max(0, len(chunks) - max_y)
scroll = max(0, min(scroll, max_scroll))
style = UIColors.style(UIColors.NUMBER)
for idx, chunk in enumerate(chunks[scroll : scroll + max_y]):
try:
self.win.addstr(idx, 0, chunk, style)
except curses.error:
break
self.win.noutrefresh()
return scroll
class HelpView:
"""Bottom row with key hints."""
def __init__(self, y: int, x: int, width: int) -> None:
self.win = curses.newwin(1, width, y, x)
def render(self) -> None:
message = " ↑↓ scroll • q quit"
try:
self.win.addstr(0, 0, message, UIColors.style(UIColors.STATUS, dim=True))
except curses.error:
pass
self.win.noutrefresh()