1# Copyright (c) 2019-2020 Manfred Moitzi
2# License: MIT License
3from typing import TYPE_CHECKING, Tuple
4from .dxfentity import DXFEntity, SubclassProcessor, DXFNamespace
5from ezdxf.lldxf.attributes import (
6    DXFAttr, DXFAttributes, DefSubclass, group_code_mapping,
7)
8from ezdxf.lldxf.const import DXF2004, DXF2000
9from .factory import register_entity
10
11if TYPE_CHECKING:
12    from ezdxf.eztypes import Drawing, ExtendedTags, TagWriter
13
14__all__ = ['DXFClass']
15
16class_def = DefSubclass(None, {
17    # Class DXF record name; always unique
18    'name': DXFAttr(1),
19    # C++ class name. Used to bind with software that defines object class
20    # behavior; always unique
21    'cpp_class_name': DXFAttr(2),
22    # Application name. Posted in Alert box when a class definition listed in
23    # this section is not currently loaded
24    'app_name': DXFAttr(3),
25    # Proxy capabilities flag. Bit-coded value that indicates the capabilities
26    # of this object as a proxy:
27    # 0 = No operations allowed (0)
28    # 1 = Erase allowed (0x1)
29    # 2 = Transform allowed (0x2)
30    # 4 = Color change allowed (0x4)
31    # 8 = Layer change allowed (0x8)
32    # 16 = Linetype change allowed (0x10)
33    # 32 = Linetype scale change allowed (0x20)
34    # 64 = Visibility change allowed (0x40)
35    # 128 = Cloning allowed (0x80)
36    # 256 = Lineweight change allowed (0x100)
37    # 512 = Plot Style Name change allowed (0x200)
38    # 895 = All operations except cloning allowed (0x37F)
39    # 1023 = All operations allowed (0x3FF)
40    # 1024 = Disables proxy warning dialog (0x400)
41    # 32768 = R13 format proxy (0x8000)
42    'flags': DXFAttr(90, default=0),
43    # Instance count for a custom class
44    'instance_count': DXFAttr(91, dxfversion=DXF2004, default=0),
45    # Was-a-proxy flag. Set to 1 if class was not loaded when this DXF file was
46    # created, and 0 otherwise
47    'was_a_proxy': DXFAttr(280, default=0),
48    # Is-an-entity flag. Set to 1 if class was derived from the AcDbEntity class
49    # and can reside in the BLOCKS or ENTITIES section. If 0, instances may
50    # appear only in the OBJECTS section
51    'is_an_entity': DXFAttr(281, default=0),
52})
53class_def_group_codes = group_code_mapping(class_def)
54
55
56@register_entity
57class DXFClass(DXFEntity):
58    DXFTYPE = 'CLASS'
59    DXFATTRIBS = DXFAttributes(class_def)
60    MIN_DXF_VERSION_FOR_EXPORT = DXF2000
61
62    @classmethod
63    def new(cls, handle: str = None, owner: str = None, dxfattribs: dict = None,
64            doc: 'Drawing' = None) -> 'DXFClass':
65        """ New CLASS constructor - has no handle, no owner and do not need
66        document reference .
67        """
68        dxf_class = cls()
69        dxf_class.doc = doc
70        dxfattribs = dxfattribs or {}
71        dxf_class.update_dxf_attribs(dxfattribs)
72        return dxf_class
73
74    def load_tags(self, tags: 'ExtendedTags', dxfversion=None) -> None:
75        """ Called by load constructor. CLASS is special. """
76        if tags:
77            # do not process base class!!!
78            self.dxf = DXFNamespace(entity=self)
79            processor = SubclassProcessor(tags)
80            processor.fast_load_dxfattribs(
81                self.dxf, class_def_group_codes, 0, log=False)
82
83    def export_dxf(self, tagwriter: 'TagWriter'):
84        """ Do complete export here, because CLASS is special. """
85        dxfversion = tagwriter.dxfversion
86        if dxfversion < DXF2000:
87            return
88        attribs = self.dxf
89        tagwriter.write_tag2(0, self.DXFTYPE)
90        attribs.export_dxf_attribs(tagwriter, [
91            'name', 'cpp_class_name', 'app_name', 'flags', 'instance_count',
92            'was_a_proxy', 'is_an_entity',
93        ])
94
95    @property
96    def key(self) -> Tuple[str, str]:
97        return self.dxf.name, self.dxf.cpp_class_name
98