bastd.ui.teamnamescolors

Provides a window to customize team names and colors.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides a window to customize team names and colors."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING, cast
  8
  9import ba
 10from bastd.ui import popup
 11
 12if TYPE_CHECKING:
 13    from typing import Sequence
 14    from bastd.ui.colorpicker import ColorPicker
 15
 16
 17class TeamNamesColorsWindow(popup.PopupWindow):
 18    """A popup window for customizing team names and colors."""
 19
 20    def __init__(self, scale_origin: tuple[float, float]):
 21        from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
 22
 23        self._width = 500
 24        self._height = 330
 25        self._transitioning_out = False
 26        self._max_name_length = 16
 27
 28        # Creates our _root_widget.
 29        uiscale = ba.app.ui.uiscale
 30        scale = (
 31            1.69
 32            if uiscale is ba.UIScale.SMALL
 33            else 1.1
 34            if uiscale is ba.UIScale.MEDIUM
 35            else 0.85
 36        )
 37        super().__init__(
 38            position=scale_origin, size=(self._width, self._height), scale=scale
 39        )
 40
 41        appconfig = ba.app.config
 42        self._names = list(
 43            appconfig.get('Custom Team Names', DEFAULT_TEAM_NAMES)
 44        )
 45
 46        # We need to flatten the translation since it will be an
 47        # editable string.
 48        self._names = [
 49            ba.Lstr(translate=('teamNames', n)).evaluate() for n in self._names
 50        ]
 51        self._colors = list(
 52            appconfig.get('Custom Team Colors', DEFAULT_TEAM_COLORS)
 53        )
 54
 55        self._color_buttons: list[ba.Widget] = []
 56        self._color_text_fields: list[ba.Widget] = []
 57
 58        resetbtn = ba.buttonwidget(
 59            parent=self.root_widget,
 60            label=ba.Lstr(resource='settingsWindowAdvanced.resetText'),
 61            autoselect=True,
 62            scale=0.7,
 63            on_activate_call=self._reset,
 64            size=(120, 50),
 65            position=(self._width * 0.5 - 60 * 0.7, self._height - 60),
 66        )
 67
 68        for i in range(2):
 69            self._color_buttons.append(
 70                ba.buttonwidget(
 71                    parent=self.root_widget,
 72                    autoselect=True,
 73                    position=(50, 0 + 195 - 90 * i),
 74                    on_activate_call=ba.Call(self._color_click, i),
 75                    size=(70, 70),
 76                    color=self._colors[i],
 77                    label='',
 78                    button_type='square',
 79                )
 80            )
 81            self._color_text_fields.append(
 82                ba.textwidget(
 83                    parent=self.root_widget,
 84                    position=(135, 0 + 201 - 90 * i),
 85                    size=(280, 46),
 86                    text=self._names[i],
 87                    h_align='left',
 88                    v_align='center',
 89                    max_chars=self._max_name_length,
 90                    color=self._colors[i],
 91                    description=ba.Lstr(resource='nameText'),
 92                    editable=True,
 93                    padding=4,
 94                )
 95            )
 96        ba.widget(
 97            edit=self._color_text_fields[0],
 98            down_widget=self._color_text_fields[1],
 99        )
