bastd.ui.settings.plugins

Plugin settings UI.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Plugin settings UI."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8
  9import ba
 10
 11if TYPE_CHECKING:
 12    pass
 13
 14
 15class PluginSettingsWindow(ba.Window):
 16    """Window for configuring plugins."""
 17
 18    def __init__(self,
 19                 transition: str = 'in_right',
 20                 origin_widget: ba.Widget | None = None):
 21        # pylint: disable=too-many-locals
 22        app = ba.app
 23
 24        # If they provided an origin-widget, scale up from that.
 25        scale_origin: tuple[float, float] | None
 26        if origin_widget is not None:
 27            self._transition_out = 'out_scale'
 28            scale_origin = origin_widget.get_screen_space_center()
 29            transition = 'in_scale'
 30        else:
 31            self._transition_out = 'out_right'
 32            scale_origin = None
 33
 34        uiscale = ba.app.ui.uiscale
 35        self._width = 870.0 if uiscale is ba.UIScale.SMALL else 670.0
 36        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
 37        self._height = (390.0 if uiscale is ba.UIScale.SMALL else
 38                        450.0 if uiscale is ba.UIScale.MEDIUM else 520.0)
 39        top_extra = 10 if uiscale is ba.UIScale.SMALL else 0
 40        super().__init__(root_widget=ba.containerwidget(
 41            size=(self._width, self._height + top_extra),
 42            transition=transition,
 43            toolbar_visibility='menu_minimal',
 44            scale_origin_stack_offset=scale_origin,
 45            scale=(2.06 if uiscale is ba.UIScale.SMALL else
 46                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
 47            stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)))
 48
 49        self._scroll_width = self._width - (100 + 2 * x_inset)
 50        self._scroll_height = self._height - 115.0
 51        self._sub_width = self._scroll_width * 0.95
 52        self._sub_height = 724.0
 53
 54        if app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
 55            ba.containerwidget(edit=self._root_widget,
 56                               on_cancel_call=self._do_back)
 57            self._back_button = None
 58        else:
 59            self._back_button = ba.buttonwidget(
 60                parent=self._root_widget,
 61                position=(53 + x_inset, self._height - 60),
 62                size=(140, 60),
 63                scale=0.8,
 64                autoselect=True,
 65                label=ba.Lstr(resource='backText'),
 66                button_type='back',
 67                on_activate_call=self._do_back)
 68            ba.containerwidget(edit=self._root_widget,
 69                               cancel_button=self._back_button)
 70
 71        self._title_text = ba.textwidget(parent=self._root_widget,
 72                                         position=(0, self._height - 52),
 73                                         size=(self._width, 25),
 74                                         text=ba.Lstr(resource='pluginsText'),
 75                                         color=app.ui.title_color,
 76                                         h_align='center',
 77                                         v_align='top')
 78
 79        if self._back_button is not None:
 80            ba.buttonwidget(edit=self._back_button,
 81                            button_type='backSmall',
 82                            size=(60, 60),
 83                            label=ba.charstr(ba.SpecialChar.BACK))
 84
 85        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
 86                                             position=(50 + x_inset, 50),
 87                                             simple_culling_v=20.0,
 88                                             highlight=False,
 89                                             size=(self._scroll_width,
 90                                                   self._scroll_height),
 91                                             selection_loops_to_parent=True)
 92        ba.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
 93        self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
 94                                             selection_loops_to_parent=True)
 95
 96        if ba.app.meta.scanresults is None:
 97            ba.screenmessage('Still scanning plugins; please try again.',
 98                             color=(1, 0, 0))
 99            ba.playsound(ba.getsound('error'))
