bauiv1lib.confirm
Provides ConfirmWindow base class and commonly used derivatives.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides ConfirmWindow base class and commonly used derivatives.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING 8import logging 9 10import bauiv1 as bui 11 12if TYPE_CHECKING: 13 from typing import Any, Callable 14 15 16class ConfirmWindow: 17 """Window for answering simple yes/no questions.""" 18 19 def __init__( 20 self, 21 text: str | bui.Lstr | None = None, 22 action: Callable[[], Any] | None = None, 23 width: float = 360.0, 24 height: float = 100.0, 25 *, 26 cancel_button: bool = True, 27 cancel_is_selected: bool = False, 28 color: tuple[float, float, float] = (1, 1, 1), 29 text_scale: float = 1.0, 30 ok_text: str | bui.Lstr | None = None, 31 cancel_text: str | bui.Lstr | None = None, 32 origin_widget: bui.Widget | None = None, 33 ): 34 # pylint: disable=too-many-locals 35 if text is None: 36 text = bui.Lstr(resource='areYouSureText') 37 if ok_text is None: 38 ok_text = bui.Lstr(resource='okText') 39 if cancel_text is None: 40 cancel_text = bui.Lstr(resource='cancelText') 41 height += 40 42 width = max(width, 360) 43 self._action = action 44 45 # if they provided an origin-widget, scale up from that 46 self._transition_out: str | None 47 scale_origin: tuple[float, float] | None 48 if origin_widget is not None: 49 self._transition_out = 'out_scale' 50 scale_origin = origin_widget.get_screen_space_center() 51 transition = 'in_scale' 52 else: 53 self._transition_out = None 54 scale_origin = None 55 transition = 'in_right' 56 57 assert bui.app.classic is not None 58 uiscale = bui.app.ui_v1.uiscale 59 self.root_widget = bui.containerwidget( 60 size=(width, height), 61 transition=transition, 62 toolbar_visibility='menu_minimal_no_back', 63 parent=bui.get_special_widget('overlay_stack'), 64 scale=( 65 1.9 66 if uiscale is bui.UIScale.SMALL 67 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 68 ), 69 scale_origin_stack_offset=scale_origin, 70 ) 71 72 bui.textwidget( 73 parent=self.root_widget, 74 position=(width * 0.5, height - 5 - (height - 75) * 0.5), 75 size=(0, 0), 76 h_align='center', 77 v_align='center', 78 text=text, 79 scale=text_scale, 80 color=color, 81 maxwidth=width * 0.9, 82 max_height=height - 75, 83 ) 84 85 cbtn: bui.Widget | None 86 if cancel_button: 87 cbtn = btn = bui.buttonwidget( 88 parent=self.root_widget, 89 autoselect=True, 90 position=(20, 20), 91 size=(150, 50), 92 label=cancel_text, 93 on_activate_call=self._cancel, 94 ) 95 bui.containerwidget(edit=self.root_widget, cancel_button=btn) 96 ok_button_h = width - 175 97 else: 98 # if they don't want a cancel button, we still want back presses to 99 # be able to dismiss the window; just wire it up to do the ok 100 # button 101 ok_button_h = width * 0.5 - 75 102 cbtn = None 103 btn = bui.buttonwidget( 104 parent=self.root_widget, 105 autoselect=True, 106 position=(ok_button_h, 20), 107 size=(150, 50), 108 label=ok_text, 109 on_activate_call=self._ok, 110 ) 111 112 # if they didn't want a cancel button, we still want to be able to hit 113 # cancel/back/etc to dismiss the window 114 if not cancel_button: 115 bui.containerwidget( 116 edit=self.root_widget, on_cancel_call=btn.activate 117 ) 118 119 bui.containerwidget( 120 edit=self.root_widget, 121 selected_child=( 122 cbtn if cbtn is not None and cancel_is_selected else btn 123 ), 124 start_button=btn, 125 ) 126 127 def _cancel(self) -> None: 128 bui.containerwidget( 129 edit=self.root_widget, 130 transition=( 131 'out_right' 132 if self._transition_out is None 133 else self._transition_out 134 ), 135 ) 136 137 def _ok(self) -> None: 138 if not self.root_widget: 139 return 140 bui.containerwidget( 141 edit=self.root_widget, 142 transition=( 143 'out_left' 144 if self._transition_out is None 145 else self._transition_out 146 ), 147 ) 148 if self._action is not None: 149 self._action() 150 151 152class QuitWindow: 153 """Popup window to confirm quitting.""" 154 155 def __init__( 156 self, 157 quit_type: bui.QuitType | None = None, 158 swish: bool = False, 159 origin_widget: bui.Widget | None = None, 160 ): 161 classic = bui.app.classic 162 assert classic is not None 163 ui = bui.app.ui_v1 164 app = bui.app 165 self._quit_type = quit_type 166 167 # If there's already one of us up somewhere, kill it. 168 if ui.quit_window is not None: 169 ui.quit_window.delete() 170 ui.quit_window = None 171 if swish: 172 bui.getsound('swish').play() 173 174 if app.classic is None: 175 if bui.do_once(): 176 logging.warning( 177 'QuitWindow needs to be updated to work without classic.' 178 ) 179 quit_resource = 'exitGameText' 180 else: 181 quit_resource = ( 182 'quitGameText' 183 if app.classic.platform == 'mac' 184 else 'exitGameText' 185 ) 186 self._root_widget = ui.quit_window = ConfirmWindow( 187 bui.Lstr( 188 resource=quit_resource, 189 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 190 ), 191 lambda: ( 192 bui.quit(confirm=False, quit_type=self._quit_type) 193 if self._quit_type is not None 194 else bui.quit(confirm=False) 195 ), 196 origin_widget=origin_widget, 197 ).root_widget
class
ConfirmWindow:
17class ConfirmWindow: 18 """Window for answering simple yes/no questions.""" 19 20 def __init__( 21 self, 22 text: str | bui.Lstr | None = None, 23 action: Callable[[], Any] | None = None, 24 width: float = 360.0, 25 height: float = 100.0, 26 *, 27 cancel_button: bool = True, 28 cancel_is_selected: bool = False, 29 color: tuple[float, float, float] = (1, 1, 1), 30 text_scale: float = 1.0, 31 ok_text: str | bui.Lstr | None = None, 32 cancel_text: str | bui.Lstr | None = None, 33 origin_widget: bui.Widget | None = None, 34 ): 35 # pylint: disable=too-many-locals 36 if text is None: 37 text = bui.Lstr(resource='areYouSureText') 38 if ok_text is None: 39 ok_text = bui.Lstr(resource='okText') 40 if cancel_text is None: 41 cancel_text = bui.Lstr(resource='cancelText') 42 height += 40 43 width = max(width, 360) 44 self._action = action 45 46 # if they provided an origin-widget, scale up from that 47 self._transition_out: str | None 48 scale_origin: tuple[float, float] | None 49 if origin_widget is not None: 50 self._transition_out = 'out_scale' 51 scale_origin = origin_widget.get_screen_space_center() 52 transition = 'in_scale' 53 else: 54 self._transition_out = None 55 scale_origin = None 56 transition = 'in_right' 57 58 assert bui.app.classic is not None 59 uiscale = bui.app.ui_v1.uiscale 60 self.root_widget = bui.containerwidget( 61 size=(width, height), 62 transition=transition, 63 toolbar_visibility='menu_minimal_no_back', 64 parent=bui.get_special_widget('overlay_stack'), 65 scale=( 66 1.9 67 if uiscale is bui.UIScale.SMALL 68 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 69 ), 70 scale_origin_stack_offset=scale_origin, 71 ) 72 73 bui.textwidget( 74 parent=self.root_widget, 75 position=(width * 0.5, height - 5 - (height - 75) * 0.5), 76 size=(0, 0), 77 h_align='center', 78 v_align='center', 79 text=text, 80 scale=text_scale, 81 color=color, 82 maxwidth=width * 0.9, 83 max_height=height - 75, 84 ) 85 86 cbtn: bui.Widget | None 87 if cancel_button: 88 cbtn = btn = bui.buttonwidget( 89 parent=self.root_widget, 90 autoselect=True, 91 position=(20, 20), 92 size=(150, 50), 93 label=cancel_text, 94 on_activate_call=self._cancel, 95 ) 96 bui.containerwidget(edit=self.root_widget, cancel_button=btn) 97 ok_button_h = width - 175 98 else: 99 # if they don't want a cancel button, we still want back presses to 100 # be able to dismiss the window; just wire it up to do the ok 101 # button 102 ok_button_h = width * 0.5 - 75 103 cbtn = None 104 btn = bui.buttonwidget( 105 parent=self.root_widget, 106 autoselect=True, 107 position=(ok_button_h, 20), 108 size=(150, 50), 109 label=ok_text, 110 on_activate_call=self._ok, 111 ) 112 113 # if they didn't want a cancel button, we still want to be able to hit 114 # cancel/back/etc to dismiss the window 115 if not cancel_button: 116 bui.containerwidget( 117 edit=self.root_widget, on_cancel_call=btn.activate 118 ) 119 120 bui.containerwidget( 121 edit=self.root_widget, 122 selected_child=( 123 cbtn if cbtn is not None and cancel_is_selected else btn 124 ), 125 start_button=btn, 126 ) 127 128 def _cancel(self) -> None: 129 bui.containerwidget( 130 edit=self.root_widget, 131 transition=( 132 'out_right' 133 if self._transition_out is None 134 else self._transition_out 135 ), 136 ) 137 138 def _ok(self) -> None: 139 if not self.root_widget: 140 return 141 bui.containerwidget( 142 edit=self.root_widget, 143 transition=( 144 'out_left' 145 if self._transition_out is None 146 else self._transition_out 147 ), 148 ) 149 if self._action is not None: 150 self._action()
Window for answering simple yes/no questions.
ConfirmWindow( text: str | babase.Lstr | None = None, action: Optional[Callable[[], Any]] = None, width: float = 360.0, height: float = 100.0, *, cancel_button: bool = True, cancel_is_selected: bool = False, color: tuple[float, float, float] = (1, 1, 1), text_scale: float = 1.0, ok_text: str | babase.Lstr | None = None, cancel_text: str | babase.Lstr | None = None, origin_widget: _bauiv1.Widget | None = None)
20 def __init__( 21 self, 22 text: str | bui.Lstr | None = None, 23 action: Callable[[], Any] | None = None, 24 width: float = 360.0, 25 height: float = 100.0, 26 *, 27 cancel_button: bool = True, 28 cancel_is_selected: bool = False, 29 color: tuple[float, float, float] = (1, 1, 1), 30 text_scale: float = 1.0, 31 ok_text: str | bui.Lstr | None = None, 32 cancel_text: str | bui.Lstr | None = None, 33 origin_widget: bui.Widget | None = None, 34 ): 35 # pylint: disable=too-many-locals 36 if text is None: 37 text = bui.Lstr(resource='areYouSureText') 38 if ok_text is None: 39 ok_text = bui.Lstr(resource='okText') 40 if cancel_text is None: 41 cancel_text = bui.Lstr(resource='cancelText') 42 height += 40 43 width = max(width, 360) 44 self._action = action 45 46 # if they provided an origin-widget, scale up from that 47 self._transition_out: str | None 48 scale_origin: tuple[float, float] | None 49 if origin_widget is not None: 50 self._transition_out = 'out_scale' 51 scale_origin = origin_widget.get_screen_space_center() 52 transition = 'in_scale' 53 else: 54 self._transition_out = None 55 scale_origin = None 56 transition = 'in_right' 57 58 assert bui.app.classic is not None 59 uiscale = bui.app.ui_v1.uiscale 60 self.root_widget = bui.containerwidget( 61 size=(width, height), 62 transition=transition, 63 toolbar_visibility='menu_minimal_no_back', 64 parent=bui.get_special_widget('overlay_stack'), 65 scale=( 66 1.9 67 if uiscale is bui.UIScale.SMALL 68 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.0 69 ), 70 scale_origin_stack_offset=scale_origin, 71 ) 72 73 bui.textwidget( 74 parent=self.root_widget, 75 position=(width * 0.5, height - 5 - (height - 75) * 0.5), 76 size=(0, 0), 77 h_align='center', 78 v_align='center', 79 text=text, 80 scale=text_scale, 81 color=color, 82 maxwidth=width * 0.9, 83 max_height=height - 75, 84 ) 85 86 cbtn: bui.Widget | None 87 if cancel_button: 88 cbtn = btn = bui.buttonwidget( 89 parent=self.root_widget, 90 autoselect=True, 91 position=(20, 20), 92 size=(150, 50), 93 label=cancel_text, 94 on_activate_call=self._cancel, 95 ) 96 bui.containerwidget(edit=self.root_widget, cancel_button=btn) 97 ok_button_h = width - 175 98 else: 99 # if they don't want a cancel button, we still want back presses to 100 # be able to dismiss the window; just wire it up to do the ok 101 # button 102 ok_button_h = width * 0.5 - 75 103 cbtn = None 104 btn = bui.buttonwidget( 105 parent=self.root_widget, 106 autoselect=True, 107 position=(ok_button_h, 20), 108 size=(150, 50), 109 label=ok_text, 110 on_activate_call=self._ok, 111 ) 112 113 # if they didn't want a cancel button, we still want to be able to hit 114 # cancel/back/etc to dismiss the window 115 if not cancel_button: 116 bui.containerwidget( 117 edit=self.root_widget, on_cancel_call=btn.activate 118 ) 119 120 bui.containerwidget( 121 edit=self.root_widget, 122 selected_child=( 123 cbtn if cbtn is not None and cancel_is_selected else btn 124 ), 125 start_button=btn, 126 )
class
QuitWindow:
153class QuitWindow: 154 """Popup window to confirm quitting.""" 155 156 def __init__( 157 self, 158 quit_type: bui.QuitType | None = None, 159 swish: bool = False, 160 origin_widget: bui.Widget | None = None, 161 ): 162 classic = bui.app.classic 163 assert classic is not None 164 ui = bui.app.ui_v1 165 app = bui.app 166 self._quit_type = quit_type 167 168 # If there's already one of us up somewhere, kill it. 169 if ui.quit_window is not None: 170 ui.quit_window.delete() 171 ui.quit_window = None 172 if swish: 173 bui.getsound('swish').play() 174 175 if app.classic is None: 176 if bui.do_once(): 177 logging.warning( 178 'QuitWindow needs to be updated to work without classic.' 179 ) 180 quit_resource = 'exitGameText' 181 else: 182 quit_resource = ( 183 'quitGameText' 184 if app.classic.platform == 'mac' 185 else 'exitGameText' 186 ) 187 self._root_widget = ui.quit_window = ConfirmWindow( 188 bui.Lstr( 189 resource=quit_resource, 190 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 191 ), 192 lambda: ( 193 bui.quit(confirm=False, quit_type=self._quit_type) 194 if self._quit_type is not None 195 else bui.quit(confirm=False) 196 ), 197 origin_widget=origin_widget, 198 ).root_widget
Popup window to confirm quitting.
QuitWindow( quit_type: babase.QuitType | None = None, swish: bool = False, origin_widget: _bauiv1.Widget | None = None)
156 def __init__( 157 self, 158 quit_type: bui.QuitType | None = None, 159 swish: bool = False, 160 origin_widget: bui.Widget | None = None, 161 ): 162 classic = bui.app.classic 163 assert classic is not None 164 ui = bui.app.ui_v1 165 app = bui.app 166 self._quit_type = quit_type 167 168 # If there's already one of us up somewhere, kill it. 169 if ui.quit_window is not None: 170 ui.quit_window.delete() 171 ui.quit_window = None 172 if swish: 173 bui.getsound('swish').play() 174 175 if app.classic is None: 176 if bui.do_once(): 177 logging.warning( 178 'QuitWindow needs to be updated to work without classic.' 179 ) 180 quit_resource = 'exitGameText' 181 else: 182 quit_resource = ( 183 'quitGameText' 184 if app.classic.platform == 'mac' 185 else 'exitGameText' 186 ) 187 self._root_widget = ui.quit_window = ConfirmWindow( 188 bui.Lstr( 189 resource=quit_resource, 190 subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], 191 ), 192 lambda: ( 193 bui.quit(confirm=False, quit_type=self._quit_type) 194 if self._quit_type is not None 195 else bui.quit(confirm=False) 196 ), 197 origin_widget=origin_widget, 198 ).root_widget