def checkboxlist_dialog( title: AnyFormattedText = '', text: AnyFormattedText = '', ok_text: str = 'Ok', cancel_text: str = 'Cancel', values: Optional[List[Tuple[_T, AnyFormattedText]]] = None, style: Optional[BaseStyle] = None) -> Application[List[_T]]: """ Display a simple list of element the user can choose multiple values amongst. Several elements can be selected at a time using Arrow keys and Enter. The focus can be moved between the list and the Ok/Cancel button with tab. """ if values is None: values = [] def ok_handler() -> None: get_app().exit(result=cb_list.current_values) cb_list = CheckboxList(values) dialog = Dialog(title=title, body=HSplit([ Label(text=text, dont_extend_height=True), cb_list, ], padding=1), buttons=[ Button(text=ok_text, handler=ok_handler), Button(text=cancel_text, handler=_return_none), ], with_background=True) return _create_app(dialog, style)
def __init__(self, title='', label_text='', completer=None): 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) 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 __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 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
def __init__(self, title, text): self.future = Future() def set_done(): self.future.set_result(None) ok_button = Button(text='OK', handler=(lambda: set_done())) self.dialog = Dialog(title=title, body=HSplit([ Label(text=text), ]), buttons=[ok_button], width=D(preferred=80), modal=True)
def __init__(self, body: AnyContainer, padding: AnyDimension = None, padding_left: AnyDimension = None, padding_right: AnyDimension = None, padding_top: AnyDimension = None, padding_bottom: AnyDimension = None, width: AnyDimension = None, height: AnyDimension = None, style: str = '', char: Union[None, str, Callable[[], str]] = None, modal: bool = False, key_bindings: Optional[KeyBindings] = None) -> None: if padding is None: padding = D(preferred=0) def get(value: AnyDimension) -> D: 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)
def test_layout_class(): c1 = BufferControl() c2 = BufferControl() c3 = BufferControl() win1 = Window(content=c1) win2 = Window(content=c2) win3 = Window(content=c3) layout = Layout(container=VSplit([HSplit([win1, win2]), win3])) # Listing of windows/controls. assert list(layout.find_all_windows()) == [win1, win2, win3] assert list(layout.find_all_controls()) == [c1, c2, c3] # Focusing something. layout.focus(c1) assert layout.has_focus(c1) assert layout.has_focus(win1) assert layout.current_control == c1 assert layout.previous_control == c1 layout.focus(c2) assert layout.has_focus(c2) assert layout.has_focus(win2) assert layout.current_control == c2 assert layout.previous_control == c1 layout.focus(win3) assert layout.has_focus(c3) assert layout.has_focus(win3) assert layout.current_control == c3 assert layout.previous_control == c2 # Pop focus. This should focus the previous control again. layout.focus_last() assert layout.has_focus(c2) assert layout.has_focus(win2) assert layout.current_control == c2 assert layout.previous_control == c1
def input_dialog(title: AnyFormattedText = '', text: AnyFormattedText = '', ok_text: str = 'OK', cancel_text: str = 'Cancel', completer: Optional[Completer] = None, password: FilterOrBool = False, style: Optional[BaseStyle] = None) -> Application[str]: """ Display a text input box. Return the given text, or None when cancelled. """ def accept(buf: Buffer) -> bool: get_app().layout.focus(ok_button) return True # Keep text. def ok_handler() -> None: 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 _create_app(dialog, style)
'mouse', 'rabbit', 'rat', 'snake', 'spider', 'turkey', 'turtle', ], ignore_case=True) # The layout buff = Buffer(completer=animal_completer, complete_while_typing=True) body = FloatContainer(content=HSplit([ Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'), Window(BufferControl(buffer=buff)), ]), floats=[ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1)) ]) # Key bindings kb = KeyBindings() @kb.add('q') @kb.add('c-c')
def test_create_invalid_layout(): with pytest.raises(InvalidLayoutError): Layout(HSplit([]))
body = HSplit([ Frame(Window(FormattedTextControl(TITLE), height=2), style='bg:#88ff88 #000000'), VSplit([ Window(FormattedTextControl(HTML(' <u>VerticalAlign.TOP</u>')), height=4, ignore_content_width=True, style='bg:#ff3333 #000000 bold', align=WindowAlign.CENTER), Window(FormattedTextControl(HTML(' <u>VerticalAlign.CENTER</u>')), height=4, ignore_content_width=True, style='bg:#ff3333 #000000 bold', align=WindowAlign.CENTER), Window(FormattedTextControl(HTML(' <u>VerticalAlign.BOTTOM</u>')), height=4, ignore_content_width=True, style='bg:#ff3333 #000000 bold', align=WindowAlign.CENTER), Window(FormattedTextControl(HTML(' <u>VerticalAlign.JUSTIFY</u>')), height=4, ignore_content_width=True, style='bg:#ff3333 #000000 bold', align=WindowAlign.CENTER), ], height=1, padding=1, padding_style='bg:#ff3333'), VSplit( [ # Top alignment. HSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=VerticalAlign.TOP, padding_char='~'), # Center alignment. HSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=VerticalAlign.CENTER, padding_char='~'), # Bottom alignment. HSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=VerticalAlign.BOTTOM, padding_char='~'), # Justify HSplit([ Window(FormattedTextControl(LIPSUM), style='bg:#444488'), Window(FormattedTextControl(LIPSUM), style='bg:#444488'), Window(FormattedTextControl(LIPSUM), style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=VerticalAlign.JUSTIFY, padding_char='~'), ], padding=1, padding_style="bg:#ff3333 #ffffff", padding_char='.') ])
'leopard', 'lion', 'mouse', 'rabbit', 'rat', 'snake', 'spider', 'turkey', 'turtle', ], ignore_case=True) root_container = HSplit([ VSplit([ Frame(body=Label(text='Left frame\ncontent')), Dialog(title='The custom window', body=Label('hello\ntest')), textfield, ], height=D()), VSplit([ Frame(body=ProgressBar(), title='Progress bar'), Frame(title='Checkbox list', body=HSplit([ checkbox1, checkbox2, ])), Frame(title='Radio list', body=radios), ], padding=1), Box( body=VSplit([ yes_button, no_button, ], align='CENTER', padding=3), style='class:button-bar', height=3, ), ]) root_container = MenuContainer(body=root_container, menu_items=[ MenuItem('File', children=[
# bottom by using an HSplit. def get_titlebar_text(): return [ ('class:title', ' Hello world '), ('class:title', ' (Press [Ctrl-Q] to quit.)'), ] root_container = HSplit([ # The titlebar. Window(height=1, content=FormattedTextControl(get_titlebar_text), align=WindowAlign.CENTER), # Horizontal separator. Window(height=1, char='-', style='class:line'), # The 'body', like defined above. body, ]) # 2. Adding key bindings # -------------------- # As a demonstration, we will add just a ControlQ key binding to exit the # application. Key bindings are registered in a # `prompt_toolkit_dev.key_bindings.registry.Registry` instance. We use the # `load_default_key_bindings` utility function to create a registry that # already contains the default key bindings.
sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus.""" * 40 # Create text buffers. The margins will update if you scroll up or down. buff = Buffer() buff.text = LIPSUM # 1. The layout body = HSplit([ Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'), Window( BufferControl(buffer=buff), # Add margins. left_margins=[NumberedMargin(), ScrollbarMargin()], right_margins=[ScrollbarMargin(), ScrollbarMargin()], ), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') @kb.add('c-c') def _(event): " Quit application. " event.app.exit()
def __init__(self, body: AnyContainer, title: AnyFormattedText = '', style: str = '', width: AnyDimension = None, height: AnyDimension = None, key_bindings: Optional[KeyBindings] = None, modal: bool = False) -> None: self.title = title self.body = body fill = partial(Window, style='class:frame.border') style = 'class:frame ' + style top_row_with_title = VSplit( [ fill(width=1, height=1, char=Border.TOP_LEFT), fill(char=Border.HORIZONTAL), fill(width=1, height=1, char='|'), # Notice: we use `Template` here, because `self.title` can be an # `HTML` object for instance. Label(lambda: Template(' {} ').format(self.title), style='class:frame.label', dont_extend_width=True), fill(width=1, height=1, char='|'), fill(char=Border.HORIZONTAL), fill(width=1, height=1, char=Border.TOP_RIGHT), ], height=1) top_row_without_title = VSplit([ fill(width=1, height=1, char=Border.TOP_LEFT), fill(char=Border.HORIZONTAL), fill(width=1, height=1, char=Border.TOP_RIGHT), ], height=1) @Condition def has_title() -> bool: return bool(self.title) self.container = HSplit( [ ConditionalContainer(content=top_row_with_title, filter=has_title), ConditionalContainer(content=top_row_without_title, filter=~has_title), VSplit( [ fill(width=1, char=Border.VERTICAL), DynamicContainer(lambda: self.body), fill(width=1, char=Border.VERTICAL), # Padding is required to make sure that if the content is # too small, the right frame border is still aligned. ], padding=0), VSplit([ fill(width=1, height=1, char=Border.BOTTOM_LEFT), fill(char=Border.HORIZONTAL), fill(width=1, height=1, char=Border.BOTTOM_RIGHT), ]), ], width=width, height=height, style=style, key_bindings=key_bindings, modal=modal)
body = HSplit([ Frame( Window(FormattedTextControl(TITLE), height=2), style='bg:#88ff88 #000000'), HSplit([ # Left alignment. VSplit([ Window(FormattedTextControl(HTML('<u>LEFT</u>')), width=10, ignore_content_width=True, style='bg:#ff3333 ansiblack', align=WindowAlign.CENTER), VSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=HorizontalAlign.LEFT, height=5, padding_char='|'), ]), # Center alignment. VSplit([ Window(FormattedTextControl(HTML('<u>CENTER</u>')), width=10, ignore_content_width=True, style='bg:#ff3333 ansiblack', align=WindowAlign.CENTER), VSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=HorizontalAlign.CENTER, height=5, padding_char='|'), ]), # Right alignment. VSplit([ Window(FormattedTextControl(HTML('<u>RIGHT</u>')), width=10, ignore_content_width=True, style='bg:#ff3333 ansiblack', align=WindowAlign.CENTER), VSplit([ Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), Window(FormattedTextControl(LIPSUM), height=4, style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=HorizontalAlign.RIGHT, height=5, padding_char='|'), ]), # Justify VSplit([ Window(FormattedTextControl(HTML('<u>JUSTIFY</u>')), width=10, ignore_content_width=True, style='bg:#ff3333 ansiblack', align=WindowAlign.CENTER), VSplit([ Window(FormattedTextControl(LIPSUM), style='bg:#444488'), Window(FormattedTextControl(LIPSUM), style='bg:#444488'), Window(FormattedTextControl(LIPSUM), style='bg:#444488'), ], padding=1, padding_style='bg:#888888', align=HorizontalAlign.JUSTIFY, height=5, padding_char='|'), ]), ], padding=1, padding_style="bg:#ff3333 #ffffff", padding_char='.', align=VerticalAlign.TOP) ])
tempus vehicula augue non venenatis. Mauris aliquam velit turpis, nec congue risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus. """ left_top = Window(BufferControl(Buffer(document=Document(LIPSUM)))) left_bottom = Window(BufferControl(Buffer(document=Document(LIPSUM)))) right_top = Window(BufferControl(Buffer(document=Document(LIPSUM)))) right_bottom = Window(BufferControl(Buffer(document=Document(LIPSUM)))) body = HSplit([ Window(FormattedTextControl(top_text), height=2, style='reverse'), Window(height=1, char='-'), # Horizontal line in the middle. VSplit([left_top, Window(width=1, char='|'), right_top]), Window(height=1, char='-'), # Horizontal line in the middle. VSplit([left_bottom, Window(width=1, char='|'), right_bottom]), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit() @kb.add('a')
def main(): # The layout. search_field = SearchToolbar() # For reverse search. output_field = TextArea(style='class:output-field', text=help_text) input_field = TextArea(height=1, prompt='>>> ', style='class:input-field', multiline=False, wrap_lines=False, search_field=search_field) container = HSplit([ output_field, Window(height=1, char='-', style='class:line'), input_field, search_field, ]) # Attach accept handler to the input field. We do this by assigning the # handler to the `TextArea` that we created earlier. it is also possible to # pass it to the constructor of `TextArea`. # NOTE: It's better to assign an `accept_handler`, rather then adding a # custom ENTER key binding. This will automatically reset the input # field and add the strings to the history. def accept(buff): # Evaluate "calculator" expression. try: output = '\n\nIn: {}\nOut: {}'.format( input_field.text, eval(input_field.text)) # Don't do 'eval' in real code! except BaseException as e: output = '\n\n{}'.format(e) new_text = output_field.text + output # Add text to output buffer. output_field.buffer.document = Document(text=new_text, cursor_position=len(new_text)) input_field.accept_handler = accept # The key bindings. kb = KeyBindings() @kb.add('c-c') @kb.add('c-q') def _(event): " Pressing Ctrl-Q or Ctrl-C will exit the user interface. " event.app.exit() # Style. style = Style([ ('output-field', 'bg:#000044 #ffffff'), ('input-field', 'bg:#000000 #ffffff'), ('line', '#004400'), ]) # Run application. application = Application(layout=Layout(container, focused_element=input_field), key_bindings=kb, style=style, mouse_support=True, full_screen=True) application.run()
risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus.""" # Create text buffers. Cursorcolumn/cursorline are mostly combined with an # (editable) text buffers, where the user can move the cursor. buff = Buffer() buff.text = LIPSUM # 1. The layout body = HSplit([ Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'), Window(BufferControl(buffer=buff), cursorcolumn=True, cursorline=True), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit() # 3. The `Application` application = Application(layout=Layout(body),
risus aliquam sit amet. Pellentesque blandit scelerisque felis, faucibus consequat ante. Curabitur tempor tortor a imperdiet tincidunt. Nam sed justo sit amet odio bibendum congue. Quisque varius ligula nec ligula gravida, sed convallis augue faucibus. Nunc ornare pharetra bibendum. Praesent blandit ex quis sodales maximus.""" # 1. The layout left_text = '\nLeft aligned text. - (Press "q" to quit)\n\n' + LIPSUM center_text = 'Centered text.\n\n' + LIPSUM right_text = 'Right aligned text.\n\n' + LIPSUM body = HSplit([ Window(FormattedTextControl(left_text), align=WindowAlign.LEFT), Window(height=1, char='-'), Window(FormattedTextControl(center_text), align=WindowAlign.CENTER), Window(height=1, char='-'), Window(FormattedTextControl(right_text), align=WindowAlign.RIGHT), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit() # 3. The `Application`
quis sodales maximus.""" # Create text buffers. buff = Buffer() buff.text = LIPSUM # 1. The layout color_columns = [ ColorColumn(50), ColorColumn(80, style='bg:#ff0000'), ColorColumn(10, style='bg:#ff0000'), ] body = HSplit([ Window(FormattedTextControl('Press "q" to quit.'), height=1, style='reverse'), Window(BufferControl(buffer=buff), colorcolumns=color_columns), ]) # 2. Key bindings kb = KeyBindings() @kb.add('q') def _(event): " Quit application. " event.app.exit() # 3. The `Application` application = Application(layout=Layout(body),
search_field = SearchToolbar( text_if_not_searching=[('class:not-searching', "Press '/' to start searching.")]) text_area = TextArea(text=text, read_only=True, scrollbar=True, line_numbers=True, search_field=search_field, lexer=PygmentsLexer(PythonLexer)) root_container = HSplit([ # The top toolbar. Window(content=FormattedTextControl(get_statusbar_text), height=D.exact(1), style='class:status'), # The main content. text_area, search_field, ]) # Key bindings. bindings = KeyBindings() @bindings.add('c-c') @bindings.add('q') def _(event): " Quit. " event.app.exit()
def __init__(self, body: AnyContainer, menu_items: List['MenuItem'], floats: Optional[List[Float]] = None, key_bindings: Optional[KeyBindingsBase] = None) -> None: self.body = body self.menu_items = menu_items self.selected_menu = [0] # Key bindings. kb = KeyBindings() @Condition def in_main_menu() -> bool: return len(self.selected_menu) == 1 @Condition def in_sub_menu() -> bool: return len(self.selected_menu) > 1 # Navigation through the main menu. @kb.add('left', filter=in_main_menu) def _(event: E) -> None: self.selected_menu[0] = max(0, self.selected_menu[0] - 1) @kb.add('right', filter=in_main_menu) def _(event: E) -> None: self.selected_menu[0] = min( len(self.menu_items) - 1, self.selected_menu[0] + 1) @kb.add('down', filter=in_main_menu) def _(event: E) -> None: self.selected_menu.append(0) @kb.add('c-c', filter=in_main_menu) @kb.add('c-g', filter=in_main_menu) def _(event: E) -> None: " Leave menu. " event.app.layout.focus_last() # Sub menu navigation. @kb.add('left', filter=in_sub_menu) @kb.add('c-g', filter=in_sub_menu) @kb.add('c-c', filter=in_sub_menu) def _(event: E) -> None: " Go back to parent menu. " if len(self.selected_menu) > 1: self.selected_menu.pop() @kb.add('right', filter=in_sub_menu) def _(event: E) -> None: " go into sub menu. " if self._get_menu(len(self.selected_menu) - 1).children: self.selected_menu.append(0) # If This item does not have a sub menu. Go up in the parent menu. elif len(self.selected_menu) == 2 and self.selected_menu[0] < len(self.menu_items) - 1: self.selected_menu = [min( len(self.menu_items) - 1, self.selected_menu[0] + 1)] if self.menu_items[self.selected_menu[0]].children: self.selected_menu.append(0) @kb.add('up', filter=in_sub_menu) def _(event: E) -> None: " Select previous (enabled) menu item or return to main menu. " # Look for previous enabled items in this sub menu. menu = self._get_menu(len(self.selected_menu) - 2) index = self.selected_menu[-1] previous_indexes = [i for i, item in enumerate(menu.children) if i < index and not item.disabled] if previous_indexes: self.selected_menu[-1] = previous_indexes[-1] elif len(self.selected_menu) == 2: # Return to main menu. self.selected_menu.pop() @kb.add('down', filter=in_sub_menu) def _(event: E) -> None: " Select next (enabled) menu item. " menu = self._get_menu(len(self.selected_menu) - 2) index = self.selected_menu[-1] next_indexes = [i for i, item in enumerate(menu.children) if i > index and not item.disabled] if next_indexes: self.selected_menu[-1] = next_indexes[0] @kb.add('enter') def _(event: E) -> None: " Click the selected menu item. " item = self._get_menu(len(self.selected_menu) - 1) if item.handler: event.app.layout.focus_last() item.handler() # Controls. self.control = FormattedTextControl( self._get_menu_fragments, key_bindings=kb, focusable=True, show_cursor=False) self.window = Window( height=1, content=self.control, style='class:menu-bar') submenu = self._submenu(0) submenu2 = self._submenu(1) submenu3 = self._submenu(2) @Condition def has_focus() -> bool: return get_app().layout.current_window == self.window self.container = FloatContainer( content=HSplit([ # The titlebar. self.window, # The 'body', like defined above. body, ]), floats=[ Float(xcursor=True, ycursor=True, content=ConditionalContainer( content=Shadow(body=submenu), filter=has_focus)), Float(attach_to_window=submenu, xcursor=True, ycursor=True, allow_cover_cursor=True, content=ConditionalContainer( content=Shadow(body=submenu2), filter=has_focus & Condition(lambda: len(self.selected_menu) >= 1))), Float(attach_to_window=submenu2, xcursor=True, ycursor=True, allow_cover_cursor=True, content=ConditionalContainer( content=Shadow(body=submenu3), filter=has_focus & Condition(lambda: len(self.selected_menu) >= 2))), # -- ] + (floats or []), key_bindings=key_bindings, )
return HTML('[%s.%s] <style bg="ansigreen" fg="ansiblack">%s</style>') % ( lineno, wrap_count, text) # Global wrap lines flag. wrap_lines = True # The layout buff = Buffer(complete_while_typing=True) buff.text = LIPSUM body = FloatContainer(content=HSplit([ Window(FormattedTextControl( 'Press "q" to quit. Press "w" to enable/disable wrapping.'), height=1, style='reverse'), Window(BufferControl(buffer=buff), get_line_prefix=get_line_prefix, wrap_lines=Condition(lambda: wrap_lines)), ]), floats=[ Float(xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1)) ]) # Key bindings kb = KeyBindings()
buttons=[ok_button], width=D(preferred=80), modal=True) def __pt_container__(self): return self.dialog body = HSplit([ text_field, search_toolbar, ConditionalContainer( content=VSplit([ Window(FormattedTextControl(get_statusbar_text), style='class:status'), Window(FormattedTextControl(get_statusbar_right_text), style='class:status.right', width=9, align=WindowAlign.RIGHT), ], height=1), filter=Condition(lambda: ApplicationState.show_status_bar)), ]) # Global key bindings. bindings = KeyBindings() @bindings.add('c-c') def _(event): " Focus menu. "