[MouseFox logo]
The MouseFox Project
Join The Community Discord Server
[Discord logo]
Edit on GitHub

mousefox.app.lobbyframe

Home of LobbyFrame.

  1"""Home of `LobbyFrame`."""
  2
  3from typing import Optional
  4import arrow
  5import kvex as kx
  6import pgnet
  7
  8
  9LINE_WIDGET_HEIGHT = 40
 10AUTO_REFRESH_INTERVAL = 1
 11
 12
 13class LobbyFrame(kx.XAnchor):
 14    """Widget for interacting with the server lobby."""
 15
 16    _conpath = "client.user.lobby"
 17
 18    def __init__(self, client: pgnet.Client):
 19        """Initialize the class."""
 20        super().__init__()
 21        self._client = client
 22        self._next_dir_refresh: arrow.Arrow = arrow.now()
 23        self.game_dir = dict()
 24        self._make_widgets()
 25        self.app.controller.bind(f"{self._conpath}.focus", self._focus_list)
 26        self.app.controller.bind(f"{self._conpath}.focus_create", self._focus_create)
 27        self.app.controller.bind(f"{self._conpath}.focus_list", self._focus_list)
 28        self.app.controller.set_active_callback(self._conpath, self._focus_list)
 29
 30    def update(self):
 31        """Priodically refresh game directory."""
 32        if not self.app.controller.is_active(self._conpath):
 33            return
 34        if not self._client.connected:
 35            return
 36        if arrow.now() < self._next_dir_refresh:
 37            return
 38        self._next_dir_refresh = arrow.now().shift(seconds=AUTO_REFRESH_INTERVAL)
 39        self._refresh_games()
 40
 41    def on_parent(self, w, parent):
 42        """Refresh when shown."""
 43        if parent:
 44            self._refresh_games()
 45            self._show_game()
 46            self.games_list.focus = True
 47
 48    def _make_widgets(self):
 49        # Game list
 50        with self.app.subtheme_context("secondary"):
 51            title = kx.fwrap(kx.XLabel(text="[b]Server lobby[/b]", font_size="18sp"))
 52            title.set_size(y=LINE_WIDGET_HEIGHT)
 53        self.games_list = kx.XList(
 54            items=[""],
 55            selection_color=(1, 1, 1),
 56            item_height=LINE_WIDGET_HEIGHT,
 57        )
 58        self.games_list.bind(
 59            on_invoke=self._on_game_invoke,
 60            selection=self._show_game,
 61        )
 62        list_box = kx.XBox(orientation="vertical")
 63        list_box.add_widgets(title, self.games_list)
 64        list_frame = kx.pwrap(kx.fpwrap(list_box))
 65
 66        # Game info
 67        join_iwidgets = dict(password=kx.XInputPanelWidget("Password", "password"))
 68        with self.app.subtheme_context("secondary"):
 69            info_title = kx.XLabel(text="[b]Game Details[/b]")
 70            info_title.set_size(y=LINE_WIDGET_HEIGHT)
 71            self.game_info_label = kx.XLabel(halign="left", valign="top")
 72            self.join_panel = kx.XInputPanel(
 73                join_iwidgets,
 74                reset_text="",
 75                invoke_text="Join",
 76            )
 77            self.join_panel.bind(on_invoke=self._join_game)
 78            self.join_panel.set_size(y=LINE_WIDGET_HEIGHT * 2)
 79            info_panel = kx.XBox(orientation="vertical")
 80            info_panel.add_widgets(
 81                info_title,
 82                self.game_info_label,
 83                self.join_panel,
 84            )
 85            right_box = kx.XBox(orientation="vertical")
 86            right_box.add_widget(kx.pwrap(info_panel))
 87            right_frame = kx.fwrap(right_box)
 88
 89        # Create game
 90        pwidgets = dict(
 91            name=kx.XInputPanelWidget("Name"),
 92            password=kx.XInputPanelWidget("Password", "password"),
 93        )
 94        with self.app.subtheme_context("accent"):
 95            create_title = kx.XLabel(text="[b]Create new game[/b]")
 96            create_title.set_size(y=LINE_WIDGET_HEIGHT)
 97            self.create_panel = kx.XInputPanel(
 98                pwidgets,
 99                invoke_text="Create game",
100                reset_text="",
101            )
102            self.create_panel.bind(on_invoke=self._create_game)
103            self.create_panel.set_size(y="200dp")
104            create_box = kx.XBox(orientation="vertical")
105            create_box.add_widgets(create_title, self.create_panel)
106            create_frame = kx.pwrap(kx.fpwrap(create_box))
107            create_frame.set_size(y=self.create_panel.height + create_title.height)
108            right_box.add_widget(create_frame)
109
110        # Assemble
111        main_frame = kx.XBox()
112        main_frame.add_widgets(list_frame, kx.pwrap(right_frame))
113        self.add_widget(main_frame)
114
115    def _create_game(self, *args):
116        values = self.create_panel.get_values()
117        name = values["name"]
118        password = values["password"]
119        self._client.create_game(
120            name,
121            password=password,
122            callback=self.app.feedback_response,
123        )
124
125    def _join_game(self, *args, name: Optional[str] = None):
126        name = name or self.games_list.items[self.games_list.selection]
127        password = None
128        game = self.game_dir.get(name)
129        if not game:
130            return
131        if game.get("password_protected"):
132            password = self.join_panel.get_value("password")
133        self._client.join_game(
134            name,
135            password=password,
136            callback=self.app.feedback_response,
137        )
138
139    def _refresh_games(self, *args):
140        self._client.get_game_dir(self._on_game_dir_response)
141
142    def _on_game_dir_response(self, game_dir_response: pgnet.Response):
143        self.game_dir = game_dir_response.payload.get("games") or dict()
144        games = sorted(self.game_dir.keys()) or [""]
145        self.games_list.items = games
146        self._show_game()
147
148    def _on_game_invoke(self, w, index: int, label: str):
149        self._join_game(name=label)
150
151    def _show_game(self, *args, name: str = ""):
152        name = self.games_list.items[self.games_list.selection]
153        game = self.game_dir.get(name)
154        if not game:
155            self.game_info_label.text = "No games found. Create a new game."
156            self.join_panel.set_showing("password", False)
157            return
158        users = game.get("users")
159        passprot = game.get("password_protected")
160        password = "[i]Password protected.[/i]" if passprot else ""
161        ginfo = game.get("info")
162        if ginfo:
163            ginfo = kx.escape_markup(ginfo)
164        else:
165            ginfo = "[i]No game information available.[/i]"
166        text = "\n\n".join([
167            f"[b]{name}[/b]",
168            f"{users} users in game.",
169            password,
170            "[u]Game info[/u]",
171            ginfo,
172        ])
173        self.game_info_label.text = text
174        self.join_panel.set_showing("password", passprot)
175
176    def _focus_create(self):
177        self.create_panel.set_focus("name")
178
179    def _focus_list(self):
180        self.games_list.focus = True
181
182    set_focus = _focus_list
class LobbyFrame(kvex.widgets.layouts.XAnchor):
 14class LobbyFrame(kx.XAnchor):
 15    """Widget for interacting with the server lobby."""
 16
 17    _conpath = "client.user.lobby"
 18
 19    def __init__(self, client: pgnet.Client):
 20        """Initialize the class."""
 21        super().__init__()
 22        self._client = client
 23        self._next_dir_refresh: arrow.Arrow = arrow.now()
 24        self.game_dir = dict()
 25        self._make_widgets()
 26        self.app.controller.bind(f"{self._conpath}.focus", self._focus_list)
 27        self.app.controller.bind(f"{self._conpath}.focus_create", self._focus_create)
 28        self.app.controller.bind(f"{self._conpath}.focus_list", self._focus_list)
 29        self.app.controller.set_active_callback(self._conpath, self._focus_list)
 30
 31    def update(self):
 32        """Priodically refresh game directory."""
 33        if not self.app.controller.is_active(self._conpath):
 34            return
 35        if not self._client.connected:
 36            return
 37        if arrow.now() < self._next_dir_refresh:
 38            return
 39        self._next_dir_refresh = arrow.now().shift(seconds=AUTO_REFRESH_INTERVAL)
 40        self._refresh_games()
 41
 42    def on_parent(self, w, parent):
 43        """Refresh when shown."""
 44        if parent:
 45            self._refresh_games()
 46            self._show_game()
 47            self.games_list.focus = True
 48
 49    def _make_widgets(self):
 50        # Game list
 51        with self.app.subtheme_context("secondary"):
 52            title = kx.fwrap(kx.XLabel(text="[b]Server lobby[/b]", font_size="18sp"))
 53            title.set_size(y=LINE_WIDGET_HEIGHT)
 54        self.games_list = kx.XList(
 55            items=[""],
 56            selection_color=(1, 1, 1),
 57            item_height=LINE_WIDGET_HEIGHT,
 58        )
 59        self.games_list.bind(
 60            on_invoke=self._on_game_invoke,
 61            selection=self._show_game,
 62        )
 63        list_box = kx.XBox(orientation="vertical")
 64        list_box.add_widgets(title, self.games_list)
 65        list_frame = kx.pwrap(kx.fpwrap(list_box))
 66
 67        # Game info
 68        join_iwidgets = dict(password=kx.XInputPanelWidget("Password", "password"))
 69        with self.app.subtheme_context("secondary"):
 70            info_title = kx.XLabel(text="[b]Game Details[/b]")
 71            info_title.set_size(y=LINE_WIDGET_HEIGHT)
 72            self.game_info_label = kx.XLabel(halign="left", valign="top")
 73            self.join_panel = kx.XInputPanel(
 74                join_iwidgets,
 75                reset_text="",
 76                invoke_text="Join",
 77            )
 78            self.join_panel.bind(on_invoke=self._join_game)
 79            self.join_panel.set_size(y=LINE_WIDGET_HEIGHT * 2)
 80            info_panel = kx.XBox(orientation="vertical")
 81            info_panel.add_widgets(
 82                info_title,
 83                self.game_info_label,
 84                self.join_panel,
 85            )
 86            right_box = kx.XBox(orientation="vertical")
 87            right_box.add_widget(kx.pwrap(info_panel))
 88            right_frame = kx.fwrap(right_box)
 89
 90        # Create game
 91        pwidgets = dict(
 92            name=kx.XInputPanelWidget("Name"),
 93            password=kx.XInputPanelWidget("Password", "password"),
 94        )
 95        with self.app.subtheme_context("accent"):
 96            create_title = kx.XLabel(text="[b]Create new game[/b]")
 97            create_title.set_size(y=LINE_WIDGET_HEIGHT)
 98            self.create_panel = kx.XInputPanel(
 99                pwidgets,
100                invoke_text="Create game",
101                reset_text="",
102            )
103            self.create_panel.bind(on_invoke=self._create_game)
104            self.create_panel.set_size(y="200dp")
105            create_box = kx.XBox(orientation="vertical")
106            create_box.add_widgets(create_title, self.create_panel)
107            create_frame = kx.pwrap(kx.fpwrap(create_box))
108            create_frame.set_size(y=self.create_panel.height + create_title.height)
109            right_box.add_widget(create_frame)
110
111        # Assemble
112        main_frame = kx.XBox()
113        main_frame.add_widgets(list_frame, kx.pwrap(right_frame))
114        self.add_widget(main_frame)
115
116    def _create_game(self, *args):
117        values = self.create_panel.get_values()
118        name = values["name"]
119        password = values["password"]
120        self._client.create_game(
121            name,
122            password=password,
123            callback=self.app.feedback_response,
124        )
125
126    def _join_game(self, *args, name: Optional[str] = None):
127        name = name or self.games_list.items[self.games_list.selection]
128        password = None
129        game = self.game_dir.get(name)
130        if not game:
131            return
132        if game.get("password_protected"):
133            password = self.join_panel.get_value("password")
134        self._client.join_game(
135            name,
136            password=password,
137            callback=self.app.feedback_response,
138        )
139
140    def _refresh_games(self, *args):
141        self._client.get_game_dir(self._on_game_dir_response)
142
143    def _on_game_dir_response(self, game_dir_response: pgnet.Response):
144        self.game_dir = game_dir_response.payload.get("games") or dict()
145        games = sorted(self.game_dir.keys()) or [""]
146        self.games_list.items = games
147        self._show_game()
148
149    def _on_game_invoke(self, w, index: int, label: str):
150        self._join_game(name=label)
151
152    def _show_game(self, *args, name: str = ""):
153        name = self.games_list.items[self.games_list.selection]
154        game = self.game_dir.get(name)
155        if not game:
156            self.game_info_label.text = "No games found. Create a new game."
157            self.join_panel.set_showing("password", False)
158            return
159        users = game.get("users")
160        passprot = game.get("password_protected")
161        password = "[i]Password protected.[/i]" if passprot else ""
162        ginfo = game.get("info")
163        if ginfo:
164            ginfo = kx.escape_markup(ginfo)
165        else:
166            ginfo = "[i]No game information available.[/i]"
167        text = "\n\n".join([
168            f"[b]{name}[/b]",
169            f"{users} users in game.",
170            password,
171            "[u]Game info[/u]",
172            ginfo,
173        ])
174        self.game_info_label.text = text
175        self.join_panel.set_showing("password", passprot)
176
177    def _focus_create(self):
178        self.create_panel.set_focus("name")
179
180    def _focus_list(self):
181        self.games_list.focus = True
182
183    set_focus = _focus_list

