"""Module for the Region types."""from__future__importannotationsimportabcimporttypingimportnumpyasnpfrom..importconfigfrom..configimportrefs,typesfrom..reportingimportwarnfrom._layoutimportLayoutiftyping.TYPE_CHECKING:from..coreimportScaffoldfrom.partitionimportPartition
[docs]@config.dynamic(attr_name="type",required=False,default="group",auto_classmap=True)classRegion(abc.ABC):""" Base region. When arranging will simply call arrange/layout on its children but won't cause any changes itself. """scaffold:Scaffoldname:str=config.attr(key=True)children:list[Region|Partition]=config.reflist(refs.regional_ref,backref="region",required=True)""" Reference to Regions or Partitions belonging to this region. """@propertydefdata(self):# The data property is read-only to users, but `_data` is assigned# during the layout processreturnself._data
[docs]@config.nodeclassRegionGroup(Region,classmap_entry="group"):""" Base implementation of Region. Any transformation on the region will be directly applied to its children (Regions or Partitions). """
[docs]@config.nodeclassStack(RegionGroup,classmap_entry="stack"):""" Stack components on top of each other and adjust its own height accordingly. """axis:typing.Literal["x"]|typing.Literal["y"]|typing.Literal["z"]=config.attr(type=types.in_(["x","y","z"]),default="z")""" Axis along which the stack's children will be stacked. """anchor:Region|Partition=config.ref(refs.regional_ref)""" Reference to one child of the stack, which origin will become the origin of the stack. """def_resolve_anchor_offset(self,children,axis_idx):""" Check if the anchor is one of the children of the stack and if so, return the offset so the anchor is at the origin of the stack. """children_owners=[child._ownerforchildinchildren]ifself.anchorisnotNoneandself.anchorinchildren_owners:index=children_owners.index(self.anchor)returnchildren[index].data.ldc[axis_idx]-sum(children[i].data.dimensions[axis_idx]foriinrange(index))else:# if anchor is not defined or one of the children# then the origin of the stack corresponds to the origin of the first childreturnchildren[0].data.ldc[axis_idx]
[docs]defget_layout(self,hint):layout=super().get_layout(hint)axis_idx=("x","y","z").index(self.axis)trans_eye=np.zeros(3)trans_eye[axis_idx]=1cumul_offset=self._resolve_anchor_offset(layout.children,axis_idx)forchildinlayout.children:ifchild.dataisNone:warn(f"Skipped layout arrangement of {child._owner.name} in {self.name}")continuetranslation=(layout.data.ldc[axis_idx]+cumul_offset-child.data.ldc)*trans_eyeifnotnp.allclose(0,translation):child.propose_translate(translation)cumul_offset+=child.data.dimensions[axis_idx]ldc=layout.data.ldcmdc=layout.data.mdcmdc[axis_idx]=ldc[axis_idx]+cumul_offsetreturnlayout