bastd.ui.tabs
UI functionality for creating tab style buttons.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI functionality for creating tab style buttons.""" 4 5from __future__ import annotations 6 7from dataclasses import dataclass 8from typing import TYPE_CHECKING, TypeVar, Generic 9 10import ba 11 12if TYPE_CHECKING: 13 from typing import Any, Callable 14 15 16@dataclass 17class Tab: 18 """Info for an individual tab in a TabRow""" 19 button: ba.Widget 20 position: tuple[float, float] 21 size: tuple[float, float] 22 23 24T = TypeVar('T') 25 26 27class TabRow(Generic[T]): 28 """Encapsulates a row of tab-styled buttons. 29 30 Tabs are indexed by id which is an arbitrary user-provided type. 31 """ 32 33 def __init__(self, 34 parent: ba.Widget, 35 tabdefs: list[tuple[T, ba.Lstr]], 36 pos: tuple[float, float], 37 size: tuple[float, float], 38 on_select_call: Callable[[T], None] | None = None) -> None: 39 if not tabdefs: 40 raise ValueError('At least one tab def is required') 41 self.tabs: dict[T, Tab] = {} 42 tab_pos_v = pos[1] 43 tab_button_width = float(size[0]) / len(tabdefs) 44 tab_spacing = (250.0 - tab_button_width) * 0.06 45 h = pos[0] 46 for tab_id, tab_label in tabdefs: 47 pos = (h + tab_spacing * 0.5, tab_pos_v) 48 size = (tab_button_width - tab_spacing, 50.0) 49 btn = ba.buttonwidget(parent=parent, 50 position=pos, 51 autoselect=True, 52 button_type='tab', 53 size=size, 54 label=tab_label, 55 enable_sound=False, 56 on_activate_call=ba.Call( 57 self._tick_and_call, on_select_call, 58 tab_id)) 59 h += tab_button_width 60 self.tabs[tab_id] = Tab(button=btn, position=pos, size=size) 61 62 def update_appearance(self, selected_tab_id: T) -> None: 63 """Update appearances to make the provided tab appear selected.""" 64 for tab_id, tab in self.tabs.items(): 65 if tab_id == selected_tab_id: 66 ba.buttonwidget(edit=tab.button, 67 color=(0.5, 0.4, 0.93), 68 textcolor=(0.85, 0.75, 0.95)) # lit 69 else: 70 ba.buttonwidget(edit=tab.button, 71 color=(0.52, 0.48, 0.63), 72 textcolor=(0.65, 0.6, 0.7)) # unlit 73 74 def _tick_and_call(self, call: Callable[[Any], None] | None, 75 arg: Any) -> None: 76 ba.playsound(ba.getsound('click01')) 77 if call is not None: 78 call(arg)
@dataclass
class
Tab:
17@dataclass 18class Tab: 19 """Info for an individual tab in a TabRow""" 20 button: ba.Widget 21 position: tuple[float, float] 22 size: tuple[float, float]
Info for an individual tab in a TabRow
class
TabRow(typing.Generic[~T]):
28class TabRow(Generic[T]): 29 """Encapsulates a row of tab-styled buttons. 30 31 Tabs are indexed by id which is an arbitrary user-provided type. 32 """ 33 34 def __init__(self, 35 parent: ba.Widget, 36 tabdefs: list[tuple[T, ba.Lstr]], 37 pos: tuple[float, float], 38 size: tuple[float, float], 39 on_select_call: Callable[[T], None] | None = None) -> None: 40 if not tabdefs: 41 raise ValueError('At least one tab def is required') 42 self.tabs: dict[T, Tab] = {} 43 tab_pos_v = pos[1] 44 tab_button_width = float(size[0]) / len(tabdefs) 45 tab_spacing = (250.0 - tab_button_width) * 0.06 46 h = pos[0] 47 for tab_id, tab_label in tabdefs: 48 pos = (h + tab_spacing * 0.5, tab_pos_v) 49 size = (tab_button_width - tab_spacing, 50.0) 50 btn = ba.buttonwidget(parent=parent, 51 position=pos, 52 autoselect=True, 53 button_type='tab', 54 size=size, 55 label=tab_label, 56 enable_sound=False, 57 on_activate_call=ba.Call( 58 self._tick_and_call, on_select_call, 59 tab_id)) 60 h += tab_button_width 61 self.tabs[tab_id] = Tab(button=btn, position=pos, size=size) 62 63 def update_appearance(self, selected_tab_id: T) -> None: 64 """Update appearances to make the provided tab appear selected.""" 65 for tab_id, tab in self.tabs.items(): 66 if tab_id == selected_tab_id: 67 ba.buttonwidget(edit=tab.button, 68 color=(0.5, 0.4, 0.93), 69 textcolor=(0.85, 0.75, 0.95)) # lit 70 else: 71 ba.buttonwidget(edit=tab.button, 72 color=(0.52, 0.48, 0.63), 73 textcolor=(0.65, 0.6, 0.7)) # unlit 74 75 def _tick_and_call(self, call: Callable[[Any], None] | None, 76 arg: Any) -> None: 77 ba.playsound(ba.getsound('click01')) 78 if call is not None: 79 call(arg)
Encapsulates a row of tab-styled buttons.
Tabs are indexed by id which is an arbitrary user-provided type.
TabRow( parent: _ba.Widget, tabdefs: list[tuple[~T, ba._language.Lstr]], pos: tuple[float, float], size: tuple[float, float], on_select_call: Optional[Callable[[~T], NoneType]] = None)
34 def __init__(self, 35 parent: ba.Widget, 36 tabdefs: list[tuple[T, ba.Lstr]], 37 pos: tuple[float, float], 38 size: tuple[float, float], 39 on_select_call: Callable[[T], None] | None = None) -> None: 40 if not tabdefs: 41 raise ValueError('At least one tab def is required') 42 self.tabs: dict[T, Tab] = {} 43 tab_pos_v = pos[1] 44 tab_button_width = float(size[0]) / len(tabdefs) 45 tab_spacing = (250.0 - tab_button_width) * 0.06 46 h = pos[0] 47 for tab_id, tab_label in tabdefs: 48 pos = (h + tab_spacing * 0.5, tab_pos_v) 49 size = (tab_button_width - tab_spacing, 50.0) 50 btn = ba.buttonwidget(parent=parent, 51 position=pos, 52 autoselect=True, 53 button_type='tab', 54 size=size, 55 label=tab_label, 56 enable_sound=False, 57 on_activate_call=ba.Call( 58 self._tick_and_call, on_select_call, 59 tab_id)) 60 h += tab_button_width 61 self.tabs[tab_id] = Tab(button=btn, position=pos, size=size)
def
update_appearance(self, selected_tab_id: ~T) -> None:
63 def update_appearance(self, selected_tab_id: T) -> None: 64 """Update appearances to make the provided tab appear selected.""" 65 for tab_id, tab in self.tabs.items(): 66 if tab_id == selected_tab_id: 67 ba.buttonwidget(edit=tab.button, 68 color=(0.5, 0.4, 0.93), 69 textcolor=(0.85, 0.75, 0.95)) # lit 70 else: 71 ba.buttonwidget(edit=tab.button, 72 color=(0.52, 0.48, 0.63), 73 textcolor=(0.65, 0.6, 0.7)) # unlit
Update appearances to make the provided tab appear selected.