Пример #1
0
def main():
    style = Style([
        ('terminal not-focused', '#888888'),
        ('title', 'bg:#000044 #ffffff underline'),
    ])

    done_count = [0]  # nonlocal.

    def done():
        done_count[0] += 1
        if done_count[0] == 2:
            application.exit()
        else:
            switch_focus()

    term1 = Terminal(width=D(preferred=80),
                     height=D(preferred=40),
                     style='class:terminal',
                     done_callback=done)

    term2 = Terminal(width=D(preferred=80),
                     height=D(preferred=40),
                     style='class:terminal',
                     done_callback=done)

    kb = KeyBindings()

    @kb.add('c-w')
    def _(event):
        switch_focus()

    def switch_focus():
        " Change focus when Control-W is pressed."
        if application.layout.has_focus(term1):
            application.layout.focus(term2)
        else:
            application.layout.focus(term1)

    application = Application(
        layout=Layout(container=HSplit([
            Window(
                height=1,
                style='class:title',
                content=FormattedTextControl(
                    HTML(
                        ' Press <u fg="#ff8888"><b>Control-W</b></u> to <b>switch focus</b>.'
                    ))),
            VSplit([
                term1,
                Window(style='bg:#aaaaff', width=1),
                term2,
            ]),
        ]),
                      focused_element=term1),
        style=style,
        key_bindings=kb,
        full_screen=True,
        mouse_support=True,
    )
    application.run()
Пример #2
0
    def __init__(self, title='', label_text='', completer=None):
        self.future = Future()

        def accept_text():
            get_app().layout.focus(ok_button)
            self.text_area.buffer.complete_state = None

        def accept():
            self.future.set_result(self.text_area.text)

        def cancel():
            self.future.set_result(None)

        self.text_area = TextArea(
            completer=completer,
            multiline=False,
            width=D(preferred=40),
            accept_handler=accept_text)

        ok_button = Button(text='OK', handler=accept)
        cancel_button = Button(text='Cancel', handler=cancel)

        self.dialog = Dialog(
            title=title,
            body=HSplit([
                Label(text=label_text),
                self.text_area
            ]),
            buttons=[ok_button, cancel_button],
            width=D(preferred=80),
            modal=True)
        def get():
            result = []

            # Padding left.
            if self.align in (HorizontalAlign.CENTER, HorizontalAlign.RIGHT):
                result.append(Window(width=D(preferred=0)))

            # Border left is first inserted in children loop.

            # The children with padding.
            c = 0
            for child in self.children:
                result.append(_VerticalBorder(borders=self.borders))
                result.append(child)
                c += child.merge
            # Fill in any missing columns
            for _ in range(self.columns - c):
                result.append(_VerticalBorder(borders=self.borders))
                result.append(_Cell(cell=None, table=self.table, row=self))

            # Border right.
            result.append(_VerticalBorder(borders=self.borders))

            # Padding right.
            if self.align in (HorizontalAlign.CENTER, HorizontalAlign.LEFT):
                result.append(Window(width=D(preferred=0)))

            return result
        def get():
            result = []

            # Padding top.
            if self.align in (VerticalAlign.CENTER, VerticalAlign.BOTTOM):
                result.append(Window(width=D(preferred=0)))

            # Border top is first inserted in children loop.

            # The children with padding.
            prev = None
            for child in self.children:
                result.append(_Border(
                    prev=prev,
                    next=child,
                    table=self,
                    borders=self.borders))
                result.append(child)
                prev = child

            # Border bottom.
            result.append(_Border(prev=prev, next=None, table=self, borders=self.borders))

            # Padding bottom.
            if self.align in (VerticalAlign.CENTER, VerticalAlign.TOP):
                result.append(Window(width=D(preferred=0)))

            return result
Пример #5
0
    def __init__(self, title="", label_text="", completer=None):
        self.future = Future()

        def accept_text(buf):
            app.layout.focus(ok_button)
            buf.complete_state = None
            return True

        def accept():
            self.future.set_result(self.text_area.text)

        def cancel():
            self.future.set_result(None)

        self.text_area = TextArea(
            completer=completer,
            multiline=False,
            width=D(preferred=40),
            accept_handler=accept_text,
        )

        ok_button = Button(text="OK", handler=accept)
        cancel_button = Button(text="Cancel", handler=cancel)

        self.dialog = Dialog(
            title=title,
            body=HSplit([Label(text=label_text), self.text_area]),
            buttons=[ok_button, cancel_button],
            width=D(preferred=80),
            modal=True,
        )