Widget for interacting with the server lobby.

LobbyFrame(client: pgnet.client.Client)
19    def __init__(self, client: pgnet.Client):
20        """Initialize the class."""
21        super().__init__()
22        self._client = client
23        self._next_dir_refresh: arrow.Arrow = arrow.now()
24        self.game_dir = dict()
25        self._make_widgets()
26        self.app.controller.bind(f"{self._conpath}.focus", self._focus_list)
27        self.app.controller.bind(f"{self._conpath}.focus_create", self._focus_create)
28        self.app.controller.bind(f"{self._conpath}.focus_list", self._focus_list)
29        self.app.controller.set_active_callback(self._conpath, self._focus_list)

Initialize the class.

def update(self):
31    def update(self):
32        """Priodically refresh game directory."""
33        if not self.app.controller.is_active(self._conpath):
34            return
35        if not self._client.connected:
36            return
37        if arrow.now() < self._next_dir_refresh:
38            return
39        self._next_dir_refresh = arrow.now().shift(seconds=AUTO_REFRESH_INTERVAL)
40        self._refresh_games()

Priodically refresh game directory.

def on_parent(self, w, parent):
42    def on_parent(self, w, parent):
43        """Refresh when shown."""
44        if parent:
45            self._refresh_games()
46            self._show_game()
47            self.games_list.focus = True

