1# Copyright (c) 2019-2020, Manfred Moitzi
2# License: MIT-License
3from typing import TYPE_CHECKING, List
4from ezdxf.lldxf.const import SUBCLASS_MARKER, DXFStructureError
5from ezdxf.lldxf.attributes import (
6    DXFAttributes, DefSubclass, DXFAttr, group_code_mapping,
7)
8from .dxfentity import base_class, SubclassProcessor
9from .dxfobj import DXFObject
10from .factory import register_entity
11
12if TYPE_CHECKING:
13    from ezdxf.eztypes import TagWriter, DXFNamespace, Tags
14
15__all__ = ['IDBuffer', 'FieldList', 'LayerFilter']
16
17acdb_id_buffer = DefSubclass('AcDbIdBuffer', {})
18
19
20@register_entity
21class IDBuffer(DXFObject):
22    """ DXF IDBUFFER entity """
23    DXFTYPE = 'IDBUFFER'
24    DXFATTRIBS = DXFAttributes(base_class, acdb_id_buffer)
25
26    def __init__(self):
27        super().__init__()
28        self.handles: List[str] = []
29
30    def _copy_data(self, entity: 'IDBuffer') -> None:
31        """ Copy handles """
32        entity.handles = list(self.handles)
33
34    def load_dxf_attribs(
35            self, processor: SubclassProcessor = None) -> 'DXFNamespace':
36        dxf = super().load_dxf_attribs(processor)
37        if processor:
38            if len(processor.subclasses) < 2:
39                raise DXFStructureError(
40                    f'Missing required subclass in IDBUFFER(#{dxf.handle})')
41            self.load_handles(processor.subclasses[1])
42        return dxf
43
44    def load_handles(self, tags: 'Tags'):
45        self.handles = [value for code, value in tags if code == 330]
46
47    def export_entity(self, tagwriter: 'TagWriter') -> None:
48        """ Export entity specific data as DXF tags. """
49        super().export_entity(tagwriter)
50        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_id_buffer.name)
51        self.export_handles(tagwriter)
52
53    def export_handles(self, tagwriter: 'TagWriter'):
54        for handle in self.handles:
55            tagwriter.write_tag2(330, handle)
56
57
58acdb_id_set = DefSubclass('AcDbIdSet', {
59    'flags': DXFAttr(90, default=0),  # not documented by Autodesk
60})
61acdb_id_set_group_codes = group_code_mapping(acdb_id_set)
62acdb_field_list = DefSubclass('AcDbFieldList', {})
63
64
65@register_entity
66class FieldList(IDBuffer):
67    """ DXF FIELDLIST entity """
68    DXFTYPE = 'FIELDLIST'
69    DXFATTRIBS = DXFAttributes(base_class, acdb_id_set, acdb_field_list)
70
71    def load_dxf_attribs(
72            self, processor: SubclassProcessor = None) -> 'DXFNamespace':
73        dxf = super(DXFObject, self).load_dxf_attribs(processor)
74        if processor:
75            if len(processor.subclasses) < 3:
76                raise DXFStructureError(
77                    f'Missing required subclass in FIELDLIST(#{dxf.handle})')
78            processor.fast_load_dxfattribs(dxf, acdb_id_set_group_codes, 1)
79            # Load field list:
80            self.load_handles(processor.subclasses[2])
81        return dxf
82
83    def export_entity(self, tagwriter: 'TagWriter') -> None:
84        """ Export entity specific data as DXF tags. """
85        super(DXFObject, self).export_entity(tagwriter)
86        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_id_set.name)
87        self.dxf.export_dxf_attribs(tagwriter, 'flags')
88        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_field_list.name)
89        self.export_handles(tagwriter)
90
91
92acdb_filter = DefSubclass('AcDbFilter', {})
93acdb_layer_filter = DefSubclass('AcDbLayerFilter', {})
94
95
96@register_entity
97class LayerFilter(IDBuffer):
98    """ DXF LAYER_FILTER entity """
99    DXFTYPE = 'LAYER_FILTER'
100    DXFATTRIBS = DXFAttributes(base_class, acdb_filter, acdb_layer_filter)
101
102    def load_dxf_attribs(
103            self, processor: SubclassProcessor = None) -> 'DXFNamespace':
104        dxf = super(DXFObject, self).load_dxf_attribs(processor)
105        if processor:
106            if len(processor.subclasses) < 3:
107                raise DXFStructureError(
108                    f'Missing required subclass in LAYER_FILTER(#{dxf.handle})')
109            # Load layer filter:
110            self.load_handles(processor.subclasses[2])
111        return dxf
112
113    def export_entity(self, tagwriter: 'TagWriter') -> None:
114        """ Export entity specific data as DXF tags. """
115        super(DXFObject, self).export_entity(tagwriter)
116        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_filter.name)
117        tagwriter.write_tag2(SUBCLASS_MARKER, acdb_layer_filter.name)
118        self.export_handles(tagwriter)
119