bauiv1lib.settings.testing
Provides UI for test settings.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides UI for test settings.""" 4 5from __future__ import annotations 6 7import copy 8from typing import TYPE_CHECKING, override 9 10import bauiv1 as bui 11 12if TYPE_CHECKING: 13 from typing import Any, Callable 14 15 16class TestingWindow(bui.MainWindow): 17 """Window for conveniently testing various settings.""" 18 19 def __init__( 20 self, 21 title: bui.Lstr, 22 entries: list[dict[str, Any]], 23 transition: str | None = 'in_right', 24 origin_widget: bui.Widget | None = None, 25 ): 26 # pylint: disable=too-many-locals 27 assert bui.app.classic is not None 28 uiscale = bui.app.ui_v1.uiscale 29 self._width = 1200 if uiscale is bui.UIScale.SMALL else 600 30 self._height = 800 if uiscale is bui.UIScale.SMALL else 400 31 self._entries_orig = copy.deepcopy(entries) 32 self._entries = copy.deepcopy(entries) 33 34 # Do some fancy math to fill all available screen area up to the 35 # size of our backing container. This lets us fit to the exact 36 # screen shape at small ui scale. 37 screensize = bui.get_virtual_screen_size() 38 scale = ( 39 2.27 40 if uiscale is bui.UIScale.SMALL 41 else 1.2 if uiscale is bui.UIScale.MEDIUM else 1.0 42 ) 43 # Calc screen size in our local container space and clamp to a 44 # bit smaller than our container size. 45 target_width = min(self._width - 60, screensize[0] / scale) 46 target_height = min(self._height - 70, screensize[1] / scale) 47 48 # To get top/left coords, go to the center of our window and 49 # offset by half the width/height of our target area. 50 yoffs = 0.5 * self._height + 0.5 * target_height + 30.0 51 52 self._scroll_width = target_width 53 self._scroll_height = target_height - 47 54 self._scroll_bottom = yoffs - 78 - self._scroll_height 55 56 super().__init__( 57 root_widget=bui.containerwidget( 58 size=(self._width, self._height), 59 scale=scale, 60 toolbar_visibility=( 61 'menu_minimal' 62 if uiscale is bui.UIScale.SMALL 63 else 'menu_full' 64 ), 65 ), 66 transition=transition, 67 origin_widget=origin_widget, 68 # We're affected by screen size only at small ui-scale. 69 refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL, 70 ) 71 72 if uiscale is bui.UIScale.SMALL: 73 self._back_button = bui.get_special_widget('back_button') 74 bui.containerwidget( 75 edit=self._root_widget, on_cancel_call=self.main_window_back 76 ) 77 else: 78 self._back_button = btn = bui.buttonwidget( 79 parent=self._root_widget, 80 autoselect=True, 81 position=(35, yoffs - 59), 82 size=(60, 60), 83 scale=0.8, 84 text_scale=1.2, 85 label=bui.charstr(bui.SpecialChar.BACK), 86 button_type='backSmall', 87 on_activate_call=self.main_window_back, 88 ) 89 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 90 91 self.title = title 92 bui.textwidget( 93 parent=self._root_widget, 94 position=( 95 self._width * 0.5, 96 yoffs - (43 if uiscale is bui.UIScale.SMALL else 35), 97 ), 98 size=(0, 0), 99 scale=0.7 if uiscale is bui.UIScale.SMALL else 1.0, 100 color=bui.app.ui_v1.title_color, 101 h_align='center', 102 v_align='center', 103 maxwidth=245, 104 text=self.title, 105 ) 106 107 bui.textwidget( 108 parent=self._root_widget, 109 position=( 110 self._width * 0.5, 111 yoffs - 65, 112 ), 113 size=(0, 0), 114 scale=0.5, 115 color=bui.app.ui_v1.infotextcolor, 116 h_align='center', 117 v_align='center', 118 maxwidth=self._scroll_width * 0.75, 119 text=bui.Lstr(resource='settingsWindowAdvanced.forTestingText'), 120 ) 121 self._scrollwidget = bui.scrollwidget( 122 parent=self._root_widget, 123 size=(self._scroll_width, self._scroll_height), 124 position=( 125 self._width * 0.5 - self._scroll_width * 0.5, 126 self._scroll_bottom, 127 ), 128 highlight=False, 129 border_opacity=0.4, 130 ) 131 bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) 132 133 self._spacing = 50 134 135 self._sub_width = self._scroll_width * 0.95 136 self._sub_height = 50 + len(self._entries) * self._spacing + 60 137 self._subcontainer = bui.containerwidget( 138 parent=self._scrollwidget, 139 size=(self._sub_width, self._sub_height), 140 background=False, 141 ) 142 143 h = 230 144 v = self._sub_height - 48 145 146 for i, entry in enumerate(self._entries): 147 entry_name = entry['name'] 148 149 # If we haven't yet, record the default value for this name 150 # so we can reset if we want.. 151 if entry_name not in bui.app.classic.value_test_defaults: 152 bui.app.classic.value_test_defaults[entry_name] = ( 153 bui.app.classic.value_test(entry_name) 154 ) 155 156 bui.textwidget( 157 parent=self._subcontainer, 158 position=(h, v), 159 size=(0, 0), 160 h_align='right', 161 v_align='center', 162 maxwidth=200, 163 text=entry['label'], 164 ) 165 btn = bui.buttonwidget( 166 parent=self._subcontainer, 167 position=(h + 20, v - 19), 168 size=(40, 40), 169 autoselect=True, 170 repeat=True, 171 left_widget=self._back_button, 172 button_type='square', 173 label='-', 174 on_activate_call=bui.Call(self._on_minus_press, entry['name']), 175 ) 176 if i == 0: 177 bui.widget(edit=btn, up_widget=self._back_button) 178 entry['widget'] = bui.textwidget( 179 parent=self._subcontainer, 180 position=(h + 100, v), 181 size=(0, 0), 182 h_align='center', 183 v_align='center', 184 maxwidth=60, 185 text=f'{bui.app.classic.value_test(entry_name):.4g}', 186 ) 187 btn = bui.buttonwidget( 188 parent=self._subcontainer, 189 position=(h + 140, v - 19), 190 size=(40, 40), 191 autoselect=True, 192 repeat=True, 193 button_type='square', 194 label='+', 195 on_activate_call=bui.Call(self._on_plus_press, entry['name']), 196 ) 197 if i == 0: 198 bui.widget(edit=btn, up_widget=self._back_button) 199 v -= self._spacing 200 v -= 35 201 bui.buttonwidget( 202 parent=self._subcontainer, 203 autoselect=True, 204 size=(200, 50), 205 position=(self._sub_width * 0.5 - 100, v), 206 label=bui.Lstr(resource='settingsWindowAdvanced.resetText'), 207 right_widget=btn, 208 on_activate_call=self._on_reset_press, 209 ) 210 211 def _get_entry(self, name: str) -> dict[str, Any]: 212 for entry in self._entries: 213 if entry['name'] == name: 214 return entry 215 raise bui.NotFoundError(f'Entry not found: {name}') 216 217 def _on_reset_press(self) -> None: 218 assert bui.app.classic is not None 219 for entry in self._entries: 220 bui.app.classic.value_test( 221 entry['name'], 222 absolute=bui.app.classic.value_test_defaults[entry['name']], 223 ) 224 bui.textwidget( 225 edit=entry['widget'], 226 text=f'{bui.app.classic.value_test(entry['name']):.4g}', 227 ) 228 229 def _on_minus_press(self, entry_name: str) -> None: 230 assert bui.app.classic is not None 231 entry = self._get_entry(entry_name) 232 bui.app.classic.value_test(entry['name'], change=-entry['increment']) 233 # pylint: disable=consider-using-f-string 234 bui.textwidget( 235 edit=entry['widget'], 236 text='%.4g' % bui.app.classic.value_test(entry['name']), 237 ) 238 239 def _on_plus_press(self, entry_name: str) -> None: 240 assert bui.app.classic is not None 241 entry = self._get_entry(entry_name) 242 bui.app.classic.value_test(entry['name'], change=entry['increment']) 243 # pylint: disable=consider-using-f-string 244 bui.textwidget( 245 edit=entry['widget'], 246 text='%.4g' % bui.app.classic.value_test(entry['name']), 247 ) 248 249 @override 250 def get_main_window_state(self) -> bui.MainWindowState: 251 # Support recreating our window for back/refresh purposes. 252 cls = type(self) 253 254 # Pull values from self here; if we do it in the lambda we'll 255 # keep self alive which we don't want. 256 title = self.title 257 entries = self._entries_orig 258 259 return bui.BasicMainWindowState( 260 create_call=lambda transition, origin_widget: cls( 261 title=title, 262 entries=entries, 263 transition=transition, 264 origin_widget=origin_widget, 265 ) 266 )
class
TestingWindow(bauiv1._uitypes.MainWindow):
17class TestingWindow(bui.MainWindow): 18 """Window for conveniently testing various settings.""" 19 20 def __init__( 21 self, 22 title: bui.Lstr, 23 entries: list[dict[str, Any]], 24 transition: str | None = 'in_right', 25 origin_widget: bui.Widget | None = None, 26 ): 27 # pylint: disable=too-many-locals 28 assert bui.app.classic is not None 29 uiscale = bui.app.ui_v1.uiscale 30 self._width = 1200 if uiscale is bui.UIScale.SMALL else 600 31 self._height = 800 if uiscale is bui.UIScale.SMALL else 400 32 self._entries_orig = copy.deepcopy(entries) 33 self._entries = copy.deepcopy(entries) 34 35 # Do some fancy math to fill all available screen area up to the 36 # size of our backing container. This lets us fit to the exact 37 # screen shape at small ui scale. 38 screensize = bui.get_virtual_screen_size() 39 scale = ( 40 2.27 41 if uiscale is bui.UIScale.SMALL 42 else 1.2 if uiscale is bui.UIScale.MEDIUM else 1.0 43 ) 44 # Calc screen size in our local container space and clamp to a 45 # bit smaller than our container size. 46 target_width = min(self._width - 60, screensize[0] / scale) 47 target_height = min(self._height - 70, screensize[1] / scale) 48 49 # To get top/left coords, go to the center of our window and 50 # offset by half the width/height of our target area. 51 yoffs = 0.5 * self._height + 0.5 * target_height + 30.0 52 53 self._scroll_width = target_width 54 self._scroll_height = target_height - 47 55 self._scroll_bottom = yoffs - 78 - self._scroll_height 56 57 super().__init__( 58 root_widget=bui.containerwidget( 59 size=(self._width, self._height), 60 scale=scale, 61 toolbar_visibility=( 62 'menu_minimal' 63 if uiscale is bui.UIScale.SMALL 64 else 'menu_full' 65 ), 66 ), 67 transition=transition, 68 origin_widget=origin_widget, 69 # We're affected by screen size only at small ui-scale. 70 refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL, 71 ) 72 73 if uiscale is bui.UIScale.SMALL: 74 self._back_button = bui.get_special_widget('back_button') 75 bui.containerwidget( 76 edit=self._root_widget, on_cancel_call=self.main_window_back 77 ) 78 else: 79 self._back_button = btn = bui.buttonwidget( 80 parent=self._root_widget, 81 autoselect=True, 82 position=(35, yoffs - 59), 83 size=(60, 60), 84 scale=0.8, 85 text_scale=1.2, 86 label=bui.charstr(bui.SpecialChar.BACK), 87 button_type='backSmall', 88 on_activate_call=self.main_window_back, 89 ) 90 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 91 92 self.title = title 93 bui.textwidget( 94 parent=self._root_widget, 95 position=( 96 self._width * 0.5, 97 yoffs - (43 if uiscale is bui.UIScale.SMALL else 35), 98 ), 99 size=(0, 0), 100 scale=0.7 if uiscale is bui.UIScale.SMALL else 1.0, 101 color=bui.app.ui_v1.title_color, 102 h_align='center', 103 v_align='center', 104 maxwidth=245, 105 text=self.title, 106 ) 107 108 bui.textwidget( 109 parent=self._root_widget, 110 position=( 111 self._width * 0.5, 112 yoffs - 65, 113 ), 114 size=(0, 0), 115 scale=0.5, 116 color=bui.app.ui_v1.infotextcolor, 117 h_align='center', 118 v_align='center', 119 maxwidth=self._scroll_width * 0.75, 120 text=bui.Lstr(resource='settingsWindowAdvanced.forTestingText'), 121 ) 122 self._scrollwidget = bui.scrollwidget( 123 parent=self._root_widget, 124 size=(self._scroll_width, self._scroll_height), 125 position=( 126 self._width * 0.5 - self._scroll_width * 0.5, 127 self._scroll_bottom, 128 ), 129 highlight=False, 130 border_opacity=0.4, 131 ) 132 bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) 133 134 self._spacing = 50 135 136 self._sub_width = self._scroll_width * 0.95 137 self._sub_height = 50 + len(self._entries) * self._spacing + 60 138 self._subcontainer = bui.containerwidget( 139 parent=self._scrollwidget, 140 size=(self._sub_width, self._sub_height), 141 background=False, 142 ) 143 144 h = 230 145 v = self._sub_height - 48 146 147 for i, entry in enumerate(self._entries): 148 entry_name = entry['name'] 149 150 # If we haven't yet, record the default value for this name 151 # so we can reset if we want.. 152 if entry_name not in bui.app.classic.value_test_defaults: 153 bui.app.classic.value_test_defaults[entry_name] = ( 154 bui.app.classic.value_test(entry_name) 155 ) 156 157 bui.textwidget( 158 parent=self._subcontainer, 159 position=(h, v), 160 size=(0, 0), 161 h_align='right', 162 v_align='center', 163 maxwidth=200, 164 text=entry['label'], 165 ) 166 btn = bui.buttonwidget( 167 parent=self._subcontainer, 168 position=(h + 20, v - 19), 169 size=(40, 40), 170 autoselect=True, 171 repeat=True, 172 left_widget=self._back_button, 173 button_type='square', 174 label='-', 175 on_activate_call=bui.Call(self._on_minus_press, entry['name']), 176 ) 177 if i == 0: 178 bui.widget(edit=btn, up_widget=self._back_button) 179 entry['widget'] = bui.textwidget( 180 parent=self._subcontainer, 181 position=(h + 100, v), 182 size=(0, 0), 183 h_align='center', 184 v_align='center', 185 maxwidth=60, 186 text=f'{bui.app.classic.value_test(entry_name):.4g}', 187 ) 188 btn = bui.buttonwidget( 189 parent=self._subcontainer, 190 position=(h + 140, v - 19), 191 size=(40, 40), 192 autoselect=True, 193 repeat=True, 194 button_type='square', 195 label='+', 196 on_activate_call=bui.Call(self._on_plus_press, entry['name']), 197 ) 198 if i == 0: 199 bui.widget(edit=btn, up_widget=self._back_button) 200 v -= self._spacing 201 v -= 35 202 bui.buttonwidget( 203 parent=self._subcontainer, 204 autoselect=True, 205 size=(200, 50), 206 position=(self._sub_width * 0.5 - 100, v), 207 label=bui.Lstr(resource='settingsWindowAdvanced.resetText'), 208 right_widget=btn, 209 on_activate_call=self._on_reset_press, 210 ) 211 212 def _get_entry(self, name: str) -> dict[str, Any]: 213 for entry in self._entries: 214 if entry['name'] == name: 215 return entry 216 raise bui.NotFoundError(f'Entry not found: {name}') 217 218 def _on_reset_press(self) -> None: 219 assert bui.app.classic is not None 220 for entry in self._entries: 221 bui.app.classic.value_test( 222 entry['name'], 223 absolute=bui.app.classic.value_test_defaults[entry['name']], 224 ) 225 bui.textwidget( 226 edit=entry['widget'], 227 text=f'{bui.app.classic.value_test(entry['name']):.4g}', 228 ) 229 230 def _on_minus_press(self, entry_name: str) -> None: 231 assert bui.app.classic is not None 232 entry = self._get_entry(entry_name) 233 bui.app.classic.value_test(entry['name'], change=-entry['increment']) 234 # pylint: disable=consider-using-f-string 235 bui.textwidget( 236 edit=entry['widget'], 237 text='%.4g' % bui.app.classic.value_test(entry['name']), 238 ) 239 240 def _on_plus_press(self, entry_name: str) -> None: 241 assert bui.app.classic is not None 242 entry = self._get_entry(entry_name) 243 bui.app.classic.value_test(entry['name'], change=entry['increment']) 244 # pylint: disable=consider-using-f-string 245 bui.textwidget( 246 edit=entry['widget'], 247 text='%.4g' % bui.app.classic.value_test(entry['name']), 248 ) 249 250 @override 251 def get_main_window_state(self) -> bui.MainWindowState: 252 # Support recreating our window for back/refresh purposes. 253 cls = type(self) 254 255 # Pull values from self here; if we do it in the lambda we'll 256 # keep self alive which we don't want. 257 title = self.title 258 entries = self._entries_orig 259 260 return bui.BasicMainWindowState( 261 create_call=lambda transition, origin_widget: cls( 262 title=title, 263 entries=entries, 264 transition=transition, 265 origin_widget=origin_widget, 266 ) 267 )
Window for conveniently testing various settings.
TestingWindow( title: babase.Lstr, entries: list[dict[str, typing.Any]], transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
20 def __init__( 21 self, 22 title: bui.Lstr, 23 entries: list[dict[str, Any]], 24 transition: str | None = 'in_right', 25 origin_widget: bui.Widget | None = None, 26 ): 27 # pylint: disable=too-many-locals 28 assert bui.app.classic is not None 29 uiscale = bui.app.ui_v1.uiscale 30 self._width = 1200 if uiscale is bui.UIScale.SMALL else 600 31 self._height = 800 if uiscale is bui.UIScale.SMALL else 400 32 self._entries_orig = copy.deepcopy(entries) 33 self._entries = copy.deepcopy(entries) 34 35 # Do some fancy math to fill all available screen area up to the 36 # size of our backing container. This lets us fit to the exact 37 # screen shape at small ui scale. 38 screensize = bui.get_virtual_screen_size() 39 scale = ( 40 2.27 41 if uiscale is bui.UIScale.SMALL 42 else 1.2 if uiscale is bui.UIScale.MEDIUM else 1.0 43 ) 44 # Calc screen size in our local container space and clamp to a 45 # bit smaller than our container size. 46 target_width = min(self._width - 60, screensize[0] / scale) 47 target_height = min(self._height - 70, screensize[1] / scale) 48 49 # To get top/left coords, go to the center of our window and 50 # offset by half the width/height of our target area. 51 yoffs = 0.5 * self._height + 0.5 * target_height + 30.0 52 53 self._scroll_width = target_width 54 self._scroll_height = target_height - 47 55 self._scroll_bottom = yoffs - 78 - self._scroll_height 56 57 super().__init__( 58 root_widget=bui.containerwidget( 59 size=(self._width, self._height), 60 scale=scale, 61 toolbar_visibility=( 62 'menu_minimal' 63 if uiscale is bui.UIScale.SMALL 64 else 'menu_full' 65 ), 66 ), 67 transition=transition, 68 origin_widget=origin_widget, 69 # We're affected by screen size only at small ui-scale. 70 refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL, 71 ) 72 73 if uiscale is bui.UIScale.SMALL: 74 self._back_button = bui.get_special_widget('back_button') 75 bui.containerwidget( 76 edit=self._root_widget, on_cancel_call=self.main_window_back 77 ) 78 else: 79 self._back_button = btn = bui.buttonwidget( 80 parent=self._root_widget, 81 autoselect=True, 82 position=(35, yoffs - 59), 83 size=(60, 60), 84 scale=0.8, 85 text_scale=1.2, 86 label=bui.charstr(bui.SpecialChar.BACK), 87 button_type='backSmall', 88 on_activate_call=self.main_window_back, 89 ) 90 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 91 92 self.title = title 93 bui.textwidget( 94 parent=self._root_widget, 95 position=( 96 self._width * 0.5, 97 yoffs - (43 if uiscale is bui.UIScale.SMALL else 35), 98 ), 99 size=(0, 0), 100 scale=0.7 if uiscale is bui.UIScale.SMALL else 1.0, 101 color=bui.app.ui_v1.title_color, 102 h_align='center', 103 v_align='center', 104 maxwidth=245, 105 text=self.title, 106 ) 107 108 bui.textwidget( 109 parent=self._root_widget, 110 position=( 111 self._width * 0.5, 112 yoffs - 65, 113 ), 114 size=(0, 0), 115 scale=0.5, 116 color=bui.app.ui_v1.infotextcolor, 117 h_align='center', 118 v_align='center', 119 maxwidth=self._scroll_width * 0.75, 120 text=bui.Lstr(resource='settingsWindowAdvanced.forTestingText'), 121 ) 122 self._scrollwidget = bui.scrollwidget( 123 parent=self._root_widget, 124 size=(self._scroll_width, self._scroll_height), 125 position=( 126 self._width * 0.5 - self._scroll_width * 0.5, 127 self._scroll_bottom, 128 ), 129 highlight=False, 130 border_opacity=0.4, 131 ) 132 bui.containerwidget(edit=self._scrollwidget, claims_left_right=True) 133 134 self._spacing = 50 135 136 self._sub_width = self._scroll_width * 0.95 137 self._sub_height = 50 + len(self._entries) * self._spacing + 60 138 self._subcontainer = bui.containerwidget( 139 parent=self._scrollwidget, 140 size=(self._sub_width, self._sub_height), 141 background=False, 142 ) 143 144 h = 230 145 v = self._sub_height - 48 146 147 for i, entry in enumerate(self._entries): 148 entry_name = entry['name'] 149 150 # If we haven't yet, record the default value for this name 151 # so we can reset if we want.. 152 if entry_name not in bui.app.classic.value_test_defaults: 153 bui.app.classic.value_test_defaults[entry_name] = ( 154 bui.app.classic.value_test(entry_name) 155 ) 156 157 bui.textwidget( 158 parent=self._subcontainer, 159 position=(h, v), 160 size=(0, 0), 161 h_align='right', 162 v_align='center', 163 maxwidth=200, 164 text=entry['label'], 165 ) 166 btn = bui.buttonwidget( 167 parent=self._subcontainer, 168 position=(h + 20, v - 19), 169 size=(40, 40), 170 autoselect=True, 171 repeat=True, 172 left_widget=self._back_button, 173 button_type='square', 174 label='-', 175 on_activate_call=bui.Call(self._on_minus_press, entry['name']), 176 ) 177 if i == 0: 178 bui.widget(edit=btn, up_widget=self._back_button) 179 entry['widget'] = bui.textwidget( 180 parent=self._subcontainer, 181 position=(h + 100, v), 182 size=(0, 0), 183 h_align='center', 184 v_align='center', 185 maxwidth=60, 186 text=f'{bui.app.classic.value_test(entry_name):.4g}', 187 ) 188 btn = bui.buttonwidget( 189 parent=self._subcontainer, 190 position=(h + 140, v - 19), 191 size=(40, 40), 192 autoselect=True, 193 repeat=True, 194 button_type='square', 195 label='+', 196 on_activate_call=bui.Call(self._on_plus_press, entry['name']), 197 ) 198 if i == 0: 199 bui.widget(edit=btn, up_widget=self._back_button) 200 v -= self._spacing 201 v -= 35 202 bui.buttonwidget( 203 parent=self._subcontainer, 204 autoselect=True, 205 size=(200, 50), 206 position=(self._sub_width * 0.5 - 100, v), 207 label=bui.Lstr(resource='settingsWindowAdvanced.resetText'), 208 right_widget=btn, 209 on_activate_call=self._on_reset_press, 210 )
Create a MainWindow given a root widget and transition info.
Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.
250 @override 251 def get_main_window_state(self) -> bui.MainWindowState: 252 # Support recreating our window for back/refresh purposes. 253 cls = type(self) 254 255 # Pull values from self here; if we do it in the lambda we'll 256 # keep self alive which we don't want. 257 title = self.title 258 entries = self._entries_orig 259 260 return bui.BasicMainWindowState( 261 create_call=lambda transition, origin_widget: cls( 262 title=title, 263 entries=entries, 264 transition=transition, 265 origin_widget=origin_widget, 266 ) 267 )
Return a WindowState to recreate this window, if supported.