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

mousefox.app.clientframe

Home of ClientFrame.

  1"""Home of `ClientFrame`."""
  2
  3from typing import Optional
  4import asyncio
  5import functools
  6import kvex as kx
  7import pgnet
  8from .connectpanel import ConnectPanel
  9from .userframe import UserFrame
 10
 11
 12class ClientFrame(kx.XAnchor):
 13    """Main client frame.
 14
 15    This frame contains the `ConnectPanel` and spawns a `UserFrame` for each
 16    successful connection.
 17    """
 18
 19    _conpath = "client"
 20
 21    def __init__(self, app_config):
 22        """Initialize the class with an `AppConfig`."""
 23        super().__init__()
 24        self._game_widget_factory = app_config.game_widget
 25        self._make_widgets(app_config)
 26        self._client: Optional[pgnet.Client] = None
 27        self.app.menu.set_callback("app", "disconnect", self._disconnect)
 28        self.app.controller.bind("client.user.disconnect", self._disconnect)
 29        self.app.controller.set_active_callback(self._conpath, self._on_screen)
 30        self._on_screen()
 31
 32    def update(self, *args):
 33        """Background refresh tasks."""
 34        if self._user_container.content:
 35            self._user_container.content.update()
 36
 37    def _make_widgets(self, app_config):
 38        self._connect_panel = ConnectPanel(app_config, self._set_client)
 39        placeholder = kx.XPlaceholder(label_text="Error: not connected.")
 40        self._user_container = kx.XContainer(placeholder)
 41        self._sm = kx.XScreenManager.from_widgets(
 42            dict(
 43                connect=self._connect_panel,
 44                user=self._user_container,
 45            ),
 46            transition=kx.FadeTransition(duration=0.2),
 47        )
 48        self._sm.bind(current=self._on_screen)
 49        self.add_widget(self._sm)
 50
 51    def _on_screen(self, *args):
 52        if self._sm.current == "connect":
 53            assert self._user_container.content is None
 54            self.app.menu.get_button("app", "disconnect").disabled = True
 55            self.app.menu.get_button("app", "leave_game").disabled = True
 56            if self.app.controller.active.startswith(self._conpath):
 57                self.app.controller.active = f"{self._conpath}.connect"
 58            self._connect_panel.set_focus()
 59        elif self._sm.current == "user":
 60            self.app.menu.get_button("app", "disconnect").disabled = False
 61            if self.app.controller.active.startswith(self._conpath):
 62                self.app.controller.active = f"{self._conpath}.user"
 63            userframe = self._user_container.content
 64            if userframe:
 65                userframe.set_focus()
 66        else:
 67            raise RuntimeError(f"Unknown screen: {self._sm.current}")
 68
 69    def _set_client(self, client: pgnet.Client, /):
 70        """Set a client for the app to use."""
 71        asyncio.create_task(self._async_set_client(client))
 72
 73    async def _async_set_client(self, client: pgnet.Client, /):
 74        assert not self._client
 75        self._client = client
 76        self.app.set_feedback(client.status)
 77        user_frame = UserFrame(client, self._game_widget_factory)
 78        self._user_container.content = user_frame
 79        client.on_status = functools.partial(self._on_client_status, client)
 80        client.on_connection = functools.partial(self._on_client_connected, client)
 81        await client.async_connect()
 82        assert not client.connected
 83        self._user_container.content = None
 84        self._client = None
 85        self._sm.current = "connect"
 86
 87    def _on_client_connected(self, client: pgnet.Client, connected: bool):
 88        assert client is self._client
 89        if not connected:
 90            return
 91        client.on_connection = None
 92        self._sm.current = "user"
 93
 94    def _on_client_status(self, client: pgnet.Client, status_message: str):
 95        assert client is self._client
 96        status = pgnet.Status.OK if client.connected else pgnet.Status.BAD
 97        self.app.set_feedback(status_message, status)
 98
 99    def _disconnect(self, *args):
