bauiv1lib.store.button
UI functionality for a button leading to the store.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI functionality for a button leading to the store.""" 4from __future__ import annotations 5 6import logging 7from typing import TYPE_CHECKING 8 9from efro.util import utc_now 10 11import bauiv1 as bui 12 13if TYPE_CHECKING: 14 from typing import Any, Sequence, Callable 15 16 17class StoreButton: 18 """A button leading to the store.""" 19 20 def __init__( 21 self, 22 parent: bui.Widget, 23 position: Sequence[float], 24 size: Sequence[float], 25 scale: float, 26 *, 27 on_activate_call: Callable[[], Any] | None = None, 28 transition_delay: float | None = None, 29 color: Sequence[float] | None = None, 30 textcolor: Sequence[float] | None = None, 31 show_tickets: bool = False, 32 button_type: str | None = None, 33 sale_scale: float = 1.0, 34 ): 35 self._position = position 36 self._size = size 37 self._scale = scale 38 39 if on_activate_call is None: 40 on_activate_call = bui.WeakCall(self._default_on_activate_call) 41 self._on_activate_call = on_activate_call 42 43 self._button = bui.buttonwidget( 44 parent=parent, 45 size=size, 46 label='' if show_tickets else bui.Lstr(resource='storeText'), 47 scale=scale, 48 autoselect=True, 49 on_activate_call=self._on_activate, 50 transition_delay=transition_delay, 51 color=color, 52 button_type=button_type, 53 ) 54 55 self._title_text: bui.Widget | None 56 self._ticket_text: bui.Widget | None 57 58 if show_tickets: 59 self._title_text = bui.textwidget( 60 parent=parent, 61 position=( 62 position[0] + size[0] * 0.5 * scale, 63 position[1] + size[1] * 0.65 * scale, 64 ), 65 size=(0, 0), 66 h_align='center', 67 v_align='center', 68 maxwidth=size[0] * scale * 0.65, 69 text=bui.Lstr(resource='storeText'), 70 draw_controller=self._button, 71 scale=scale, 72 transition_delay=transition_delay, 73 color=textcolor, 74 ) 75 self._ticket_text = bui.textwidget( 76 parent=parent, 77 size=(0, 0), 78 h_align='center', 79 v_align='center', 80 maxwidth=size[0] * scale * 0.85, 81 text='', 82 color=(0.2, 1.0, 0.2), 83 flatness=1.0, 84 shadow=0.0, 85 scale=scale * 0.6, 86 transition_delay=transition_delay, 87 ) 88 else: 89 self._title_text = None 90 self._ticket_text = None 91 92 self._circle_rad = 12 * scale 93 self._circle_center = (0.0, 0.0) 94 self._sale_circle_center = (0.0, 0.0) 95 96 self._available_purchase_backing = bui.imagewidget( 97 parent=parent, 98 color=(1, 0, 0), 99 draw_controller=self._button, 100 size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), 101 texture=bui.gettexture('circleShadow'), 102 transition_delay=transition_delay, 103 ) 104 self._available_purchase_text = bui.textwidget( 105 parent=parent, 106 size=(0, 0), 107 h_align='center', 108 v_align='center', 109 text='', 110 draw_controller=self._button, 111 color=(1, 1, 1), 112 flatness=1.0, 113 shadow=1.0, 114 scale=0.6 * scale, 115 maxwidth=self._circle_rad * 1.4, 116 transition_delay=transition_delay, 117 ) 118 119 self._sale_circle_rad = 18 * scale * sale_scale 120 self._sale_backing = bui.imagewidget( 121 parent=parent, 122 color=(0.5, 0, 1.0), 123 draw_controller=self._button, 124 size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), 125 texture=bui.gettexture('circleZigZag'), 126 transition_delay=transition_delay, 127 ) 128 self._sale_title_text = bui.textwidget( 129 parent=parent, 130 size=(0, 0), 131 h_align='center', 132 v_align='center', 133 draw_controller=self._button, 134 color=(0, 1, 0), 135 flatness=1.0, 136 shadow=0.0, 137 scale=0.5 * scale * sale_scale, 138 maxwidth=self._sale_circle_rad * 1.5, 139 transition_delay=transition_delay, 140 ) 141 self._sale_time_text = bui.textwidget( 142 parent=parent, 143 size=(0, 0), 144 h_align='center', 145 v_align='center', 146 draw_controller=self._button, 147 color=(0, 1, 0), 148 flatness=1.0, 149 shadow=0.0, 150 scale=0.4 * scale * sale_scale, 151 maxwidth=self._sale_circle_rad * 1.5, 152 transition_delay=transition_delay, 153 ) 154 155 self.set_position(position) 156 self._update_timer = bui.AppTimer( 157 1.0, bui.WeakCall(self._update), repeat=True 158 ) 159 self._update() 160 161 def _on_activate(self) -> None: 162 bui.increment_analytics_count('Store button press') 163 self._on_activate_call() 164 165 def set_position(self, position: Sequence[float]) -> None: 166 """Set the button position.""" 167 self._position = position 168 self._circle_center = ( 169 position[0] + 0.1 * self._size[0] * self._scale, 170 position[1] + self._size[1] * self._scale * 0.8, 171 ) 172 self._sale_circle_center = ( 173 position[0] + 0.07 * self._size[0] * self._scale, 174 position[1] + self._size[1] * self._scale * 0.8, 175 ) 176 177 if not self._button: 178 return 179 bui.buttonwidget(edit=self._button, position=self._position) 180 if self._title_text is not None: 181 bui.textwidget( 182 edit=self._title_text, 183 position=( 184 self._position[0] + self._size[0] * 0.5 * self._scale, 185 self._position[1] + self._size[1] * 0.65 * self._scale, 186 ), 187 ) 188 if self._ticket_text is not None: 189 bui.textwidget( 190 edit=self._ticket_text, 191 position=( 192 position[0] + self._size[0] * 0.5 * self._scale, 193 position[1] + self._size[1] * 0.28 * self._scale, 194 ), 195 size=(0, 0), 196 ) 197 bui.imagewidget( 198 edit=self._available_purchase_backing, 199 position=( 200 self._circle_center[0] - self._circle_rad * 1.02, 201 self._circle_center[1] - self._circle_rad * 1.13, 202 ), 203 ) 204 bui.textwidget( 205 edit=self._available_purchase_text, position=self._circle_center 206 ) 207 208 bui.imagewidget( 209 edit=self._sale_backing, 210 position=( 211 self._sale_circle_center[0] - self._sale_circle_rad, 212 self._sale_circle_center[1] - self._sale_circle_rad, 213 ), 214 ) 215 bui.textwidget( 216 edit=self._sale_title_text, 217 position=( 218 self._sale_circle_center[0], 219 self._sale_circle_center[1] + self._sale_circle_rad * 0.3, 220 ), 221 ) 222 bui.textwidget( 223 edit=self._sale_time_text, 224 position=( 225 self._sale_circle_center[0], 226 self._sale_circle_center[1] - self._sale_circle_rad * 0.3, 227 ), 228 ) 229 230 def _default_on_activate_call(self) -> None: 231 # pylint: disable=cyclic-import 232 from bauiv1lib.account import show_sign_in_prompt 233 234 # from bauiv1lib.store.browser import StoreBrowserWindow 235 236 plus = bui.app.plus 237 assert plus is not None 238 if plus.get_v1_account_state() != 'signed_in': 239 show_sign_in_prompt() 240 return 241 242 raise RuntimeError('no longer wired up') 243 244 # StoreBrowserWindow(modal=True, origin_widget=self._button) 245 246 def get_button(self) -> bui.Widget: 247 """Return the underlying button widget.""" 248 return self._button 249 250 def _update(self) -> None: 251 # pylint: disable=too-many-branches 252 # pylint: disable=cyclic-import 253 from babase import SpecialChar 254 255 plus = bui.app.plus 256 assert plus is not None 257 assert bui.app.classic is not None 258 store = bui.app.classic.store 259 260 if not self._button: 261 return # Our instance may outlive our UI objects. 262 263 if self._ticket_text is not None: 264 if plus.get_v1_account_state() == 'signed_in': 265 sval = bui.charstr(SpecialChar.TICKET) + str( 266 plus.get_v1_account_ticket_count() 267 ) 268 else: 269 sval = '-' 270 bui.textwidget(edit=self._ticket_text, text=sval) 271 available_purchases = store.get_available_purchase_count() 272 273 # Old pro sale stuff.. 274 sale_time = store.get_available_sale_time('extras') 275 276 # ..also look for new style sales. 277 if sale_time is None: 278 import datetime 279 280 sales_raw = plus.get_v1_account_misc_read_val('sales', {}) 281 sale_times = [] 282 try: 283 # Look at the current set of sales; filter any with time 284 # remaining that we don't own. 285 for sale_item, sale_info in list(sales_raw.items()): 286 if not plus.get_v1_account_product_purchased(sale_item): 287 to_end = ( 288 datetime.datetime.fromtimestamp( 289 sale_info['e'], datetime.UTC 290 ) 291 - utc_now() 292 ).total_seconds() 293 if to_end > 0: 294 sale_times.append(to_end) 295 except Exception: 296 logging.exception('Error parsing sales.') 297 if sale_times: 298 sale_time = int(min(sale_times) * 1000) 299 300 if sale_time is not None: 301 bui.textwidget( 302 edit=self._sale_title_text, 303 text=bui.Lstr(resource='store.saleText'), 304 ) 305 bui.textwidget( 306 edit=self._sale_time_text, 307 text=bui.timestring(sale_time / 1000.0, centi=False), 308 ) 309 bui.imagewidget(edit=self._sale_backing, opacity=1.0) 310 bui.imagewidget(edit=self._available_purchase_backing, opacity=1.0) 311 bui.textwidget(edit=self._available_purchase_text, text='') 312 bui.imagewidget(edit=self._available_purchase_backing, opacity=0.0) 313 else: 314 bui.imagewidget(edit=self._sale_backing, opacity=0.0) 315 bui.textwidget(edit=self._sale_time_text, text='') 316 bui.textwidget(edit=self._sale_title_text, text='') 317 if available_purchases > 0: 318 bui.textwidget( 319 edit=self._available_purchase_text, 320 text=str(available_purchases), 321 ) 322 bui.imagewidget( 323 edit=self._available_purchase_backing, opacity=1.0 324 ) 325 else: 326 bui.textwidget(edit=self._available_purchase_text, text='') 327 bui.imagewidget( 328 edit=self._available_purchase_backing, opacity=0.0 329 )
class
StoreButton:
18class StoreButton: 19 """A button leading to the store.""" 20 21 def __init__( 22 self, 23 parent: bui.Widget, 24 position: Sequence[float], 25 size: Sequence[float], 26 scale: float, 27 *, 28 on_activate_call: Callable[[], Any] | None = None, 29 transition_delay: float | None = None, 30 color: Sequence[float] | None = None, 31 textcolor: Sequence[float] | None = None, 32 show_tickets: bool = False, 33 button_type: str | None = None, 34 sale_scale: float = 1.0, 35 ): 36 self._position = position 37 self._size = size 38 self._scale = scale 39 40 if on_activate_call is None: 41 on_activate_call = bui.WeakCall(self._default_on_activate_call) 42 self._on_activate_call = on_activate_call 43 44 self._button = bui.buttonwidget( 45 parent=parent, 46 size=size, 47 label='' if show_tickets else bui.Lstr(resource='storeText'), 48 scale=scale, 49 autoselect=True, 50 on_activate_call=self._on_activate, 51 transition_delay=transition_delay, 52 color=color, 53 button_type=button_type, 54 ) 55 56 self._title_text: bui.Widget | None 57 self._ticket_text: bui.Widget | None 58 59 if show_tickets: 60 self._title_text = bui.textwidget( 61 parent=parent, 62 position=( 63 position[0] + size[0] * 0.5 * scale, 64 position[1] + size[1] * 0.65 * scale, 65 ), 66 size=(0, 0), 67 h_align='center', 68 v_align='center', 69 maxwidth=size[0] * scale * 0.65, 70 text=bui.Lstr(resource='storeText'), 71 draw_controller=self._button, 72 scale=scale, 73 transition_delay=transition_delay, 74 color=textcolor, 75 ) 76 self._ticket_text = bui.textwidget( 77 parent=parent, 78 size=(0, 0), 79 h_align='center', 80 v_align='center', 81 maxwidth=size[0] * scale * 0.85, 82 text='', 83 color=(0.2, 1.0, 0.2), 84 flatness=1.0, 85 shadow=0.0, 86 scale=scale * 0.6, 87 transition_delay=transition_delay, 88 ) 89 else: 90 self._title_text = None 91 self._ticket_text = None 92 93 self._circle_rad = 12 * scale 94 self._circle_center = (0.0, 0.0) 95 self._sale_circle_center = (0.0, 0.0) 96 97 self._available_purchase_backing = bui.imagewidget( 98 parent=parent, 99 color=(1, 0, 0), 100 draw_controller=self._button, 101 size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), 102 texture=bui.gettexture('circleShadow'), 103 transition_delay=transition_delay, 104 ) 105 self._available_purchase_text = bui.textwidget( 106 parent=parent, 107 size=(0, 0), 108 h_align='center', 109 v_align='center', 110 text='', 111 draw_controller=self._button, 112 color=(1, 1, 1), 113 flatness=1.0, 114 shadow=1.0, 115 scale=0.6 * scale, 116 maxwidth=self._circle_rad * 1.4, 117 transition_delay=transition_delay, 118 ) 119 120 self._sale_circle_rad = 18 * scale * sale_scale 121 self._sale_backing = bui.imagewidget( 122 parent=parent, 123 color=(0.5, 0, 1.0), 124 draw_controller=self._button, 125 size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), 126 texture=bui.gettexture('circleZigZag'), 127 transition_delay=transition_delay, 128 ) 129 self._sale_title_text = bui.textwidget( 130 parent=parent, 131 size=(0, 0), 132 h_align='center', 133 v_align='center', 134 draw_controller=self._button, 135 color=(0, 1, 0), 136 flatness=1.0, 137 shadow=0.0, 138 scale=0.5 * scale * sale_scale, 139 maxwidth=self._sale_circle_rad * 1.5, 140 transition_delay=transition_delay, 141 ) 142 self._sale_time_text = bui.textwidget( 143 parent=parent, 144 size=(0, 0), 145 h_align='center', 146 v_align='center', 147 draw_controller=self._button, 148 color=(0, 1, 0), 149 flatness=1.0, 150 shadow=0.0, 151 scale=0.4 * scale * sale_scale, 152 maxwidth=self._sale_circle_rad * 1.5, 153 transition_delay=transition_delay, 154 ) 155 156 self.set_position(position) 157 self._update_timer = bui.AppTimer( 158 1.0, bui.WeakCall(self._update), repeat=True 159 ) 160 self._update() 161 162 def _on_activate(self) -> None: 163 bui.increment_analytics_count('Store button press') 164 self._on_activate_call() 165 166 def set_position(self, position: Sequence[float]) -> None: 167 """Set the button position.""" 168 self._position = position 169 self._circle_center = ( 170 position[0] + 0.1 * self._size[0] * self._scale, 171 position[1] + self._size[1] * self._scale * 0.8, 172 ) 173 self._sale_circle_center = ( 174 position[0] + 0.07 * self._size[0] * self._scale, 175 position[1] + self._size[1] * self._scale * 0.8, 176 ) 177 178 if not self._button: 179 return 180 bui.buttonwidget(edit=self._button, position=self._position) 181 if self._title_text is not None: 182 bui.textwidget( 183 edit=self._title_text, 184 position=( 185 self._position[0] + self._size[0] * 0.5 * self._scale, 186 self._position[1] + self._size[1] * 0.65 * self._scale, 187 ), 188 ) 189 if self._ticket_text is not None: 190 bui.textwidget( 191 edit=self._ticket_text, 192 position=( 193 position[0] + self._size[0] * 0.5 * self._scale, 194 position[1] + self._size[1] * 0.28 * self._scale, 195 ), 196 size=(0, 0), 197 ) 198 bui.imagewidget( 199 edit=self._available_purchase_backing, 200 position=( 201 self._circle_center[0] - self._circle_rad * 1.02, 202 self._circle_center[1] - self._circle_rad * 1.13, 203 ), 204 ) 205 bui.textwidget( 206 edit=self._available_purchase_text, position=self._circle_center 207 ) 208 209 bui.imagewidget( 210 edit=self._sale_backing, 211 position=( 212 self._sale_circle_center[0] - self._sale_circle_rad, 213 self._sale_circle_center[1] - self._sale_circle_rad, 214 ), 215 ) 216 bui.textwidget( 217 edit=self._sale_title_text, 218 position=( 219 self._sale_circle_center[0], 220 self._sale_circle_center[1] + self._sale_circle_rad * 0.3, 221 ), 222 ) 223 bui.textwidget( 224 edit=self._sale_time_text, 225 position=( 226 self._sale_circle_center[0], 227 self._sale_circle_center[1] - self._sale_circle_rad * 0.3, 228 ), 229 ) 230 231 def _default_on_activate_call(self) -> None: 232 # pylint: disable=cyclic-import 233 from bauiv1lib.account import show_sign_in_prompt 234 235 # from bauiv1lib.store.browser import StoreBrowserWindow 236 237 plus = bui.app.plus 238 assert plus is not None 239 if plus.get_v1_account_state() != 'signed_in': 240 show_sign_in_prompt() 241 return 242 243 raise RuntimeError('no longer wired up') 244 245 # StoreBrowserWindow(modal=True, origin_widget=self._button) 246 247 def get_button(self) -> bui.Widget: 248 """Return the underlying button widget.""" 249 return self._button 250 251 def _update(self) -> None: 252 # pylint: disable=too-many-branches 253 # pylint: disable=cyclic-import 254 from babase import SpecialChar 255 256 plus = bui.app.plus 257 assert plus is not None 258 assert bui.app.classic is not None 259 store = bui.app.classic.store 260 261 if not self._button: 262 return # Our instance may outlive our UI objects. 263 264 if self._ticket_text is not None: 265 if plus.get_v1_account_state() == 'signed_in': 266 sval = bui.charstr(SpecialChar.TICKET) + str( 267 plus.get_v1_account_ticket_count() 268 ) 269 else: 270 sval = '-' 271 bui.textwidget(edit=self._ticket_text, text=sval) 272 available_purchases = store.get_available_purchase_count() 273 274 # Old pro sale stuff.. 275 sale_time = store.get_available_sale_time('extras') 276 277 # ..also look for new style sales. 278 if sale_time is None: 279 import datetime 280 281 sales_raw = plus.get_v1_account_misc_read_val('sales', {}) 282 sale_times = [] 283 try: 284 # Look at the current set of sales; filter any with time 285 # remaining that we don't own. 286 for sale_item, sale_info in list(sales_raw.items()): 287 if not plus.get_v1_account_product_purchased(sale_item): 288 to_end = ( 289 datetime.datetime.fromtimestamp( 290 sale_info['e'], datetime.UTC 291 ) 292 - utc_now() 293 ).total_seconds() 294 if to_end > 0: 295 sale_times.append(to_end) 296 except Exception: 297 logging.exception('Error parsing sales.') 298 if sale_times: 299 sale_time = int(min(sale_times) * 1000) 300 301 if sale_time is not None: 302 bui.textwidget( 303 edit=self._sale_title_text, 304 text=bui.Lstr(resource='store.saleText'), 305 ) 306 bui.textwidget( 307 edit=self._sale_time_text, 308 text=bui.timestring(sale_time / 1000.0, centi=False), 309 ) 310 bui.imagewidget(edit=self._sale_backing, opacity=1.0) 311 bui.imagewidget(edit=self._available_purchase_backing, opacity=1.0) 312 bui.textwidget(edit=self._available_purchase_text, text='') 313 bui.imagewidget(edit=self._available_purchase_backing, opacity=0.0) 314 else: 315 bui.imagewidget(edit=self._sale_backing, opacity=0.0) 316 bui.textwidget(edit=self._sale_time_text, text='') 317 bui.textwidget(edit=self._sale_title_text, text='') 318 if available_purchases > 0: 319 bui.textwidget( 320 edit=self._available_purchase_text, 321 text=str(available_purchases), 322 ) 323 bui.imagewidget( 324 edit=self._available_purchase_backing, opacity=1.0 325 ) 326 else: 327 bui.textwidget(edit=self._available_purchase_text, text='') 328 bui.imagewidget( 329 edit=self._available_purchase_backing, opacity=0.0 330 )
A button leading to the store.
StoreButton( parent: _bauiv1.Widget, position: Sequence[float], size: Sequence[float], scale: float, *, on_activate_call: Optional[Callable[[], Any]] = None, transition_delay: float | None = None, color: Optional[Sequence[float]] = None, textcolor: Optional[Sequence[float]] = None, show_tickets: bool = False, button_type: str | None = None, sale_scale: float = 1.0)
21 def __init__( 22 self, 23 parent: bui.Widget, 24 position: Sequence[float], 25 size: Sequence[float], 26 scale: float, 27 *, 28 on_activate_call: Callable[[], Any] | None = None, 29 transition_delay: float | None = None, 30 color: Sequence[float] | None = None, 31 textcolor: Sequence[float] | None = None, 32 show_tickets: bool = False, 33 button_type: str | None = None, 34 sale_scale: float = 1.0, 35 ): 36 self._position = position 37 self._size = size 38 self._scale = scale 39 40 if on_activate_call is None: 41 on_activate_call = bui.WeakCall(self._default_on_activate_call) 42 self._on_activate_call = on_activate_call 43 44 self._button = bui.buttonwidget( 45 parent=parent, 46 size=size, 47 label='' if show_tickets else bui.Lstr(resource='storeText'), 48 scale=scale, 49 autoselect=True, 50 on_activate_call=self._on_activate, 51 transition_delay=transition_delay, 52 color=color, 53 button_type=button_type, 54 ) 55 56 self._title_text: bui.Widget | None 57 self._ticket_text: bui.Widget | None 58 59 if show_tickets: 60 self._title_text = bui.textwidget( 61 parent=parent, 62 position=( 63 position[0] + size[0] * 0.5 * scale, 64 position[1] + size[1] * 0.65 * scale, 65 ), 66 size=(0, 0), 67 h_align='center', 68 v_align='center', 69 maxwidth=size[0] * scale * 0.65, 70 text=bui.Lstr(resource='storeText'), 71 draw_controller=self._button, 72 scale=scale, 73 transition_delay=transition_delay, 74 color=textcolor, 75 ) 76 self._ticket_text = bui.textwidget( 77 parent=parent, 78 size=(0, 0), 79 h_align='center', 80 v_align='center', 81 maxwidth=size[0] * scale * 0.85, 82 text='', 83 color=(0.2, 1.0, 0.2), 84 flatness=1.0, 85 shadow=0.0, 86 scale=scale * 0.6, 87 transition_delay=transition_delay, 88 ) 89 else: 90 self._title_text = None 91 self._ticket_text = None 92 93 self._circle_rad = 12 * scale 94 self._circle_center = (0.0, 0.0) 95 self._sale_circle_center = (0.0, 0.0) 96 97 self._available_purchase_backing = bui.imagewidget( 98 parent=parent, 99 color=(1, 0, 0), 100 draw_controller=self._button, 101 size=(2.2 * self._circle_rad, 2.2 * self._circle_rad), 102 texture=bui.gettexture('circleShadow'), 103 transition_delay=transition_delay, 104 ) 105 self._available_purchase_text = bui.textwidget( 106 parent=parent, 107 size=(0, 0), 108 h_align='center', 109 v_align='center', 110 text='', 111 draw_controller=self._button, 112 color=(1, 1, 1), 113 flatness=1.0, 114 shadow=1.0, 115 scale=0.6 * scale, 116 maxwidth=self._circle_rad * 1.4, 117 transition_delay=transition_delay, 118 ) 119 120 self._sale_circle_rad = 18 * scale * sale_scale 121 self._sale_backing = bui.imagewidget( 122 parent=parent, 123 color=(0.5, 0, 1.0), 124 draw_controller=self._button, 125 size=(2 * self._sale_circle_rad, 2 * self._sale_circle_rad), 126 texture=bui.gettexture('circleZigZag'), 127 transition_delay=transition_delay, 128 ) 129 self._sale_title_text = bui.textwidget( 130 parent=parent, 131 size=(0, 0), 132 h_align='center', 133 v_align='center', 134 draw_controller=self._button, 135 color=(0, 1, 0), 136 flatness=1.0, 137 shadow=0.0, 138 scale=0.5 * scale * sale_scale, 139 maxwidth=self._sale_circle_rad * 1.5, 140 transition_delay=transition_delay, 141 ) 142 self._sale_time_text = bui.textwidget( 143 parent=parent, 144 size=(0, 0), 145 h_align='center', 146 v_align='center', 147 draw_controller=self._button, 148 color=(0, 1, 0), 149 flatness=1.0, 150 shadow=0.0, 151 scale=0.4 * scale * sale_scale, 152 maxwidth=self._sale_circle_rad * 1.5, 153 transition_delay=transition_delay, 154 ) 155 156 self.set_position(position) 157 self._update_timer = bui.AppTimer( 158 1.0, bui.WeakCall(self._update), repeat=True 159 ) 160 self._update()
def
set_position(self, position: Sequence[float]) -> None:
166 def set_position(self, position: Sequence[float]) -> None: 167 """Set the button position.""" 168 self._position = position 169 self._circle_center = ( 170 position[0] + 0.1 * self._size[0] * self._scale, 171 position[1] + self._size[1] * self._scale * 0.8, 172 ) 173 self._sale_circle_center = ( 174 position[0] + 0.07 * self._size[0] * self._scale, 175 position[1] + self._size[1] * self._scale * 0.8, 176 ) 177 178 if not self._button: 179 return 180 bui.buttonwidget(edit=self._button, position=self._position) 181 if self._title_text is not None: 182 bui.textwidget( 183 edit=self._title_text, 184 position=( 185 self._position[0] + self._size[0] * 0.5 * self._scale, 186 self._position[1] + self._size[1] * 0.65 * self._scale, 187 ), 188 ) 189 if self._ticket_text is not None: 190 bui.textwidget( 191 edit=self._ticket_text, 192 position=( 193 position[0] + self._size[0] * 0.5 * self._scale, 194 position[1] + self._size[1] * 0.28 * self._scale, 195 ), 196 size=(0, 0), 197 ) 198 bui.imagewidget( 199 edit=self._available_purchase_backing, 200 position=( 201 self._circle_center[0] - self._circle_rad * 1.02, 202 self._circle_center[1] - self._circle_rad * 1.13, 203 ), 204 ) 205 bui.textwidget( 206 edit=self._available_purchase_text, position=self._circle_center 207 ) 208 209 bui.imagewidget( 210 edit=self._sale_backing, 211 position=( 212 self._sale_circle_center[0] - self._sale_circle_rad, 213 self._sale_circle_center[1] - self._sale_circle_rad, 214 ), 215 ) 216 bui.textwidget( 217 edit=self._sale_title_text, 218 position=( 219 self._sale_circle_center[0], 220 self._sale_circle_center[1] + self._sale_circle_rad * 0.3, 221 ), 222 ) 223 bui.textwidget( 224 edit=self._sale_time_text, 225 position=( 226 self._sale_circle_center[0], 227 self._sale_circle_center[1] - self._sale_circle_rad * 0.3, 228 ), 229 )
Set the button position.