1# Copyright (c) 2019-2020, Manfred Moitzi 2# License: MIT License 3from typing import TYPE_CHECKING 4 5if TYPE_CHECKING: 6 from ezdxf.eztypes import Drawing, DXFEntity, ExtendedTags 7 8__all__ = [ 9 'register_entity', 'ENTITY_CLASSES', 'replace_entity', 10 'new', 'cls', 'is_bound', 'create_db_entry', 'load', 'bind' 11] 12# Stores all registered classes: 13ENTITY_CLASSES = {} 14# use @set_default_class to register the default entity class: 15DEFAULT_CLASS = None 16 17 18def set_default_class(cls): 19 global DEFAULT_CLASS 20 DEFAULT_CLASS = cls 21 return cls 22 23 24def replace_entity(cls): 25 name = cls.DXFTYPE 26 ENTITY_CLASSES[name] = cls 27 return cls 28 29 30def register_entity(cls): 31 name = cls.DXFTYPE 32 if name in ENTITY_CLASSES: 33 raise TypeError(f'Double registration for DXF type {name}.') 34 ENTITY_CLASSES[name] = cls 35 return cls 36 37 38def new(dxftype: str, dxfattribs: dict = None, 39 doc: 'Drawing' = None) -> 'DXFEntity': 40 """ Create a new entity, does not require an instantiated DXF document. """ 41 entity = cls(dxftype).new( 42 handle=None, 43 owner=None, 44 dxfattribs=dxfattribs, 45 doc=doc, 46 ) 47 return entity.cast() if hasattr(entity, 'cast') else entity 48 49 50def create_db_entry(dxftype, dxfattribs: dict, doc: 'Drawing') -> 'DXFEntity': 51 entity = new(dxftype=dxftype, dxfattribs=dxfattribs) 52 bind(entity, doc) 53 return entity 54 55 56def load(tags: 'ExtendedTags') -> 'DXFEntity': 57 entity = cls(tags.dxftype()).load(tags) 58 return entity.cast() if hasattr(entity, 'cast') else entity 59 60 61def cls(dxftype: str) -> 'DXFEntity': 62 """ Returns registered class for `dxftype`. """ 63 return ENTITY_CLASSES.get(dxftype, DEFAULT_CLASS) 64 65 66def bind(entity: 'DXFEntity', doc: 'Drawing') -> None: 67 """ Bind `entity` to the DXF document `doc`. 68 69 The bind process stores the DXF `entity` in the entity database of the DXF 70 document. 71 72 """ 73 assert entity.is_alive, 'Can not bind destroyed entity.' 74 assert doc.entitydb is not None, 'Missing entity database.' 75 entity.doc = doc 76 doc.entitydb.add(entity) 77 78 # Do not call the post_bind_hook() while loading from external sources, 79 # not all entities and resources are loaded at this point of time! 80 if not doc.is_loading: 81 entity.post_bind_hook() 82 83 84def unbind(entity: 'DXFEntity'): 85 """ Unbind `entity` from document and layout, but does not destroy the 86 entity. 87 88 Turns `entity` into a virtual entity: no handle, no owner, no document. 89 """ 90 if entity.is_alive and not entity.is_virtual: 91 doc = entity.doc 92 if entity.dxf.owner is not None: 93 try: 94 layout = doc.layouts.get_layout_for_entity(entity) 95 except KeyError: 96 pass 97 else: 98 layout.unlink_entity(entity) 99 100 process_sub_entities = getattr(entity, 'process_sub_entities', None) 101 if process_sub_entities: 102 process_sub_entities(lambda e: unbind(e)) 103 104 doc.entitydb.discard(entity) 105 entity.doc = None 106 107 108def is_bound(entity: 'DXFEntity', doc: 'Drawing') -> bool: 109 """ Returns ``True`` if `entity`is bound to DXF document `doc`. 110 """ 111 if not entity.is_alive: 112 return False 113 if entity.is_virtual or entity.doc is not doc: 114 return False 115 assert doc.entitydb, 'Missing entity database.' 116 return entity.dxf.handle in doc.entitydb 117