| | """ |
| | Collection of reusable components for building full screen applications. |
| | """ |
| |
|
| | from __future__ import annotations |
| |
|
| | from typing import Sequence |
| |
|
| | from prompt_toolkit.filters import has_completions, has_focus |
| | from prompt_toolkit.formatted_text import AnyFormattedText |
| | from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous |
| | from prompt_toolkit.key_binding.key_bindings import KeyBindings |
| | from prompt_toolkit.layout.containers import ( |
| | AnyContainer, |
| | DynamicContainer, |
| | HSplit, |
| | VSplit, |
| | ) |
| | from prompt_toolkit.layout.dimension import AnyDimension |
| | from prompt_toolkit.layout.dimension import Dimension as D |
| |
|
| | from .base import Box, Button, Frame, Shadow |
| |
|
| | __all__ = [ |
| | "Dialog", |
| | ] |
| |
|
| |
|
| | class Dialog: |
| | """ |
| | Simple dialog window. This is the base for input dialogs, message dialogs |
| | and confirmation dialogs. |
| | |
| | Changing the title and body of the dialog is possible at runtime by |
| | assigning to the `body` and `title` attributes of this class. |
| | |
| | :param body: Child container object. |
| | :param title: Text to be displayed in the heading of the dialog. |
| | :param buttons: A list of `Button` widgets, displayed at the bottom. |
| | """ |
| |
|
| | def __init__( |
| | self, |
| | body: AnyContainer, |
| | title: AnyFormattedText = "", |
| | buttons: Sequence[Button] | None = None, |
| | modal: bool = True, |
| | width: AnyDimension = None, |
| | with_background: bool = False, |
| | ) -> None: |
| | self.body = body |
| | self.title = title |
| |
|
| | buttons = buttons or [] |
| |
|
| | |
| | buttons_kb = KeyBindings() |
| | if len(buttons) > 1: |
| | first_selected = has_focus(buttons[0]) |
| | last_selected = has_focus(buttons[-1]) |
| |
|
| | buttons_kb.add("left", filter=~first_selected)(focus_previous) |
| | buttons_kb.add("right", filter=~last_selected)(focus_next) |
| |
|
| | frame_body: AnyContainer |
| | if buttons: |
| | frame_body = HSplit( |
| | [ |
| | |
| | Box( |
| | body=DynamicContainer(lambda: self.body), |
| | padding=D(preferred=1, max=1), |
| | padding_bottom=0, |
| | ), |
| | |
| | Box( |
| | body=VSplit(buttons, padding=1, key_bindings=buttons_kb), |
| | height=D(min=1, max=3, preferred=3), |
| | ), |
| | ] |
| | ) |
| | else: |
| | frame_body = body |
| |
|
| | |
| | kb = KeyBindings() |
| | kb.add("tab", filter=~has_completions)(focus_next) |
| | kb.add("s-tab", filter=~has_completions)(focus_previous) |
| |
|
| | frame = Shadow( |
| | body=Frame( |
| | title=lambda: self.title, |
| | body=frame_body, |
| | style="class:dialog.body", |
| | width=(None if with_background is None else width), |
| | key_bindings=kb, |
| | modal=modal, |
| | ) |
| | ) |
| |
|
| | self.container: Box | Shadow |
| | if with_background: |
| | self.container = Box(body=frame, style="class:dialog", width=width) |
| | else: |
| | self.container = frame |
| |
|
| | def __pt_container__(self) -> AnyContainer: |
| | return self.container |
| |
|