Source code for pyggui.gui.container

"""
Module containing container classes used for storing and moving grouped items.
"""

from typing import List, Tuple

import pygame

from pyggui.gui.item import ResizableItem, StaticItem
from pyggui.exceptions import NotResizableError


[docs]class StaticContainer(StaticItem): """ Container object for holding items inside, items are moved with the container. Static container can not be resized but can still be moved. """ def __init__(self, position: List[int] = [0, 0], size: Tuple[int, int] = (100, 100), visible: bool = False, selected: bool = False, resizable: bool = False ): super().__init__(position, size, visible, selected) """ Args: position (List[int]): Position of container on screen or on Page. Defaults to [0, 0, 0]. size (Tuple[int, int]): Size of container object. Defaults to white. visible (bool): If container boundaries rectangle should be displayed. Defaults to False. selected (bool): If the container is currently selected. Defaults to False. resizable (bool): If the container is resizable. Defaults to false. """ self.resizable: bool = resizable self.items_positions: list[tuple] = [] # List containing attached items positions
[docs] def add_item(self, item: any, relative_position: Tuple[int, int]) -> int: """ Method adds item in a position relative to self upper left corner. Item will be moved along with the container object. Args: item (any): Item to add. relative_position (Tuple[int, int]): Position of added item in container based on upper left corner. Returns: int: Position (index) in items list of added item. """ self.items.append(item) item_position = [relative_position[0], relative_position[1]] self.items_positions.append(item_position) self.items[-1].position = item_position # Update new items position return len(self.items) - 1
[docs] def change_item_at_index(self, index: int, item: any) -> None: """ Method changes item at index inside the items list. Position of item inside container stays the same. Args: index (int): Index in items list to change item. item (any): Item to add. """ self.items[index] = item self.items[index].position = self.items_positions[index]
[docs] def update(self) -> None: """ Updates all items and its positions relative to self. """ for i, item in enumerate(self.items): # Update items positions relative to current self position item.position = [self.x + self.items_positions[i][0], self.y + self.items_positions[i][1]] item.selected = self.selected item.update()
[docs] def draw(self) -> None: """ Used for drawing itself and every item attached to it. """ if self.visible: pygame.draw.rect( self.display, (255, 255, 255), self.rect, width=1 ) for item in self.items: item.draw()
[docs]class ResizableContainer(ResizableItem): """ Container object can be resized along with every item contained in it. Because of this only re-sizable items can be added. """ def __init__(self, position: List[int] = [0, 0], size: Tuple[int, int] = (100, 100), visible: bool = False, selected: bool = False, resizable: bool = False ): """ Args: position (List[int]): Position of container on screen or on Page. Defaults to [0, 0, 0]. size (Tuple[int, int]): Size of container object. Defaults to white. visible (bool): If container boundaries rectangle should be displayed. Defaults to False. selected (bool): If the container is currently selected. Defaults to False. resizable (bool): If the container is resizable. Defaults to false. """ super().__init__(position, size, visible, selected) self.resizable: bool = resizable self.items_positions: list[tuple] = [] # List containing attached items positions self.resized_items_positions: list[tuple] = []
[docs] def resize(self, factor: float) -> None: """ Method re-sizes self and every item inside by a factor passed as an argument. Args: factor (float): Representing scale to resize in the interval (0, inf] """ super(ResizableContainer, self).resize(factor) self.resized_size = [int(self.width * factor), int(self.height * factor)] for i, item in enumerate(self.items): # Re-size and scale items positions based on factor self.resized_items_positions[i] = [int(self.items_positions[i][0] * factor), int(self.items_positions[i][1] * factor)] item.resize(factor)
[docs] def reset_size(self) -> None: """ Method resets size of self and every item to the initially set size. """ super(ResizableContainer, self).reset_size() self.size = self.initial_size # Reset size of self rect for item in self.items: item.reset_size()
[docs] def add_item(self, item: any, relative_position: Tuple[int, int]) -> int: """ Method adds item in a position relative to self upper left corner. Item will be moved along with the container object. Args: item (any): Item to add. relative_position (Tuple[int, int]): Position of added item in container based on upper left corner. Returns: int: Position (index) in items list of added item. """ if self.resizable and not hasattr(item, "is_resized"): # If container resizable, expect only resizable items raise NotResizableError("Added item is not resizable; " "Container is set to be resizable and only accepts resizable items.") self.items.append(item) item_position = [relative_position[0], relative_position[1]] self.items_positions.append(item_position) self.resized_items_positions.append(item_position) self.items[-1].position = item_position # Update this items position return len(self.items) - 1
[docs] def change_item_at_index(self, index: int, item: any) -> None: """ Method changes item at index inside the items list. Position of item inside container stays the same. Args: index (int): Index in items list to change item. item (any): Item to add. """ self.items[index] = item self.items[index].position = self.items_positions[index]
[docs] def update(self) -> None: """ Updates all items and its positions relative to self. """ for i, item in enumerate(self.items): # Update items positions relative to current self position item.position = [self.scaled_x + self.resized_items_positions[i][0], self.scaled_y + self.resized_items_positions[i][1]] item.selected = self.selected item.update()
[docs] def draw(self) -> None: """ Used for drawing itself and every item attached to it. """ if self.visible: if self.is_resized: pygame.draw.rect( self.display, (255, 255, 255), [self.scaled_x, self.scaled_y, self.resized_size[0], self.resized_size[1]], width=1 ) else: pygame.draw.rect( self.display, (255, 255, 255), self.rect, width=1 ) for item in self.items: item.draw()
[docs]class Container: """ Container objects can store items in positions relative to self. If items get added to a container object, those items can all be moved together by moving the container object. Passing the argument resizable as True will create a Resizable container, otherwise a StaticContainer where it and its items can't be resized. """ def __new__(cls, *args, **kwargs): kwargs_copy = kwargs.copy() # Mutate copy so all kwargs go through resizable = kwargs_copy.pop("resizable", False) # Return correct container if resizable: return ResizableContainer(*args, **kwargs) else: return StaticContainer(*args, **kwargs) def __init__(self, position: List[int] = [0, 0], size: Tuple[int, int] = (100, 100), visible: bool = False, selected: bool = False, resizable: bool = False ): """ Args: position (List[int]): Position of container on screen or on Page. Defaults to [0, 0, 0]. size (Tuple[int, int]): Size of container object. Defaults to white. visible (bool): If container boundaries rectangle should be displayed. Defaults to False. selected (bool): If the container is currently selected. Defaults to False. resizable (bool): If the container is resizable. Defaults to false. """ pass