from __future__ import annotations
from typing import Union, Callable
-from recordclass import recordclass
+from circuitpython_typing import WriteableBuffer
+from ._structs import TransformStruct
from ._tilegrid import TileGrid
+from ._colorspace import Colorspace
+from ._area import Area
-__version__ = "0.0.0-auto.0"
+__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
-Transform = recordclass("Transform", "x y dx dy scale transpose_xy mirror_x mirror_y")
-
-
class Group:
+ # pylint: disable=too-many-instance-attributes
"""
Manage a group of sprites and groups and how they are inter-related.
if not isinstance(scale, int) or scale < 1:
raise ValueError("Scale must be >= 1")
self._scale = 1 # Use the setter below to actually set the scale
+ self._name = "Group"
self._group_x = x
self._group_y = y
self._hidden_group = False
+ self._hidden_by_parent = False
self._layers = []
self._supported_types = (TileGrid, Group)
- self.in_group = False
- self._absolute_transform = Transform(0, 0, 1, 1, 1, False, False, False)
+ self._in_group = False
+ self._item_removed = False
+ self._absolute_transform = TransformStruct(0, 0, 1, 1, 1, False, False, False)
self._set_scale(scale) # Set the scale via the setter
def _update_transform(self, parent_transform):
"""Update the parent transform and child transforms"""
- self.in_group = parent_transform is not None
- if self.in_group:
+ self._in_group = parent_transform is not None
+ if self._in_group:
x = self._group_x
y = self._group_y
if parent_transform.transpose_xy:
def _update_child_transforms(self):
# pylint: disable=protected-access
- if self.in_group:
+ if self._in_group:
for layer in self._layers:
layer._update_transform(self._absolute_transform)
- # pylint: enable=protected-access
def _removal_cleanup(self, index):
+ # pylint: disable=protected-access
layer = self._layers[index]
- layer._update_transform(None) # pylint: disable=protected-access
+ layer._update_transform(None)
def _layer_update(self, index):
# pylint: disable=protected-access
layer = self._layers[index]
layer._update_transform(self._absolute_transform)
- # pylint: enable=protected-access
def append(self, layer: Union[Group, TileGrid]) -> None:
"""Append a layer to the group. It will be drawn
"""Insert a layer into the group."""
if not isinstance(layer, self._supported_types):
raise ValueError("Invalid Group Member")
- if layer.in_group:
+ if layer._in_group: # pylint: disable=protected-access
raise ValueError("Layer already in a group.")
self._layers.insert(index, layer)
self._layer_update(index)
"""
return self._layers.index(layer)
- def pop(self, index=-1) -> Union[Group, TileGrid]:
+ def pop(self, index: int = -1) -> Union[Group, TileGrid]:
"""Remove the ith item and return it."""
self._removal_cleanup(index)
return self._layers.pop(index)
- def remove(self, layer) -> None:
+ def remove(self, layer: Union[Group, TileGrid]) -> None:
"""Remove the first copy of layer. Raises ValueError
if it is not present."""
index = self.index(layer)
self._layers.pop(index)
+ def __bool__(self) -> bool:
+ """Returns if there are any layers"""
+ return len(self._layers) > 0
+
def __len__(self) -> int:
"""Returns the number of layers in a Group"""
return len(self._layers)
- def __getitem__(self, index) -> Union[Group, TileGrid]:
+ def __getitem__(self, index: int) -> Union[Group, TileGrid]:
"""Returns the value at the given index."""
return self._layers[index]
- def __setitem__(self, index, value) -> None:
+ def __setitem__(self, index: int, value: Union[Group, TileGrid]) -> None:
"""Sets the value at the given index."""
self._removal_cleanup(index)
self._layers[index] = value
self._layer_update(index)
- def __delitem__(self, index) -> None:
+ def __delitem__(self, index: int) -> None:
"""Deletes the value at the given index."""
del self._layers[index]
- def _fill_area(self, buffer):
- if self._hidden_group:
- return
-
- for layer in self._layers:
- if isinstance(layer, (Group, TileGrid)):
- layer._fill_area(buffer) # pylint: disable=protected-access
+ def _fill_area(
+ self,
+ colorspace: Colorspace,
+ area: Area,
+ mask: WriteableBuffer,
+ buffer: WriteableBuffer,
+ ) -> bool:
+ if not self._hidden_group:
+ for layer in reversed(self._layers):
+ if isinstance(layer, (Group, TileGrid)):
+ if layer._fill_area( # pylint: disable=protected-access
+ colorspace, area, mask, buffer
+ ):
+ return True
+ return False
def sort(self, key: Callable, reverse: bool) -> None:
"""Sort the members of the group."""
self._layers.sort(key=key, reverse=reverse)
+ def _finish_refresh(self):
+ for layer in reversed(self._layers):
+ if isinstance(layer, (Group, TileGrid)):
+ layer._finish_refresh() # pylint: disable=protected-access
+
+ def _get_refresh_areas(self, areas: list[Area]) -> None:
+ # pylint: disable=protected-access
+ for layer in reversed(self._layers):
+ if isinstance(layer, Group):
+ layer._get_refresh_areas(areas)
+ elif isinstance(layer, TileGrid):
+ if not layer._get_rendered_hidden():
+ layer._get_refresh_areas(areas)
+
+ def _set_hidden(self, hidden: bool) -> None:
+ if self._hidden_group == hidden:
+ return
+ self._hidden_group = hidden
+ if self._hidden_by_parent:
+ return
+ for layer in self._layers:
+ if isinstance(layer, (Group, TileGrid)):
+ layer._set_hidden_by_parent(hidden) # pylint: disable=protected-access
+
+ def _set_hidden_by_parent(self, hidden: bool) -> None:
+ if self._hidden_by_parent == hidden:
+ return
+ self._hidden_by_parent = hidden
+ if self._hidden_group:
+ return
+ for layer in self._layers:
+ if isinstance(layer, (Group, TileGrid)):
+ layer._set_hidden_by_parent(hidden) # pylint: disable=protected-access
+
@property
def hidden(self) -> bool:
- """True when the Group and all of it’s layers are not visible. When False, the
- Group’s layers are visible if they haven’t been hidden.
+ """True when the Group and all of it's layers are not visible. When False, the
+ Group’s layers are visible if they haven't been hidden.
"""
return self._hidden_group
@hidden.setter
- def hidden(self, value: bool):
+ def hidden(self, value: bool) -> None:
if not isinstance(value, (bool, int)):
raise ValueError("Expecting a boolean or integer value")
- self._hidden_group = bool(value)
+ value = bool(value)
+ self._set_hidden(value)
@property
def scale(self) -> int:
self._absolute_transform.y += dy_value * (value - self._group_y)
self._group_y = value
self._update_child_transforms()
+
+
+circuitpython_splash = Group(scale=2, x=0, y=0)