aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py3/prompt_toolkit/widgets/dialogs.py
blob: d814d275eacd01e8fb3ca836cade6140290069c1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
""" 
Collection of reusable components for building full screen applications. 
""" 
from typing import Optional, Sequence, Union 
 
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: Optional[Sequence[Button]] = 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: Union[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