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