100        ba.widget(
101            edit=self._color_text_fields[1],
102            up_widget=self._color_text_fields[0],
103        )
104        ba.widget(edit=self._color_text_fields[0], up_widget=resetbtn)
105
106        cancelbtn = ba.buttonwidget(
107            parent=self.root_widget,
108            label=ba.Lstr(resource='cancelText'),
109            autoselect=True,
110            on_activate_call=self._on_cancel_press,
111            size=(150, 50),
112            position=(self._width * 0.5 - 200, 20),
113        )
114        okbtn = ba.buttonwidget(
115            parent=self.root_widget,
116            label=ba.Lstr(resource='okText'),
117            autoselect=True,
118            on_activate_call=self._ok,
119            size=(150, 50),
120            position=(self._width * 0.5 + 50, 20),
121        )
122        ba.containerwidget(
123            edit=self.root_widget, selected_child=self._color_buttons[0]
124        )
125        ba.widget(edit=okbtn, left_widget=cancelbtn)
126        self._update()
127
128    def _color_click(self, i: int) -> None:
129        from bastd.ui.colorpicker import ColorPicker
130
131        ColorPicker(
132            parent=self.root_widget,
133            position=self._color_buttons[i].get_screen_space_center(),
134            offset=(270.0, 0),
135            initial_color=self._colors[i],
136            delegate=self,
137            tag=i,
138        )
139
140    def color_picker_closing(self, picker: ColorPicker) -> None:
141        """Called when the color picker is closing."""
142
143    def color_picker_selected_color(
144        self, picker: ColorPicker, color: Sequence[float]
145    ) -> None:
146        """Called when a color is selected in the color picker."""
147        self._colors[picker.get_tag()] = color
148        self._update()
149
150    def _reset(self) -> None:
151        from ba.internal import DEFAULT_TEAM_NAMES, DEFAULT_TEAM_COLORS
152
153        for i in range(2):
154            self._colors[i] = DEFAULT_TEAM_COLORS[i]
155            name = ba.Lstr(
156                translate=('teamNames', DEFAULT_TEAM_NAMES[i])
157            ).evaluate()
158            if len(name) > self._max_name_length:
159                print('GOT DEFAULT TEAM NAME LONGER THAN MAX LENGTH')
160            ba.textwidget(edit=self._color_text_fields[i], text=name)
161        self._update()
162
163    def _update(self) -> None:
164        for i in range(2):
165            ba.buttonwidget(edit=self._color_buttons[i], color=self._colors[i])
166            ba.textwidget(
167                edit=self._color_text_fields[i], color=self._colors[i]
168            )
169
170    def _ok(self) -> None:
171        from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
172
173        cfg = ba.app.config
174
175        # First, determine whether the values here are defaults, in which case
176        # we can clear any values from prefs.  Currently if the string matches
177        # either the default raw value or its translation we consider it
178        # default. (the fact that team names get translated makes this
179        # situation a bit sloppy)
180        new_names: list[str] = []
181        is_default = True
182        for i in range(2):
183            name = cast(str, ba.textwidget(query=self._color_text_fields[i]))
184            if not name:
185                ba.screenmessage(
186                    ba.Lstr(resource='nameNotEmptyText'), color=(1, 0, 0)
187                )
188                ba.playsound(ba.getsound('error'))
189                return
190            new_names.append(name)
191
192        for i in range(2):
193            if self._colors[i] != DEFAULT_TEAM_COLORS[i]:
194                is_default = False
195            default_team_name = DEFAULT_TEAM_NAMES[i]
196            default_team_name_translated = ba.Lstr(
197                translate=('teamNames', default_team_name)
198            ).evaluate()
199            if (
200                new_names[i] != default_team_name
201                and new_names[i] != default_team_name_translated
202            ):
203                is_default = False
204
205        if is_default:
206            for key in ('Custom Team Names', 'Custom Team Colors'):
207                if key in cfg:
208                    del cfg[key]
209        else:
210            cfg['Custom Team Names'] = list(new_names)
211            cfg['Custom Team Colors'] = list(self._colors)
212
213        cfg.commit()
214        self._transition_out()
215
216    def _transition_out(self, transition: str = 'out_scale') -> None:
217        if not self._transitioning_out:
218            self._transitioning_out = True
219            ba.containerwidget(edit=self.root_widget, transition=transition)
220
221    def on_popup_cancel(self) -> None:
222        ba.playsound(ba.getsound('swish'))
223        self._transition_out()
224
225    def _on_cancel_press(self) -> None:
226        self._transition_out()
class TeamNamesColorsWindow(bastd.ui.popup.PopupWindow):
 18class TeamNamesColorsWindow(popup.PopupWindow):
 19    """A popup window for customizing team names and colors."""
 20
 21    def __init__(self, scale_origin: tuple[float, float]):
 22        from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
 23
 24        self._width = 500
 25        self._height = 330
 26        self._transitioning_out = False
 27        self._max_name_length = 16
 28
 29        # Creates our _root_widget.
 30        uiscale = ba.app.ui.uiscale
 31        scale = (
 32            1.69
 33            if uiscale is ba.UIScale.SMALL
 34            else 1.1
 35            if uiscale is ba.UIScale.MEDIUM
 36            else 0.85
 37        )
 38        super().__init__(
 39            position=scale_origin, size=(self._width, self._height), scale=scale
 40        )
 41
 42        appconfig = ba.app.config
 43        self._names = list(
 44            appconfig.get('Custom Team Names', DEFAULT_TEAM_NAMES)
 45        )
 46
 47        # We need to flatten the translation since it will be an
 48        # editable string.
 49        self._names = [
 50            ba.Lstr(translate=('teamNames', n)).evaluate() for n in self._names
 51        ]
 52        self._colors = list(
 53            appconfig.get('Custom Team Colors', DEFAULT_TEAM_COLORS)
 54        )
 55
 56        self._color_buttons: list[ba.Widget] = []
 57        self._color_text_fields: list[ba.Widget] = []
 58
 59        resetbtn = ba.buttonwidget(
 60            parent=self.root_widget,
 61            label=ba.Lstr(resource='settingsWindowAdvanced.resetText'),
 62            autoselect=True,
 63            scale=0.7,
 64            on_activate_call=self._reset,
 65            size=(120, 50),
 66            position=(self._width * 0.5 - 60 * 0.7, self._height - 60),
 67        )
 68
 69        for i in range(2):
 70            self._color_buttons.append(
 71                ba.buttonwidget(
 72                    parent=self.root_widget,
 73                    autoselect=True,
 74                    position=(50, 0 + 195 - 90 * i),
 75                    on_activate_call=ba.Call(self._color_click, i),
 76                    size=(70, 70),
 77                    color=self._colors[i],
 78                    label='',
 79                    button_type='square',
 80                )
 81            )
 82            self._color_text_fields.append(
 83                ba.textwidget(
 84                    parent=self.root_widget,
 85                    position=(135, 0 + 201 - 90 * i),
 86                    size=(280, 46),
 87                    text=self._names[i],
 88                    h_align='left',
 89                    v_align='center',
 90                    max_chars=self._max_name_length,
 91                    color=self._colors[i],
 92                    description=ba.Lstr(resource='nameText'),
 93                    editable=True,
 94                    padding=4,
 95                )
 96            )
 97        ba.widget(
 98            edit=self._color_text_fields[0],
 99            down_widget=self._color_text_fields[1],
100        )
101        ba.widget(
102            edit=self._color_text_fields[1],
103            up_widget=self._color_text_fields[0],
104        )
105        ba.widget(edit=self._color_text_fields[0], up_widget=resetbtn)
106
107        cancelbtn = ba.buttonwidget(
108            parent=self.root_widget,
109            label=ba.Lstr(resource='cancelText'),
110            autoselect=True,
111            on_activate_call=self._on_cancel_press,
112            size=(150, 50),
113            position=(self._width * 0.5 - 200, 20),
114        )
115        okbtn = ba.buttonwidget(
116            parent=self.root_widget,
117            label=ba.Lstr(resource='okText'),
118            autoselect=True,
119            on_activate_call=self._ok,
120            size=(150, 50),
121            position=(self._width * 0.5 + 50, 20),
122        )
123        ba.containerwidget(
124            edit=self.root_widget, selected_child=self._color_buttons[0]
125        )
126        ba.widget(edit=okbtn, left_widget=cancelbtn)
127        self._update()
128
129    def _color_click(self, i: int) -> None:
130        from bastd.ui.colorpicker import ColorPicker
131
132        ColorPicker(
133            parent=self.root_widget,
134            position=self._color_buttons[i].get_screen_space_center(),
135            offset=(270.0, 0),
136            initial_color=self._colors[i],
137            delegate=self,
138            tag=i,
139        )
140
141    def color_picker_closing(self, picker: ColorPicker) -> None:
142        """Called when the color picker is closing."""
143
144    def color_picker_selected_color(
145        self, picker: ColorPicker, color: Sequence[float]
146    ) -> None:
147        """Called when a color is selected in the color picker."""
148        self._colors[picker.get_tag()] = color
149        self._update()
150
151    def _reset(self) -> None:
152        from ba.internal import DEFAULT_TEAM_NAMES, DEFAULT_TEAM_COLORS
153
154        for i in range(2):
155            self._colors[i] = DEFAULT_TEAM_COLORS[i]
156            name = ba.Lstr(
157                translate=('teamNames', DEFAULT_TEAM_NAMES[i])
158            ).evaluate()
159            if len(name) > self._max_name_length:
160                print('GOT DEFAULT TEAM NAME LONGER THAN MAX LENGTH')
161            ba.textwidget(edit=self._color_text_fields[i], text=name)
162        self._update()
163
164    def _update(self) -> None:
165        for i in range(2):
166            ba.buttonwidget(edit=self._color_buttons[i], color=self._colors[i])
167            ba.textwidget(
168                edit=self._color_text_fields[i], color=self._colors[i]
169            )
170
171    def _ok(self) -> None:
172        from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
173
174        cfg = ba.app.config
175
176        # First, determine whether the values here are defaults, in which case
177        # we can clear any values from prefs.  Currently if the string matches
178        # either the default raw value or its translation we consider it
179        # default. (the fact that team names get translated makes this
180        # situation a bit sloppy)
181        new_names: list[str] = []
182        is_default = True
183        for i in range(2):
184            name = cast(str, ba.textwidget(query=self._color_text_fields[i]))
185            if not name:
186                ba.screenmessage(
187                    ba.Lstr(resource='nameNotEmptyText'), color=(1, 0, 0)
188                )
189                ba.playsound(ba.getsound('error'))
190                return
191            new_names.append(name)
192
193        for i in range(2):
194            if self._colors[i] != DEFAULT_TEAM_COLORS[i]:
195                is_default = False
196            default_team_name = DEFAULT_TEAM_NAMES[i]
197            default_team_name_translated = ba.Lstr(
198                translate=('teamNames', default_team_name)
199            ).evaluate()
200            if (
201                new_names[i] != default_team_name
202                and new_names[i] != default_team_name_translated
203            ):
204                is_default = False
205
206        if is_default:
207            for key in ('Custom Team Names', 'Custom Team Colors'):
208                if key in cfg:
209                    del cfg[key]
210        else:
211            cfg['Custom Team Names'] = list(new_names)
212            cfg['Custom Team Colors'] = list(self._colors)
213
214        cfg.commit()
215        self._transition_out()
216
217    def _transition_out(self, transition: str = 'out_scale') -> None:
218        if not self._transitioning_out:
219            self._transitioning_out = True
220            ba.containerwidget(edit=self.root_widget, transition=transition)
221
222    def on_popup_cancel(self) -> None:
223        ba.playsound(ba.getsound('swish'))
224        self._transition_out()
225
226    def _on_cancel_press(self) -> None:
227        self._transition_out()