Пример #6
0
    def __init__(self) -> None:
        self._percentage = 60

        self.label = Label('60%')
        self.container = FloatContainer(
            content=Window(height=1),
            floats=[
                # We first draw the label, then the actual progress bar.  Right
                # now, this is the only way to have the colors of the progress
                # bar appear on top of the label. The problem is that our label
                # can't be part of any `Window` below.
                Float(content=self.label, top=0, bottom=0),
                Float(left=0,
                      top=0,
                      right=0,
                      bottom=0,
                      content=VSplit([
                          Window(
                              style='class:progress-bar.used',
                              width=lambda: D(weight=int(self._percentage))),
                          Window(style='class:progress-bar',
                                 width=lambda: D(weight=int(100 - self.
                                                            _percentage))),
                      ])),
            ])
Пример #7
0
    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
Пример #8
0
    def get_width(self, progress_bar):
        if self.width:
            return self.width

        all_names = [self._add_suffix(c.label) for c in progress_bar.counters]
        if all_names:
            max_widths = max(get_cwidth(name) for name in all_names)
            return D(preferred=max_widths, max=max_widths)
        else:
            return D()
Пример #9
0
    def get_width(self, progress_bar):
        if self.width:
            return self.width

        all_labels = [self._add_suffix(c.label) for c in progress_bar.counters]
        if all_labels:
            max_widths = max(fragment_list_width(l) for l in all_labels)
            return D(preferred=max_widths, max=max_widths)
        else:
            return D()
Пример #10
0
 def get_width() -> AnyDimension:
     if width is None:
         text_fragments = to_formatted_text(self.text)
         text = fragment_list_to_text(text_fragments)
         if text:
             longest_line = max(get_cwidth(line) for line in text.splitlines())
         else:
             return D(preferred=0)
         return D(preferred=longest_line)
     else:
         return width
