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