bauiv1lib.settings.plugins
Plugin Window UI.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Plugin Window UI.""" 4 5from __future__ import annotations 6 7from enum import Enum 8import logging 9from typing import TYPE_CHECKING, assert_never 10 11import bauiv1 as bui 12from bauiv1lib import popup 13 14if TYPE_CHECKING: 15 pass 16 17 18class Category(Enum): 19 """Categories we can display.""" 20 21 ALL = 'all' 22 ENABLED = 'enabled' 23 DISABLED = 'disabled' 24 25 @property 26 def resource(self) -> str: 27 """Resource name for us.""" 28 return f'{self.value}Text' 29 30 31class PluginWindow(bui.Window): 32 """Window for configuring plugins.""" 33 34 def __init__( 35 self, 36 transition: str = 'in_right', 37 origin_widget: bui.Widget | None = None, 38 ): 39 # pylint: disable=too-many-statements 40 app = bui.app 41 42 self._category = Category.ALL 43 44 # If they provided an origin-widget, scale up from that. 45 scale_origin: tuple[float, float] | None 46 if origin_widget is not None: 47 self._transition_out = 'out_scale' 48 scale_origin = origin_widget.get_screen_space_center() 49 transition = 'in_scale' 50 else: 51 self._transition_out = 'out_right' 52 scale_origin = None 53 54 assert bui.app.classic is not None 55 uiscale = bui.app.ui_v1.uiscale 56 self._width = 870.0 if uiscale is bui.UIScale.SMALL else 670.0 57 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 58 self._height = ( 59 390.0 60 if uiscale is bui.UIScale.SMALL 61 else 450.0 62 if uiscale is bui.UIScale.MEDIUM 63 else 520.0 64 ) 65 top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 66 super().__init__( 67 root_widget=bui.containerwidget( 68 size=(self._width, self._height + top_extra), 69 transition=transition, 70 toolbar_visibility='menu_minimal', 71 scale_origin_stack_offset=scale_origin, 72 scale=( 73 2.06 74 if uiscale is bui.UIScale.SMALL 75 else 1.4 76 if uiscale is bui.UIScale.MEDIUM 77 else 1.0 78 ), 79 stack_offset=(0, -25) 80 if uiscale is bui.UIScale.SMALL 81 else (0, 0), 82 ) 83 ) 84 85 self._scroll_width = self._width - (100 + 2 * x_inset) 86 self._scroll_height = self._height - 115.0 87 self._sub_width = self._scroll_width * 0.95 88 self._sub_height = 724.0 89 90 assert app.classic is not None 91 if app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: 92 bui.containerwidget( 93 edit=self._root_widget, on_cancel_call=self._do_back 94 ) 95 self._back_button = None 96 else: 97 self._back_button = bui.buttonwidget( 98 parent=self._root_widget, 99 position=(53 + x_inset, self._height - 60), 100 size=(140, 60), 101 scale=0.8, 102 autoselect=True, 103 label=bui.Lstr(resource='backText'), 104 button_type='back', 105 on_activate_call=self._do_back, 106 ) 107 bui.containerwidget( 108 edit=self._root_widget, cancel_button=self._back_button 109 ) 110 111 self._title_text = bui.textwidget( 112 parent=self._root_widget, 113 position=(self._width * 0.5, self._height - 38), 114 size=(0, 0), 115 text=bui.Lstr(resource='pluginsText'), 116 color=app.ui_v1.title_color, 117 maxwidth=200, 118 h_align='center', 119 v_align='center', 120 ) 121 122 if self._back_button is not None: 123 bui.buttonwidget( 124 edit=self._back_button, 125 button_type='backSmall', 126 size=(60, 60), 127 label=bui.charstr(bui.SpecialChar.BACK), 128 ) 129 130 settings_button_x = 670 if uiscale is bui.UIScale.SMALL else 570 131 132 self._category_button = bui.buttonwidget( 133 parent=self._root_widget, 134 scale=0.7, 135 position=(settings_button_x - 105, self._height - 60), 136 size=(130, 60), 137 label=bui.Lstr(resource='allText'), 138 autoselect=True, 139 on_activate_call=bui.WeakCall(self._show_category_options), 140 color=(0.55, 0.73, 0.25), 141 iconscale=1.2, 142 ) 143 144 self._settings_button = bui.buttonwidget( 145 parent=self._root_widget, 146 position=(settings_button_x, self._height - 58), 147 size=(40, 40), 148 label='', 149 on_activate_call=self._open_settings, 150 ) 151 152 bui.imagewidget( 153 parent=self._root_widget, 154 position=(settings_button_x + 3, self._height - 57), 155 draw_controller=self._settings_button, 156 size=(35, 35), 157 texture=bui.gettexture('settingsIcon'), 158 ) 159 160 bui.widget( 161 edit=self._settings_button, 162 up_widget=self._settings_button, 163 right_widget=self._settings_button, 164 ) 165 166 self._scrollwidget = bui.scrollwidget( 167 parent=self._root_widget, 168 position=(50 + x_inset, 50), 169 simple_culling_v=20.0, 170 highlight=False, 171 size=(self._scroll_width, self._scroll_height), 172 selection_loops_to_parent=True, 173 claims_left_right=True, 174 ) 175 bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget) 176 177 if bui.app.meta.scanresults is None: 178 bui.screenmessage( 179 'Still scanning plugins; please try again.', color=(1, 0, 0) 180 ) 181 bui.getsound('error').play() 182 plugspecs = bui.app.plugins.plugin_specs 183 plugstates: dict[str, dict] = bui.app.config.get('Plugins', {}) 184 assert isinstance(plugstates, dict) 185 186 plug_line_height = 50 187 sub_width = self._scroll_width 188 sub_height = len(plugspecs) * plug_line_height 189 self._subcontainer = bui.containerwidget( 190 parent=self._scrollwidget, 191 size=(sub_width, sub_height), 192 background=False, 193 ) 194 self._show_plugins() 195 bui.containerwidget( 196 edit=self._root_widget, selected_child=self._scrollwidget 197 ) 198 self._restore_state() 199 200 def _check_value_changed(self, plug: bui.PluginSpec, value: bool) -> None: 201 bui.screenmessage( 202 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 203 color=(1.0, 0.5, 0.0), 204 ) 205 plugstates: dict[str, dict] = bui.app.config.setdefault('Plugins', {}) 206 assert isinstance(plugstates, dict) 207 plugstate = plugstates.setdefault(plug.class_path, {}) 208 plugstate['enabled'] = value 209 bui.app.config.commit() 210 211 def _open_settings(self) -> None: 212 # pylint: disable=cyclic-import 213 from bauiv1lib.settings.pluginsettings import PluginSettingsWindow 214 215 self._save_state() 216 bui.containerwidget(edit=self._root_widget, transition='out_left') 217 assert bui.app.classic is not None 218 bui.app.ui_v1.set_main_menu_window( 219 PluginSettingsWindow(transition='in_right').get_root_widget() 220 ) 221 222 def _show_category_options(self) -> None: 223 uiscale = bui.app.ui_v1.uiscale 224 225 popup.PopupMenuWindow( 226 position=self._category_button.get_screen_space_center(), 227 scale=( 228 2.3 229 if uiscale is bui.UIScale.SMALL 230 else 1.65 231 if uiscale is bui.UIScale.MEDIUM 232 else 1.23 233 ), 234 choices=[c.value for c in Category], 235 choices_display=[bui.Lstr(resource=c.resource) for c in Category], 236 current_choice=self._category.value, 237 delegate=self, 238 ) 239 240 def popup_menu_selected_choice( 241 self, popup_window: popup.PopupMenuWindow, choice: str 242 ) -> None: 243 """Called when a choice is selected in the popup.""" 244 del popup_window # unused 245 self._category = Category(choice) 246 self._clear_scroll_widget() 247 self._show_plugins() 248 249 bui.buttonwidget( 250 edit=self._category_button, 251 label=bui.Lstr(resource=self._category.resource), 252 ) 253 254 def popup_menu_closing(self, popup_window: popup.PopupWindow) -> None: 255 """Called when the popup is closing.""" 256 257 def _clear_scroll_widget(self) -> None: 258 existing_widgets = self._subcontainer.get_children() 259 if existing_widgets: 260 for i in existing_widgets: 261 i.delete() 262 263 def _show_plugins(self) -> None: 264 # pylint: disable=too-many-locals 265 # pylint: disable=too-many-branches 266 plugspecs = bui.app.plugins.plugin_specs 267 plugstates: dict[str, dict] = bui.app.config.setdefault('Plugins', {}) 268 assert isinstance(plugstates, dict) 269 270 plug_line_height = 50 271 sub_width = self._scroll_width 272 num_enabled = 0 273 num_disabled = 0 274 275 plugspecs_sorted = sorted(plugspecs.items()) 276 277 for _classpath, plugspec in plugspecs_sorted: 278 # counting number of enabled and disabled plugins 279 # plugstate = plugstates.setdefault(plugspec[0], {}) 280 if plugspec.enabled: 281 num_enabled += 1 282 else: 283 num_disabled += 1 284 285 if self._category is Category.ALL: 286 sub_height = len(plugspecs) * plug_line_height 287 bui.containerwidget( 288 edit=self._subcontainer, size=(self._scroll_width, sub_height) 289 ) 290 elif self._category is Category.ENABLED: 291 sub_height = num_enabled * plug_line_height 292 bui.containerwidget( 293 edit=self._subcontainer, size=(self._scroll_width, sub_height) 294 ) 295 elif self._category is Category.DISABLED: 296 sub_height = num_disabled * plug_line_height 297 bui.containerwidget( 298 edit=self._subcontainer, size=(self._scroll_width, sub_height) 299 ) 300 else: 301 # Make sure we handle all cases. 302 assert_never(self._category) 303 304 num_shown = 0 305 for classpath, plugspec in plugspecs_sorted: 306 plugin = plugspec.plugin 307 enabled = plugspec.enabled 308 309 if self._category is Category.ALL: 310 show = True 311 elif self._category is Category.ENABLED: 312 show = enabled 313 elif self._category is Category.DISABLED: 314 show = not enabled 315 else: 316 assert_never(self._category) 317 # show = False 318 319 if not show: 320 continue 321 322 item_y = sub_height - (num_shown + 1) * plug_line_height 323 check = bui.checkboxwidget( 324 parent=self._subcontainer, 325 text=bui.Lstr(value=classpath), 326 autoselect=True, 327 value=enabled, 328 maxwidth=self._scroll_width - 200, 329 position=(10, item_y), 330 size=(self._scroll_width - 40, 50), 331 on_value_change_call=bui.Call( 332 self._check_value_changed, plugspec 333 ), 334 textcolor=( 335 (0.8, 0.3, 0.3) 336 if (plugspec.attempted_load and plugspec.plugin is None) 337 else (0.6, 0.6, 0.6) 338 if plugspec.plugin is None 339 else (0, 1, 0) 340 ), 341 ) 342 # noinspection PyUnresolvedReferences 343 if plugin is not None and plugin.has_settings_ui(): 344 button = bui.buttonwidget( 345 parent=self._subcontainer, 346 label=bui.Lstr(resource='mainMenu.settingsText'), 347 autoselect=True, 348 size=(100, 40), 349 position=(sub_width - 130, item_y + 6), 350 ) 351 # noinspection PyUnresolvedReferences 352 bui.buttonwidget( 353 edit=button, 354 on_activate_call=bui.Call(plugin.show_settings_ui, button), 355 ) 356 else: 357 button = None 358 359 # Allow getting back to back button. 360 if num_shown == 0: 361 bui.widget( 362 edit=check, 363 up_widget=self._back_button, 364 left_widget=self._back_button, 365 right_widget=self._settings_button, 366 ) 367 if button is not None: 368 bui.widget(edit=button, up_widget=self._back_button) 369 370 # Make sure we scroll all the way to the end when using 371 # keyboard/button nav. 372 bui.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40) 373 num_shown += 1 374 375 def _save_state(self) -> None: 376 try: 377 sel = self._root_widget.get_selected_child() 378 if sel == self._category_button: 379 sel_name = 'Category' 380 elif sel == self._settings_button: 381 sel_name = 'Settings' 382 elif sel == self._back_button: 383 sel_name = 'Back' 384 elif sel == self._scrollwidget: 385 sel_name = 'Scroll' 386 else: 387 raise ValueError(f'unrecognized selection \'{sel}\'') 388 assert bui.app.classic is not None 389 bui.app.ui_v1.window_states[type(self)] = sel_name 390 except Exception: 391 logging.exception('Error saving state for %s.', self) 392 393 def _restore_state(self) -> None: 394 try: 395 assert bui.app.classic is not None 396 sel_name = bui.app.ui_v1.window_states.get(type(self)) 397 sel: bui.Widget | None 398 if sel_name == 'Category': 399 sel = self._category_button 400 elif sel_name == 'Settings': 401 sel = self._settings_button 402 elif sel_name == 'Back': 403 sel = self._back_button 404 else: 405 sel = self._scrollwidget 406 if sel: 407 bui.containerwidget(edit=self._root_widget, selected_child=sel) 408 except Exception: 409 logging.exception('Error restoring state for %s.', self) 410 411 def _do_back(self) -> None: 412 # pylint: disable=cyclic-import 413 from bauiv1lib.settings.advanced import AdvancedSettingsWindow 414 415 self._save_state() 416 bui.containerwidget( 417 edit=self._root_widget, transition=self._transition_out 418 ) 419 assert bui.app.classic is not None 420 bui.app.ui_v1.set_main_menu_window( 421 AdvancedSettingsWindow(transition='in_left').get_root_widget() 422 )
class
Category(enum.Enum):
19class Category(Enum): 20 """Categories we can display.""" 21 22 ALL = 'all' 23 ENABLED = 'enabled' 24 DISABLED = 'disabled' 25 26 @property 27 def resource(self) -> str: 28 """Resource name for us.""" 29 return f'{self.value}Text'
Categories we can display.
ALL =
<Category.ALL: 'all'>
ENABLED =
<Category.ENABLED: 'enabled'>
DISABLED =
<Category.DISABLED: 'disabled'>
Inherited Members
- enum.Enum
- name
- value
class
PluginWindow(bauiv1._uitypes.Window):
32class PluginWindow(bui.Window): 33 """Window for configuring plugins.""" 34 35 def __init__( 36 self, 37 transition: str = 'in_right', 38 origin_widget: bui.Widget | None = None, 39 ): 40 # pylint: disable=too-many-statements 41 app = bui.app 42 43 self._category = Category.ALL 44 45 # If they provided an origin-widget, scale up from that. 46 scale_origin: tuple[float, float] | None 47 if origin_widget is not None: 48 self._transition_out = 'out_scale' 49 scale_origin = origin_widget.get_screen_space_center() 50 transition = 'in_scale' 51 else: 52 self._transition_out = 'out_right' 53 scale_origin = None 54 55 assert bui.app.classic is not None 56 uiscale = bui.app.ui_v1.uiscale 57 self._width = 870.0 if uiscale is bui.UIScale.SMALL else 670.0 58 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 59 self._height = ( 60 390.0 61 if uiscale is bui.UIScale.SMALL 62 else 450.0 63 if uiscale is bui.UIScale.MEDIUM 64 else 520.0 65 ) 66 top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 67 super().__init__( 68 root_widget=bui.containerwidget( 69 size=(self._width, self._height + top_extra), 70 transition=transition, 71 toolbar_visibility='menu_minimal', 72 scale_origin_stack_offset=scale_origin, 73 scale=( 74 2.06 75 if uiscale is bui.UIScale.SMALL 76 else 1.4 77 if uiscale is bui.UIScale.MEDIUM 78 else 1.0 79 ), 80 stack_offset=(0, -25) 81 if uiscale is bui.UIScale.SMALL 82 else (0, 0), 83 ) 84 ) 85 86 self._scroll_width = self._width - (100 + 2 * x_inset) 87 self._scroll_height = self._height - 115.0 88 self._sub_width = self._scroll_width * 0.95 89 self._sub_height = 724.0 90 91 assert app.classic is not None 92 if app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: 93 bui.containerwidget( 94 edit=self._root_widget, on_cancel_call=self._do_back 95 ) 96 self._back_button = None 97 else: 98 self._back_button = bui.buttonwidget( 99 parent=self._root_widget, 100 position=(53 + x_inset, self._height - 60), 101 size=(140, 60), 102 scale=0.8, 103 autoselect=True, 104 label=bui.Lstr(resource='backText'), 105 button_type='back', 106 on_activate_call=self._do_back, 107 ) 108 bui.containerwidget( 109 edit=self._root_widget, cancel_button=self._back_button 110 ) 111 112 self._title_text = bui.textwidget( 113 parent=self._root_widget, 114 position=(self._width * 0.5, self._height - 38), 115 size=(0, 0), 116 text=bui.Lstr(resource='pluginsText'), 117 color=app.ui_v1.title_color, 118 maxwidth=200, 119 h_align='center', 120 v_align='center', 121 ) 122 123 if self._back_button is not None: 124 bui.buttonwidget( 125 edit=self._back_button, 126 button_type='backSmall', 127 size=(60, 60), 128 label=bui.charstr(bui.SpecialChar.BACK), 129 ) 130 131 settings_button_x = 670 if uiscale is bui.UIScale.SMALL else 570 132 133 self._category_button = bui.buttonwidget( 134 parent=self._root_widget, 135 scale=0.7, 136 position=(settings_button_x - 105, self._height - 60), 137 size=(130, 60), 138 label=bui.Lstr(resource='allText'), 139 autoselect=True, 140 on_activate_call=bui.WeakCall(self._show_category_options), 141 color=(0.55, 0.73, 0.25), 142 iconscale=1.2, 143 ) 144 145 self._settings_button = bui.buttonwidget( 146 parent=self._root_widget, 147 position=(settings_button_x, self._height - 58), 148 size=(40, 40), 149 label='', 150 on_activate_call=self._open_settings, 151 ) 152 153 bui.imagewidget( 154 parent=self._root_widget, 155 position=(settings_button_x + 3, self._height - 57), 156 draw_controller=self._settings_button, 157 size=(35, 35), 158 texture=bui.gettexture('settingsIcon'), 159 ) 160 161 bui.widget( 162 edit=self._settings_button, 163 up_widget=self._settings_button, 164 right_widget=self._settings_button, 165 ) 166 167 self._scrollwidget = bui.scrollwidget( 168 parent=self._root_widget, 169 position=(50 + x_inset, 50), 170 simple_culling_v=20.0, 171 highlight=False, 172 size=(self._scroll_width, self._scroll_height), 173 selection_loops_to_parent=True, 174 claims_left_right=True, 175 ) 176 bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget) 177 178 if bui.app.meta.scanresults is None: 179 bui.screenmessage( 180 'Still scanning plugins; please try again.', color=(1, 0, 0) 181 ) 182 bui.getsound('error').play() 183 plugspecs = bui.app.plugins.plugin_specs 184 plugstates: dict[str, dict] = bui.app.config.get('Plugins', {}) 185 assert isinstance(plugstates, dict) 186 187 plug_line_height = 50 188 sub_width = self._scroll_width 189 sub_height = len(plugspecs) * plug_line_height 190 self._subcontainer = bui.containerwidget( 191 parent=self._scrollwidget, 192 size=(sub_width, sub_height), 193 background=False, 194 ) 195 self._show_plugins() 196 bui.containerwidget( 197 edit=self._root_widget, selected_child=self._scrollwidget 198 ) 199 self._restore_state() 200 201 def _check_value_changed(self, plug: bui.PluginSpec, value: bool) -> None: 202 bui.screenmessage( 203 bui.Lstr(resource='settingsWindowAdvanced.mustRestartText'), 204 color=(1.0, 0.5, 0.0), 205 ) 206 plugstates: dict[str, dict] = bui.app.config.setdefault('Plugins', {}) 207 assert isinstance(plugstates, dict) 208 plugstate = plugstates.setdefault(plug.class_path, {}) 209 plugstate['enabled'] = value 210 bui.app.config.commit() 211 212 def _open_settings(self) -> None: 213 # pylint: disable=cyclic-import 214 from bauiv1lib.settings.pluginsettings import PluginSettingsWindow 215 216 self._save_state() 217 bui.containerwidget(edit=self._root_widget, transition='out_left') 218 assert bui.app.classic is not None 219 bui.app.ui_v1.set_main_menu_window( 220 PluginSettingsWindow(transition='in_right').get_root_widget() 221 ) 222 223 def _show_category_options(self) -> None: 224 uiscale = bui.app.ui_v1.uiscale 225 226 popup.PopupMenuWindow( 227 position=self._category_button.get_screen_space_center(), 228 scale=( 229 2.3 230 if uiscale is bui.UIScale.SMALL 231 else 1.65 232 if uiscale is bui.UIScale.MEDIUM 233 else 1.23 234 ), 235 choices=[c.value for c in Category], 236 choices_display=[bui.Lstr(resource=c.resource) for c in Category], 237 current_choice=self._category.value, 238 delegate=self, 239 ) 240 241 def popup_menu_selected_choice( 242 self, popup_window: popup.PopupMenuWindow, choice: str 243 ) -> None: 244 """Called when a choice is selected in the popup.""" 245 del popup_window # unused 246 self._category = Category(choice) 247 self._clear_scroll_widget() 248 self._show_plugins() 249 250 bui.buttonwidget( 251 edit=self._category_button, 252 label=bui.Lstr(resource=self._category.resource), 253 ) 254 255 def popup_menu_closing(self, popup_window: popup.PopupWindow) -> None: 256 """Called when the popup is closing.""" 257 258 def _clear_scroll_widget(self) -> None: 259 existing_widgets = self._subcontainer.get_children() 260 if existing_widgets: 261 for i in existing_widgets: 262 i.delete() 263 264 def _show_plugins(self) -> None: 265 # pylint: disable=too-many-locals 266 # pylint: disable=too-many-branches 267 plugspecs = bui.app.plugins.plugin_specs 268 plugstates: dict[str, dict] = bui.app.config.setdefault('Plugins', {}) 269 assert isinstance(plugstates, dict) 270 271 plug_line_height = 50 272 sub_width = self._scroll_width 273 num_enabled = 0 274 num_disabled = 0 275 276 plugspecs_sorted = sorted(plugspecs.items()) 277 278 for _classpath, plugspec in plugspecs_sorted: 279 # counting number of enabled and disabled plugins 280 # plugstate = plugstates.setdefault(plugspec[0], {}) 281 if plugspec.enabled: 282 num_enabled += 1 283 else: 284 num_disabled += 1 285 286 if self._category is Category.ALL: 287 sub_height = len(plugspecs) * plug_line_height 288 bui.containerwidget( 289 edit=self._subcontainer, size=(self._scroll_width, sub_height) 290 ) 291 elif self._category is Category.ENABLED: 292 sub_height = num_enabled * plug_line_height 293 bui.containerwidget( 294 edit=self._subcontainer, size=(self._scroll_width, sub_height) 295 ) 296 elif self._category is Category.DISABLED: 297 sub_height = num_disabled * plug_line_height 298 bui.containerwidget( 299 edit=self._subcontainer, size=(self._scroll_width, sub_height) 300 ) 301 else: 302 # Make sure we handle all cases. 303 assert_never(self._category) 304 305 num_shown = 0 306 for classpath, plugspec in plugspecs_sorted: 307 plugin = plugspec.plugin 308 enabled = plugspec.enabled 309 310 if self._category is Category.ALL: 311 show = True 312 elif self._category is Category.ENABLED: 313 show = enabled 314 elif self._category is Category.DISABLED: 315 show = not enabled 316 else: 317 assert_never(self._category) 318 # show = False 319 320 if not show: 321 continue 322 323 item_y = sub_height - (num_shown + 1) * plug_line_height 324 check = bui.checkboxwidget( 325 parent=self._subcontainer, 326 text=bui.Lstr(value=classpath), 327 autoselect=True, 328 value=enabled, 329 maxwidth=self._scroll_width - 200, 330 position=(10, item_y), 331 size=(self._scroll_width - 40, 50), 332 on_value_change_call=bui.Call( 333 self._check_value_changed, plugspec 334 ), 335 textcolor=( 336 (0.8, 0.3, 0.3) 337 if (plugspec.attempted_load and plugspec.plugin is None) 338 else (0.6, 0.6, 0.6) 339 if plugspec.plugin is None 340 else (0, 1, 0) 341 ), 342 ) 343 # noinspection PyUnresolvedReferences 344 if plugin is not None and plugin.has_settings_ui(): 345 button = bui.buttonwidget( 346 parent=self._subcontainer, 347 label=bui.Lstr(resource='mainMenu.settingsText'), 348 autoselect=True, 349 size=(100, 40), 350 position=(sub_width - 130, item_y + 6), 351 ) 352 # noinspection PyUnresolvedReferences 353 bui.buttonwidget( 354 edit=button, 355 on_activate_call=bui.Call(plugin.show_settings_ui, button), 356 ) 357 else: 358 button = None 359 360 # Allow getting back to back button. 361 if num_shown == 0: 362 bui.widget( 363 edit=check, 364 up_widget=self._back_button, 365 left_widget=self._back_button, 366 right_widget=self._settings_button, 367 ) 368 if button is not None: 369 bui.widget(edit=button, up_widget=self._back_button) 370 371 # Make sure we scroll all the way to the end when using 372 # keyboard/button nav. 373 bui.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40) 374 num_shown += 1 375 376 def _save_state(self) -> None: 377 try: 378 sel = self._root_widget.get_selected_child() 379 if sel == self._category_button: 380 sel_name = 'Category' 381 elif sel == self._settings_button: 382 sel_name = 'Settings' 383 elif sel == self._back_button: 384 sel_name = 'Back' 385 elif sel == self._scrollwidget: 386 sel_name = 'Scroll' 387 else: 388 raise ValueError(f'unrecognized selection \'{sel}\'') 389 assert bui.app.classic is not None 390 bui.app.ui_v1.window_states[type(self)] = sel_name 391 except Exception: 392 logging.exception('Error saving state for %s.', self) 393 394 def _restore_state(self) -> None: 395 try: 396 assert bui.app.classic is not None 397 sel_name = bui.app.ui_v1.window_states.get(type(self)) 398 sel: bui.Widget | None 399 if sel_name == 'Category': 400 sel = self._category_button 401 elif sel_name == 'Settings': 402 sel = self._settings_button 403 elif sel_name == 'Back': 404 sel = self._back_button 405 else: 406 sel = self._scrollwidget 407 if sel: 408 bui.containerwidget(edit=self._root_widget, selected_child=sel) 409 except Exception: 410 logging.exception('Error restoring state for %s.', self) 411 412 def _do_back(self) -> None: 413 # pylint: disable=cyclic-import 414 from bauiv1lib.settings.advanced import AdvancedSettingsWindow 415 416 self._save_state() 417 bui.containerwidget( 418 edit=self._root_widget, transition=self._transition_out 419 ) 420 assert bui.app.classic is not None 421 bui.app.ui_v1.set_main_menu_window( 422 AdvancedSettingsWindow(transition='in_left').get_root_widget() 423 )
Window for configuring plugins.
PluginWindow( transition: str = 'in_right', origin_widget: _bauiv1.Widget | None = None)
35 def __init__( 36 self, 37 transition: str = 'in_right', 38 origin_widget: bui.Widget | None = None, 39 ): 40 # pylint: disable=too-many-statements 41 app = bui.app 42 43 self._category = Category.ALL 44 45 # If they provided an origin-widget, scale up from that. 46 scale_origin: tuple[float, float] | None 47 if origin_widget is not None: 48 self._transition_out = 'out_scale' 49 scale_origin = origin_widget.get_screen_space_center() 50 transition = 'in_scale' 51 else: 52 self._transition_out = 'out_right' 53 scale_origin = None 54 55 assert bui.app.classic is not None 56 uiscale = bui.app.ui_v1.uiscale 57 self._width = 870.0 if uiscale is bui.UIScale.SMALL else 670.0 58 x_inset = 100 if uiscale is bui.UIScale.SMALL else 0 59 self._height = ( 60 390.0 61 if uiscale is bui.UIScale.SMALL 62 else 450.0 63 if uiscale is bui.UIScale.MEDIUM 64 else 520.0 65 ) 66 top_extra = 10 if uiscale is bui.UIScale.SMALL else 0 67 super().__init__( 68 root_widget=bui.containerwidget( 69 size=(self._width, self._height + top_extra), 70 transition=transition, 71 toolbar_visibility='menu_minimal', 72 scale_origin_stack_offset=scale_origin, 73 scale=( 74 2.06 75 if uiscale is bui.UIScale.SMALL 76 else 1.4 77 if uiscale is bui.UIScale.MEDIUM 78 else 1.0 79 ), 80 stack_offset=(0, -25) 81 if uiscale is bui.UIScale.SMALL 82 else (0, 0), 83 ) 84 ) 85 86 self._scroll_width = self._width - (100 + 2 * x_inset) 87 self._scroll_height = self._height - 115.0 88 self._sub_width = self._scroll_width * 0.95 89 self._sub_height = 724.0 90 91 assert app.classic is not None 92 if app.ui_v1.use_toolbars and uiscale is bui.UIScale.SMALL: 93 bui.containerwidget( 94 edit=self._root_widget, on_cancel_call=self._do_back 95 ) 96 self._back_button = None 97 else: 98 self._back_button = bui.buttonwidget( 99 parent=self._root_widget, 100 position=(53 + x_inset, self._height - 60), 101 size=(140, 60), 102 scale=0.8, 103 autoselect=True, 104 label=bui.Lstr(resource='backText'), 105 button_type='back', 106 on_activate_call=self._do_back, 107 ) 108 bui.containerwidget( 109 edit=self._root_widget, cancel_button=self._back_button 110 ) 111 112 self._title_text = bui.textwidget( 113 parent=self._root_widget, 114 position=(self._width * 0.5, self._height - 38), 115 size=(0, 0), 116 text=bui.Lstr(resource='pluginsText'), 117 color=app.ui_v1.title_color, 118 maxwidth=200, 119 h_align='center', 120 v_align='center', 121 ) 122 123 if self._back_button is not None: 124 bui.buttonwidget( 125 edit=self._back_button, 126 button_type='backSmall', 127 size=(60, 60), 128 label=bui.charstr(bui.SpecialChar.BACK), 129 ) 130 131 settings_button_x = 670 if uiscale is bui.UIScale.SMALL else 570 132 133 self._category_button = bui.buttonwidget( 134 parent=self._root_widget, 135 scale=0.7, 136 position=(settings_button_x - 105, self._height - 60), 137 size=(130, 60), 138 label=bui.Lstr(resource='allText'), 139 autoselect=True, 140 on_activate_call=bui.WeakCall(self._show_category_options), 141 color=(0.55, 0.73, 0.25), 142 iconscale=1.2, 143 ) 144 145 self._settings_button = bui.buttonwidget( 146 parent=self._root_widget, 147 position=(settings_button_x, self._height - 58), 148 size=(40, 40), 149 label='', 150 on_activate_call=self._open_settings, 151 ) 152 153 bui.imagewidget( 154 parent=self._root_widget, 155 position=(settings_button_x + 3, self._height - 57), 156 draw_controller=self._settings_button, 157 size=(35, 35), 158 texture=bui.gettexture('settingsIcon'), 159 ) 160 161 bui.widget( 162 edit=self._settings_button, 163 up_widget=self._settings_button, 164 right_widget=self._settings_button, 165 ) 166 167 self._scrollwidget = bui.scrollwidget( 168 parent=self._root_widget, 169 position=(50 + x_inset, 50), 170 simple_culling_v=20.0, 171 highlight=False, 172 size=(self._scroll_width, self._scroll_height), 173 selection_loops_to_parent=True, 174 claims_left_right=True, 175 ) 176 bui.widget(edit=self._scrollwidget, right_widget=self._scrollwidget) 177 178 if bui.app.meta.scanresults is None: 179 bui.screenmessage( 180 'Still scanning plugins; please try again.', color=(1, 0, 0) 181 ) 182 bui.getsound('error').play() 183 plugspecs = bui.app.plugins.plugin_specs 184 plugstates: dict[str, dict] = bui.app.config.get('Plugins', {}) 185 assert isinstance(plugstates, dict) 186 187 plug_line_height = 50 188 sub_width = self._scroll_width 189 sub_height = len(plugspecs) * plug_line_height 190 self._subcontainer = bui.containerwidget( 191 parent=self._scrollwidget, 192 size=(sub_width, sub_height), 193 background=False, 194 ) 195 self._show_plugins() 196 bui.containerwidget( 197 edit=self._root_widget, selected_child=self._scrollwidget 198 ) 199 self._restore_state()
Inherited Members
- bauiv1._uitypes.Window
- get_root_widget