ui+roster: implement removing players

This commit is contained in:
rr-
2018-11-05 21:04:39 +01:00
parent a265dc6d9d
commit ec601478dc
4 changed files with 77 additions and 30 deletions
+3
View File
@@ -12,6 +12,9 @@ class Roster:
def add_player(self, player: Player) -> None: def add_player(self, player: Player) -> None:
self.players.append(player) self.players.append(player)
def delete_player_at(self, player_idx: int) -> None:
del self.players[player_idx]
@staticmethod @staticmethod
def load(path: Path) -> "Roster": def load(path: Path) -> "Roster":
if path.exists(): if path.exists():
+34 -12
View File
@@ -2,9 +2,10 @@ import typing as T
import urwid import urwid
from pqcli import random
from pqcli.mechanic import Player from pqcli.mechanic import Player
from pqcli.roster import Roster from pqcli.roster import Roster
from pqcli.ui.exit_view import ExitView from pqcli.ui.confirm_dialog import ConfirmDialog
from pqcli.ui.new_game_view import NewGameView from pqcli.ui.new_game_view import NewGameView
from pqcli.ui.roster_view import RosterView from pqcli.ui.roster_view import RosterView
@@ -19,6 +20,11 @@ PALETTE: T.List[T.Tuple[str, str, str]] = [
] ]
class ConfirmExitDialog(ConfirmDialog):
def __init__(self, old_view: urwid.Widget) -> None:
super().__init__("Really quit?", old_view)
def bind_commands() -> None: def bind_commands() -> None:
for key, direction in { for key, direction in {
"k": "up", "k": "up",
@@ -40,7 +46,7 @@ class Ui:
self.loop = urwid.MainLoop( self.loop = urwid.MainLoop(
None, PALETTE, unhandled_input=self.unhandled_input None, PALETTE, unhandled_input=self.unhandled_input
) )
self.old_view: T.Optional[urwid.Widget] = None self.old_views: T.List[urwid.Widget] = []
self.switch_to_roster_view() self.switch_to_roster_view()
@@ -53,7 +59,6 @@ class Ui:
return True return True
if key == "ctrl q": if key == "ctrl q":
self.old_view = self.loop.widget
self.switch_to_exit_view() self.switch_to_exit_view()
return True return True
@@ -63,13 +68,16 @@ class Ui:
self.loop.widget = RosterView(self.roster) self.loop.widget = RosterView(self.roster)
self._connect("load_game", self.switch_to_game_view) self._connect("load_game", self.switch_to_game_view)
self._connect("new_game", self.switch_to_new_game_view) self._connect("new_game", self.switch_to_new_game_view)
self._connect("delete_game", self.switch_to_delete_player_view)
self._connect("exit", self.switch_to_exit_view) self._connect("exit", self.switch_to_exit_view)
def switch_to_exit_view(self) -> None: def switch_to_exit_view(self) -> None:
self.old_view = self.loop.widget if isinstance(self.loop.widget, ConfirmExitDialog):
self.loop.widget = ExitView(self.old_view) return
self._connect("exit", self.exit) self.old_views.append(self.loop.widget)
self._connect("cancel", self.cancel_exit) self.loop.widget = ConfirmExitDialog(self.old_views[-1])
self._connect("confirm", self.exit)
self._connect("cancel", self.cancel_dialog)
def switch_to_new_game_view(self) -> None: def switch_to_new_game_view(self) -> None:
self.loop.widget = NewGameView() self.loop.widget = NewGameView()
@@ -80,16 +88,30 @@ class Ui:
self.roster.add_player(player) self.roster.add_player(player)
self.switch_to_roster_view() self.switch_to_roster_view()
def switch_to_game_view(self, player_name: str) -> None: def delete_player(self, player_idx: int) -> None:
self.roster.delete_player_at(player_idx)
self.switch_to_roster_view()
def switch_to_game_view(self, player_idx: int) -> None:
raise NotImplementedError("not implemented") raise NotImplementedError("not implemented")
def switch_to_delete_player_view(self, player_idx: int) -> None:
adjective = random.choice(["faithful", "noble", "loyal", "brave"])
player_name = self.roster.players[player_idx].name
self.old_views.append(self.loop.widget)
self.loop.widget = ConfirmDialog(
f"Terminate {adjective} {player_name}?", self.old_views[-1]
)
self._connect("confirm", lambda: self.delete_player(player_idx))
self._connect("cancel", self.cancel_dialog)
def exit(self) -> None: def exit(self) -> None:
raise urwid.ExitMainLoop() raise urwid.ExitMainLoop()
def cancel_exit(self) -> None: def cancel_dialog(self) -> None:
assert self.old_view is not None assert len(self.old_views)
self.loop.widget = self.old_view self.loop.widget = self.old_views.pop()
self.old_view = None
def _connect(self, signal_name: str, callback: T.Callable) -> None: def _connect(self, signal_name: str, callback: T.Callable) -> None:
urwid.signals.connect_signal( urwid.signals.connect_signal(
@@ -5,13 +5,13 @@ import urwid
from pqcli.ui.button import MenuButton from pqcli.ui.button import MenuButton
class ExitView(urwid.Overlay): class ConfirmDialog(urwid.Overlay):
signals = ["exit", "cancel"] signals = ["confirm", "cancel"]
def __init__(self, parent: urwid.Widget) -> None: def __init__(self, label: str, parent: urwid.Widget) -> None:
question = urwid.Text(("bold", "Really quit?"), "center") question = urwid.Text(("bold", label), "center")
yes_btn = MenuButton( yes_btn = MenuButton(
"Yes", hint="Y", on_press=lambda _user_data: self.exit() "Yes", hint="Y", on_press=lambda _user_data: self.confirm()
) )
no_btn = MenuButton( no_btn = MenuButton(
"No", hint="N", on_press=lambda _user_data: self.cancel() "No", hint="N", on_press=lambda _user_data: self.cancel()
@@ -23,19 +23,21 @@ class ExitView(urwid.Overlay):
) )
) )
super().__init__(line_box, parent, "center", 20, "middle", 5) super().__init__(
line_box, parent, "center", len(label) + 6, "middle", 5
)
def keypress(self, size: T.Any, key: str) -> T.Optional[str]: def keypress(self, size: T.Any, key: str) -> T.Optional[str]:
if key in {"y", "Y"}: if key in {"y", "Y"}:
self.exit() self.confirm()
return None return None
if key in {"n", "N"}: if key in {"n", "N"}:
self.cancel() self.cancel()
return None return None
return T.cast(T.Optional[str], super().keypress(size, key)) return T.cast(T.Optional[str], super().keypress(size, key))
def exit(self) -> None: def confirm(self) -> None:
self._emit("exit") self._emit("confirm")
def cancel(self) -> None: def cancel(self) -> None:
self._emit("cancel") self._emit("cancel")
+26 -6
View File
@@ -7,7 +7,7 @@ from pqcli.ui.button import MenuButton
class RosterView(urwid.Filler): class RosterView(urwid.Filler):
signals = ["load_game", "new_game", "exit"] signals = ["load_game", "new_game", "delete_game", "exit"]
def __init__(self, roster: Roster) -> None: def __init__(self, roster: Roster) -> None:
self.roster = roster self.roster = roster
@@ -15,12 +15,24 @@ class RosterView(urwid.Filler):
logo = urwid.BigText("ProgressQuest", urwid.HalfBlock5x4Font()) logo = urwid.BigText("ProgressQuest", urwid.HalfBlock5x4Font())
buttons = [] buttons = []
for player in self.roster.players: for player_idx, player in enumerate(self.roster.players):
buttons.append( buttons.append(
urwid.Columns(
[
MenuButton( MenuButton(
label=player.name, label=player.name,
on_press=self.on_resume_game_press, on_press=self.on_resume_game_press,
user_data=player.name, user_data=player_idx,
),
(
10,
MenuButton(
label="Delete",
on_press=self.on_delete_game_press,
user_data=player_idx,
),
),
]
) )
) )
@@ -51,9 +63,17 @@ class RosterView(urwid.Filler):
) )
) )
def on_resume_game_press(self, user_data: T.Any) -> None: def on_resume_game_press(
player_name = T.cast(str, user_data) self, _widget: urwid.Widget, user_data: T.Any
self._emit("load_game", player_data) ) -> None:
player_idx = T.cast(int, user_data)
self._emit("load_game", player_idx)
def on_delete_game_press(
self, _widget: urwid.Widget, user_data: T.Any
) -> None:
player_idx = T.cast(int, user_data)
self._emit("delete_game", player_idx)
def on_new_game_press(self, _user_data: T.Any) -> None: def on_new_game_press(self, _user_data: T.Any) -> None:
self._emit("new_game") self._emit("new_game")