Created
February 6, 2021 18:13
-
-
Save daddycocoaman/b3b86fd5c0b89e42c53db6efbb061cec to your computer and use it in GitHub Desktop.
Revisions
-
daddycocoaman created this gist
Feb 6, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,178 @@ # Customized from https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/prompt_toolkit/widgets/base.py from typing import Generic, Sequence, Tuple, TypeVar from prompt_toolkit.application import get_app from prompt_toolkit.filters import Condition from prompt_toolkit.formatted_text import ( AnyFormattedText, StyleAndTextTuples, to_formatted_text, ) from prompt_toolkit.key_binding.key_bindings import KeyBindings from prompt_toolkit.key_binding.key_processor import KeyPressEvent from prompt_toolkit.layout import ScrollOffsets from prompt_toolkit.layout.containers import Container, Window, WindowAlign from prompt_toolkit.layout.controls import FormattedTextControl from prompt_toolkit.layout.margins import ConditionalMargin, ScrollbarMargin from prompt_toolkit.lexers import DynamicLexer, PygmentsLexer from prompt_toolkit.mouse_events import MouseEvent, MouseEventType from prompt_toolkit.widgets import TextArea E = KeyPressEvent _T = TypeVar("_T") class DCSRadioList(Generic[_T]): """ List of radio buttons. Only one can be checked at the same time. :param values: List of (value, label) tuples. """ open_character = "[" close_character = "]" container_style = "class:radio-list" default_style = "class:radio" selected_style = "class:radio-selected" checked_style = "class:radio-checked" show_scrollbar: bool = True def __init__(self, values: Sequence[Tuple[_T, AnyFormattedText]]) -> None: assert len(values) > 0 self.values = values self.values_length = len(self.values) self.current_value: _T = values[0][0] self._selected_index = 0 # Key bindings. kb = KeyBindings() @kb.add("up") def _up(event: E) -> None: self._selected_index = max(0, self._selected_index - 1) self._handle_enter() @kb.add("down") def _down(event: E) -> None: self._selected_index = min(self.values_length - 1, self._selected_index + 1) self._handle_enter() @kb.add("pageup") def _pageup(event: E) -> None: w = event.app.layout.current_window if w.render_info: self._selected_index = max( 0, self._selected_index - len(w.render_info.displayed_lines) ) self._handle_enter() @kb.add("pagedown") def _pagedown(event: E) -> None: w = event.app.layout.current_window if w.render_info: self._selected_index = min( self.values_length - 1, self._selected_index + len(w.render_info.displayed_lines), ) self._handle_enter() @kb.add("enter") @kb.add(" ") def _click(event: E) -> None: self._handle_enter() # Control and window. self.control = FormattedTextControl( self._get_text_fragments, key_bindings=kb, focusable=True ) self.window = Window( content=self.control, style=self.container_style, right_margins=[ ConditionalMargin( margin=ScrollbarMargin(display_arrows=True), filter=Condition(lambda: self.show_scrollbar), ), ], scroll_offsets=ScrollOffsets(bottom=10), wrap_lines=False, allow_scroll_beyond_bottom=True, ignore_content_height=True, align=WindowAlign.LEFT, width=60, ) def _handle_enter(self) -> None: """Update the text display area when a new radio option is selected.""" self.current_value = self.values[self._selected_index][0] # DO SOME STUFF HERE! In this case, I display file contents in another window app = get_app() # Configure text area text_area = TextArea( self.current_value.source.read_text("latin-1"), lexer=DynamicLexer( lambda: PygmentsLexer.from_filename(str(self.current_value.source)) ), scrollbar=True, line_numbers=True, focus_on_click=True, read_only=True, ) if self.current_value.source.suffix == ".config": text_area.lexer = DynamicLexer(lambda: PygmentsLexer.from_filename(".xml")) app.layout.container.children[1].children[1] = text_area.window text_area.buffer.cursor_down(self.current_value.lineno + 15) def _get_text_fragments(self) -> StyleAndTextTuples: def mouse_handler(mouse_event: MouseEvent) -> None: """ Set `_selected_index` and `current_value` according to the y position of the mouse click event. """ if mouse_event.event_type == MouseEventType.MOUSE_UP: self._selected_index = mouse_event.position.y result: StyleAndTextTuples = [] # We only need to render what is on the screen for massive lists. Try 15. for i, value in enumerate( self.values[self._selected_index : self._selected_index + 15], start=self._selected_index, ): checked = value[0] == self.current_value selected = i == self._selected_index style = "" if checked: style += " " + self.checked_style if selected: style += " " + self.selected_style result.append((style, self.open_character)) if selected: result.append(("[SetCursorPosition]", "")) if checked: result.append((style, "*" * len(str(i)))) else: result.append((style, str(i + 1))) result.append((style, self.close_character)) result.append((self.default_style, "\n")) result.extend(to_formatted_text(value[1], style=self.default_style)) result.append(("", "\n")) # Add mouse handler to all fragments. for i in range(10): result[i] = (result[i][0], result[i][1], mouse_handler) return result def __pt_container__(self) -> Container: return self.window