Refresh when shown.

def set_focus(self):
180    def _focus_list(self):
181        self.games_list.focus = True

Set the focus on this widget.

Inherited Members
kivy.uix.anchorlayout.AnchorLayout
padding
anchor_x
anchor_y
do_layout
kivy.uix.layout.Layout
add_widget
remove_widget
layout_hint_with_bounds
kivy.uix.widget.Widget
proxy_ref
apply_class_lang_rules
collide_point
collide_widget
on_motion
on_touch_down
on_touch_move
on_touch_up
on_kv_post
clear_widgets
register_for_motion_event
unregister_for_motion_event
export_to_png
export_as_image
get_root_window
get_parent_window
walk
walk_reverse
to_widget
to_window
to_parent
to_local
get_window_matrix
x
y
width
height
pos
size
get_right
set_right
right
get_top
set_top
top
get_center_x
set_center_x
center_x
get_center_y
set_center_y
center_y
center
cls
children
parent
size_hint_x
size_hint_y
size_hint
pos_hint
size_hint_min_x
size_hint_min_y
size_hint_min
size_hint_max_x
size_hint_max_y
size_hint_max
ids
opacity
on_opacity
canvas
get_disabled
set_disabled
inc_disabled
dec_disabled
disabled
motion_filter
kivy._event.EventDispatcher
register_event_type
unregister_event_types
unregister_event_type
is_event_type
bind
unbind
fbind
funbind
unbind_uid
get_property_observers
events
dispatch
dispatch_generic
dispatch_children
setter
getter
property
properties
create_property
apply_property