Source code for cursesmenu.item_group

"""A group of items that belong to a CursesMenu."""

import sys
from typing import (
    TYPE_CHECKING,
    Any,
    Iterable,
    Iterator,
    List,
    Optional,
    Union,
    cast,
    overload,
)

if sys.version_info >= (3, 9):  # pragma: py-lt-39
    from collections.abc import MutableSequence
else:  # pragma: py-gte-39
    from typing import MutableSequence

if TYPE_CHECKING:
    from cursesmenu.curses_menu import CursesMenu
    from cursesmenu.items.menu_item import MenuItem
else:
    CursesMenu = Any
    MenuItem = Any


[docs]class ItemGroup(MutableSequence[MenuItem]): """ A group of items that belong to a CursesMenu. Holds the items and ensures that the menu updates when a new one is added. Implements MutableSequence, so should act like a list. """ def __init__( self, menu: CursesMenu, items: Optional[Iterable[MenuItem]] = None, ) -> None: """Initialize the group.""" if items is None: items = [] self.items: List[MenuItem] = list(items) self.menu = menu for item in items: item.menu = self.menu def insert(self, index: int, item: MenuItem) -> None: """Insert an item.""" item.menu = self.menu self.items.insert(index, item) self.menu.adjust_screen_size() @overload def __getitem__(self, i: int) -> MenuItem: ... @overload def __getitem__(self, i: slice) -> "ItemGroup": ... def __getitem__(self, i: Union[int, slice]) -> Union[MenuItem, "ItemGroup"]: if isinstance(i, slice): return ItemGroup(self.menu, self.items[i]) else: return self.items[i] @overload def __setitem__(self, i: int, item: MenuItem) -> None: ... @overload def __setitem__(self, i: slice, item: Iterable[MenuItem]) -> None: ... def __setitem__( self, i: Union[int, slice], item: Union[MenuItem, Iterable[MenuItem]], ) -> None: """Set an item.""" from cursesmenu.items.menu_item import MenuItem if isinstance(i, int): item = cast(MenuItem, item) item.menu = self.menu self.items[i] = item else: item = cast(Iterable[MenuItem], item) for it in item: it.menu = self.menu self.items[i] = item self.menu.adjust_screen_size() @overload def __delitem__(self, i: int) -> None: ... @overload def __delitem__(self, i: slice) -> None: ... def __delitem__(self, i: Union[int, slice]) -> None: """Delete an item.""" del self.items[i] self.menu.adjust_screen_size() def __iter__(self) -> Iterator[MenuItem]: """Get an iterator for the group.""" return iter(self.items) def __len__(self) -> int: """Get the number of items in the group.""" return len(self.items) def __add__(self, other: "ItemGroup") -> "ItemGroup": """ Add two groups together. The resulting group will have the menu of the first group. """ return ItemGroup(self.menu, self.items + other.items) def __eq__(self, other: object) -> bool: if not isinstance(other, ItemGroup): return NotImplemented if self.menu != other.menu: return False if len(self) != len(other): return False for item1, item2 in zip(self, other): if item1 != item2: return False return True