mirror of
https://github.com/rr-/pq-cli.git
synced 2026-09-28 22:33:59 -06:00
ui/curses: add focus to character name view
This commit is contained in:
@@ -4,8 +4,9 @@ import typing as T
|
|||||||
|
|
||||||
from pqcli.mechanic import generate_name
|
from pqcli.mechanic import generate_name
|
||||||
from pqcli.ui.curses.event_handler import EventHandler
|
from pqcli.ui.curses.event_handler import EventHandler
|
||||||
from pqcli.ui.curses.util import KEYS_CANCEL
|
from pqcli.ui.curses.util import KEYS_CANCEL, KEYS_DOWN, KEYS_UP
|
||||||
from pqcli.ui.curses.views.base_view import BaseView
|
from pqcli.ui.curses.views.base_view import BaseView
|
||||||
|
from pqcli.ui.curses.widgets.focusable import focus_standout
|
||||||
|
|
||||||
|
|
||||||
class ChooseCharacterNameView(BaseView):
|
class ChooseCharacterNameView(BaseView):
|
||||||
@@ -17,7 +18,9 @@ class ChooseCharacterNameView(BaseView):
|
|||||||
self.on_cancel = EventHandler()
|
self.on_cancel = EventHandler()
|
||||||
self.on_confirm = EventHandler()
|
self.on_confirm = EventHandler()
|
||||||
|
|
||||||
|
self._active_widget = 0
|
||||||
self._win: T.Optional[T.Any] = None
|
self._win: T.Optional[T.Any] = None
|
||||||
|
self._text_win: T.Optional[T.Any] = None
|
||||||
self._text = character_name or generate_name()
|
self._text = character_name or generate_name()
|
||||||
|
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
@@ -30,49 +33,85 @@ class ChooseCharacterNameView(BaseView):
|
|||||||
w = 30
|
w = 30
|
||||||
y = (scr_height - h - 2) // 2
|
y = (scr_height - h - 2) // 2
|
||||||
x = (scr_width - w - 2) // 2
|
x = (scr_width - w - 2) // 2
|
||||||
self._win = curses.newwin(3, w + 2, y + 2, x - 1)
|
self._text_win = curses.newwin(3, w + 2, y + 2, x - 1)
|
||||||
self._win.box()
|
self._win = curses.newwin(h + 2, w + 2, y, x)
|
||||||
self.screen.addstr(y, x, "Choose character name:")
|
|
||||||
self.screen.addstr(y + 6, x, "[F5 ] generate random name")
|
|
||||||
self.screen.addstr(y + 7, x, "[Esc ] cancel")
|
|
||||||
self.screen.addstr(y + 8, x, "[Enter] confirm")
|
|
||||||
self._win.refresh()
|
|
||||||
self._render()
|
self._render()
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
del self._win
|
del self._win
|
||||||
|
del self._text_win
|
||||||
self._win = None
|
self._win = None
|
||||||
|
self._text_win = None
|
||||||
|
|
||||||
def keypress(self, key: int) -> None:
|
def keypress(self, key: int) -> None:
|
||||||
if key == curses.ascii.ESC:
|
if key == curses.KEY_F5:
|
||||||
self.on_cancel()
|
|
||||||
|
|
||||||
elif key == curses.KEY_F5:
|
|
||||||
self._text = generate_name()
|
self._text = generate_name()
|
||||||
|
|
||||||
elif curses.ascii.isprint(key):
|
elif key == curses.KEY_F10:
|
||||||
self._text += chr(key)
|
self._finish()
|
||||||
|
|
||||||
elif key == curses.KEY_BACKSPACE or key == curses.ascii.DEL:
|
elif self._active_widget == 0:
|
||||||
self._text = self._text[:-1]
|
if key == curses.ascii.ESC:
|
||||||
|
self.on_cancel()
|
||||||
|
elif curses.ascii.isprint(key):
|
||||||
|
self._text += chr(key)
|
||||||
|
elif key == curses.KEY_BACKSPACE or key == curses.ascii.DEL:
|
||||||
|
self._text = self._text[:-1]
|
||||||
|
elif key == curses.ascii.NL:
|
||||||
|
self._finish()
|
||||||
|
elif key == curses.ascii.ETB: # ^w
|
||||||
|
self._text = ""
|
||||||
|
elif key == curses.KEY_DOWN:
|
||||||
|
self._active_widget = 1
|
||||||
|
|
||||||
elif key == curses.ascii.NL:
|
else:
|
||||||
self._text = self._text.strip()
|
if key == curses.ascii.NL:
|
||||||
if self._text:
|
if self._active_widget == 1:
|
||||||
self.on_confirm(self._text)
|
self._text = generate_name()
|
||||||
else:
|
elif self._active_widget == 2:
|
||||||
|
self._finish()
|
||||||
|
elif self._active_widget == 3:
|
||||||
|
self.on_cancel()
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
elif key in KEYS_CANCEL:
|
||||||
self.on_cancel()
|
self.on_cancel()
|
||||||
|
|
||||||
elif key == curses.ascii.ETB: # ^w
|
elif key in KEYS_DOWN and self._active_widget < 3:
|
||||||
self._text = ""
|
self._active_widget += 1
|
||||||
|
|
||||||
|
elif key in KEYS_UP and self._active_widget > 0:
|
||||||
|
self._active_widget -= 1
|
||||||
|
|
||||||
self._render()
|
self._render()
|
||||||
|
|
||||||
|
def _finish(self) -> None:
|
||||||
|
self._text = self._text.strip()
|
||||||
|
if self._text:
|
||||||
|
self.on_confirm(self._text)
|
||||||
|
else:
|
||||||
|
self.on_cancel()
|
||||||
|
|
||||||
def _render(self) -> None:
|
def _render(self) -> None:
|
||||||
if not self._win:
|
if not self._win or not self._text_win:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._win.erase()
|
self._win.erase()
|
||||||
self._win.box()
|
self._win.addstr(0, 0, "Choose character name:")
|
||||||
self._win.addnstr(1, 1, self._text, self._win.getmaxyx()[1] - 2)
|
with focus_standout(self._active_widget == 1, self._win):
|
||||||
|
self._win.addstr(6, 0, "[F5 ] generate random name")
|
||||||
|
with focus_standout(self._active_widget == 2, self._win):
|
||||||
|
self._win.addstr(7, 0, "[F10 ] continue")
|
||||||
|
with focus_standout(self._active_widget == 3, self._win):
|
||||||
|
self._win.addstr(8, 0, "[Esc ] cancel")
|
||||||
self._win.refresh()
|
self._win.refresh()
|
||||||
|
|
||||||
|
self._text_win.erase()
|
||||||
|
with focus_standout(self._active_widget == 0, self._text_win):
|
||||||
|
self._text_win.box()
|
||||||
|
self._text_win.addnstr(
|
||||||
|
1, 1, self._text, self._text_win.getmaxyx()[1] - 2
|
||||||
|
)
|
||||||
|
self._text_win.refresh()
|
||||||
|
|||||||
Reference in New Issue
Block a user