1# Copyright (c) 2019-2020, Manfred Moitzi 2# License: MIT License 3from typing import TYPE_CHECKING, Iterable, Optional, Union 4from ezdxf.lldxf import const 5from .base import BaseLayout 6 7if TYPE_CHECKING: 8 from ezdxf.eztypes import DXFGraphic, AttDef 9 10 11class BlockLayout(BaseLayout): 12 """ BlockLayout has the same factory-functions as Layout, but is managed 13 in the :class:`BlocksSection` class. It represents a DXF Block. 14 15 """ 16 17 def __contains__(self, entity: Union['DXFGraphic', str]) -> bool: 18 """ Returns ``True`` if block contains `entity`. 19 20 Args: 21 entity: :class:`DXFGraphic` object or handle as hex string 22 23 """ 24 if isinstance(entity, str): 25 entity = self.entitydb[entity] 26 return entity in self.entity_space 27 28 @property 29 def block(self): 30 """ the associated :class:`~ezdxf.entities.Block` entity. """ 31 return self.block_record.block 32 33 @property 34 def endblk(self): 35 """ the associated :class:`~ezdxf.entities.EndBlk` entity. """ 36 return self.block_record.endblk 37 38 @property 39 def name(self) -> str: 40 """ Get block and block_record name """ 41 return self.block_record.dxf.name 42 43 @name.setter 44 def name(self, new_name) -> None: 45 """ Set block and block_record name """ 46 self.block_record.rename(new_name) 47 48 @property 49 def dxf(self): 50 """ DXF name space of associated :class:`~ezdxf.entities.BlockRecord` 51 table entry. 52 """ 53 return self.block_record.dxf 54 55 @property 56 def can_explode(self) -> bool: 57 """ Set property to ``True`` to allow exploding block references of 58 this block. 59 """ 60 return bool(self.block_record.dxf.explode) 61 62 @can_explode.setter 63 def can_explode(self, value: bool): 64 self.block_record.dxf.explode = int(value) 65 66 @property 67 def scale_uniformly(self) -> bool: 68 """ Set property to ``True`` to allow block references of this block 69 only scale uniformly. 70 """ 71 return bool(self.block_record.dxf.scale) 72 73 @scale_uniformly.setter 74 def scale_uniformly(self, value: bool): 75 self.block_record.dxf.scale = int(value) 76 77 def attdefs(self) -> Iterable['AttDef']: 78 """ Returns iterable of all :class:`~ezdxf.entities.attrib.Attdef` 79 entities. 80 """ 81 return (entity for entity in self if entity.dxftype() == 'ATTDEF') 82 83 def has_attdef(self, tag: str) -> bool: 84 """ Returns ``True`` if an :class:`~ezdxf.entities.attrib.Attdef` for 85 `tag` exist. 86 """ 87 return self.get_attdef(tag) is not None 88 89 def get_attdef(self, tag: str) -> Optional['DXFGraphic']: 90 """ Returns attached :class:`~ezdxf.entities.attrib.Attdef` entity by 91 `tag` name. 92 """ 93 for attdef in self.attdefs(): 94 if tag == attdef.dxf.tag: 95 return attdef 96 97 def get_attdef_text(self, tag: str, default: str = None) -> str: 98 """ Returns text content for :class:`~ezdxf.entities.attrib.Attdef` 99 `tag` as string or returns `default` if no :class:`Attdef` for `tag` 100 exist. 101 102 Args: 103 tag: name of tag 104 default: default value if `tag` not exist 105 106 """ 107 attdef = self.get_attdef(tag) 108 if attdef is None: 109 return default 110 return attdef.dxf.text 111 112 def get_const_attdefs(self) -> Iterable['AttDef']: 113 """ Returns iterable for all constant ATTDEF entities. (internal API) 114 """ 115 return (attdef for attdef in self.attdefs() if attdef.is_const) 116 117 def has_non_const_attdef(self) -> bool: 118 """ Returns ``True`` if the block has a non constant attribute 119 definition. 120 """ 121 return any(not attdef.is_const for attdef in self.attdefs()) 122 123 def update_block_flags(self): 124 state = self.has_non_const_attdef() 125 self.block.set_flag_state(const.BLK_NON_CONSTANT_ATTRIBUTES, state)