mirror of
https://github.com/rr-/pq-cli.git
synced 2026-09-29 06:44:00 -06:00
ui+roster: implement removing players
This commit is contained in:
@@ -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
@@ -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
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user