100        pluglist = ba.app.plugins.potential_plugins
101        plugstates: dict[str, dict] = ba.app.config.setdefault('Plugins', {})
102        assert isinstance(plugstates, dict)
103        for i, availplug in enumerate(pluglist):
104            active = availplug.class_path in ba.app.plugins.active_plugins
105
106            plugstate = plugstates.setdefault(availplug.class_path, {})
107            checked = plugstate.get('enabled', False)
108            assert isinstance(checked, bool)
109            check = ba.checkboxwidget(
110                parent=self._subcontainer,
111                text=availplug.display_name,
112                value=checked,
113                maxwidth=self._scroll_width - 100,
114                size=(self._scroll_width - 40, 50),
115                on_value_change_call=ba.Call(self._check_value_changed,
116                                             availplug),
117                textcolor=((0.8, 0.3, 0.3) if not availplug.available else
118                           (0, 1, 0) if active else (0.6, 0.6, 0.6)))
119
120            # Make sure we scroll all the way to the end when using
121            # keyboard/button nav.
122            ba.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40)
123
124            # Keep last from looping to back button when down is pressed.
125            if i == len(pluglist) - 1:
126                ba.widget(edit=check, down_widget=check)
127        ba.containerwidget(edit=self._root_widget,
128                           selected_child=self._scrollwidget)
129
130        self._restore_state()
131
132    def _check_value_changed(self, plug: ba.PotentialPlugin,
133                             value: bool) -> None:
134        ba.screenmessage(
135            ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
136            color=(1.0, 0.5, 0.0))
137        plugstates: dict[str, dict] = ba.app.config.setdefault('Plugins', {})
138        assert isinstance(plugstates, dict)
139        plugstate = plugstates.setdefault(plug.class_path, {})
140        plugstate['enabled'] = value
141        ba.app.config.commit()
142
143    def _save_state(self) -> None:
144        pass
145
146    def _restore_state(self) -> None:
147        pass
148
149    def _do_back(self) -> None:
150        # pylint: disable=cyclic-import
151        from bastd.ui.settings.advanced import AdvancedSettingsWindow
152        self._save_state()
153        ba.containerwidget(edit=self._root_widget,
154                           transition=self._transition_out)
155        ba.app.ui.set_main_menu_window(
156            AdvancedSettingsWindow(transition='in_left').get_root_widget())
class PluginSettingsWindow(ba.ui.Window):
 16class PluginSettingsWindow(ba.Window):
 17    """Window for configuring plugins."""
 18
 19    def __init__(self,
 20                 transition: str = 'in_right',
 21                 origin_widget: ba.Widget | None = None):
 22        # pylint: disable=too-many-locals
 23        app = ba.app
 24
 25        # If they provided an origin-widget, scale up from that.
 26        scale_origin: tuple[float, float] | None
 27        if origin_widget is not None:
 28            self._transition_out = 'out_scale'
 29            scale_origin = origin_widget.get_screen_space_center()
 30            transition = 'in_scale'
 31        else:
 32            self._transition_out = 'out_right'
 33            scale_origin = None
 34
 35        uiscale = ba.app.ui.uiscale
 36        self._width = 870.0 if uiscale is ba.UIScale.SMALL else 670.0
 37        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
 38        self._height = (390.0 if uiscale is ba.UIScale.SMALL else
 39                        450.0 if uiscale is ba.UIScale.MEDIUM else 520.0)
 40        top_extra = 10 if uiscale is ba.UIScale.SMALL else 0
 41        super().__init__(root_widget=ba.containerwidget(
 42            size=(self._width, self._height + top_extra),
 43            transition=transition,
 44            toolbar_visibility='menu_minimal',
 45            scale_origin_stack_offset=scale_origin,
 46            scale=(2.06 if uiscale is ba.UIScale.SMALL else
 47                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
 48            stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)))
 49
 50        self._scroll_width = self._width - (100 + 2 * x_inset)
 51        self._scroll_height = self._height - 115.0
 52        self._sub_width = self._scroll_width * 0.95
 53        self._sub_height = 724.0
 54
 55        if app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
 56            ba.containerwidget(edit=self._root_widget,
 57                               on_cancel_call=self._do_back)
 58            self._back_button = None
 59        else:
 60            self._back_button = ba.buttonwidget(
 61                parent=self._root_widget,
 62                position=(53 + x_inset, self._height - 60),
 63                size=(140, 60),
 64                scale=0.8,
 65                autoselect=True,
 66                label=ba.Lstr(resource='backText'),
 67                button_type='back',
 68                on_activate_call=self._do_back)
 69            ba.containerwidget(edit=self._root_widget,
 70                               cancel_button=self._back_button)
 71
 72        self._title_text = ba.textwidget(parent=self._root_widget,
 73                                         position=(0, self._height - 52),
 74                                         size=(self._width, 25),
 75                                         text=ba.Lstr(resource='pluginsText'),
 76                                         color=app.ui.title_color,
 77                                         h_align='center',
 78                                         v_align='top')
 79
 80        if self._back_button is not None:
 81            ba.buttonwidget(edit=self._back_button,
 82                            button_type='backSmall',
 83                            size=(60, 60),
 84                            label=ba.charstr(ba.SpecialChar.BACK))
 85
 86        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
 87                                             position=(50 + x_inset, 50),
 88                                             simple_culling_v=20.0,
 89                                             highlight=False,
 90                                             size=(self._scroll_width,
 91                                                   self._scroll_height),
 92                                             selection_loops_to_parent=True)
 93        ba.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
 94        self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
 95                                             selection_loops_to_parent=True)
 96
 97        if ba.app.meta.scanresults is None:
 98            ba.screenmessage('Still scanning plugins; please try again.',
 99                             color=(1, 0, 0))
