bauiv1lib.soundtrack.entrytypeselect

Provides UI for selecting soundtrack entry types.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides UI for selecting soundtrack entry types."""
  4from __future__ import annotations
  5
  6import copy
  7from typing import TYPE_CHECKING, override
  8
  9import bauiv1 as bui
 10
 11if TYPE_CHECKING:
 12    from typing import Any, Callable
 13
 14
 15class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
 16    """Window for selecting a soundtrack entry type."""
 17
 18    def __init__(
 19        self,
 20        callback: Callable[[Any], Any],
 21        current_entry: Any,
 22        selection_target_name: str,
 23        transition: str | None = 'in_right',
 24        origin_widget: bui.Widget | None = None,
 25    ):
 26        # pylint: disable=too-many-locals
 27        assert bui.app.classic is not None
 28        music = bui.app.classic.music
 29        self._r = 'editSoundtrackWindow'
 30
 31        self._selection_target_name = selection_target_name
 32        self._callback = callback
 33        self._current_entry = copy.deepcopy(current_entry)
 34
 35        self._width = 580
 36        self._height = 220
 37        spacing = 80
 38
 39        # FIXME: Generalize this so new custom soundtrack types can add
 40        # themselves here.
 41        do_default = True
 42        do_mac_music_app_playlist = music.supports_soundtrack_entry_type(
 43            'iTunesPlaylist'
 44        )
 45        do_music_file = music.supports_soundtrack_entry_type('musicFile')
 46        do_music_folder = music.supports_soundtrack_entry_type('musicFolder')
 47
 48        if do_mac_music_app_playlist:
 49            self._height += spacing
 50        if do_music_file:
 51            self._height += spacing
 52        if do_music_folder:
 53            self._height += spacing
 54
 55        uiscale = bui.app.ui_v1.uiscale
 56
 57        # NOTE: When something is selected, we close our UI and kick off
 58        # another window which then calls us back when its done, so the
 59        # standard UI-cleanup-check complains that something is holding
 60        # on to our instance after its ui is gone. Should restructure in
 61        # a cleaner way, but just disabling that check for now.
 62        super().__init__(
 63            root_widget=bui.containerwidget(
 64                size=(self._width, self._height),
 65                scale=(
 66                    1.7
 67                    if uiscale is bui.UIScale.SMALL
 68                    else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
 69                ),
 70            ),
 71            cleanupcheck=False,
 72            transition=transition,
 73            origin_widget=origin_widget,
 74        )
 75        btn = bui.buttonwidget(
 76            parent=self._root_widget,
 77            position=(35, self._height - 65),
 78            size=(160, 60),
 79            scale=0.8,
 80            text_scale=1.2,
 81            label=bui.Lstr(resource='cancelText'),
 82            on_activate_call=self._on_cancel_press,
 83        )
 84        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 85        bui.textwidget(
 86            parent=self._root_widget,
 87            position=(self._width * 0.5, self._height - 32),
 88            size=(0, 0),
 89            text=bui.Lstr(resource=f'{self._r}.selectASourceText'),
 90            color=bui.app.ui_v1.title_color,
 91            maxwidth=230,
 92            h_align='center',
 93            v_align='center',
 94        )
 95
 96        bui.textwidget(
 97            parent=self._root_widget,
 98            position=(self._width * 0.5, self._height - 56),
 99            size=(0, 0),
100            text=selection_target_name,
101            color=bui.app.ui_v1.infotextcolor,
102            scale=0.7,
103            maxwidth=230,
104            h_align='center',
105            v_align='center',
106        )
107
108        v = self._height - 155
109
110        current_entry_type = music.get_soundtrack_entry_type(current_entry)
111
112        if do_default:
113            btn = bui.buttonwidget(
114                parent=self._root_widget,
115                size=(self._width - 100, 60),
116                position=(50, v),
117                label=bui.Lstr(resource=f'{self._r}.useDefaultGameMusicText'),
118                on_activate_call=self._on_default_press,
119            )
120            if current_entry_type == 'default':
121                bui.containerwidget(edit=self._root_widget, selected_child=btn)
122            v -= spacing
123
124        if do_mac_music_app_playlist:
125            btn = bui.buttonwidget(
126                parent=self._root_widget,
127                size=(self._width - 100, 60),
128                position=(50, v),
129                label=bui.Lstr(resource=f'{self._r}.useITunesPlaylistText'),
130                on_activate_call=self._on_mac_music_app_playlist_press,
131                icon=None,
132            )
133            if current_entry_type == 'iTunesPlaylist':
134                bui.containerwidget(edit=self._root_widget, selected_child=btn)
135            v -= spacing
136
137        if do_music_file:
138            btn = bui.buttonwidget(
139                parent=self._root_widget,
140                size=(self._width - 100, 60),
141                position=(50, v),
142                label=bui.Lstr(resource=f'{self._r}.useMusicFileText'),
143                on_activate_call=self._on_music_file_press,
144                icon=bui.gettexture('file'),
145            )
146            if current_entry_type == 'musicFile':
147                bui.containerwidget(edit=self._root_widget, selected_child=btn)
148            v -= spacing
149
150        if do_music_folder:
151            btn = bui.buttonwidget(
152                parent=self._root_widget,
153                size=(self._width - 100, 60),
154                position=(50, v),
155                label=bui.Lstr(resource=f'{self._r}.useMusicFolderText'),
156                on_activate_call=self._on_music_folder_press,
157                icon=bui.gettexture('folder'),
158                icon_color=(1.1, 0.8, 0.2),
159            )
160            if current_entry_type == 'musicFolder':
161                bui.containerwidget(edit=self._root_widget, selected_child=btn)
162            v -= spacing
163
164    @override
165    def get_main_window_state(self) -> bui.MainWindowState:
166        # Support recreating our window for back/refresh purposes.
167        cls = type(self)
168
169        # Pull these out of self here; if we reference self in the
170        # lambda we'll keep our window alive which is bad.
171        current_entry = self._current_entry
172        callback = self._callback
173        selection_target_name = self._selection_target_name
174
175        return bui.BasicMainWindowState(
176            create_call=lambda transition, origin_widget: cls(
177                transition=transition,
178                origin_widget=origin_widget,
179                current_entry=current_entry,
180                callback=callback,
181                selection_target_name=selection_target_name,
182            )
183        )
184
185    def _on_mac_music_app_playlist_press(self) -> None:
186        assert bui.app.classic is not None
187        music = bui.app.classic.music
188        from bauiv1lib.soundtrack.macmusicapp import (
189            MacMusicAppPlaylistSelectWindow,
190        )
191
192        # no-op if we're not in control.
193        if not self.main_window_has_control():
194            return
195
196        current_playlist_entry: str | None
197        if (
198            music.get_soundtrack_entry_type(self._current_entry)
199            == 'iTunesPlaylist'
200        ):
201            current_playlist_entry = music.get_soundtrack_entry_name(
202                self._current_entry
203            )
204        else:
205            current_playlist_entry = None
206
207        self.main_window_replace(
208            MacMusicAppPlaylistSelectWindow(
209                self._callback, current_playlist_entry, self._current_entry
210            )
211        )
212
213    def _on_music_file_press(self) -> None:
214        from babase import android_get_external_files_dir
215        from baclassic.osmusic import OSMusicPlayer
216        from bauiv1lib.fileselector import FileSelectorWindow
217
218        # no-op if we're not in control.
219        if not self.main_window_has_control():
220            return
221
222        base_path = android_get_external_files_dir()
223        assert bui.app.classic is not None
224
225        self.main_window_replace(
226            FileSelectorWindow(
227                base_path,
228                callback=self._music_file_selector_cb,
229                show_base_path=False,
230                valid_file_extensions=(
231                    OSMusicPlayer.get_valid_music_file_extensions()
232                ),
233                allow_folders=False,
234            ),
235        )
236
237    def _on_music_folder_press(self) -> None:
238        from bauiv1lib.fileselector import FileSelectorWindow
239        from babase import android_get_external_files_dir
240
241        # no-op if we're not in control.
242        if not self.main_window_has_control():
243            return
244
245        base_path = android_get_external_files_dir()
246        assert bui.app.classic is not None
247
248        self.main_window_replace(
249            FileSelectorWindow(
250                base_path,
251                callback=self._music_folder_selector_cb,
252                show_base_path=False,
253                valid_file_extensions=[],
254                allow_folders=True,
255            ),
256        )
257
258    def _music_file_selector_cb(self, result: str | None) -> None:
259        if result is None:
260            self._callback(self._current_entry)
261        else:
262            self._callback({'type': 'musicFile', 'name': result})
263
264    def _music_folder_selector_cb(self, result: str | None) -> None:
265        if result is None:
266            self._callback(self._current_entry)
267        else:
268            self._callback({'type': 'musicFolder', 'name': result})
269
270    def _on_default_press(self) -> None:
271        self.main_window_back()
272        self._callback(None)
273
274    def _on_cancel_press(self) -> None:
275        self.main_window_back()
276        self._callback(self._current_entry)
class SoundtrackEntryTypeSelectWindow(bauiv1._uitypes.MainWindow):
 16class SoundtrackEntryTypeSelectWindow(bui.MainWindow):
 17    """Window for selecting a soundtrack entry type."""
 18
 19    def __init__(
 20        self,
 21        callback: Callable[[Any], Any],
 22        current_entry: Any,
 23        selection_target_name: str,
 24        transition: str | None = 'in_right',
 25        origin_widget: bui.Widget | None = None,
 26    ):
 27        # pylint: disable=too-many-locals
 28        assert bui.app.classic is not None
 29        music = bui.app.classic.music
 30        self._r = 'editSoundtrackWindow'
 31
 32        self._selection_target_name = selection_target_name
 33        self._callback = callback
 34        self._current_entry = copy.deepcopy(current_entry)
 35
 36        self._width = 580
 37        self._height = 220
 38        spacing = 80
 39
 40        # FIXME: Generalize this so new custom soundtrack types can add
 41        # themselves here.
 42        do_default = True
 43        do_mac_music_app_playlist = music.supports_soundtrack_entry_type(
 44            'iTunesPlaylist'
 45        )
 46        do_music_file = music.supports_soundtrack_entry_type('musicFile')
 47        do_music_folder = music.supports_soundtrack_entry_type('musicFolder')
 48
 49        if do_mac_music_app_playlist:
 50            self._height += spacing
 51        if do_music_file:
 52            self._height += spacing
 53        if do_music_folder:
 54            self._height += spacing
 55
 56        uiscale = bui.app.ui_v1.uiscale
 57
 58        # NOTE: When something is selected, we close our UI and kick off
 59        # another window which then calls us back when its done, so the
 60        # standard UI-cleanup-check complains that something is holding
 61        # on to our instance after its ui is gone. Should restructure in
 62        # a cleaner way, but just disabling that check for now.
 63        super().__init__(
 64            root_widget=bui.containerwidget(
 65                size=(self._width, self._height),
 66                scale=(
 67                    1.7
 68                    if uiscale is bui.UIScale.SMALL
 69                    else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
 70                ),
 71            ),
 72            cleanupcheck=False,
 73            transition=transition,
 74            origin_widget=origin_widget,
 75        )
 76        btn = bui.buttonwidget(
 77            parent=self._root_widget,
 78            position=(35, self._height - 65),
 79            size=(160, 60),
 80            scale=0.8,
 81            text_scale=1.2,
 82            label=bui.Lstr(resource='cancelText'),
 83            on_activate_call=self._on_cancel_press,
 84        )
 85        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 86        bui.textwidget(
 87            parent=self._root_widget,
 88            position=(self._width * 0.5, self._height - 32),
 89            size=(0, 0),
 90            text=bui.Lstr(resource=f'{self._r}.selectASourceText'),
 91            color=bui.app.ui_v1.title_color,
 92            maxwidth=230,
 93            h_align='center',
 94            v_align='center',
 95        )
 96
 97        bui.textwidget(
 98            parent=self._root_widget,
 99            position=(self._width * 0.5, self._height - 56),
100            size=(0, 0),
101            text=selection_target_name,
102            color=bui.app.ui_v1.infotextcolor,
103            scale=0.7,
104            maxwidth=230,
105            h_align='center',
106            v_align='center',
107        )
108
109        v = self._height - 155
110
111        current_entry_type = music.get_soundtrack_entry_type(current_entry)
112
113        if do_default:
114            btn = bui.buttonwidget(
115                parent=self._root_widget,
116                size=(self._width - 100, 60),
117                position=(50, v),
118                label=bui.Lstr(resource=f'{self._r}.useDefaultGameMusicText'),
119                on_activate_call=self._on_default_press,
120            )
121            if current_entry_type == 'default':
122                bui.containerwidget(edit=self._root_widget, selected_child=btn)
123            v -= spacing
124
125        if do_mac_music_app_playlist:
126            btn = bui.buttonwidget(
127                parent=self._root_widget,
128                size=(self._width - 100, 60),
129                position=(50, v),
130                label=bui.Lstr(resource=f'{self._r}.useITunesPlaylistText'),
131                on_activate_call=self._on_mac_music_app_playlist_press,
132                icon=None,
133            )
134            if current_entry_type == 'iTunesPlaylist':
135                bui.containerwidget(edit=self._root_widget, selected_child=btn)
136            v -= spacing
137
138        if do_music_file:
139            btn = bui.buttonwidget(
140                parent=self._root_widget,
141                size=(self._width - 100, 60),
142                position=(50, v),
143                label=bui.Lstr(resource=f'{self._r}.useMusicFileText'),
144                on_activate_call=self._on_music_file_press,
145                icon=bui.gettexture('file'),
146            )
147            if current_entry_type == 'musicFile':
148                bui.containerwidget(edit=self._root_widget, selected_child=btn)
149            v -= spacing
150
151        if do_music_folder:
152            btn = bui.buttonwidget(
153                parent=self._root_widget,
154                size=(self._width - 100, 60),
155                position=(50, v),
156                label=bui.Lstr(resource=f'{self._r}.useMusicFolderText'),
157                on_activate_call=self._on_music_folder_press,
158                icon=bui.gettexture('folder'),
159                icon_color=(1.1, 0.8, 0.2),
160            )
161            if current_entry_type == 'musicFolder':
162                bui.containerwidget(edit=self._root_widget, selected_child=btn)
163            v -= spacing
164
165    @override
166    def get_main_window_state(self) -> bui.MainWindowState:
167        # Support recreating our window for back/refresh purposes.
168        cls = type(self)
169
170        # Pull these out of self here; if we reference self in the
171        # lambda we'll keep our window alive which is bad.
172        current_entry = self._current_entry
173        callback = self._callback
174        selection_target_name = self._selection_target_name
175
176        return bui.BasicMainWindowState(
177            create_call=lambda transition, origin_widget: cls(
178                transition=transition,
179                origin_widget=origin_widget,
180                current_entry=current_entry,
181                callback=callback,
182                selection_target_name=selection_target_name,
183            )
184        )
185
186    def _on_mac_music_app_playlist_press(self) -> None:
187        assert bui.app.classic is not None
188        music = bui.app.classic.music
189        from bauiv1lib.soundtrack.macmusicapp import (
190            MacMusicAppPlaylistSelectWindow,
191        )
192
193        # no-op if we're not in control.
194        if not self.main_window_has_control():
195            return
196
197        current_playlist_entry: str | None
198        if (
199            music.get_soundtrack_entry_type(self._current_entry)
200            == 'iTunesPlaylist'
201        ):
202            current_playlist_entry = music.get_soundtrack_entry_name(
203                self._current_entry
204            )
205        else:
206            current_playlist_entry = None
207
208        self.main_window_replace(
209            MacMusicAppPlaylistSelectWindow(
210                self._callback, current_playlist_entry, self._current_entry
211            )
212        )
213
214    def _on_music_file_press(self) -> None:
215        from babase import android_get_external_files_dir
216        from baclassic.osmusic import OSMusicPlayer
217        from bauiv1lib.fileselector import FileSelectorWindow
218
219        # no-op if we're not in control.
220        if not self.main_window_has_control():
221            return
222
223        base_path = android_get_external_files_dir()
224        assert bui.app.classic is not None
225
226        self.main_window_replace(
227            FileSelectorWindow(
228                base_path,
229                callback=self._music_file_selector_cb,
230                show_base_path=False,
231                valid_file_extensions=(
232                    OSMusicPlayer.get_valid_music_file_extensions()
233                ),
234                allow_folders=False,
235            ),
236        )
237
238    def _on_music_folder_press(self) -> None:
239        from bauiv1lib.fileselector import FileSelectorWindow
240        from babase import android_get_external_files_dir
241
242        # no-op if we're not in control.
243        if not self.main_window_has_control():
244            return
245
246        base_path = android_get_external_files_dir()
247        assert bui.app.classic is not None
248
249        self.main_window_replace(
250            FileSelectorWindow(
251                base_path,
252                callback=self._music_folder_selector_cb,
253                show_base_path=False,
254                valid_file_extensions=[],
255                allow_folders=True,
256            ),
257        )
258
259    def _music_file_selector_cb(self, result: str | None) -> None:
260        if result is None:
261            self._callback(self._current_entry)
262        else:
263            self._callback({'type': 'musicFile', 'name': result})
264
265    def _music_folder_selector_cb(self, result: str | None) -> None:
266        if result is None:
267            self._callback(self._current_entry)
268        else:
269            self._callback({'type': 'musicFolder', 'name': result})
270
271    def _on_default_press(self) -> None:
272        self.main_window_back()
273        self._callback(None)
274
275    def _on_cancel_press(self) -> None:
276        self.main_window_back()
277        self._callback(self._current_entry)

Window for selecting a soundtrack entry type.

SoundtrackEntryTypeSelectWindow( callback: Callable[[Any], Any], current_entry: Any, selection_target_name: str, transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
 19    def __init__(
 20        self,
 21        callback: Callable[[Any], Any],
 22        current_entry: Any,
 23        selection_target_name: str,
 24        transition: str | None = 'in_right',
 25        origin_widget: bui.Widget | None = None,
 26    ):
 27        # pylint: disable=too-many-locals
 28        assert bui.app.classic is not None
 29        music = bui.app.classic.music
 30        self._r = 'editSoundtrackWindow'
 31
 32        self._selection_target_name = selection_target_name
 33        self._callback = callback
 34        self._current_entry = copy.deepcopy(current_entry)
 35
 36        self._width = 580
 37        self._height = 220
 38        spacing = 80
 39
 40        # FIXME: Generalize this so new custom soundtrack types can add
 41        # themselves here.
 42        do_default = True
 43        do_mac_music_app_playlist = music.supports_soundtrack_entry_type(
 44            'iTunesPlaylist'
 45        )
 46        do_music_file = music.supports_soundtrack_entry_type('musicFile')
 47        do_music_folder = music.supports_soundtrack_entry_type('musicFolder')
 48
 49        if do_mac_music_app_playlist:
 50            self._height += spacing
 51        if do_music_file:
 52            self._height += spacing
 53        if do_music_folder:
 54            self._height += spacing
 55
 56        uiscale = bui.app.ui_v1.uiscale
 57
 58        # NOTE: When something is selected, we close our UI and kick off
 59        # another window which then calls us back when its done, so the
 60        # standard UI-cleanup-check complains that something is holding
 61        # on to our instance after its ui is gone. Should restructure in
 62        # a cleaner way, but just disabling that check for now.
 63        super().__init__(
 64            root_widget=bui.containerwidget(
 65                size=(self._width, self._height),
 66                scale=(
 67                    1.7
 68                    if uiscale is bui.UIScale.SMALL
 69                    else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0
 70                ),
 71            ),
 72            cleanupcheck=False,
 73            transition=transition,
 74            origin_widget=origin_widget,
 75        )
 76        btn = bui.buttonwidget(
 77            parent=self._root_widget,
 78            position=(35, self._height - 65),
 79            size=(160, 60),
 80            scale=0.8,
 81            text_scale=1.2,
 82            label=bui.Lstr(resource='cancelText'),
 83            on_activate_call=self._on_cancel_press,
 84        )
 85        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 86        bui.textwidget(
 87            parent=self._root_widget,
 88            position=(self._width * 0.5, self._height - 32),
 89            size=(0, 0),
 90            text=bui.Lstr(resource=f'{self._r}.selectASourceText'),
 91            color=bui.app.ui_v1.title_color,
 92            maxwidth=230,
 93            h_align='center',
 94            v_align='center',
 95        )
 96
 97        bui.textwidget(
 98            parent=self._root_widget,
 99            position=(self._width * 0.5, self._height - 56),
100            size=(0, 0),
101            text=selection_target_name,
102            color=bui.app.ui_v1.infotextcolor,
103            scale=0.7,
104            maxwidth=230,
105            h_align='center',
106            v_align='center',
107        )
108
109        v = self._height - 155
110
111        current_entry_type = music.get_soundtrack_entry_type(current_entry)
112
113        if do_default:
114            btn = bui.buttonwidget(
115                parent=self._root_widget,
116                size=(self._width - 100, 60),
117                position=(50, v),
118                label=bui.Lstr(resource=f'{self._r}.useDefaultGameMusicText'),
119                on_activate_call=self._on_default_press,
120            )
121            if current_entry_type == 'default':
122                bui.containerwidget(edit=self._root_widget, selected_child=btn)
123            v -= spacing
124
125        if do_mac_music_app_playlist:
126            btn = bui.buttonwidget(
127                parent=self._root_widget,
128                size=(self._width - 100, 60),
129                position=(50, v),
130                label=bui.Lstr(resource=f'{self._r}.useITunesPlaylistText'),
131                on_activate_call=self._on_mac_music_app_playlist_press,
132                icon=None,
133            )
134            if current_entry_type == 'iTunesPlaylist':
135                bui.containerwidget(edit=self._root_widget, selected_child=btn)
136            v -= spacing
137
138        if do_music_file:
139            btn = bui.buttonwidget(
140                parent=self._root_widget,
141                size=(self._width - 100, 60),
142                position=(50, v),
143                label=bui.Lstr(resource=f'{self._r}.useMusicFileText'),
144                on_activate_call=self._on_music_file_press,
145                icon=bui.gettexture('file'),
146            )
147            if current_entry_type == 'musicFile':
148                bui.containerwidget(edit=self._root_widget, selected_child=btn)
149            v -= spacing
150
151        if do_music_folder:
152            btn = bui.buttonwidget(
153                parent=self._root_widget,
154                size=(self._width - 100, 60),
155                position=(50, v),
156                label=bui.Lstr(resource=f'{self._r}.useMusicFolderText'),
157                on_activate_call=self._on_music_folder_press,
158                icon=bui.gettexture('folder'),
159                icon_color=(1.1, 0.8, 0.2),
160            )
161            if current_entry_type == 'musicFolder':
162                bui.containerwidget(edit=self._root_widget, selected_child=btn)
163            v -= spacing

Create a MainWindow given a root widget and transition info.

Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.

@override
def get_main_window_state(self) -> bauiv1.MainWindowState:
165    @override
166    def get_main_window_state(self) -> bui.MainWindowState:
167        # Support recreating our window for back/refresh purposes.
168        cls = type(self)
169
170        # Pull these out of self here; if we reference self in the
171        # lambda we'll keep our window alive which is bad.
172        current_entry = self._current_entry
173        callback = self._callback
174        selection_target_name = self._selection_target_name
175
176        return bui.BasicMainWindowState(
177            create_call=lambda transition, origin_widget: cls(
178                transition=transition,
179                origin_widget=origin_widget,
180                current_entry=current_entry,
181                callback=callback,
182                selection_target_name=selection_target_name,
183            )
184        )

Return a WindowState to recreate this window, if supported.

Inherited Members
bauiv1._uitypes.MainWindow
main_window_back_state
main_window_is_top_level
main_window_close
main_window_has_control
main_window_back
main_window_replace
on_main_window_close
bauiv1._uitypes.Window
get_root_widget