aboutsummaryrefslogtreecommitdiff
path: root/app/ui/tui.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/ui/tui.py')
-rw-r--r--app/ui/tui.py51
1 files changed, 46 insertions, 5 deletions
diff --git a/app/ui/tui.py b/app/ui/tui.py
index a647444..933626f 100644
--- a/app/ui/tui.py
+++ b/app/ui/tui.py
@@ -1492,9 +1492,50 @@ def checkbox_tree(scr, title: str, families: List[dict],
if options:
checked.add((index, options[0]["key"]))
expanded.add(index)
+ else:
+ _, index, option_key = node
+ if (index, option_key) in checked:
+ checked.discard((index, option_key))
else:
- _, index, option_key = node
- if (index, option_key) in checked:
- checked.discard((index, option_key))
- else:
- checked.add((index, option_key))
+ checked.add((index, option_key))
+
+
+# ---------------------------------------------------------------------------
+# Widget: scrollable text viewer
+# ---------------------------------------------------------------------------
+
+def text_viewer(scr, title: str, lines: Sequence[str],
+ back_value: object = None) -> object:
+ """Show LINES as a read-only dialog; Esc/q/Enter closes it.
+
+ A scrollable pop-up for longer explanatory text (the hub's Help
+ screen). Rows wrap like body rows and stay centered; none is
+ selectable, so no cursor bar is drawn — but the (logical) cursor
+ still scrolls the view into place: Up/Down (or k/j) move one line,
+ Home/End jump to the top/bottom, PageUp/PageDown page, and the
+ frame's scroll indicator (``x/y`` in the border) appears whenever
+ the text overflows the dialog. Closing returns BACK_VALUE when it
+ is given (not None), so the caller can fall back a screen; without
+ one, Esc/q raise WizardCancelled as in menu().
+ """
+ frame = Frame(scr, title,
+ "Up/Down = scroll PgUp/PgDn = page Enter/Esc = close")
+ for line in lines:
+ frame.mark(line)
+ cursor = 0
+ while True:
+ cursor = max(0, min(cursor, len(frame.rows) - 1))
+ frame.cursor = cursor if frame.rows else None
+ frame.draw()
+ key = frame.get_key(cancel_keys=())
+ if key in _CANCEL_KEYS:
+ if back_value is not None:
+ return back_value
+ raise WizardCancelled()
+ moved = frame.motion(key, cursor, len(frame.rows))
+ if moved is not None:
+ cursor = moved
+ elif key in (10, 13):
+ if back_value is not None:
+ return back_value
+ raise WizardCancelled()