123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- """
- 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 []
- # When a button is selected, handle left/right key bindings.
- 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(
- [
- # Add optional padding around the body.
- Box(
- body=DynamicContainer(lambda: self.body),
- padding=D(preferred=1, max=1),
- padding_bottom=0,
- ),
- # The buttons.
- Box(
- body=VSplit(buttons, padding=1, key_bindings=buttons_kb),
- height=D(min=1, max=3, preferred=3),
- ),
- ]
- )
- else:
- frame_body = body
- # Key bindings for whole dialog.
- 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
|