# Released under the MIT License. See LICENSE for details.
#
"""UI functionality for creating tab style buttons."""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
import bauiv1 as bui
if TYPE_CHECKING:
from typing import Any, Callable
[docs]
@dataclass
class Tab:
"""Info for an individual tab in a TabRow"""
button: bui.Widget
position: tuple[float, float]
size: tuple[float, float]
[docs]
class TabRow[T]:
"""Encapsulates a row of tab-styled buttons.
Tabs are indexed by id which is an arbitrary user-provided type.
"""
def __init__(
self,
parent: bui.Widget,
tabdefs: list[tuple[T, bui.Lstr]],
pos: tuple[float, float],
size: tuple[float, float],
*,
on_select_call: Callable[[T], None] | None = None,
) -> None:
if not tabdefs:
raise ValueError('At least one tab def is required')
self.tabs: dict[T, Tab] = {}
tab_pos_v = pos[1]
tab_button_width = float(size[0]) / len(tabdefs)
tab_spacing = (250.0 - tab_button_width) * 0.06
h = pos[0]
for tab_id, tab_label in tabdefs:
pos = (h + tab_spacing * 0.5, tab_pos_v)
size = (tab_button_width - tab_spacing, 50.0)
btn = bui.buttonwidget(
parent=parent,
position=pos,
autoselect=True,
button_type='tab',
size=size,
label=tab_label,
enable_sound=False,
on_activate_call=bui.Call(
self._tick_and_call, on_select_call, tab_id
),
)
h += tab_button_width
self.tabs[tab_id] = Tab(button=btn, position=pos, size=size)
[docs]
def update_appearance(self, selected_tab_id: T) -> None:
"""Update appearances to make the provided tab appear selected."""
for tab_id, tab in self.tabs.items():
if tab_id == selected_tab_id:
bui.buttonwidget(
edit=tab.button,
color=(0.5, 0.4, 0.93),
textcolor=(0.82, 0.72, 0.92),
) # lit
else:
bui.buttonwidget(
edit=tab.button,
color=(0.50, 0.44, 0.63),
textcolor=(0.65, 0.6, 0.7),
) # unlit
def _tick_and_call(
self, call: Callable[[Any], None] | None, arg: Any
) -> None:
bui.getsound('click01').play()
if call is not None:
call(arg)
# Docs-generation hack; import some stuff that we likely only forward-declared
# in our actual source code so that docs tools can find it.
from typing import (Coroutine, Any, Literal, Callable,
Generator, Awaitable, Sequence, Self)
import asyncio
from concurrent.futures import Future
from pathlib import Path
from enum import Enum