A popup window for customizing team names and colors.

TeamNamesColorsWindow(scale_origin: tuple[float, float])
 21    def __init__(self, scale_origin: tuple[float, float]):
 22        from ba.internal import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
 23
 24        self._width = 500
 25        self._height = 330
 26        self._transitioning_out = False
 27        self._max_name_length = 16
 28
 29        # Creates our _root_widget.
 30        uiscale = ba.app.ui.uiscale
 31        scale = (
 32            1.69
 33            if uiscale is ba.UIScale.SMALL
 34            else 1.1
 35            if uiscale is ba.UIScale.MEDIUM
 36            else 0.85
 37        )
 38        super().__init__(
 39            position=scale_origin, size=(self._width, self._height), scale=scale
 40        )
 41
 42        appconfig = ba.app.config
 43        self._names = list(
 44            appconfig.get('Custom Team Names', DEFAULT_TEAM_NAMES)
 45        )
 46
 47        # We need to flatten the translation since it will be an
 48        # editable string.
 49        self._names = [
 50            ba.Lstr(translate=('teamNames', n)).evaluate() for n in self._names
 51        ]
 52        self._colors = list(
 53            appconfig.get('Custom Team Colors', DEFAULT_TEAM_COLORS)
 54        )
 55
 56        self._color_buttons: list[ba.Widget] = []
 57        self._color_text_fields: list[ba.Widget] = []
 58
 59        resetbtn = ba.buttonwidget(
 60            parent=self.root_widget,
 61            label=ba.Lstr(resource='settingsWindowAdvanced.resetText'),
 62            autoselect=True,
 63            scale=0.7,
 64            on_activate_call=self._reset,
 65            size=(120, 50),
 66            position=(self._width * 0.5 - 60 * 0.7, self._height - 60),
 67        )
 68
 69        for i in range(2):
 70            self._color_buttons.append(
 71                ba.buttonwidget(
 72                    parent=self.root_widget,
 73                    autoselect=True,
 74                    position=(50, 0 + 195 - 90 * i),
 75                    on_activate_call=ba.Call(self._color_click, i),
 76                    size=(70, 70),
 77                    color=self._colors[i],
 78                    label='',
 79                    button_type='square',
 80                )
 81            )
 82            self._color_text_fields.append(
 83                ba.textwidget(
 84                    parent=self.root_widget,
 85                    position=(135, 0 + 201 - 90 * i),
 86                    size=(280, 46),
 87                    text=self._names[i],
 88                    h_align='left',
 89                    v_align='center',
 90                    max_chars=self._max_name_length,
 91                    color=self._colors[i],
 92                    description=ba.Lstr(resource='nameText'),
 93                    editable=True,
 94                    padding=4,
 95                )
 96            )
 97        ba.widget(
 98            edit=self._color_text_fields[0],
 99            down_widget=self._color_text_fields[1],
100        )
101        ba.widget(
102            edit=self._color_text_fields[1],
103            up_widget=self._color_text_fields[0],
104        )
105        ba.widget(edit=self._color_text_fields[0], up_widget=resetbtn)
106
107        cancelbtn = ba.buttonwidget(
108            parent=self.root_widget,
109            label=ba.Lstr(resource='cancelText'),
110            autoselect=True,
111            on_activate_call=self._on_cancel_press,
112            size=(150, 50),
113            position=(self._width * 0.5 - 200, 20),
114        )
115        okbtn = ba.buttonwidget(
116            parent=self.root_widget,
117            label=ba.Lstr(resource='okText'),
118            autoselect=True,
119            on_activate_call=self._ok,
120            size=(150, 50),
121            position=(self._width * 0.5 + 50, 20),
122        )
123        ba.containerwidget(
124            edit=self.root_widget, selected_child=self._color_buttons[0]
125        )
126        ba.widget(edit=okbtn, left_widget=cancelbtn)
127        self._update()
def color_picker_closing(self, picker: bastd.ui.colorpicker.ColorPicker) -> None:
141    def color_picker_closing(self, picker: ColorPicker) -> None:
142        """Called when the color picker is closing."""

Called when the color picker is closing.

def color_picker_selected_color( self, picker: bastd.ui.colorpicker.ColorPicker, color: Sequence[float]) -> None:
144    def color_picker_selected_color(
145        self, picker: ColorPicker, color: Sequence[float]
146    ) -> None:
147        """Called when a color is selected in the color picker."""
148        self._colors[picker.get_tag()] = color
149        self._update()

Called when a color is selected in the color picker.

def on_popup_cancel(self) -> None:
222    def on_popup_cancel(self) -> None:
223        ba.playsound(ba.getsound('swish'))
224        self._transition_out()

Called when the popup is canceled.

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