mousefox.app.connectpanel
Home of ConnectPanel
.
1"""Home of `ConnectPanel`.""" 2 3from typing import Callable 4from dataclasses import dataclass 5from loguru import logger 6import json 7import kvex as kx 8import pgnet 9from .. import util 10 11 12LINE_HEIGHT = 40 13CONFIG_FILE = util.get_appdata_dir() / "connection_config.json" 14 15 16@dataclass 17class _ConnectionConfig: 18 online: bool = False 19 username: str = pgnet.util.ADMIN_USERNAME 20 address: str = "localhost" 21 port: int = pgnet.util.DEFAULT_PORT 22 pubkey: str = "" 23 24 @classmethod 25 def load_from_disk(cls) -> "_ConnectionConfig": 26 if not CONFIG_FILE.is_file(): 27 return cls() 28 with open(CONFIG_FILE) as f: 29 try: 30 config = json.load(f) 31 except json.decoder.JSONDecodeError as e: 32 logger.warning(f"Failed to load connection config: {e}") 33 return cls() 34 return cls(**config) 35 36 def save_to_disk(self): 37 data = {k: getattr(self, k) for k in self.__dataclass_fields__.keys()} 38 with open(CONFIG_FILE, "w") as f: 39 json.dump(data, f, indent=4) 40 41 42class ConnectPanel(kx.XAnchor): 43 """Widget enabling creation of clients.""" 44 45 _conpath = "client.connect" 46 47 def __init__( 48 self, 49 app_config: "mousefox.AppConfig", # noqa: F821 50 on_client: Callable, 51 ): 52 """Initialize the class.""" 53 super().__init__() 54 if app_config.disable_local and app_config.disable_remote: 55 raise ValueError("Cannot disable both local and remote clients.") 56 self._client_class = app_config.client_class 57 self._game_class = app_config.game_class 58 self._server_factory = app_config.server_factory 59 self._enable_local = not app_config.disable_local 60 self._enable_remote = not app_config.disable_remote 61 self._on_client = on_client 62 self._make_widgets(app_config.info_text, app_config.online_info_text) 63 self.app.controller.set_active_callback(self._conpath, self.set_focus) 64 self.app.controller.bind(f"{self._conpath}.focus", self.set_focus) 65 66 def _make_widgets(self, info_text, online_info_text): 67 self.clear_widgets() 68 config = _ConnectionConfig.load_from_disk() 69 if not self._enable_remote and config.online: 70 config.online = False 71 elif not self._enable_local and not config.online: 72 config.online = True 73 # Side panel 74 info_label = kx.XLabel( 75 text=info_text, 76 valign="top", 77 halign="left", 78 padding=(10, 10), 79 fixed_width=True, 80 ) 81 online_info_label = kx.XLabel( 82 text=online_info_text, 83 valign="top", 84 halign="left", 85 padding=(10, 10), 86 fixed_width=True, 87 ) 88 self._online_info_label = kx.XCurtain( 89 content=online_info_label, 90 showing=config.online, 91 ) 92 left_labels = kx.XDBox() 93 left_labels.add_widgets(info_label, self._online_info_label) 94 left_frame = kx.XBox(orientation="vertical") 95 left_frame.add_widgets(left_labels, kx.XAnchor()) 96 # Connection details 97 pwidgets = dict( 98 online=kx.XInputPanelWidget( 99 "Online", 100 "bool", 101 default=config.online, 102 bold=True, 103 italic=False, 104 showing=self._enable_local and self._enable_remote, 105 ), 106 username=kx.XInputPanelWidget("Username", default=config.username), 107 password=kx.XInputPanelWidget( 108 "Password", 109 "password", 110 showing=config.online, 111 ), 112 address=kx.XInputPanelWidget( 113 "IP Address", 114 default=config.address, 115 showing=config.online, 116 ), 117 invite_code=kx.XInputPanelWidget( 118 "Invite code", 119 showing=config.online, 120 ), 121 advanced=kx.XInputPanelWidget( 122 "Advanced", 123 "bool", 124 default=False, 125 bold=True, 126 italic=False, 127 showing=config.online, 128 ), 129 port=kx.XInputPanelWidget( 130 "Port number", 131 "int", 132 default=config.port, 133 showing=False, 134 ), 135 pubkey=kx.XInputPanelWidget( 136 "Server verification", 137 default=config.pubkey, 138 showing=False, 139 ), 140 ) 141 with self.app.subtheme_context("secondary"): 142 self.connection_panel = kx.XInputPanel(pwidgets, invoke_text="Connect") 143 connection_panel = kx.fwrap(self.connection_panel) 144 self.connection_panel.bind( 145 on_invoke=self._connect, 146 on_values=self._on_connection_values, 147 ) 148 # Assemble 149 main_frame = kx.XBox() 150 main_frame.add_widgets(kx.pwrap(left_frame), kx.pwrap(connection_panel)) 151 self.add_widget(kx.pwrap(kx.fwrap(main_frame))) 152 153 def _connect(self, *args): 154 self.connection_panel.set_focus("username") 155 get_value = self.connection_panel.get_value 156 online = get_value("online") 157 advanced = online and get_value("advanced") 158 online = get_value("online") 159 username = get_value("username") 160 password = get_value("password") 161 invite_code = get_value("invite_code") 162 address = get_value("address") if online else _ConnectionConfig.address 163 port = get_value("port") if advanced else _ConnectionConfig.port 164 pubkey = get_value("pubkey") if advanced else _ConnectionConfig.pubkey 165 if online: 166 client = self._client_class.remote( 167 address=address, 168 port=port, 169 username=username, 170 password=password, 171 invite_code=invite_code, 172 verify_server_pubkey=pubkey or None, 173 ) 174 else: 175 client = self._client_class.local( 176 username=username, 177 password=pgnet.util.DEFAULT_ADMIN_PASSWORD, 178 game=self._game_class, 179 server_factory=self._server_factory, 180 ) 181 config = _ConnectionConfig(online, username, address, port, pubkey) 182 config.save_to_disk() 183 self._on_client(client) 184 185 def _on_connection_values(self, w, values: dict): 186 online = values["online"] 187 advanced = online and values["advanced"] 188 self._online_info_label.showing = online 189 for iname in ("password", "address", "invite_code", "advanced"): 190 self.connection_panel.set_showing(iname, online) 191 for iname in ("port", "pubkey"): 192 self.connection_panel.set_showing(iname, advanced) 193 194 def set_focus(self, *args): 195 """Focus the input widgets.""" 196 self.connection_panel.set_focus("username")
43class ConnectPanel(kx.XAnchor): 44 """Widget enabling creation of clients.""" 45 46 _conpath = "client.connect" 47 48 def __init__( 49 self, 50 app_config: "mousefox.AppConfig", # noqa: F821 51 on_client: Callable, 52 ): 53 """Initialize the class.""" 54 super().__init__() 55 if app_config.disable_local and app_config.disable_remote: 56 raise ValueError("Cannot disable both local and remote clients.") 57 self._client_class = app_config.client_class 58 self._game_class = app_config.game_class 59 self._server_factory = app_config.server_factory 60 self._enable_local = not app_config.disable_local 61 self._enable_remote = not app_config.disable_remote 62 self._on_client = on_client 63 self._make_widgets(app_config.info_text, app_config.online_info_text) 64 self.app.controller.set_active_callback(self._conpath, self.set_focus) 65 self.app.controller.bind(f"{self._conpath}.focus", self.set_focus) 66 67 def _make_widgets(self, info_text, online_info_text): 68 self.clear_widgets() 69 config = _ConnectionConfig.load_from_disk() 70 if not self._enable_remote and config.online: 71 config.online = False 72 elif not self._enable_local and not config.online: 73 config.online = True 74 # Side panel 75 info_label = kx.XLabel( 76 text=info_text, 77 valign="top", 78 halign="left", 79 padding=(10, 10), 80 fixed_width=True, 81 ) 82 online_info_label = kx.XLabel( 83 text=online_info_text, 84 valign="top", 85 halign="left", 86 padding=(10, 10), 87 fixed_width=True, 88 ) 89 self._online_info_label = kx.XCurtain( 90 content=online_info_label, 91 showing=config.online, 92 ) 93 left_labels = kx.XDBox() 94 left_labels.add_widgets(info_label, self._online_info_label) 95 left_frame = kx.XBox(orientation="vertical") 96 left_frame.add_widgets(left_labels, kx.XAnchor()) 97 # Connection details 98 pwidgets = dict( 99 online=kx.XInputPanelWidget( 100 "Online", 101 "bool", 102 default=config.online, 103 bold=True, 104 italic=False, 105 showing=self._enable_local and self._enable_remote, 106 ), 107 username=kx.XInputPanelWidget("Username", default=config.username), 108 password=kx.XInputPanelWidget( 109 "Password", 110 "password", 111 showing=config.online, 112 ), 113 address=kx.XInputPanelWidget( 114 "IP Address", 115 default=config.address, 116 showing=config.online, 117 ), 118 invite_code=kx.XInputPanelWidget( 119 "Invite code", 120 showing=config.online, 121 ), 122 advanced=kx.XInputPanelWidget( 123 "Advanced", 124 "bool", 125 default=False, 126 bold=True, 127 italic=False, 128 showing=config.online, 129 ), 130 port=kx.XInputPanelWidget( 131 "Port number", 132 "int", 133 default=config.port, 134 showing=False, 135 ), 136 pubkey=kx.XInputPanelWidget( 137 "Server verification", 138 default=config.pubkey, 139 showing=False, 140 ), 141 ) 142 with self.app.subtheme_context("secondary"): 143 self.connection_panel = kx.XInputPanel(pwidgets, invoke_text="Connect") 144 connection_panel = kx.fwrap(self.connection_panel) 145 self.connection_panel.bind( 146 on_invoke=self._connect, 147 on_values=self._on_connection_values, 148 ) 149 # Assemble 150 main_frame = kx.XBox() 151 main_frame.add_widgets(kx.pwrap(left_frame), kx.pwrap(connection_panel)) 152 self.add_widget(kx.pwrap(kx.fwrap(main_frame))) 153 154 def _connect(self, *args): 155 self.connection_panel.set_focus("username") 156 get_value = self.connection_panel.get_value 157 online = get_value("online") 158 advanced = online and get_value("advanced") 159 online = get_value("online") 160 username = get_value("username") 161 password = get_value("password") 162 invite_code = get_value("invite_code") 163 address = get_value("address") if online else _ConnectionConfig.address 164 port = get_value("port") if advanced else _ConnectionConfig.port 165 pubkey = get_value("pubkey") if advanced else _ConnectionConfig.pubkey 166 if online: 167 client = self._client_class.remote( 168 address=address, 169 port=port, 170 username=username, 171 password=password, 172 invite_code=invite_code, 173 verify_server_pubkey=pubkey or None, 174 ) 175 else: 176 client = self._client_class.local( 177 username=username, 178 password=pgnet.util.DEFAULT_ADMIN_PASSWORD, 179 game=self._game_class, 180 server_factory=self._server_factory, 181 ) 182 config = _ConnectionConfig(online, username, address, port, pubkey) 183 config.save_to_disk() 184 self._on_client(client) 185 186 def _on_connection_values(self, w, values: dict): 187 online = values["online"] 188 advanced = online and values["advanced"] 189 self._online_info_label.showing = online 190 for iname in ("password", "address", "invite_code", "advanced"): 191 self.connection_panel.set_showing(iname, online) 192 for iname in ("port", "pubkey"): 193 self.connection_panel.set_showing(iname, advanced) 194 195 def set_focus(self, *args): 196 """Focus the input widgets.""" 197 self.connection_panel.set_focus("username")
Widget enabling creation of clients.
ConnectPanel(app_config: mousefox.app.app.AppConfig, on_client: Callable)
48 def __init__( 49 self, 50 app_config: "mousefox.AppConfig", # noqa: F821 51 on_client: Callable, 52 ): 53 """Initialize the class.""" 54 super().__init__() 55 if app_config.disable_local and app_config.disable_remote: 56 raise ValueError("Cannot disable both local and remote clients.") 57 self._client_class = app_config.client_class 58 self._game_class = app_config.game_class 59 self._server_factory = app_config.server_factory 60 self._enable_local = not app_config.disable_local 61 self._enable_remote = not app_config.disable_remote 62 self._on_client = on_client 63 self._make_widgets(app_config.info_text, app_config.online_info_text) 64 self.app.controller.set_active_callback(self._conpath, self.set_focus) 65 self.app.controller.bind(f"{self._conpath}.focus", self.set_focus)
Initialize the class.
def
set_focus(self, *args):
195 def set_focus(self, *args): 196 """Focus the input widgets.""" 197 self.connection_panel.set_focus("username")
Focus the input widgets.
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