100            ba.playsound(ba.getsound('error'))
101        pluglist = ba.app.plugins.potential_plugins
102        plugstates: dict[str, dict] = ba.app.config.setdefault('Plugins', {})
103        assert isinstance(plugstates, dict)
104        for i, availplug in enumerate(pluglist):
105            active = availplug.class_path in ba.app.plugins.active_plugins
106
107            plugstate = plugstates.setdefault(availplug.class_path, {})
108            checked = plugstate.get('enabled', False)
109            assert isinstance(checked, bool)
110            check = ba.checkboxwidget(
111                parent=self._subcontainer,
112                text=availplug.display_name,
113                value=checked,
114                maxwidth=self._scroll_width - 100,
115                size=(self._scroll_width - 40, 50),
116                on_value_change_call=ba.Call(self._check_value_changed,
117                                             availplug),
118                textcolor=((0.8, 0.3, 0.3) if not availplug.available else
119                           (0, 1, 0) if active else (0.6, 0.6, 0.6)))
120
121            # Make sure we scroll all the way to the end when using
122            # keyboard/button nav.
123            ba.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40)
124
125            # Keep last from looping to back button when down is pressed.
126            if i == len(pluglist) - 1:
127                ba.widget(edit=check, down_widget=check)
128        ba.containerwidget(edit=self._root_widget,
129                           selected_child=self._scrollwidget)
130
131        self._restore_state()
132
133    def _check_value_changed(self, plug: ba.PotentialPlugin,
134                             value: bool) -> None:
135        ba.screenmessage(
136            ba.Lstr(resource='settingsWindowAdvanced.mustRestartText'),
137            color=(1.0, 0.5, 0.0))
138        plugstates: dict[str, dict] = ba.app.config.setdefault('Plugins', {})
139        assert isinstance(plugstates, dict)
140        plugstate = plugstates.setdefault(plug.class_path, {})
141        plugstate['enabled'] = value
142        ba.app.config.commit()
143
144    def _save_state(self) -> None:
145        pass
146
147    def _restore_state(self) -> None:
148        pass
149
150    def _do_back(self) -> None:
151        # pylint: disable=cyclic-import
152        from bastd.ui.settings.advanced import AdvancedSettingsWindow
153        self._save_state()
154        ba.containerwidget(edit=self._root_widget,
155                           transition=self._transition_out)
156        ba.app.ui.set_main_menu_window(
157            AdvancedSettingsWindow(transition='in_left').get_root_widget())

Window for configuring plugins.

