Source code for neoscore.interface.positioned_object_interface

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional
from warnings import warn

from PyQt5.QtWidgets import QGraphicsItem

from neoscore.core import neoscore
from neoscore.core.point import Point


[docs]@dataclass(frozen=True) class PositionedObjectInterface: """Interface for a generic graphic object. All graphic interfaces for renderable objects should descend from this and also be immutable dataclasses. """ pos: Point """The position of the object. If a parent is provided, this position is relative to that interface. Otherwise it is in absolute document coordinates. """ parent: Optional[PositionedObjectInterface] """The object's parent, if any. If a parent interface is provided, it must be rendered before this interface. """ scale: float """A scaling factor, where 1 is no scaling. This occurs relative to ``transform_origin``. Scaling is inherited from parents to children along the interface tree. """ rotation: float """Rotation angle in degrees, where 0 is no rotation. This occurs relative to ``transform_origin``. Rotation is inherited from parents to children along the interface tree. """ transform_origin: Point """The origin point for rotation and scaling transforms""" _qt_object: Optional[QGraphicsItem] = field(init=False, compare=False, repr=False) """A corresponding Qt object for internal use only. This value is set during rendering and is not meant to be set more than once. """
[docs] def render(self): """Render the object to the scene. This is typically done by constructing a `QGraphicsItem` subclass and calling `_register_qt_object` with it. Do *not* manually assign the Qt object's parent or add it to the Qt scene. """ raise NotImplementedError
def _parent_qt_obj(self) -> Optional[QGraphicsItem]: if self.parent: parent_qt_obj = getattr(self.parent, "_qt_object", None) if not parent_qt_obj: warn( "Parent interface was provided but corresponding Qt object" + f" not available when needed for {self}" ) # implicitly return None return parent_qt_obj return None def _register_qt_object(self, obj: QGraphicsItem): parent_obj = self._parent_qt_obj() if parent_obj: obj.setParentItem(parent_obj) else: neoscore.app_interface.scene.addItem(obj) super().__setattr__("_qt_object", obj)