Пример #11
0
    def __init__(self,
                 body,
                 title='',
                 buttons=None,
                 modal=True,
                 width=None,
                 with_background=False):
        assert is_formatted_text(title)
        assert buttons is None or isinstance(buttons, list)

        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)

        if buttons:
            frame_body = HSplit([
                # Add optional padding around the body.
                Box(body=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=title,
            body=frame_body,
            style='class:dialog.body',
            width=(None if with_background is None else width),
            key_bindings=kb,
            modal=modal,
        ))

        if with_background:
            self.container = Box(body=frame, style='class:dialog', width=width)
        else:
            self.container = frame
        def get():
            result = []

            # Padding left.
            if self.align in (HorizontalAlign.CENTER, HorizontalAlign.RIGHT):
                result.append(Window(width=D(preferred=0)))

            def char(i, pc=False, nc=False):
                if i == 0:
                    if self.prev and self.next:
                        return self.borders.LEFT_T
                    elif self.prev:
                        return self.borders.BOTTOM_LEFT
                    else:
                        return self.borders.TOP_LEFT

                if i == self.columns:
                    if self.prev and self.next:
                        return self.borders.RIGHT_T
                    elif self.prev:
                        return self.borders.BOTTOM_RIGHT
                    else:
                        return self.borders.TOP_RIGHT

                if pc and nc:
                    return self.borders.INTERSECT
                elif pc:
                    return self.borders.BOTTOM_T
                elif nc:
                    return self.borders.TOP_T
                else:
                    return self.borders.HORIZONTAL

            # Border left is first inserted in children loop.

            # The children with padding.
            pcs = self.has_borders(self.prev)
            ncs = self.has_borders(self.next)
            for i, (child, pc, nc) in enumerate(zip(self.children, pcs, ncs)):
                result.append(_UnitBorder(char=char(i, pc, nc)))
                result.append(child)

            # Border right.
            result.append(_UnitBorder(char=char(self.columns)))

            # Padding right.
            if self.align in (HorizontalAlign.CENTER, HorizontalAlign.LEFT):
                result.append(Window(width=D(preferred=0)))

            return result
Пример #13
0
    def process_steps(self):
        if self.intro:
            layout = Window(
                FormattedTextControl(to_formatted_text(HTML(self.intro))),
                wrap_lines=True,
            )
            self.steps.append(
                {
                    'layout': layout,
                    'label': 'Introduction',
                    'handler': None,
                }, )

        for handler in self.handlers:
            layout = handler.get_layout()
            layout.align = HorizontalAlign.JUSTIFY
            self.steps.append(
                {
                    'layout': layout,
                    'label': handler.get_label(),
                    'handler': handler,
                }, )

        if self.summary:
            layout = Box(
                body=DynamicContainer(self.get_summary),
                padding=D(preferred=1, max=1),
                padding_bottom=1,
            )
            self.steps.append(
                {
                    'layout': layout,
                    'label': 'Summary',
                    'handler': None,
                }, )
Пример #14
0
    def __init__(self,
                 title='',
                 text='',
                 ok_text='Ok',
                 width=None,
                 wrap_lines=True,
                 scrollbar=False):
        self.future = Future()

        def accept_text(buf):
            get_app().layout.focus(ok_button)
            buf.complete_state = None
            return True

        def accept():
            self.future.set_result(self.text_area.text)

        def cancel():
            self.future.set_result(None)

        text_width = len(max(text.split('\n'), key=len)) + 2

        self.text_area = TextArea(completer=completer,
                                  multiline=False,
                                  width=D(preferred=text_width),
                                  accept_handler=accept_text)

        ok_button = Button(text='OK', handler=accept)
        cancel_button = Button(text='Cancel', handler=cancel)

        self.dialog = Dialog(title=title,
                             body=HSplit([Label(text=text), self.text_area]),
                             buttons=[ok_button, cancel_button],
                             width=width,
                             modal=True)
Пример #15
0
    def __init__(self, event, auth):

        super().__init__()

        self.event = event
        self.authtype = 'digest'

        authuser = auth.get('user', '')
        authpass = auth.get('password', '')

        self.authuser.text = authuser
        self.authuser.buffer.document = Document(authuser, len(authuser))

        self.authpass_one.text = authpass
        self.authpass_one.buffer.document = Document(authpass, len(authpass))

        self.authpass_two.text = authpass
        self.authpass_two.buffer.document = Document(authpass, len(authpass))

        self.dialog = Dialog(
            title='Digest Authentication',
            body=HSplit([
                Label(text='Username:\n'), self.authuser,
                Window(height=1, char=' '),
                Label(text='Password'), self.authpass_one,
                Window(height=1, char=' '),
                Label(text='Retype password'), self.authpass_two
            ]),
            buttons=[self.ok_button, self.cancel_button, self.delete_button],
            width=D(preferred=80),
            with_background=True,
            modal=True)

        root_container.floats.append(Float(self.dialog))
        event.app.layout.focus(self.dialog)
Пример #16
0
    def __init__(self, event, dialog):
        def ok_handler():
            root_container.floats.pop()
            db.update_one(values={'name': name, 'auth': None})
            event.app.layout.focus(ButtonManager.prev_button)
            select_item(event)

        def cancel_handler():
            root_container.floats.pop()
            root_container.floats.append(self.auth_float)
            event.app.layout.focus(dialog)

        ok_button = Button(text='OK', handler=ok_handler)
        cancel_button = Button(text='Cancel', handler=cancel_handler)

        name = ButtonManager.current_button

        self.dialog = Dialog(
            title='Delete confirmation',
            body=Label(
                text='Are you sure you want to delete authentication for {}?'.
                format(name)),
            buttons=[cancel_button, ok_button],
            width=D(preferred=80),
            with_background=True)

        self.auth_float = root_container.floats.pop()
        root_container.floats.append(Float(self.dialog))
        event.app.layout.focus(self.dialog)
Пример #17
0
 def get_layout(self):
     widget = self.get_widget()
     vsplit_components = [widget]
     if 'message' in self._question and self._question['message']:
         vsplit_components.insert(
             0,
             Label(
                 self._question['message'],
                 dont_extend_width=True,
                 dont_extend_height=False,
                 style='class:input.question',
             ),
         )
     hsplit_components = [VSplit(vsplit_components, padding=1)]
     if 'description' in self._question and self._question['description']:
         hsplit_components.insert(
             0,
             Window(
                 FormattedTextControl(
                     FormattedText([(
                         'class:input.question',
                         self._question['description'],
                     )]), ),
                 wrap_lines=True,
                 height=D(min=1, max=5, preferred=3),
             ),
         )
     return HSplit(hsplit_components, padding=1)
Пример #18
0
    def __init__(self, title, text, asking=False):
        self.future = Future()

        def set_done():
            self.future.set_result(None)

        def accept():
            self.future.set_result(True)

        def cancel():
            self.future.set_result(False)

        if asking:
            buttons = [
                Button(text="Yes", handler=accept),
                Button(text="No", handler=cancel),
            ]
        else:
            buttons = [Button(text="OK", handler=set_done)]

        text = "\n".join(
            [textwrap.fill(line, width=71) for line in text.splitlines()])
        self.dialog = Dialog(
            title=title,
            body=HSplit([Label(text=text)]),
            buttons=buttons,
            width=D(preferred=75),
            modal=True,
        )
Пример #19
0
    def __init__(self, event):
        def ok_handler():
            # if len(ButtonManager.buttons) > 0:
            delete_server(event, name)
            root_container.floats.pop()

        def cancel_handler():
            root_container.floats.pop()
            event.app.layout.focus(ButtonManager.prev_button)

        # Get data about server currently editing
        name = ButtonManager.current_button

        # Dialog configuration
        ok_button = Button(text='OK', handler=ok_handler)
        cancel_button = Button(text='Cancel', handler=cancel_handler)

        self.dialog = Dialog(
            title='Delete confirmation',
            body=Label(
                text='Are you sure you want to delete {}?'.format(name)),
            buttons=[cancel_button, ok_button],
            width=D(preferred=80),
            with_background=True)

        root_container.floats.append(Float(self.dialog))
        event.app.layout.focus(self.dialog)
Пример #20
0
    def __init__(self, title, text, yes_text, no_text, button=None):
        self.future = Future()

        def yes_handler():
            self.future.set_result(True)

        def no_handler():
            self.future.set_result(None)

        self.buttons = [
            Button(text=yes_text, handler=yes_handler),
            Button(text=no_text, handler=no_handler),
        ]

        if button:
            self.buttons.insert(
                1, Button(text=button[0], handler=lambda: button[1](self)))

        self.dialog = Dialog(
            title=title,
            body=HSplit([Label(text=text)]),
            buttons=self.buttons,
            width=D(preferred=50),
            modal=True,
        )
Пример #21
0
 def create_content(self, progress_controls):
     return VSplit(
         progress_controls,
         height=lambda: D(
             preferred=len(self.models), max=len(self.models)
         ),
     )
Пример #22
0
    def get_dimensions(cli):
        """
        Return a list of LayoutDimension instances for this split.
        These dimensions will take the weight from the
        arrangement.VSplit/HSplit instances.
        """
        average_weight = get_average_weight()

        # Make sure that weight is distributed

        result = []
        for i, item in enumerate(split):
            result.append(D(weight=split.weights.get(item) or average_weight))

            # Add dimension for the vertical border.
            last_item = i == len(split) - 1
            if is_vsplit and not last_item:
                result.append(D.exact(1))
            elif is_hsplit and not last_item:
                if pymux.enable_pane_status:
                    result.append(D.exact(0))
                else:
                    result.append(D.exact(1))

        return result
Пример #23
0
    def __init__(
        self,
        text: AnyFormattedText,
        style: str = "",
        width: AnyDimension = None,
        dont_extend_height: bool = True,
        dont_extend_width: bool = False,
    ) -> None:

        self.text = text

        def get_width() -> AnyDimension:
            if width is None:
                text_fragments = to_formatted_text(self.text)
                text = fragment_list_to_text(text_fragments)
                if text:
                    longest_line = max(
                        get_cwidth(line) for line in text.splitlines())
                else:
                    return D(preferred=0)
                return D(preferred=longest_line)
            else:
                return width

        self.formatted_text_control = FormattedTextControl(
            text=lambda: self.text)

        self.window = Window(
            content=self.formatted_text_control,
            width=get_width,
            height=D(min=1),
            style="class:label " + style,
            dont_extend_height=dont_extend_height,
            dont_extend_width=dont_extend_width,
        )
Пример #24
0
    def __init__(self, body, padding=None,
                 padding_left=None, padding_right=None,
                 padding_top=None, padding_bottom=None,
                 width=None, height=None,
                 style='', char=None, modal=False, key_bindings=None):
        assert is_container(body)

        if padding is None:
            padding = D(preferred=0)

        def get(value):
            if value is None:
                value = padding
            return to_dimension(value)

        self.padding_left = get(padding_left)
        self.padding_right = get(padding_right)
        self.padding_top = get(padding_top)
        self.padding_bottom = get(padding_bottom)
        self.body = body

        self.container = HSplit([
            Window(height=self.padding_top, char=char),
            VSplit([
                Window(width=self.padding_left, char=char),
                body,
                Window(width=self.padding_right, char=char),
            ]),
            Window(height=self.padding_bottom, char=char),
        ],
        width=width, height=height, style=style, modal=modal,
        key_bindings=None)
Пример #25
0
def make_app(sec, width, height, frame=True, gcalender=None, color=False):
    """make auto refresh application class"""
    kb = KeyBindings()

    @kb.add('c-c')
    def _(event):
        event.app.exit()

    def _vsplit(padding, m):
        return VSplit([Window(width=padding, always_hide_cursor=True), m, Window(width=padding, always_hide_cursor=True)])

    if height == 14:
        clock = BigClock(sec=sec, color=color, gcalender=gcalender)
    elif height == 7:
        clock = MinimumClock(sec=sec, color=color, gcalender=gcalender)
    else:
        clock = SmallClock(sec=sec, color=color, gcalender=gcalender)
    padding = to_dimension(D(preferred=0))
    body = Window(content=FormattedTextControl(text=clock.get_clock), width=width, height=height, always_hide_cursor=True)
    if frame:
        body = Frame(body)
    if gcalender is None:
        under_text = Window(height=padding, always_hide_cursor=True)
    else:
        ct = gcalender.get_calender_text_formatted if color else gcalender.get_calender_text
        under_text = Window(content=FormattedTextControl(text=ct), width=gcalender.get_max_length(), height=padding, always_hide_cursor=True)

    # make container app
    root_container = HSplit([Window(height=padding, always_hide_cursor=True), _vsplit(padding, body), _vsplit(padding, under_text)], key_bindings=None)
    layout = Layout(container=root_container)
    return Application(layout=layout, key_bindings=kb, full_screen=True, refresh_interval=.1)
Пример #26
0
    def __init__(self, event=None, title='', text=''):

        content = Window(height=3,
                         align=WindowAlign.CENTER,
                         content=FormattedTextControl(text=text,
                                                      show_cursor=False,
                                                      modal=True))

        body = HSplit([
            Window(height=1, char=' '),
            content,
            Window(height=1, char=' '),
        ],
                      padding=1)

        dialog = Dialog(body,
                        title=title,
                        width=D(preferred=80),
                        with_background=True)

        loading_float = Float(content=dialog)

        root_container.floats.append(loading_float)

        self.focus = event.app.layout.focus
        self.focus(content)
Пример #27
0
    def __enter__(self):
        # Create UI Application.
        title_toolbar = ConditionalContainer(
            Window(FormattedTextControl(lambda: self.title),
                   height=1,
                   style='class:progressbar,title'),
            filter=Condition(lambda: self.title is not None))

        bottom_toolbar = ConditionalContainer(
            Window(FormattedTextControl(lambda: self.bottom_toolbar,
                                        style='class:bottom-toolbar.text'),
                   style='class:bottom-toolbar',
                   height=1),
            filter=~is_done & renderer_height_is_known
            & Condition(lambda: self.bottom_toolbar is not None))

        def width_for_formatter(formatter):
            return formatter.get_width(progress_bar=self)

        progress_controls = [
            Window(content=_ProgressControl(self, f),
                   width=width_for_formatter(f)) for f in self.formatters
        ]

        self.app = Application(
            min_redraw_interval=.05,
            layout=Layout(
                HSplit([
                    title_toolbar,
                    VSplit(progress_controls,
                           height=lambda: D(preferred=len(self.counters),
                                            max=len(self.counters))),
                    Window(),
                    bottom_toolbar,
                ])),
            style=self.style,
            key_bindings=self.key_bindings,
            output=self.output,
            input=self.input)

        # Run application in different thread.
        def run():
            with _auto_refresh_context(self.app, .3):
                try:
                    self.app.run()
                except Exception as e:
                    traceback.print_exc()
                    print(e)

        self._thread = threading.Thread(target=run)
        self._thread.start()

        # Attach WINCH signal handler in main thread.
        # (Interrupt that we receive during resize events.)
        self._has_sigwinch = hasattr(signal, 'SIGWINCH') and in_main_thread()
        if self._has_sigwinch:
            self._previous_winch_handler = self._loop.add_signal_handler(
                signal.SIGWINCH, self.app.invalidate)

        return self
Пример #28
0
def input_dialog(title='', text='', ok_text='OK', cancel_text='Cancel',
                 completer=None, password=False, style=None, async_=False):
    """
    Display a text input box.
    Return the given text, or None when cancelled.
    """
    def accept(buf):
        get_app().layout.focus(ok_button)
        return True  # Keep text.

    def ok_handler():
        get_app().exit(result=textfield.text)

    ok_button = Button(text=ok_text, handler=ok_handler)
    cancel_button = Button(text=cancel_text, handler=_return_none)

    textfield = TextArea(
        multiline=False,
        password=password,
        completer=completer,
        accept_handler=accept)

    dialog = Dialog(
        title=title,
        body=HSplit([
            Label(text=text, dont_extend_height=True),
            textfield,
        ], padding=D(preferred=1, max=1)),
        buttons=[ok_button, cancel_button],
        with_background=True)

    return _run_dialog(dialog, style, async_=async_)
Пример #29
0
    def __init__(self, event, title='', text=''):
        def ok_handler():
            root_container.floats.pop()

            # If there was an original dialog, insert it back into layout
            if self.orig_dialog:
                root_container.floats.append(self.orig_dialog)
                event.app.layout.focus(root_container.float_container)
            else:
                event.app.layout.focus(ButtonManager.prev_button)

        ok_button = Button(text='OK', handler=ok_handler)

        dialog = Dialog(Window(wrap_lines=True,
                               content=FormattedTextControl(text=text),
                               always_hide_cursor=True),
                        title=title,
                        width=D(preferred=80),
                        buttons=[ok_button],
                        with_background=True)

        try:
            # If a dialog was already up, save it
            self.orig_dialog = root_container.floats.pop()
        except IndexError:
            self.orig_dialog = None

        root_container.floats.append(Float(content=dialog))
        event.app.layout.focus(ok_button)
Пример #30
0
def progress_dialog(
    title: AnyFormattedText = "",
    text: AnyFormattedText = "",
    run_callback: Callable[[Callable[[int], None], Callable[[str], None]], None] = (
        lambda *a: None
    ),
    style: Optional[BaseStyle] = None,
) -> Application[None]:
    """
    :param run_callback: A function that receives as input a `set_percentage`
        function and it does the work.
    """
    loop = get_event_loop()
    progressbar = ProgressBar()
    text_area = TextArea(
        focusable=False,
        # Prefer this text area as big as possible, to avoid having a window
        # that keeps resizing when we add text to it.
        height=D(preferred=10 ** 10),
    )

    dialog = Dialog(
        body=HSplit(
            [
                Box(Label(text=text)),
                Box(text_area, padding=D.exact(1)),
                progressbar,
            ]
        ),
        title=title,
        with_background=True,
    )
    app = _create_app(dialog, style)

    def set_percentage(value: int) -> None:
        progressbar.percentage = int(value)
        app.invalidate()

    def log_text(text: str) -> None:
        loop.call_soon_threadsafe(text_area.buffer.insert_text, text)
        app.invalidate()

    # Run the callback in the executor. When done, set a return value for the
    # UI, so that it quits.
    def start() -> None:
        try:
            run_callback(set_percentage, log_text)
        finally:
            app.exit()

    def pre_run() -> None:
        run_in_executor_with_context(start)

    app.pre_run_callables.append(pre_run)

    return app