PluginSettingsWindow( transition: str = 'in_right', origin_widget: _ba.Widget | None = None)
 19    def __init__(self,
 20                 transition: str = 'in_right',
 21                 origin_widget: ba.Widget | None = None):
 22        # pylint: disable=too-many-locals
 23        app = ba.app
 24
 25        # If they provided an origin-widget, scale up from that.
 26        scale_origin: tuple[float, float] | None
 27        if origin_widget is not None:
 28            self._transition_out = 'out_scale'
 29            scale_origin = origin_widget.get_screen_space_center()
 30            transition = 'in_scale'
 31        else:
 32            self._transition_out = 'out_right'
 33            scale_origin = None
 34
 35        uiscale = ba.app.ui.uiscale
 36        self._width = 870.0 if uiscale is ba.UIScale.SMALL else 670.0
 37        x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
 38        self._height = (390.0 if uiscale is ba.UIScale.SMALL else
 39                        450.0 if uiscale is ba.UIScale.MEDIUM else 520.0)
 40        top_extra = 10 if uiscale is ba.UIScale.SMALL else 0
 41        super().__init__(root_widget=ba.containerwidget(
 42            size=(self._width, self._height + top_extra),
 43            transition=transition,
 44            toolbar_visibility='menu_minimal',
 45            scale_origin_stack_offset=scale_origin,
 46            scale=(2.06 if uiscale is ba.UIScale.SMALL else
 47                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
 48            stack_offset=(0, -25) if uiscale is ba.UIScale.SMALL else (0, 0)))
 49
 50        self._scroll_width = self._width - (100 + 2 * x_inset)
 51        self._scroll_height = self._height - 115.0
 52        self._sub_width = self._scroll_width * 0.95
 53        self._sub_height = 724.0
 54
 55        if app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
 56            ba.containerwidget(edit=self._root_widget,
 57                               on_cancel_call=self._do_back)
 58            self._back_button = None
 59        else:
 60            self._back_button = ba.buttonwidget(
 61                parent=self._root_widget,
 62                position=(53 + x_inset, self._height - 60),
 63                size=(140, 60),
 64                scale=0.8,
 65                autoselect=True,
 66                label=ba.Lstr(resource='backText'),
 67                button_type='back',
 68                on_activate_call=self._do_back)
 69            ba.containerwidget(edit=self._root_widget,
 70                               cancel_button=self._back_button)
 71
 72        self._title_text = ba.textwidget(parent=self._root_widget,
 73                                         position=(0, self._height - 52),
 74                                         size=(self._width, 25),
 75                                         text=ba.Lstr(resource='pluginsText'),
 76                                         color=app.ui.title_color,
 77                                         h_align='center',
 78                                         v_align='top')
 79
 80        if self._back_button is not None:
 81            ba.buttonwidget(edit=self._back_button,
 82                            button_type='backSmall',
 83                            size=(60, 60),
 84                            label=ba.charstr(ba.SpecialChar.BACK))
 85
 86        self._scrollwidget = ba.scrollwidget(parent=self._root_widget,
 87                                             position=(50 + x_inset, 50),
 88                                             simple_culling_v=20.0,
 89                                             highlight=False,
 90                                             size=(self._scroll_width,
 91                                                   self._scroll_height),
 92                                             selection_loops_to_parent=True)
 93        ba.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
 94        self._subcontainer = ba.columnwidget(parent=self._scrollwidget,
 95                                             selection_loops_to_parent=True)
 96
 97        if ba.app.meta.scanresults is None:
 98            ba.screenmessage('Still scanning plugins; please try again.',
 99                             color=(1, 0, 0))
100            ba.playsound(ba.getsound('error'))
101        pluglist = ba.app.plugins.potential_plugins
102        plugstates: dict[str, dict] = ba.app.config.setdefault('Plugins', {})
103        assert isinstance(plugstates, dict)
104        for i, availplug in enumerate(pluglist):
105            active = availplug.class_path in ba.app.plugins.active_plugins
106
107            plugstate = plugstates.setdefault(availplug.class_path, {})
108            checked = plugstate.get('enabled', False)
109            assert isinstance(checked, bool)
110            check = ba.checkboxwidget(
111                parent=self._subcontainer,
112                text=availplug.display_name,
113                value=checked,
114                maxwidth=self._scroll_width - 100,
115                size=(self._scroll_width - 40, 50),
116                on_value_change_call=ba.Call(self._check_value_changed,
117                                             availplug),
118                textcolor=((0.8, 0.3, 0.3) if not availplug.available else
119                           (0, 1, 0) if active else (0.6, 0.6, 0.6)))
120
121            # Make sure we scroll all the way to the end when using
122            # keyboard/button nav.
123            ba.widget(edit=check, show_buffer_top=40, show_buffer_bottom=40)
124
125            # Keep last from looping to back button when down is pressed.
126            if i == len(pluglist) - 1:
127                ba.widget(edit=check, down_widget=check)
128        ba.containerwidget(edit=self._root_widget,
129                           selected_child=self._scrollwidget)
130
131        self._restore_state()
Inherited Members
ba.ui.Window
get_root_widget