bauiv1lib.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 bauiv1 as bui 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 20 button: bui.Widget 21 position: tuple[float, float] 22 size: tuple[float, float] 23 24 25T = TypeVar('T') 26 27 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__( 35 self, 36 parent: bui.Widget, 37 tabdefs: list[tuple[T, bui.Lstr]], 38 pos: tuple[float, float], 39 size: tuple[float, float], 40 *, 41 on_select_call: Callable[[T], None] | None = None, 42 ) -> None: 43 if not tabdefs: 44 raise ValueError('At least one tab def is required') 45 self.tabs: dict[T, Tab] = {} 46 tab_pos_v = pos[1] 47 tab_button_width = float(size[0]) / len(tabdefs) 48 tab_spacing = (250.0 - tab_button_width) * 0.06 49 h = pos[0] 50 for tab_id, tab_label in tabdefs: 51 pos = (h + tab_spacing * 0.5, tab_pos_v) 52 size = (tab_button_width - tab_spacing, 50.0) 53 btn = bui.buttonwidget( 54 parent=parent, 55 position=pos, 56 autoselect=True, 57 button_type='tab', 58 size=size, 59 label=tab_label, 60 enable_sound=False, 61 on_activate_call=bui.Call( 62 self._tick_and_call, on_select_call, tab_id 63 ), 64 ) 65 h += tab_button_width 66 self.tabs[tab_id] = Tab(button=btn, position=pos, size=size) 67 68 def update_appearance(self, selected_tab_id: T) -> None: 69 """Update appearances to make the provided tab appear selected.""" 70 for tab_id, tab in self.tabs.items(): 71 if tab_id == selected_tab_id: 72 bui.buttonwidget( 73 edit=tab.button, 74 color=(0.5, 0.4, 0.93), 75 textcolor=(0.85, 0.75, 0.95), 76 ) # lit 77 else: 78 bui.buttonwidget( 79 edit=tab.button, 80 color=(0.52, 0.48, 0.63), 81 textcolor=(0.65, 0.6, 0.7), 82 ) # unlit 83 84 def _tick_and_call( 85 self, call: Callable[[Any], None] | None, arg: Any 86 ) -> None: 87 bui.getsound('click01').play() 88 if call is not None: 89 call(arg)
@dataclass
class
Tab:
17@dataclass 18class Tab: 19 """Info for an individual tab in a TabRow""" 20 21 button: bui.Widget 22 position: tuple[float, float] 23 size: tuple[float, float]
Info for an individual tab in a TabRow
class
TabRow(typing.Generic[~T]):
29class TabRow(Generic[T]): 30 """Encapsulates a row of tab-styled buttons. 31 32 Tabs are indexed by id which is an arbitrary user-provided type. 33 """ 34 35 def __init__( 36 self, 37 parent: bui.Widget, 38 tabdefs: list[tuple[T, bui.Lstr]], 39 pos: tuple[float, float], 40 size: tuple[float, float], 41 *, 42 on_select_call: Callable[[T], None] | None = None, 43 ) -> None: 44 if not tabdefs: 45 raise ValueError('At least one tab def is required') 46 self.tabs: dict[T, Tab] = {} 47 tab_pos_v = pos[1] 48 tab_button_width = float(size[0]) / len(tabdefs) 49 tab_spacing = (250.0 - tab_button_width) * 0.06 50 h = pos[0] 51 for tab_id, tab_label in tabdefs: 52 pos = (h + tab_spacing * 0.5, tab_pos_v) 53 size = (tab_button_width - tab_spacing, 50.0) 54 btn = bui.buttonwidget( 55 parent=parent, 56 position=pos, 57 autoselect=True, 58 button_type='tab', 59 size=size, 60 label=tab_label, 61 enable_sound=False, 62 on_activate_call=bui.Call( 63 self._tick_and_call, on_select_call, tab_id 64 ), 65 ) 66 h += tab_button_width 67 self.tabs[tab_id] = Tab(button=btn, position=pos, size=size) 68 69 def update_appearance(self, selected_tab_id: T) -> None: 70 """Update appearances to make the provided tab appear selected.""" 71 for tab_id, tab in self.tabs.items(): 72 if tab_id == selected_tab_id: 73 bui.buttonwidget( 74 edit=tab.button, 75 color=(0.5, 0.4, 0.93), 76 textcolor=(0.85, 0.75, 0.95), 77 ) # lit 78 else: 79 bui.buttonwidget( 80 edit=tab.button, 81 color=(0.52, 0.48, 0.63), 82 textcolor=(0.65, 0.6, 0.7), 83 ) # unlit 84 85 def _tick_and_call( 86 self, call: Callable[[Any], None] | None, arg: Any 87 ) -> None: 88 bui.getsound('click01').play() 89 if call is not None: 90 call(arg)
Encapsulates a row of tab-styled buttons.
Tabs are indexed by id which is an arbitrary user-provided type.
TabRow( parent: _bauiv1.Widget, tabdefs: list[tuple[~T, babase.Lstr]], pos: tuple[float, float], size: tuple[float, float], *, on_select_call: Optional[Callable[[~T], NoneType]] = None)
35 def __init__( 36 self, 37 parent: bui.Widget, 38 tabdefs: list[tuple[T, bui.Lstr]], 39 pos: tuple[float, float], 40 size: tuple[float, float], 41 *, 42 on_select_call: Callable[[T], None] | None = None, 43 ) -> None: 44 if not tabdefs: 45 raise ValueError('At least one tab def is required') 46 self.tabs: dict[T, Tab] = {} 47 tab_pos_v = pos[1] 48 tab_button_width = float(size[0]) / len(tabdefs) 49 tab_spacing = (250.0 - tab_button_width) * 0.06 50 h = pos[0] 51 for tab_id, tab_label in tabdefs: 52 pos = (h + tab_spacing * 0.5, tab_pos_v) 53 size = (tab_button_width - tab_spacing, 50.0) 54 btn = bui.buttonwidget( 55 parent=parent, 56 position=pos, 57 autoselect=True, 58 button_type='tab', 59 size=size, 60 label=tab_label, 61 enable_sound=False, 62 on_activate_call=bui.Call( 63 self._tick_and_call, on_select_call, tab_id 64 ), 65 ) 66 h += tab_button_width 67 self.tabs[tab_id] = Tab(button=btn, position=pos, size=size)
tabs: dict[~T, Tab]
def
update_appearance(self, selected_tab_id: ~T) -> None:
69 def update_appearance(self, selected_tab_id: T) -> None: 70 """Update appearances to make the provided tab appear selected.""" 71 for tab_id, tab in self.tabs.items(): 72 if tab_id == selected_tab_id: 73 bui.buttonwidget( 74 edit=tab.button, 75 color=(0.5, 0.4, 0.93), 76 textcolor=(0.85, 0.75, 0.95), 77 ) # lit 78 else: 79 bui.buttonwidget( 80 edit=tab.button, 81 color=(0.52, 0.48, 0.63), 82 textcolor=(0.65, 0.6, 0.7), 83 ) # unlit
Update appearances to make the provided tab appear selected.