bastd.ui.iconpicker

Provides a picker for icons.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides a picker for icons."""
  4
  5from __future__ import annotations
  6
  7import math
  8from typing import TYPE_CHECKING
  9
 10import _ba
 11import ba
 12from bastd.ui import popup
 13
 14if TYPE_CHECKING:
 15    from typing import Any, Sequence
 16
 17
 18class IconPicker(popup.PopupWindow):
 19    """Picker for icons."""
 20
 21    def __init__(self,
 22                 parent: ba.Widget,
 23                 position: tuple[float, float] = (0.0, 0.0),
 24                 delegate: Any = None,
 25                 scale: float | None = None,
 26                 offset: tuple[float, float] = (0.0, 0.0),
 27                 tint_color: Sequence[float] = (1.0, 1.0, 1.0),
 28                 tint2_color: Sequence[float] = (1.0, 1.0, 1.0),
 29                 selected_icon: str | None = None):
 30        # pylint: disable=too-many-locals
 31        del parent  # unused here
 32        del tint_color  # unused_here
 33        del tint2_color  # unused here
 34        uiscale = ba.app.ui.uiscale
 35        if scale is None:
 36            scale = (1.85 if uiscale is ba.UIScale.SMALL else
 37                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
 38
 39        self._delegate = delegate
 40        self._transitioning_out = False
 41
 42        self._icons = [ba.charstr(ba.SpecialChar.LOGO)
 43                       ] + ba.app.accounts_v1.get_purchased_icons()
 44        count = len(self._icons)
 45        columns = 4
 46        rows = int(math.ceil(float(count) / columns))
 47
 48        button_width = 50
 49        button_height = 50
 50        button_buffer_h = 10
 51        button_buffer_v = 5
 52
 53        self._width = (10 + columns * (button_width + 2 * button_buffer_h) *
 54                       (1.0 / 0.95) * (1.0 / 0.8))
 55        self._height = (self._width *
 56                        (0.8 if uiscale is ba.UIScale.SMALL else 1.06))
 57
 58        self._scroll_width = self._width * 0.8
 59        self._scroll_height = self._height * 0.8
 60        self._scroll_position = ((self._width - self._scroll_width) * 0.5,
 61                                 (self._height - self._scroll_height) * 0.5)
 62
 63        # creates our _root_widget
 64        popup.PopupWindow.__init__(self,
 65                                   position=position,
 66                                   size=(self._width, self._height),
 67                                   scale=scale,
 68                                   bg_color=(0.5, 0.5, 0.5),
 69                                   offset=offset,
 70                                   focus_position=self._scroll_position,
 71                                   focus_size=(self._scroll_width,
 72                                               self._scroll_height))
 73
 74        self._scrollwidget = ba.scrollwidget(parent=self.root_widget,
 75                                             size=(self._scroll_width,
 76                                                   self._scroll_height),
 77                                             color=(0.55, 0.55, 0.55),
 78                                             highlight=False,
 79                                             position=self._scroll_position)
 80        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
 81
 82        self._sub_width = self._scroll_width * 0.95
 83        self._sub_height = 5 + rows * (button_height +
 84                                       2 * button_buffer_v) + 100
 85        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
 86                                                size=(self._sub_width,
 87                                                      self._sub_height),
 88                                                background=False)
 89        index = 0
 90        for y in range(rows):
 91            for x in range(columns):
 92                pos = (x * (button_width + 2 * button_buffer_h) +
 93                       button_buffer_h, self._sub_height - (y + 1) *
 94                       (button_height + 2 * button_buffer_v) + 0)
 95                btn = ba.buttonwidget(parent=self._subcontainer,
 96                                      button_type='square',
 97                                      size=(button_width, button_height),
 98                                      autoselect=True,
 99                                      text_scale=1.2,
100                                      label='',
101                                      color=(0.65, 0.65, 0.65),
102                                      on_activate_call=ba.Call(
103                                          self._select_icon,
104                                          self._icons[index]),
105                                      position=pos)
106                ba.textwidget(parent=self._subcontainer,
107                              h_align='center',
108                              v_align='center',
109                              size=(0, 0),
110                              position=(pos[0] + 0.5 * button_width - 1,
111                                        pos[1] + 15),
112                              draw_controller=btn,
113                              text=self._icons[index],
114                              scale=1.8)
115                ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60)
116                if self._icons[index] == selected_icon:
117                    ba.containerwidget(edit=self._subcontainer,
118                                       selected_child=btn,
119                                       visible_child=btn)
120                index += 1
121
122                if index >= count:
123                    break
124            if index >= count:
125                break
126        self._get_more_icons_button = btn = ba.buttonwidget(
127            parent=self._subcontainer,
128            size=(self._sub_width * 0.8, 60),
129            position=(self._sub_width * 0.1, 30),
130            label=ba.Lstr(resource='editProfileWindow.getMoreIconsText'),
131            on_activate_call=self._on_store_press,
132            color=(0.6, 0.6, 0.6),
133            textcolor=(0.8, 0.8, 0.8),
134            autoselect=True)
135        ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)
136
137    def _on_store_press(self) -> None:
138        from bastd.ui.account import show_sign_in_prompt
139        from bastd.ui.store.browser import StoreBrowserWindow
140        if _ba.get_v1_account_state() != 'signed_in':
141            show_sign_in_prompt()
142            return
143        self._transition_out()
144        StoreBrowserWindow(modal=True,
145                           show_tab=StoreBrowserWindow.TabID.ICONS,
146                           origin_widget=self._get_more_icons_button)
147
148    def _select_icon(self, icon: str) -> None:
149        if self._delegate is not None:
150            self._delegate.on_icon_picker_pick(icon)
151        self._transition_out()
152
153    def _transition_out(self) -> None:
154        if not self._transitioning_out:
155            self._transitioning_out = True
156            ba.containerwidget(edit=self.root_widget, transition='out_scale')
157
158    def on_popup_cancel(self) -> None:
159        ba.playsound(ba.getsound('swish'))
160        self._transition_out()
class IconPicker(bastd.ui.popup.PopupWindow):
 19class IconPicker(popup.PopupWindow):
 20    """Picker for icons."""
 21
 22    def __init__(self,
 23                 parent: ba.Widget,
 24                 position: tuple[float, float] = (0.0, 0.0),
 25                 delegate: Any = None,
 26                 scale: float | None = None,
 27                 offset: tuple[float, float] = (0.0, 0.0),
 28                 tint_color: Sequence[float] = (1.0, 1.0, 1.0),
 29                 tint2_color: Sequence[float] = (1.0, 1.0, 1.0),
 30                 selected_icon: str | None = None):
 31        # pylint: disable=too-many-locals
 32        del parent  # unused here
 33        del tint_color  # unused_here
 34        del tint2_color  # unused here
 35        uiscale = ba.app.ui.uiscale
 36        if scale is None:
 37            scale = (1.85 if uiscale is ba.UIScale.SMALL else
 38                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
 39
 40        self._delegate = delegate
 41        self._transitioning_out = False
 42
 43        self._icons = [ba.charstr(ba.SpecialChar.LOGO)
 44                       ] + ba.app.accounts_v1.get_purchased_icons()
 45        count = len(self._icons)
 46        columns = 4
 47        rows = int(math.ceil(float(count) / columns))
 48
 49        button_width = 50
 50        button_height = 50
 51        button_buffer_h = 10
 52        button_buffer_v = 5
 53
 54        self._width = (10 + columns * (button_width + 2 * button_buffer_h) *
 55                       (1.0 / 0.95) * (1.0 / 0.8))
 56        self._height = (self._width *
 57                        (0.8 if uiscale is ba.UIScale.SMALL else 1.06))
 58
 59        self._scroll_width = self._width * 0.8
 60        self._scroll_height = self._height * 0.8
 61        self._scroll_position = ((self._width - self._scroll_width) * 0.5,
 62                                 (self._height - self._scroll_height) * 0.5)
 63
 64        # creates our _root_widget
 65        popup.PopupWindow.__init__(self,
 66                                   position=position,
 67                                   size=(self._width, self._height),
 68                                   scale=scale,
 69                                   bg_color=(0.5, 0.5, 0.5),
 70                                   offset=offset,
 71                                   focus_position=self._scroll_position,
 72                                   focus_size=(self._scroll_width,
 73                                               self._scroll_height))
 74
 75        self._scrollwidget = ba.scrollwidget(parent=self.root_widget,
 76                                             size=(self._scroll_width,
 77                                                   self._scroll_height),
 78                                             color=(0.55, 0.55, 0.55),
 79                                             highlight=False,
 80                                             position=self._scroll_position)
 81        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
 82
 83        self._sub_width = self._scroll_width * 0.95
 84        self._sub_height = 5 + rows * (button_height +
 85                                       2 * button_buffer_v) + 100
 86        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
 87                                                size=(self._sub_width,
 88                                                      self._sub_height),
 89                                                background=False)
 90        index = 0
 91        for y in range(rows):
 92            for x in range(columns):
 93                pos = (x * (button_width + 2 * button_buffer_h) +
 94                       button_buffer_h, self._sub_height - (y + 1) *
 95                       (button_height + 2 * button_buffer_v) + 0)
 96                btn = ba.buttonwidget(parent=self._subcontainer,
 97                                      button_type='square',
 98                                      size=(button_width, button_height),
 99                                      autoselect=True,
100                                      text_scale=1.2,
101                                      label='',
102                                      color=(0.65, 0.65, 0.65),
103                                      on_activate_call=ba.Call(
104                                          self._select_icon,
105                                          self._icons[index]),
106                                      position=pos)
107                ba.textwidget(parent=self._subcontainer,
108                              h_align='center',
109                              v_align='center',
110                              size=(0, 0),
111                              position=(pos[0] + 0.5 * button_width - 1,
112                                        pos[1] + 15),
113                              draw_controller=btn,
114                              text=self._icons[index],
115                              scale=1.8)
116                ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60)
117                if self._icons[index] == selected_icon:
118                    ba.containerwidget(edit=self._subcontainer,
119                                       selected_child=btn,
120                                       visible_child=btn)
121                index += 1
122
123                if index >= count:
124                    break
125            if index >= count:
126                break
127        self._get_more_icons_button = btn = ba.buttonwidget(
128            parent=self._subcontainer,
129            size=(self._sub_width * 0.8, 60),
130            position=(self._sub_width * 0.1, 30),
131            label=ba.Lstr(resource='editProfileWindow.getMoreIconsText'),
132            on_activate_call=self._on_store_press,
133            color=(0.6, 0.6, 0.6),
134            textcolor=(0.8, 0.8, 0.8),
135            autoselect=True)
136        ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)
137
138    def _on_store_press(self) -> None:
139        from bastd.ui.account import show_sign_in_prompt
140        from bastd.ui.store.browser import StoreBrowserWindow
141        if _ba.get_v1_account_state() != 'signed_in':
142            show_sign_in_prompt()
143            return
144        self._transition_out()
145        StoreBrowserWindow(modal=True,
146                           show_tab=StoreBrowserWindow.TabID.ICONS,
147                           origin_widget=self._get_more_icons_button)
148
149    def _select_icon(self, icon: str) -> None:
150        if self._delegate is not None:
151            self._delegate.on_icon_picker_pick(icon)
152        self._transition_out()
153
154    def _transition_out(self) -> None:
155        if not self._transitioning_out:
156            self._transitioning_out = True
157            ba.containerwidget(edit=self.root_widget, transition='out_scale')
158
159    def on_popup_cancel(self) -> None:
160        ba.playsound(ba.getsound('swish'))
161        self._transition_out()

Picker for icons.

IconPicker( parent: _ba.Widget, position: tuple[float, float] = (0.0, 0.0), delegate: Any = None, scale: float | None = None, offset: tuple[float, float] = (0.0, 0.0), tint_color: Sequence[float] = (1.0, 1.0, 1.0), tint2_color: Sequence[float] = (1.0, 1.0, 1.0), selected_icon: str | None = None)
 22    def __init__(self,
 23                 parent: ba.Widget,
 24                 position: tuple[float, float] = (0.0, 0.0),
 25                 delegate: Any = None,
 26                 scale: float | None = None,
 27                 offset: tuple[float, float] = (0.0, 0.0),
 28                 tint_color: Sequence[float] = (1.0, 1.0, 1.0),
 29                 tint2_color: Sequence[float] = (1.0, 1.0, 1.0),
 30                 selected_icon: str | None = None):
 31        # pylint: disable=too-many-locals
 32        del parent  # unused here
 33        del tint_color  # unused_here
 34        del tint2_color  # unused here
 35        uiscale = ba.app.ui.uiscale
 36        if scale is None:
 37            scale = (1.85 if uiscale is ba.UIScale.SMALL else
 38                     1.65 if uiscale is ba.UIScale.MEDIUM else 1.23)
 39
 40        self._delegate = delegate
 41        self._transitioning_out = False
 42
 43        self._icons = [ba.charstr(ba.SpecialChar.LOGO)
 44                       ] + ba.app.accounts_v1.get_purchased_icons()
 45        count = len(self._icons)
 46        columns = 4
 47        rows = int(math.ceil(float(count) / columns))
 48
 49        button_width = 50
 50        button_height = 50
 51        button_buffer_h = 10
 52        button_buffer_v = 5
 53
 54        self._width = (10 + columns * (button_width + 2 * button_buffer_h) *
 55                       (1.0 / 0.95) * (1.0 / 0.8))
 56        self._height = (self._width *
 57                        (0.8 if uiscale is ba.UIScale.SMALL else 1.06))
 58
 59        self._scroll_width = self._width * 0.8
 60        self._scroll_height = self._height * 0.8
 61        self._scroll_position = ((self._width - self._scroll_width) * 0.5,
 62                                 (self._height - self._scroll_height) * 0.5)
 63
 64        # creates our _root_widget
 65        popup.PopupWindow.__init__(self,
 66                                   position=position,
 67                                   size=(self._width, self._height),
 68                                   scale=scale,
 69                                   bg_color=(0.5, 0.5, 0.5),
 70                                   offset=offset,
 71                                   focus_position=self._scroll_position,
 72                                   focus_size=(self._scroll_width,
 73                                               self._scroll_height))
 74
 75        self._scrollwidget = ba.scrollwidget(parent=self.root_widget,
 76                                             size=(self._scroll_width,
 77                                                   self._scroll_height),
 78                                             color=(0.55, 0.55, 0.55),
 79                                             highlight=False,
 80                                             position=self._scroll_position)
 81        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
 82
 83        self._sub_width = self._scroll_width * 0.95
 84        self._sub_height = 5 + rows * (button_height +
 85                                       2 * button_buffer_v) + 100
 86        self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
 87                                                size=(self._sub_width,
 88                                                      self._sub_height),
 89                                                background=False)
 90        index = 0
 91        for y in range(rows):
 92            for x in range(columns):
 93                pos = (x * (button_width + 2 * button_buffer_h) +
 94                       button_buffer_h, self._sub_height - (y + 1) *
 95                       (button_height + 2 * button_buffer_v) + 0)
 96                btn = ba.buttonwidget(parent=self._subcontainer,
 97                                      button_type='square',
 98                                      size=(button_width, button_height),
 99                                      autoselect=True,
100                                      text_scale=1.2,
101                                      label='',
102                                      color=(0.65, 0.65, 0.65),
103                                      on_activate_call=ba.Call(
104                                          self._select_icon,
105                                          self._icons[index]),
106                                      position=pos)
107                ba.textwidget(parent=self._subcontainer,
108                              h_align='center',
109                              v_align='center',
110                              size=(0, 0),
111                              position=(pos[0] + 0.5 * button_width - 1,
112                                        pos[1] + 15),
113                              draw_controller=btn,
114                              text=self._icons[index],
115                              scale=1.8)
116                ba.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60)
117                if self._icons[index] == selected_icon:
118                    ba.containerwidget(edit=self._subcontainer,
119                                       selected_child=btn,
120                                       visible_child=btn)
121                index += 1
122
123                if index >= count:
124                    break
125            if index >= count:
126                break
127        self._get_more_icons_button = btn = ba.buttonwidget(
128            parent=self._subcontainer,
129            size=(self._sub_width * 0.8, 60),
130            position=(self._sub_width * 0.1, 30),
131            label=ba.Lstr(resource='editProfileWindow.getMoreIconsText'),
132            on_activate_call=self._on_store_press,
133            color=(0.6, 0.6, 0.6),
134            textcolor=(0.8, 0.8, 0.8),
135            autoselect=True)
136        ba.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)
def on_popup_cancel(self) -> None:
159    def on_popup_cancel(self) -> None:
160        ba.playsound(ba.getsound('swish'))
161        self._transition_out()

Called when the popup is canceled.

Cancels can occur due to clicking outside the window, hitting escape, etc.