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()
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