bastd.ui.serverdialog

Dialog window controlled by the master server.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Dialog window controlled by the master server."""
  4
  5from __future__ import annotations
  6
  7import logging
  8from dataclasses import dataclass, field
  9from typing import TYPE_CHECKING, Annotated
 10
 11from efro.dataclassio import ioprepped, IOAttrs
 12
 13import ba
 14import ba.internal
 15
 16if TYPE_CHECKING:
 17    pass
 18
 19
 20@ioprepped
 21@dataclass
 22class ServerDialogData:
 23    """Data for ServerDialog."""
 24
 25    dialog_id: Annotated[str, IOAttrs('dialogID')]
 26    text: Annotated[str, IOAttrs('text')]
 27    subs: Annotated[list[tuple[str, str]], IOAttrs('subs')] = field(
 28        default_factory=list
 29    )
 30    show_cancel: Annotated[bool, IOAttrs('showCancel')] = True
 31    copy_text: Annotated[str | None, IOAttrs('copyText')] = None
 32
 33
 34class ServerDialogWindow(ba.Window):
 35    """A dialog window driven by the master-server."""
 36
 37    def __init__(self, data: ServerDialogData):
 38        self._data = data
 39        txt = ba.Lstr(
 40            translate=('serverResponses', data.text), subs=data.subs
 41        ).evaluate()
 42        txt = txt.strip()
 43        txt_scale = 1.5
 44        txt_height = (
 45            ba.internal.get_string_height(txt, suppress_warning=True)
 46            * txt_scale
 47        )
 48        self._width = 500
 49        self._height = 160 + min(200, txt_height)
 50        uiscale = ba.app.ui.uiscale
 51        super().__init__(
 52            root_widget=ba.containerwidget(
 53                size=(self._width, self._height),
 54                transition='in_scale',
 55                scale=(
 56                    1.8
 57                    if uiscale is ba.UIScale.SMALL
 58                    else 1.35
 59                    if uiscale is ba.UIScale.MEDIUM
 60                    else 1.0
 61                ),
 62            )
 63        )
 64        self._starttime = ba.time(ba.TimeType.REAL)
 65
 66        ba.playsound(ba.getsound('swish'))
 67        ba.textwidget(
 68            parent=self._root_widget,
 69            position=(self._width * 0.5, 70 + (self._height - 70) * 0.5),
 70            size=(0, 0),
 71            color=(1.0, 3.0, 1.0),
 72            scale=txt_scale,
 73            h_align='center',
 74            v_align='center',
 75            text=txt,
 76            maxwidth=self._width * 0.85,
 77            max_height=(self._height - 110),
 78        )
 79
 80        show_copy = data.copy_text is not None and ba.clipboard_is_supported()
 81
 82        # Currently can't do both copy and cancel since they go in the same
 83        # spot. Cancel wins in this case since it is important functionality
 84        # and copy is just for convenience (and not even always available).
 85        if show_copy and data.show_cancel:
 86            logging.warning(
 87                'serverdialog requesting both copy and cancel;'
 88                ' copy will not be shown.'
 89            )
 90            show_copy = False
 91
 92        self._cancel_button = (
 93            None
 94            if not data.show_cancel
 95            else ba.buttonwidget(
 96                parent=self._root_widget,
 97                position=(30, 30),
 98                size=(160, 60),
 99                autoselect=True,
100                label=ba.Lstr(resource='cancelText'),
101                on_activate_call=self._cancel_press,
102            )
103        )
104
105        self._copy_button = (
106            None
107            if not show_copy
108            else ba.buttonwidget(
109                parent=self._root_widget,
110                position=(30, 30),
111                size=(160, 60),
112                autoselect=True,
113                label=ba.Lstr(resource='copyText'),
114                on_activate_call=self._copy_press,
115            )
116        )
117
118        self._ok_button = ba.buttonwidget(
119            parent=self._root_widget,
120            position=(
121                (self._width - 182)
122                if (data.show_cancel or show_copy)
123                else (self._width * 0.5 - 80),
124                30,
125            ),
126            size=(160, 60),
127            autoselect=True,
128            label=ba.Lstr(resource='okText'),
129            on_activate_call=self._ok_press,
130        )
131
132        ba.containerwidget(
133            edit=self._root_widget,
134            cancel_button=self._cancel_button,
135            start_button=self._ok_button,
136            selected_child=self._ok_button,
137        )
138
139    def _copy_press(self) -> None:
140        assert self._data.copy_text is not None
141        ba.clipboard_set_text(self._data.copy_text)
142        ba.screenmessage(ba.Lstr(resource='copyConfirmText'), color=(0, 1, 0))
143
144    def _ok_press(self) -> None:
145        if ba.time(ba.TimeType.REAL) - self._starttime < 1.0:
146            ba.playsound(ba.getsound('error'))
147            return
148        ba.internal.add_transaction(
149            {
150                'type': 'DIALOG_RESPONSE',
151                'dialogID': self._data.dialog_id,
152                'response': 1,
153            }
154        )
155        ba.containerwidget(edit=self._root_widget, transition='out_scale')
156
157    def _cancel_press(self) -> None:
158        if ba.time(ba.TimeType.REAL) - self._starttime < 1.0:
159            ba.playsound(ba.getsound('error'))
160            return
161        ba.internal.add_transaction(
162            {
163                'type': 'DIALOG_RESPONSE',
164                'dialogID': self._data.dialog_id,
165                'response': 0,
166            }
167        )
168        ba.containerwidget(edit=self._root_widget, transition='out_scale')
@ioprepped
@dataclass
class ServerDialogData:
21@ioprepped
22@dataclass
23class ServerDialogData:
24    """Data for ServerDialog."""
25
26    dialog_id: Annotated[str, IOAttrs('dialogID')]
27    text: Annotated[str, IOAttrs('text')]
28    subs: Annotated[list[tuple[str, str]], IOAttrs('subs')] = field(
29        default_factory=list
30    )
31    show_cancel: Annotated[bool, IOAttrs('showCancel')] = True
32    copy_text: Annotated[str | None, IOAttrs('copyText')] = None

Data for ServerDialog.

ServerDialogData( dialog_id: typing.Annotated[str, <efro.dataclassio.IOAttrs object at 0x10ffc2f50>], text: typing.Annotated[str, <efro.dataclassio.IOAttrs object at 0x10ffc2f20>], subs: typing.Annotated[list[tuple[str, str]], <efro.dataclassio.IOAttrs object at 0x10ffa62f0>] = <factory>, show_cancel: typing.Annotated[bool, <efro.dataclassio.IOAttrs object at 0x10ffc2ef0>] = True, copy_text: typing.Annotated[str | None, <efro.dataclassio.IOAttrs object at 0x10ffa4190>] = None)
class ServerDialogWindow(ba.ui.Window):
 35class ServerDialogWindow(ba.Window):
 36    """A dialog window driven by the master-server."""
 37
 38    def __init__(self, data: ServerDialogData):
 39        self._data = data
 40        txt = ba.Lstr(
 41            translate=('serverResponses', data.text), subs=data.subs
 42        ).evaluate()
 43        txt = txt.strip()
 44        txt_scale = 1.5
 45        txt_height = (
 46            ba.internal.get_string_height(txt, suppress_warning=True)
 47            * txt_scale
 48        )
 49        self._width = 500
 50        self._height = 160 + min(200, txt_height)
 51        uiscale = ba.app.ui.uiscale
 52        super().__init__(
 53            root_widget=ba.containerwidget(
 54                size=(self._width, self._height),
 55                transition='in_scale',
 56                scale=(
 57                    1.8
 58                    if uiscale is ba.UIScale.SMALL
 59                    else 1.35
 60                    if uiscale is ba.UIScale.MEDIUM
 61                    else 1.0
 62                ),
 63            )
 64        )
 65        self._starttime = ba.time(ba.TimeType.REAL)
 66
 67        ba.playsound(ba.getsound('swish'))
 68        ba.textwidget(
 69            parent=self._root_widget,
 70            position=(self._width * 0.5, 70 + (self._height - 70) * 0.5),
 71            size=(0, 0),
 72            color=(1.0, 3.0, 1.0),
 73            scale=txt_scale,
 74            h_align='center',
 75            v_align='center',
 76            text=txt,
 77            maxwidth=self._width * 0.85,
 78            max_height=(self._height - 110),
 79        )
 80
 81        show_copy = data.copy_text is not None and ba.clipboard_is_supported()
 82
 83        # Currently can't do both copy and cancel since they go in the same
 84        # spot. Cancel wins in this case since it is important functionality
 85        # and copy is just for convenience (and not even always available).
 86        if show_copy and data.show_cancel:
 87            logging.warning(
 88                'serverdialog requesting both copy and cancel;'
 89                ' copy will not be shown.'
 90            )
 91            show_copy = False
 92
 93        self._cancel_button = (
 94            None
 95            if not data.show_cancel
 96            else ba.buttonwidget(
 97                parent=self._root_widget,
 98                position=(30, 30),
 99                size=(160, 60),
100                autoselect=True,
101                label=ba.Lstr(resource='cancelText'),
102                on_activate_call=self._cancel_press,
103            )
104        )
105
106        self._copy_button = (
107            None
108            if not show_copy
109            else ba.buttonwidget(
110                parent=self._root_widget,
111                position=(30, 30),
112                size=(160, 60),
113                autoselect=True,
114                label=ba.Lstr(resource='copyText'),
115                on_activate_call=self._copy_press,
116            )
117        )
118
119        self._ok_button = ba.buttonwidget(
120            parent=self._root_widget,
121            position=(
122                (self._width - 182)
123                if (data.show_cancel or show_copy)
124                else (self._width * 0.5 - 80),
125                30,
126            ),
127            size=(160, 60),
128            autoselect=True,
129            label=ba.Lstr(resource='okText'),
130            on_activate_call=self._ok_press,
131        )
132
133        ba.containerwidget(
134            edit=self._root_widget,
135            cancel_button=self._cancel_button,
136            start_button=self._ok_button,
137            selected_child=self._ok_button,
138        )
139
140    def _copy_press(self) -> None:
141        assert self._data.copy_text is not None
142        ba.clipboard_set_text(self._data.copy_text)
143        ba.screenmessage(ba.Lstr(resource='copyConfirmText'), color=(0, 1, 0))
144
145    def _ok_press(self) -> None:
146        if ba.time(ba.TimeType.REAL) - self._starttime < 1.0:
147            ba.playsound(ba.getsound('error'))
148            return
149        ba.internal.add_transaction(
150            {
151                'type': 'DIALOG_RESPONSE',
152                'dialogID': self._data.dialog_id,
153                'response': 1,
154            }
155        )
156        ba.containerwidget(edit=self._root_widget, transition='out_scale')
157
158    def _cancel_press(self) -> None:
159        if ba.time(ba.TimeType.REAL) - self._starttime < 1.0:
160            ba.playsound(ba.getsound('error'))
161            return
162        ba.internal.add_transaction(
163            {
164                'type': 'DIALOG_RESPONSE',
165                'dialogID': self._data.dialog_id,
166                'response': 0,
167            }
168        )
169        ba.containerwidget(edit=self._root_widget, transition='out_scale')

A dialog window driven by the master-server.

ServerDialogWindow(data: bastd.ui.serverdialog.ServerDialogData)
 38    def __init__(self, data: ServerDialogData):
 39        self._data = data
 40        txt = ba.Lstr(
 41            translate=('serverResponses', data.text), subs=data.subs
 42        ).evaluate()
 43        txt = txt.strip()
 44        txt_scale = 1.5
 45        txt_height = (
 46            ba.internal.get_string_height(txt, suppress_warning=True)
 47            * txt_scale
 48        )
 49        self._width = 500
 50        self._height = 160 + min(200, txt_height)
 51        uiscale = ba.app.ui.uiscale
 52        super().__init__(
 53            root_widget=ba.containerwidget(
 54                size=(self._width, self._height),
 55                transition='in_scale',
 56                scale=(
 57                    1.8
 58                    if uiscale is ba.UIScale.SMALL
 59                    else 1.35
 60                    if uiscale is ba.UIScale.MEDIUM
 61                    else 1.0
 62                ),
 63            )
 64        )
 65        self._starttime = ba.time(ba.TimeType.REAL)
 66
 67        ba.playsound(ba.getsound('swish'))
 68        ba.textwidget(
 69            parent=self._root_widget,
 70            position=(self._width * 0.5, 70 + (self._height - 70) * 0.5),
 71            size=(0, 0),
 72            color=(1.0, 3.0, 1.0),
 73            scale=txt_scale,
 74            h_align='center',
 75            v_align='center',
 76            text=txt,
 77            maxwidth=self._width * 0.85,
 78            max_height=(self._height - 110),
 79        )
 80
 81        show_copy = data.copy_text is not None and ba.clipboard_is_supported()
 82
 83        # Currently can't do both copy and cancel since they go in the same
 84        # spot. Cancel wins in this case since it is important functionality
 85        # and copy is just for convenience (and not even always available).
 86        if show_copy and data.show_cancel:
 87            logging.warning(
 88                'serverdialog requesting both copy and cancel;'
 89                ' copy will not be shown.'
 90            )
 91            show_copy = False
 92
 93        self._cancel_button = (
 94            None
 95            if not data.show_cancel
 96            else ba.buttonwidget(
 97                parent=self._root_widget,
 98                position=(30, 30),
 99                size=(160, 60),
100                autoselect=True,
101                label=ba.Lstr(resource='cancelText'),
102                on_activate_call=self._cancel_press,
103            )
104        )
105
106        self._copy_button = (
107            None
108            if not show_copy
109            else ba.buttonwidget(
110                parent=self._root_widget,
111                position=(30, 30),
112                size=(160, 60),
113                autoselect=True,
114                label=ba.Lstr(resource='copyText'),
115                on_activate_call=self._copy_press,
116            )
117        )
118
119        self._ok_button = ba.buttonwidget(
120            parent=self._root_widget,
121            position=(
122                (self._width - 182)
123                if (data.show_cancel or show_copy)
124                else (self._width * 0.5 - 80),
125                30,
126            ),
127            size=(160, 60),
128            autoselect=True,
129            label=ba.Lstr(resource='okText'),
130            on_activate_call=self._ok_press,
131        )
132
133        ba.containerwidget(
134            edit=self._root_widget,
135            cancel_button=self._cancel_button,
136            start_button=self._ok_button,
137            selected_child=self._ok_button,
138        )
Inherited Members
ba.ui.Window
get_root_widget