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