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 get_root_container(self) -> FloatContainer: validator = CoordinateValidator(self.maze_grid) maze_grid_container = Label(text=self.maze_grid.format_grid, ) coordinates_input_container = Window( BufferControl( buffer=Buffer( validator=validator, validate_while_typing=False, multiline=False, accept_handler=self._accept_handler, ), input_processors=[ BeforeInput("Enter coordinates (x, y): "), ], ), ) validation_toolbar = ConditionalContainer( ValidationToolbar(), filter=~is_done, ) return FloatContainer( HSplit([ maze_grid_container, HorizontalLine(), coordinates_input_container, validation_toolbar, ]), floats=[], )
def __enter__(self): # Create UI Application. title_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.title), height=1), 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)) self.app = Application(min_redraw_interval=.05, layout=Layout( HSplit([ title_toolbar, Window( content=_ProgressControl(self), height=lambda: len(self.counters)), Window(), bottom_toolbar, ])), style=self.style) # Run application in different thread. def run(): try: self.app.run() except Exception as e: import traceback 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_inquirer_layout( ic: InquirerControl, get_prompt_tokens: Callable[[], List[Tuple[str, str]]], **kwargs: Any, ) -> Layout: """Create a layout combining question and inquirer selection.""" ps = PromptSession(get_prompt_tokens, reserve_space_for_menu=0, **kwargs) _fix_unecessary_blank_lines(ps) validation_prompt = PromptSession(bottom_toolbar=lambda: ic.error_message, **kwargs) return Layout( HSplit([ ps.layout.container, ConditionalContainer(Window(ic), filter=~IsDone()), ConditionalContainer( validation_prompt.layout.container, filter=Condition(lambda: ic.error_message is not None), ), ]))
def __init__(self, question): self._answer_control = AnswerControl() @Condition def answered(): return self.answer is not None self.answered = answered q = self.build_question() self._header_control = QuestionHeaderControl(question) widgets = [ VSplit( [ Window( self._header_control, wrap_lines=True, dont_extend_height=True, dont_extend_width=True, ), ConditionalContainer( Window( self._answer_control, wrap_lines=True, dont_extend_height=True, ), self.answered, ), ] ) ] if q is not None: widgets.append(ConditionalContainer(q, ~self.answered)) widgets.extend([ConditionalContainer(ValidationToolbar(), ~self.answered)]) self._widget = HSplit(widgets, key_bindings=self.key_bindings())
def create_inquirer_layout(ic: InquirerControl, get_prompt_tokens: Callable[[], List[Tuple[Text, Text]]], **kwargs) -> Layout: """Create a layout combining question and inquirer selection.""" ps = PromptSession(get_prompt_tokens, reserve_space_for_menu=0, **kwargs) _fix_unecessary_blank_lines(ps) return Layout( HSplit([ ps.layout.container, ConditionalContainer(Window(ic), filter=~IsDone()) ]))
def __init__(self, tui): super().__init__(tui) self.list = DynamicContainer(self.get_container) self.back_button = ConditionalContainer( Button("Back", handler=self.pop), filter=Condition(lambda: len(self.pages) > 1), ) self.exit_button = Button("Exit", handler=exit_app) self.container = HSplit( [ self.list, self.back_button, self.exit_button, ], height=Dimension(min=1), width=Dimension(min=1), key_bindings=self.get_key_bindings(), )
def create_help(self): ctx = self.ctx dialog = Dialog( Label( dedent( """ Tab Switch focus between INPUT/OUTPUT/COMMAND Ctrl-P Copy OUTPUT to clipboard Ctrl-O Exit and print OUTPUT to stdout Ctrl-C Exit Ctrl-T Toggle vertical/horizontal view Ctrl-L Toggle live/manual mode Ctrl-R Run processing (when in manual mode) Enter/Ctrl-M Run processing (when in manual mode, in COMMAND) F1 Toggle help """ ).strip(), dont_extend_width=False, dont_extend_height=False, ), title="Help", ) return ConditionalContainer(dialog, Condition(lambda: ctx.display_help))
def __enter__(self) -> 'ProgressBar': # 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: Formatter) -> AnyDimension: # Needs to be passed as callable (partial) to the 'width' # parameter, because we want to call it on every resize. return formatter.get_width(progress_bar=self) progress_controls = [ Window(content=_ProgressControl(self, f), width=functools.partial(width_for_formatter, f)) for f in self.formatters ] self.app: Application[None] = 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, color_depth=self.color_depth, output=self.output, input=self.input) # Run application in different thread. def run() -> None: set_event_loop(self._app_loop) with _auto_refresh_context(self.app, .3): try: self.app.run() except BaseException 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 = signal.getsignal(signal.SIGWINCH) self._loop.add_signal_handler(signal.SIGWINCH, self.invalidate) return self
def __enter__(self) -> "ProgressBar": # 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: Formatter) -> AnyDimension: # Needs to be passed as callable (partial) to the 'width' # parameter, because we want to call it on every resize. return formatter.get_width(progress_bar=self) progress_controls = [ Window( content=_ProgressControl(self, f), width=functools.partial(width_for_formatter, f), ) for f in self.formatters ] self.app: Application[None] = Application( min_redraw_interval=0.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, refresh_interval=0.3, color_depth=self.color_depth, output=self.output, input=self.input, ) # Run application in different thread. def run() -> None: set_event_loop(self._app_loop) try: self.app.run(pre_run=self._app_started.set) except BaseException as e: traceback.print_exc() print(e) ctx: contextvars.Context = contextvars.copy_context() self._thread = threading.Thread(target=ctx.run, args=(run, )) self._thread.start() return self
def __init__(self): # styling style = Style.from_dict({ 'completion-menu.completion': 'bg:#008888 #ffffff', 'completion-menu.completion.current': 'bg:#00aaaa #000000', 'scrollbar.background': 'bg:#88aaaa', 'scrollbar.button': 'bg:#222222', 'input-field': '#004400', 'buffer': '#ff0066', }) # create input fields self.source_field = make_text_area('[Source folder]: ') self.target_field = make_text_area('[Target folder]: ') self.dry_field = make_text_area('[{:13}]: '.format("Dry? (y/n)")) # get completers initialize_database() con = db_connect() self.source_field.completer = FuzzyCompleter( WordCompleter(get_source_paths(con), ignore_case=True)) self.target_field.completer = FuzzyCompleter( WordCompleter(get_target_paths(con), ignore_case=True)) self.dry_field.completer = WordCompleter( ['Yes', 'No', 'True', 'False', 'yes', 'no'], ignore_case=True) # bottom toolbar def bottom_toolbar_call(): s1 = '<b><style bg="ansired">C-H</style></b>: history mode.' s2 = '<b><style bg="ansired">C-C/C-Q</style></b>: exit app.' s3 = '<b><style bg="ansired">C-O</style></b>: ordered paths.' s4 = '<b><style bg="ansired">C-R</style></b>: reverse paths.' return HTML(" ".join([s1, s2, s3, s4])) self.bottom_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: bottom_toolbar_call, style='class:bottom-toolbar.text'), style='class:bottom-toolbar', dont_extend_height=True, height=Dimension(min=1)), filter=(~is_done & renderer_height_is_known & Condition(lambda: bottom_toolbar_call is not None))) # create app body self.body = FloatContainer(content=HSplit(children=[ self.source_field, self.target_field, self.dry_field, self.bottom_toolbar ], height=8), floats=[ Float(xcursor=True, ycursor=True, content=CompletionsMenu( max_height=12, scroll_offset=1)) ]) # define internal logic def execute_command(buff): """Send command to subprocess dealing with dry argument recursively""" dry = False if buff.text.lower() in ['n', 'no', 'false'] else True dry_flag = 'DRY' if dry else 'NOT DRY' dry_string = 'n' if dry else '' command = "rsync -avucP{} {} {}".format(dry_string, self.source_field.text, self.target_field.text) def run_script(): subprocess.call(command, shell=True) def print_info(): print_formatted_text( HTML('<ansired>{} </ansired>'.format(dry_flag))) print_formatted_text( HTML('<ansired>{} </ansired>'.format( 'You entered: {}'.format(command)))) print_formatted_text( HTML('<ansired>{} </ansired>'.format('Running...'))) run_in_terminal(print_info) if dry: run_in_terminal(run_script) return else: con = db_connect() create_rsync_record(con, self.source_field.text, self.target_field.text) run_in_terminal(run_script) app = get_app() app.exit() return self.dry_field.buffer.accept_handler = execute_command # Key bindings self.kb = KeyBindings() @self.kb.add('c-q') @self.kb.add('c-c') def _(event): " Quit application. " event.app.exit() #kb.add('enter')(focus_next) self.kb.add('tab')(focus_next) self.kb.add('s-tab')(focus_previous) # The `Application` self.app = Application( layout=Layout(self.body), #style=style, key_bindings=self.kb, full_screen=False, mouse_support=True)
wrap_lines=False, # completer=completion, complete_while_typing=True) placeholder_text = ("Nothing here yet:\n" " - Type \"help\" to see available commands.\n" " - Press \"?\" for the list of keybindings.") entry_placeholder = Label( FormattedText([("class:placeholder", placeholder_text)])) task_list = HSplit([entry_placeholder]) agenda_pane = ScrollablePane(task_list) show_kb_help = False bindings_help = ConditionalContainer(Box( Shadow(Frame(Label(""), "Key bindings:"))), filter=Condition(lambda: show_kb_help)) root_container = FloatContainer( content=HSplit([agenda_pane, HorizontalLine(), history_field, input_field]), floats=[ Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1), ), Float(bindings_help), ], )
def homeLayoutFactory(self): content = self.studio.content statusBar = Frame( Window(BufferControl(buffer=content.getBuffer("statusBar"), focusable=False), height=D(min=1, max=1, preferred=1), align=WindowAlign.CENTER)) savedModelsBox = Box(HSplit([ Label(text="Saved Models: ", style="class:blue class:underlined"), Window( BufferControl(buffer=content.getBuffer("savedModels"), focusable=False)) ]), padding=0) modelDefinitionsBox = Box(HSplit([ Label(text="Model Definitions: ", style="class:blue class:underlined"), Window( BufferControl(buffer=content.getBuffer("modelDefinitions"), focusable=False)) ]), padding=0) rightSidebar = Frame( HSplit([savedModelsBox, HorizontalLine(), modelDefinitionsBox])) createModelButton = Button("[C] Create Model ", handler=self.studio.layouts.swapper( Layouts.CREATE)) loadModelButton = Button("[L] Load Saved Model ", handler=self.studio.layouts.swapper( Layouts.LOAD)) importModelButton = Button("[I] Import Model From Definition ", handler=self.studio.layouts.swapper( Layouts.IMPORT)) editModelButton = Button("[E] Edit Model ", handler=self.studio.layouts.swapper( Layouts.EDIT)) deleteModelButton = Button("[D] Delete Model ", handler=self.studio.layouts.swapper( Layouts.DELETE)) quitButton = Button("[Q] Quit ", handler=self.studio.exit) editModelButton = ConditionalContainer( editModelButton, filter=self.studio.controller.modelExistsFilter()) leftSidebar = HSplit([ createModelButton, loadModelButton, importModelButton, editModelButton, deleteModelButton, quitButton, ]) creditBar = Label( text="Created by Samuel Ellertson - github.com/SamuelEllertson", style="class:blue") body = VSplit([Frame(Sizeable(leftSidebar)), Sizeable(rightSidebar)]) root = HSplit([statusBar, body, creditBar]) return Layout(container=root, focused_element=createModelButton)
'history': True, 'diff': False, } @Condition def diff_visible() -> bool: global WINDOW_VISIBILITY return WINDOW_VISIBILITY['diff'] MARGINS = [ ScrollbarMargin(display_arrows=True), ConditionalMargin(MyMargin(), filter=diff_visible) ] DIFF_CONTAINER = ConditionalContainer(DiffView(key_bindings=KD), filter=diff_visible) HISTORY_CONTAINER = HistoryContainer(KB, ARGUMENTS, right_margins=MARGINS) def get_container(): width = screen_width() if width >= 160: return VSplit([HISTORY_CONTAINER, DIFF_CONTAINER]) return HSplit([HISTORY_CONTAINER, DIFF_CONTAINER]) DYNAMIC_CONTAINER = DynamicContainer(get_container) LAYOUT = Layout(DYNAMIC_CONTAINER, focused_element=HISTORY_CONTAINER)
def _create_app(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: Formatter) -> AnyDimension: # Needs to be passed as callable (partial) to the 'width' # parameter, because we want to call it on every resize. return formatter.get_width(progress_bar=self) progress_controls = [ Window( content=_ProgressControl(self, f), width=functools.partial(width_for_formatter, f), ) for f in self.formatters ] body = self.create_content(progress_controls) self.root = FloatContainer( content=HSplit( [ title_toolbar, body, bottom_toolbar, ] ), floats=[] ) if self.key_bindings is None: self.create_key_bindings() self.app: Application[None] = Application( min_redraw_interval=0.05, layout=Layout(self.root), style=self.style, key_bindings=self.key_bindings, refresh_interval=0.3, color_depth=self.color_depth, output=self.output, input=self.input, full_screen=True, ) return self.app
def set_status(self, text: str) -> None: ''' Set some text to show in the status bar ''' self.content.text = text def clear(self) -> None: ''' Clear the content of the status bar ''' self.content.text = '' def create_content(self, width: int, height: int, preview_search: bool = False) -> UIContent: self.content.width = width return self.content STATUS = StatusBar() @Condition def statis_is_visible() -> bool: ''' Return `True` if status line is visible ''' return bool(STATUS.content.text) STATUS_WINDOW = ConditionalContainer(content=Window(content=STATUS, height=1, ignore_content_height=True, wrap_lines=False), filter=statis_is_visible)
no_notes_text = Window( FormattedTextControl( HTML( '\n\n\nNo notes!\nCreate a new one by hitting <style color="blue"><b>Ctrl-N</b></style>' )), align=WindowAlign.CENTER, ) main_window = VSplit([ sidebar, Window(width=2, char=f"{borders.VERTICAL} ", style="class:line"), text_window, ]) body = HSplit([ ConditionalContainer(main_window, filter=Condition(lambda: state.current_note)), ConditionalContainer(no_notes_text, filter=Condition(lambda: not state.current_note)), Window( content=FormattedTextControl(get_notification_text), height=1, style="class:notification", align=WindowAlign.CENTER, ), VSplit( [ Window( FormattedTextControl(get_statusbar_text), style="class:status", width=11, ),
from xradios.tui.buffers.display import buffer as display_buffer from xradios.tui.buffers.popup import buffer as popup_buffer from xradios.tui.buffers.prompt import buffer as prompt_buffer from xradios.tui.buffers.listview import buffer as listview_buffer layout = Layout( FloatContainer( content=HSplit([ TopBar(message="Need help! Press `F1`."), Display(display_buffer), ListView(listview_buffer), Prompt(prompt_buffer), ]), modal=True, floats=[ # Help text as a float. Float( top=3, bottom=2, left=2, right=2, content=ConditionalContainer( content=PopupWindow(popup_buffer, title="Help"), filter=has_focus(popup_buffer), ), ) ], )) layout.focus(prompt_buffer)