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)
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, )
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, )
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
def create_content(self, progress_controls): return VSplit( progress_controls, height=lambda: D( preferred=len(self.models), max=len(self.models) ), )
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) 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_)
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)
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)
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, )
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)
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
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, col_titles, row_items, height=D()): self.title = title self.col_titles self.row_items = row_items # add index column cols = [] idx_col = [ Label(text="Idx", dont_extend_width=True, style="bold cyan") ] for row_idx in range(len(row_items)): idx_col.append( Label(text="%d" % row_idx, dont_extend_width=True, style="bold cyan")) cols.append(idx_col) # add value columns for col_idx in range(len(col_titles)): col = [ Label(text=col_titles[col_idx], dont_extend_width=True, style="bold cyan") ] for row in row_items: item = row[col_idx] col.append(item.value_label) cols.append(col) # create column containers col_conts = [] for col in cols: col_cont = HSplit(col) col_conts.append(col_cont) # create the main container cont = VSplit(col_conts, height=height, width=D(), padding=3, padding_char=" ") self.container = Frame(title=self.title, body=cont)
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 __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 [] 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), height=D(min=1, max=3, preferred=3)) ]) else: frame_body = body # Key bindings. 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
async def draw_block(self): block_hash: str = self.route.split("block/")[1] async with self.store.lock: block: Optional[FullBlock] = await self.store.get_block( bytes32(bytes.fromhex(block_hash))) if block is not None: self.block_msg.text = f"Block {str(block.header_hash)}" if self.block_label.text != str(block): self.block_label.text = str(block) else: self.block_label.text = f"Block hash {block_hash} not found" try: if not self.focused: self.layout.focus(self.back_button) self.focused = True except ValueError: # Not yet in layout pass return HSplit([self.block_msg, self.block_label, self.back_button], width=D(), height=D())
def __init__(self, tosh): self._tosh = tosh self._tabs = [ToshTab(tosh)] self._active_tab = 0 layout = [ Window(TokenListControl( self._get_tabs_tokens, default_char=Char(' ', Token.Tabs), ), height=D(max=1)), self._tabs[0].layout ] super().__init__(layout)
def __init__(self, text, title): self.future = future = Future() ok_btn = Button(text='OK', handler=lambda: future.set_result(None)) self.dialog = Dialog(title=title, body=HSplit([ Label(text=text), ]), buttons=[ok_btn], width=D(preferred=80), modal=True)
def input_dialog( title: AnyFormattedText = "", text: AnyFormattedText = "", ok_text: str = "OK", cancel_text: str = "Cancel", completer: Optional[Completer] = None, validator: Optional[Validator] = None, password: FilterOrBool = False, style: Optional[BaseStyle] = None, value: str = "", ) -> 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: if textfield.buffer.validate(): get_app().exit(result=textfield.text) else: get_app().layout.focus(textfield) ok_button = Button(text=ok_text, handler=ok_handler) cancel_button = Button(text=cancel_text, handler=_return_none) textfield = TextArea( text=value, 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 __init__(self): self._percentage = 60 self.label = Label('60%') self.container = FloatContainer( content=Window(height=1), floats=[ # We first draw the label, than the actual progress bar. Right # now, this is the only way to have the colors of the progress # bar appear on to 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))), ])), ])
def main(): def done(): application.exit() term = Terminal( width=D(preferred=60), height=D(preferred=25), done_callback=done) application = Application( layout=Layout( container=Dialog( title='Terminal demo', body=term, with_background=True ), focused_element=term ), full_screen=True, mouse_support=True, ) application.run()
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 create_layout(self): self.prompt_layout = create_prompt_layout( get_prompt_tokens=self.get_prompt_tokens, reserve_space_for_menu=4, display_completions_in_columns=True, lexer=CommandLineLexer(self._tosh)) layout = [ ScrollWindow(controls.TokenListControl( self._tosh.tasks.get_tokens), wrap_lines=True, scroll_offsets=ScrollOffsets(top=0, bottom=10000), height=D(preferred=10000)), self.prompt_layout ] return layout
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:selectone.question', ), ) btn_all = Button('All', widget.select_all) btn_none = Button('None', widget.select_none) buttons = Box( body=VSplit([btn_all, btn_none], padding=1), height=D(min=1, max=3, preferred=3), padding_left=0, ) hsplit_components = [buttons, VSplit(vsplit_components, padding=1)] if 'description' in self._question and self._question['description']: hsplit_components.insert( 0, Window( FormattedTextControl( FormattedText([( 'class:selectone.question', self._question['description'], )]), ), wrap_lines=True, height=D(min=1, max=5, preferred=3), ), ) return HSplit(hsplit_components, padding=1)
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, 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 __init__(self, title, items, height=D(), use_frame=True): self.title = title self.items = {} title_labels = [] value_labels = [] for item in items: if item.name in self.items: item.name += "_1" self.items[item.name] = item title_labels.append(item.title_label) value_labels.append(item.value_label) cont = VSplit( [HSplit(title_labels), HSplit(value_labels)], height=height, width=D()) if use_frame: self.container = Frame(title=self.title, body=cont) else: title_label = Label(text="------- " + title + " -------", dont_extend_width=True, style="bold blue") self.container = HSplit([title_label, cont])
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 __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 __init__(self, cell, table, row, merge=1, padding=0, char=None, padding_left=None, padding_right=None, padding_top=None, padding_bottom=None, window_too_small=None, width=None, height=None, z_index=None, modal=False, key_bindings=None, style=''): self.table = table self.row = row self.merge = merge 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) children = [] children.append(Window(width=self.padding_left, char=char)) if cell: children.append(cell) children.append(Window(width=self.padding_right, char=char)) children = [ Window(height=self.padding_top, char=char), VSplit(children), Window(height=self.padding_bottom, char=char), ] super().__init__( children=children, window_too_small=window_too_small, width=width, height=height, z_index=z_index, modal=modal, key_bindings=key_bindings, style=style)
def get_width(self, progress_bar): all_lengths = [len('{0}'.format(c.total)) for c in progress_bar.counters] all_lengths.append(1) return D.exact(max(all_lengths) * 2 + 1)
def get_width(self, progress_bar): return D.exact(1)