def _(event): global info global selectedInfo if (not info or selected != selectedInfo): selectedInfo = selected info = True textInfo = getSelectedPassword(selected)["info"] dialog.body = Label(text=textInfo, dont_extend_height=True) layout.focus(dialog) else: info = False layout.focus(input_field)
def __init__( self, from_label='From: ', to_label=' to: ', style=None, ): self._from = MaskedInput( mask='____-__-__', allowed_chars=string.digits, style=style, ) self._to = MaskedInput( mask='____-__-__', allowed_chars=string.digits, style=style, ) components = [] if from_label: components.append( VSplit([ Label(from_label, dont_extend_width=True), self._from, ])) else: components.append(self._from) if to_label: components.append( VSplit([ Label(to_label, dont_extend_width=True), self._to, ]), ) else: components.append(self._to) super().__init__(components)
def message_dialog(title='', text='', ok_text='Ok', style=None, async_=False): """ Display a simple message box and wait until the user presses enter. """ dialog = Dialog( title=title, body=Label(text=text, dont_extend_height=True), buttons=[ Button(text=ok_text, handler=_return_none), ], with_background=True) return _run_dialog(dialog, style, async_=async_)
def get_layout(self): msg = '{}{}'.format( self._question['message'], self._question.get('question_mark', ' ?') ) extra_args = self.get_init_extra_args() remsg = '{}{}'.format( extra_args.get('remessage', 'Please repeat to confirm'), self._question.get('question_mark', ' ?') ) lbl_msg = Label(msg, dont_extend_width=True, style='class:repassword.question') lbl_remsg = Label(remsg, dont_extend_width=True, style='class:repassword.question') return HSplit( [ VSplit([lbl_msg, self.get_widget()], padding=1), VSplit([lbl_remsg, self._rewidget], padding=1) ] )
def get_root_container(self) -> FloatContainer: tree_lines = self.tree.format_tree(hide_values=True).splitlines() self.node_inputs = [ TextArea(wrap_lines=False, style="class:tree-node", width=NODE_INPUT_WIDTH) for _ in self.tree.descendants ] tree_labels = [ Label(line, dont_extend_width=True) for line in tree_lines ] tree_input_container = Frame( HSplit([ VSplit([label, button]) for label, button in zip(tree_labels, self.node_inputs) ]), title="Tree", ) buttons = [ Button("Done", handler=self.handle_input_confirm), ] button_container = Box(VSplit(buttons, padding=4), padding_top=1) tree_panel_container = Box( HSplit([ tree_input_container, button_container, ])) table_container = Label(self.closure_table.format_table()) root_container = FloatContainer( VSplit([tree_panel_container, table_container]), floats=[], ) return root_container
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 _create_ui(self): btn_start = Button("Start", handler=self.tomato.start) btn_pause = Button("Pause", handler=self.tomato.pause) btn_reset = Button("Reset", handler=self.tomato.reset) btn_reset_all = Button("Reset All", handler=self.tomato.reset_all) btn_exit = Button("Exit", handler=self._exit_clicked) # All the widgets for the UI. self.text_area = FormattedTextControl(focusable=False, show_cursor=False) text_window = Window( content=self.text_area, dont_extend_height=True, height=11, style="bg:#ffffff #000000", ) root_container = Box( HSplit([ Label(text="Press `Tab` to move the focus."), HSplit([ VSplit( [ btn_start, btn_pause, btn_reset, btn_reset_all, btn_exit, ], padding=1, style="bg:#cccccc", ), text_window, ]), ])) layout = Layout(container=root_container, focused_element=btn_start) self._set_key_bindings() # Styling. style = Style([ ("left-pane", "bg:#888800 #000000"), ("right-pane", "bg:#00aa00 #000000"), ("button", "#000000"), ("button-arrow", "#000000"), ("button focused", "bg:#ff0000"), ("red", "#ff0000"), ("green", "#00ff00"), ]) self.application = Application(layout=layout, key_bindings=self.kb, style=style, full_screen=True)
def progress_dialog(title='', text='', run_callback=None, style=None, async_=False): """ :param run_callback: A function that receives as input a `set_percentage` function and it does the work. """ assert callable(run_callback) 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): progressbar.percentage = int(value) app.invalidate() def log_text(text): 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(): try: run_callback(set_percentage, log_text) finally: app.exit() run_in_executor(start) if async_: return app.run_async() else: return app.run()
def get_layout(self): game_labels = [] for game in self.riitag_info.games: if not game: continue console_and_game_id = game.split('-') if len(console_and_game_id) == 2: console: str = console_and_game_id[0] game_id: str = console_and_game_id[1] label_text = f'<b>-</b> {game_id} ({console.title()})' else: label_text = f'<b>-</b> {console_and_game_id[0]}' game_labels.append(Label(HTML(label_text))) right_panel_layout = HSplit([]) if self.right_panel_state == 'Menu': right_panel_layout = self.menu_layout elif self.right_panel_state == 'Settings': right_panel_layout = self.settings_layout return HSplit([ Box(Label(text='Use the arrow keys and enter to navigate.'), height=3, padding_left=2), VSplit([ Frame(Box(HSplit([ Label(HTML(f'<b>Name:</b> {self.riitag_info.name}')), Label(HTML(f'<b>Games:</b> {len(game_labels)}')), *game_labels ]), padding_left=3, padding_top=2), title='Riitag'), right_panel_layout ]) ])
def conf_dialog(**kwargs): def row(label, default): buffer=Buffer() buffer.text = default return VSplit([ Label(HTML(f'{label}'), width=10), Window(width=2, char=": "), Window(content=BufferControl(buffer=buffer)), ]) help = Label(HTML(f'(Press {ansired("Tab][Down][Up")} to move cursor. {ansired("Ctrl+C][Esc")} to quit)')) rows = [row(k, v) for k, v in kwargs.items()] root_container = HSplit([ help, Window(height=1, char="-", width=10), *rows ]) kb = KeyBindings() @kb.add("c-c") @kb.add("escape") def _(event): event.app.exit() @kb.add('tab') @kb.add('down') def _(event): event.app.layout.focus_next() @kb.add("up") def _(event): event.app.layout.focus_previous() @kb.add("enter") def _(event): data = [] for child in root_container.children[2:]: value = child.children[-1].content.buffer.text data.append(value) return event.app.exit(data) layout = Layout(root_container) application = Application(layout=layout, full_screen=False, key_bindings=kb) return application.run()
def input_dialog_default( title: AnyFormattedText = "", text: AnyFormattedText = "", default_input_text="", ok_text: str = "OK", cancel_text: str = "Cancel", completer: Optional[Completer] = None, validator: Optional[Validator] = 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( text=default_input_text, multiline=False, password=password, completer=completer, validator=validator, accept_handler=accept, ) dialog = Dialog( title=title, body=HSplit( [ Label(text=text, dont_extend_height=True), textfield, ValidationToolbar(), ], padding=D(preferred=1, max=1), ), buttons=[ok_button, cancel_button], with_background=True, ) return _create_app(dialog, style)
def get_layout(self): msg = '{}{}'.format(self._question['message'], self._question.get('question_mark', ' ?')) align = HorizontalAlign.LEFT if self._mode == Mode.DIALOG: align = HorizontalAlign.JUSTIFY return VSplit([ Label(msg, dont_extend_width=True, style='class:{}.password.question'.format(self._mode)), self.widget ], padding=1, align=align)
def __init__(self, title="", label_text="", completer=None): self.future = Future() def accept_text(buf): buf.complete_state = None self.future.set_result(self.text_area.text) if self.text_area.text == "": get_app().exit() self.text_area = TextArea( completer=completer, multiline=False, width=D(preferred=40), accept_handler=accept_text, ) self.dialog = Dialog( title=title, body=HSplit( [Label(text=label_text), self.text_area, Label(text="")]), width=D(preferred=75), modal=True, )
def message_dialog(title: AnyFormattedText = '', text: AnyFormattedText = '', ok_text: str = 'Ok', style: Optional[BaseStyle] = None) -> Application[None]: """ Display a simple message box and wait until the user presses enter. """ dialog = Dialog(title=title, body=Label(text=text, dont_extend_height=True), buttons=[ Button(text=ok_text, handler=_return_none), ], with_background=True) return _create_app(dialog, style)
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 get_column_details_container(column_names, column_details): # column names labels column_name_labels = {column_name: Label(text=column_name) for column_name in column_names} # column details labels # column_details_labels = { 'col_name': {attr_key: Label(), ...} } column_details_labels = { column_name: { attr_key: Label(text=f"{attr_key:20s}: {attr_val}") for attr_key, attr_val in column_details[column_name].items() } for column_name in column_names } # container for representing column details properly column_details_container = HSplit( children=[ VSplit( children=[ # On the left side, we have just the column name and its label. Frame(column_name_labels[column_name]), # On the right handed side we have attr_key: attr_val label for every column Frame( HSplit( children=[ attr_val for attr_key, attr_val in column_details_labels[column_name].items() ] ) ), ] ) for column_name in column_details_labels.keys() ], ) return column_name_labels, column_details_labels, column_details_container
def get_layout(self): msg = '{}{}'.format( self._question['message'], self._question.get('question_mark', ' ?') ) widget = self.get_widget() widget.buffer.cursor_position = len(widget.text) return VSplit( [ Label(msg, dont_extend_width=True, style='class:input.question'), widget ], padding=1)
def get_layout(self): msg = '{}{}'.format( self._question['message'], self._question.get('question_mark', ' ?') ) extra_args = self.get_init_extra_args() if 'rows' in extra_args: self.get_widget().height = int(extra_args['rows']) return VSplit( [ Label(msg, dont_extend_width=True, style='class:text.question'), self.get_widget() ], padding=1)
def button_dialog(title='', text='', buttons=[], style=None, async_=False): """ Display a dialog with button choices (given as a list of tuples). Return the value associated with button. """ def button_handler(v): get_app().exit(result=v) dialog = Dialog( title=title, body=Label(text=text, dont_extend_height=True), buttons=[Button(text=t, handler=functools.partial(button_handler, v)) for t, v in buttons], with_background=True) return _run_dialog(dialog, style, async_=async_)
async def prompt_radio_list(self, values, title, header, allow_other=True): result = ImbTuiResult() input_done = asyncio.Event() def ok_handler() -> None: result.value = radio_list.current_value input_done.set() def back_handler() -> None: result.back_selected = True input_done.set() def other_handler() -> None: result.other_selected = True input_done.set() buttons = [ Button(text='Ok', handler=ok_handler), Button(text='Back', handler=back_handler), ] if allow_other: buttons.append(Button(text='Other', handler=other_handler)) radio_list = RadioList(list(enumerate(values))) dialog = Dialog( title=title, body=HSplit([ Label(text=HTML(" <b>{}</b>".format(header)), dont_extend_height=True), radio_list, ], padding=1), buttons=buttons, modal=False, ) # disable a_reverse style applied to dialogs dialog.container.container.content.style = "" self.app_frame.body = HSplit([ # Window(FormattedTextControl(HTML('<b>Kubernetes Config</b>')), align=WindowAlign.CENTER, height=1), # TODO: screen header Window(), dialog, Window() ]) self.app.invalidate() self.app.layout.focus(self.app_frame) await input_done.wait() return result
def __init__(self, view): self.view = view self.cwd: Path = Path('./').resolve() self.cancel_button = Button(text="Exit", handler=self.exit_handler) self.filelist = FileList(self, view.new_view) self.window = Dialog( title="Browse files", body=DynamicContainer( lambda: HSplit([ Label(text=f"Dir: {self.cwd}", dont_extend_height=True), self.filelist, ], padding=D(preferred=1, max=1))), buttons=[self.cancel_button], with_background=True)
def disconnect_dialog(my_app: "sqlApp"): def yes_handler() -> None: # This is not preferred since completer may currently have # a different connection attached. # my_app.completer.reset_completions() obj = my_app.selected_object obj.conn.dbmetadata.reset_metadata() obj.collapse() obj.conn.close() if my_app.active_conn is obj.conn: my_app.active_conn = None my_app.show_disconnect_dialog = False my_app.show_sidebar = True my_app.application.layout.focus("sidebarbuffer") def rc_handler() -> None: obj = my_app.selected_object obj.conn.dbmetadata.reset_metadata() my_app.show_disconnect_dialog = False my_app.show_sidebar = True my_app.application.layout.focus("sidebarbuffer") def no_handler() -> None: my_app.show_disconnect_dialog = False my_app.show_sidebar = True my_app.application.layout.focus("sidebarbuffer") dialog = Dialog( title = lambda: my_app.selected_object.name, body = Label(text = "Disconnect or Reset Completions?", dont_extend_height = True), buttons = [ Button(text = "Disconnect", handler = yes_handler), Button(text = "Reset Completions", handler = rc_handler, width = 20), Button(text = "Cancel", handler = no_handler), ], width = D(min = 10, preferred = 50), with_background = False, ) return ConditionalContainer( content = dialog, filter = ShowDisconnectDialog(my_app) & ~is_done )
async def start_ui(self): kb = KeyBindings() @kb.add('escape') def _(event): for t in asyncio.Task.all_tasks(): if 'Imb.main()' in str(t) and not t.done(): t.cancel() # Allow member functions to access this frame to allow switching screens self.app_frame = Frame(title='Opsani Intelligent Manifest Builder', body=Window()) self.app = Application( full_screen=True, key_bindings=kb, layout=Layout(HSplit([self.app_frame, Label('Press ESC to exit')]))) self.init_done.set() await self.app.run_async(set_exception_handler=False)
def __init__(self, event): input_clock = get_current_alarm() def button_handler(): root_container.float_container.floats.pop() event.app.layout.focus(root_container.display_layout) clock.append(self.clock.text) reload_display_layout_clock() self.clock = TextArea(multiline=False, text=input_clock) self.clock.buffer.document = Document(input_clock, len(input_clock)) self.dialog = Dialog( title="Set New Alarm", body=HSplit([Label(text="you can set a new alarm clock here:\n", dont_extend_height=True), self.clock]), buttons=[Button(text="OK", handler=button_handler)] ) root_container.float_container.floats.append(Float(content=self.dialog)) event.app.layout.focus(self.dialog)
def _create_windows(self): """Create all the windows of the display (input, output, debugger, text completer)""" module_names = [m.name for m in self.model.modules] search_field = SearchToolbar() # Generate the input text area input_field = TextArea(prompt='> ', style='class:arrow', completer=ModuleCompleter(module_names), search_field=search_field, height=1, multiline=False, wrap_lines=True) # Field to show current time end_time = str(self.model.get_end_time()) time_field = TextArea(text="", style='class:rprompt', height=1, width=len(end_time) * 2 + 7, multiline=False) output = Label(text="") self.display.update() # Create container with display window and input text area container = pt_containers.HSplit([ self.display.get_top_view(), pt_containers.Window(height=1, char='-'), output, pt_containers.VSplit([input_field, time_field]), search_field ]) # Floating menu for text completion completion_menu = CompletionsMenu(max_height=5, scroll_offset=1) body = pt_containers.FloatContainer(content=container, floats=[ pt_containers.Float( xcursor=True, ycursor=True, content=completion_menu) ]) return body, input_field, time_field, output
def show_error_dialog(messages): texts = [] for message in messages: texts.append( Label(message, style='class:error', dont_extend_height=True)) dialog = Dialog(title='Some inputs are invalid', body=HSplit(texts, padding=1), buttons=[ Button(text='Ok', handler=lambda: get_app().exit()), ], with_background=True) app = Application(layout=Layout(dialog), key_bindings=load_key_bindings(), mouse_support=True, style=for_dialog(), full_screen=True) app.run()
def create_property_editor(self): current_file_path = self.playlist.media_list[ self.playlist.current_index] _, current_file_name = os.path.split(current_file_path) self.play_info_dialog = Dialog( modal=False, title="播放记录", body=HSplit([ Label(''), Label(' 播放文件'), Button(f'{current_file_name}', ), Label(' 播放位置'), Button(f'{self.playlist.current_pos}', ), Label(''), ], width=38, padding=1)) self.skip_info_dialog = Dialog( modal=False, title="设置", body=HSplit([ Label(''), Label(' 跳过片头'), Button(f'{self.playlist.skip_head}', ), Label(' 跳过片尾'), Button(f'{self.playlist.skip_tail}', ), Label(''), ], width=38, padding=1)) left_window = VSplit([ self.play_info_dialog, self.skip_info_dialog, ], width=40, padding=2) return left_window
async def prompt_check_list(self, values, title, header, allow_other=True): result = ImbTuiResult() input_done = asyncio.Event() def ok_handler() -> None: result.value = cb_list.current_values input_done.set() def back_handler() -> None: result.back_selected = True input_done.set() def other_handler() -> None: result.other_selected = True input_done.set() buttons = [ Button(text='Ok', handler=ok_handler), Button(text='Back', handler=back_handler), ] if allow_other: buttons.append(Button(text='Other', handler=other_handler)) cb_list = CheckboxList(list(enumerate(values))) dialog = Dialog( title=title, body=HSplit([ Label(text=HTML(" <b>{}</b>".format(header)), dont_extend_height=True), cb_list, ], padding=1), buttons=buttons, modal=False, ) # disable a_reverse style applied to dialogs dialog.container.container.content.style = "" self.app_frame.body = HSplit([Window(), dialog, Window()]) self.app.invalidate() self.app.layout.focus(self.app_frame) await input_done.wait() return result
def __init__(self, title="", label_text="", completer=None): self.future = Future() def accept_text(buf) -> bool: """ Change focus to OK button after user pressed enter on text field. """ get_app().layout.focus(ok_button) buf.complete_state = None return True def accept(): """ Set future result to text from text field if user pressed OK button. """ self.future.set_result(self.text_area.text) def cancel(): """ Set future result to None if user pressed cancel button. """ self.future.set_result(None) self.text_area = TextEditor( completer=completer, multiline=False, width=D(preferred=40), accept_handler=accept_text, key_bindings=load_key_bindings(), ) 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 test_pop_all_pages(self): first_label = Label("First") self.window.push(first_label) assert len(self.window.pages) == 1 # We can't pop the last page. self.window.pop() self.window.pop() assert len(self.window.pages) == 1 children = to_container(self.window).get_children() label = children[0].get_container() assert label.text == "First" # We can reset the pages to the default container. self.window.reset() assert len(self.window.pages) == 1 children = to_container(self.window).get_children() label = children[0].get_container() assert label.content.text() == "Empty container"