100        if not self._client:
101            return
102        self._client.disconnect()
class ClientFrame(kvex.widgets.layouts.XAnchor):
 13class ClientFrame(kx.XAnchor):
 14    """Main client frame.
 15
 16    This frame contains the `ConnectPanel` and spawns a `UserFrame` for each
 17    successful connection.
 18    """
 19
 20    _conpath = "client"
 21
 22    def __init__(self, app_config):
 23        """Initialize the class with an `AppConfig`."""
 24        super().__init__()
 25        self._game_widget_factory = app_config.game_widget
 26        self._make_widgets(app_config)
 27        self._client: Optional[pgnet.Client] = None
 28        self.app.menu.set_callback("app", "disconnect", self._disconnect)
 29        self.app.controller.bind("client.user.disconnect", self._disconnect)
 30        self.app.controller.set_active_callback(self._conpath, self._on_screen)
 31        self._on_screen()
 32
 33    def update(self, *args):
 34        """Background refresh tasks."""
 35        if self._user_container.content:
 36            self._user_container.content.update()
 37
 38    def _make_widgets(self, app_config):
 39        self._connect_panel = ConnectPanel(app_config, self._set_client)
 40        placeholder = kx.XPlaceholder(label_text="Error: not connected.")
 41        self._user_container = kx.XContainer(placeholder)
 42        self._sm = kx.XScreenManager.from_widgets(
 43            dict(
 44                connect=self._connect_panel,
 45                user=self._user_container,
 46            ),
 47            transition=kx.FadeTransition(duration=0.2),
 48        )
 49        self._sm.bind(current=self._on_screen)
 50        self.add_widget(self._sm)
 51
 52    def _on_screen(self, *args):
 53        if self._sm.current == "connect":
 54            assert self._user_container.content is None
 55            self.app.menu.get_button("app", "disconnect").disabled = True
 56            self.app.menu.get_button("app", "leave_game").disabled = True
 57            if self.app.controller.active.startswith(self._conpath):
 58                self.app.controller.active = f"{self._conpath}.connect"
 59            self._connect_panel.set_focus()
 60        elif self._sm.current == "user":
 61            self.app.menu.get_button("app", "disconnect").disabled = False
 62            if self.app.controller.active.startswith(self._conpath):
 63                self.app.controller.active = f"{self._conpath}.user"
 64            userframe = self._user_container.content
 65            if userframe:
 66                userframe.set_focus()
 67        else:
 68            raise RuntimeError(f"Unknown screen: {self._sm.current}")
 69
 70    def _set_client(self, client: pgnet.Client, /):
 71        """Set a client for the app to use."""
 72        asyncio.create_task(self._async_set_client(client))
 73
 74    async def _async_set_client(self, client: pgnet.Client, /):
 75        assert not self._client
 76        self._client = client
 77        self.app.set_feedback(client.status)
 78        user_frame = UserFrame(client, self._game_widget_factory)
 79        self._user_container.content = user_frame
 80        client.on_status = functools.partial(self._on_client_status, client)
 81        client.on_connection = functools.partial(self._on_client_connected, client)
 82        await client.async_connect()
 83        assert not client.connected
 84        self._user_container.content = None
 85        self._client = None
 86        self._sm.current = "connect"
 87
 88    def _on_client_connected(self, client: pgnet.Client, connected: bool):
 89        assert client is self._client
 90        if not connected:
 91            return
 92        client.on_connection = None
 93        self._sm.current = "user"
 94
 95    def _on_client_status(self, client: pgnet.Client, status_message: str):
 96        assert client is self._client
 97        status = pgnet.Status.OK if client.connected else pgnet.Status.BAD
 98        self.app.set_feedback(status_message, status)
 99
100    def _disconnect(self, *args):
101        if not self._client:
102            return
103        self._client.disconnect()

Main client frame.

This frame contains the ConnectPanel and spawns a UserFrame for each successful connection.

ClientFrame(app_config)
22    def __init__(self, app_config):
23        """Initialize the class with an `AppConfig`."""
24        super().__init__()
25        self._game_widget_factory = app_config.game_widget
26        self._make_widgets(app_config)
27        self._client: Optional[pgnet.Client] = None
28        self.app.menu.set_callback("app", "disconnect", self._disconnect)
29        self.app.controller.bind("client.user.disconnect", self._disconnect)
30        self.app.controller.set_active_callback(self._conpath, self._on_screen)
31        self._on_screen()

Initialize the class with an AppConfig.

def update(self, *args):
33    def update(self, *args):
34        """Background refresh tasks."""
35        if self._user_container.content:
36            self._user_container.content.update()

Background refresh tasks.

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