From 187a69fd5fd350f7a1ff5720859dd30f454c58b3 Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 12 Jun 2019 08:15:40 +0000 Subject: [PATCH] Add editing widgets for popups etc. --- cheuph/euphoria/__init__.py | 2 + cheuph/euphoria/edit_widgets.py | 82 +++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 cheuph/euphoria/edit_widgets.py diff --git a/cheuph/euphoria/__init__.py b/cheuph/euphoria/__init__.py index c9ff498..d50e793 100644 --- a/cheuph/euphoria/__init__.py +++ b/cheuph/euphoria/__init__.py @@ -1,7 +1,9 @@ from typing import List +from .edit_widgets import * from .euph_renderer import * __all__: List[str] = [] +__all__ += edit_widgets.__all__ __all__ += euph_renderer.__all__ diff --git a/cheuph/euphoria/edit_widgets.py b/cheuph/euphoria/edit_widgets.py new file mode 100644 index 0000000..0d2bc93 --- /dev/null +++ b/cheuph/euphoria/edit_widgets.py @@ -0,0 +1,82 @@ +from typing import Optional, Tuple + +import urwid + +__all__ = ["EditWidget", "PasswordEditWidget"] + +class EditWidget(urwid.WidgetWrap): + + def __init__(self, + prompt: str, + caption: str = "", + style: Optional[str] = None, + ) -> None: + + self._prompt = urwid.Text(prompt, align=urwid.CENTER) + self._edit = urwid.Edit(caption=caption, align=urwid.CENTER) + + if style is None: + self._edit_wrap = self._edit + else: + self._edit_wrap = urwid.AttrMap(self._edit, style) + + self._pile = urwid.Pile([ + (urwid.PACK, self._prompt), + (urwid.PACK, self._edit_wrap), + ]) + super().__init__(self._pile) + + @property + def width(self) -> int: + prompt_width, _ = self._prompt.pack(None) + edit_width, _ = self._edit.pack(None) + return max(prompt_width, edit_width) + + @property + def text(self) -> str: + return self._edit.edit_text + +class PasswordEditWidget(urwid.WidgetWrap): + + def __init__(self, + prompt: str, + mask_char: str = "*", + style: Optional[str] = None, + ) -> None: + + self._mask_char = mask_char + + self._prompt = urwid.Text(prompt, align=urwid.CENTER) + self._edit = urwid.Edit(align=urwid.CENTER) + self._fake_edit = urwid.Edit(align=urwid.CENTER) + + if style is None: + self._fake_edit_wrap = self._fake_edit + else: + self._fake_edit_wrap = urwid.AttrMap(self._fake_edit, style) + + self._pile = urwid.Pile([ + (urwid.PACK, self._prompt), + (urwid.PACK, self._fake_edit_wrap), + ]) + super().__init__(self._pile) + + @property + def width(self) -> int: + prompt_width, _ = self._prompt.pack(None) + edit_width, _ = self._edit.pack(None) + return max(prompt_width, edit_width) + + @property + def text(self) -> str: + return self._edit.edit_text + + def update_fake_edit(self) -> None: + fake_text = self._mask_char * len(self._edit.edit_text) + self._fake_edit.edit_text = fake_text + self._fake_edit.edit_pos = self._edit.edit_pos + + def keypress(self, size: Tuple[int], key: str) -> Optional[str]: + key = self._edit.keypress(size, key) + self.update_fake_edit() + return key