Salome HOME
Issue #1834: Fix length of lines
[modules/shaper.git] / src / Model / Model_AttributeRefAttrList.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModelAPI_AttributeRefAttrList.cxx
4 // Created:     8 May 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include "Model_AttributeRefAttrList.h"
8 #include "Model_Application.h"
9 #include "Model_Data.h"
10 #include "Model_Objects.h"
11 #include <ModelAPI_Feature.h>
12 #include <TDF_ListIteratorOfLabelList.hxx>
13 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
14
15 using namespace std;
16
17 void Model_AttributeRefAttrList::append(ObjectPtr theObject)
18 {
19   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
20   myRef->Append(aData->label().Father());  // store label of the object
21   myIDs->Append(""); // for the object store an empty string
22   // do it before the transaction finish to make just created/removed objects know dependencies
23   // and reference from composite feature is removed automatically
24   ADD_BACK_REF(theObject);
25
26   owner()->data()->sendAttributeUpdated(this);
27 }
28
29 void Model_AttributeRefAttrList::append(AttributePtr theAttr)
30 {
31   std::shared_ptr<Model_Data> aData = 
32     std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
33   myRef->Append(aData->label().Father());  // store label of the object
34   myIDs->Append(theAttr->id().c_str()); // store the ID of the referenced attribute
35   // do it before the transaction finish to make just created/removed objects know dependencies
36   // and reference from composite feature is removed automatically
37   ADD_BACK_REF(theAttr->owner());
38
39   owner()->data()->sendAttributeUpdated(this);
40 }
41
42 void Model_AttributeRefAttrList::remove(ObjectPtr theObject)
43 {
44   TDF_Label aTheObjLab;
45   if (theObject.get() != NULL) {
46     aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theObject->data())->label().Father();
47   }
48   std::shared_ptr<Model_Document> aDoc = 
49     std::dynamic_pointer_cast<Model_Document>(owner()->document());
50   // remove from the both lists by clearing the list and then appending one by one
51   // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
52   TDF_LabelList aRefList = myRef->List();
53   myRef->Clear();
54   TDataStd_ListOfExtendedString anIDList = myIDs->List();
55   myIDs->Clear();
56   bool aOneisDeleted = false;
57   TDF_ListIteratorOfLabelList aRefIter(aRefList);
58   TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
59   for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
60     // append now only not removed
61     if (aOneisDeleted || aRefIter.Value() != aTheObjLab || !anIDIter.Value().IsEmpty() ||
62       (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
63       myRef->Append(aRefIter.Value());
64       myIDs->Append(anIDIter.Value());
65     } else if (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL) {
66       aOneisDeleted = true;
67     }
68   }
69   if (aOneisDeleted) {
70     REMOVE_BACK_REF(theObject);
71     owner()->data()->sendAttributeUpdated(this);
72   }
73 }
74
75 void Model_AttributeRefAttrList::remove(AttributePtr theAttr)
76 {
77   TDF_Label aTheObjLab;
78   if (theAttr->owner().get() != NULL) {
79     aTheObjLab = std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data())->label().Father();
80   }
81   std::shared_ptr<Model_Document> aDoc = 
82     std::dynamic_pointer_cast<Model_Document>(owner()->document());
83   // remove from the both lists by clearing the list and then appending one by one
84   // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
85   TDF_LabelList aRefList = myRef->List();
86   myRef->Clear();
87   TDataStd_ListOfExtendedString anIDList = myIDs->List();
88   myIDs->Clear();
89   bool aOneisDeleted = false;
90   TDF_ListIteratorOfLabelList aRefIter(aRefList);
91   TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
92   for (; aRefIter.More(); aRefIter.Next(), anIDIter.Next()) {
93     if (aOneisDeleted || anIDIter.Value() != theAttr->id().c_str() ||  
94         // append now only not removed
95         aRefIter.Value() != aTheObjLab || // append now only not removed
96         (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
97       myRef->Append(aRefIter.Value());
98       myIDs->Append(anIDIter.Value());
99     } else {
100       aOneisDeleted = true;
101     }
102   }
103   if (aOneisDeleted) {
104     REMOVE_BACK_REF(theAttr->owner());
105     owner()->data()->sendAttributeUpdated(this);
106   }
107 }
108
109 void Model_AttributeRefAttrList::clear()
110 {
111   std::list<std::pair<ObjectPtr, AttributePtr> > anOldList = list();
112   myRef->Clear();
113   myIDs->Clear();
114   std::list<std::pair<ObjectPtr, AttributePtr> >::iterator anOldIter = anOldList.begin();
115   for(; anOldIter != anOldList.end(); anOldIter++) {
116     REMOVE_BACK_REF((anOldIter->first));
117   }
118   owner()->data()->sendAttributeUpdated(this);
119 }
120
121 int Model_AttributeRefAttrList::size() const
122 {
123   return myRef->Extent();
124 }
125
126 bool Model_AttributeRefAttrList::isInitialized()
127 {
128   if (size() == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
129     return false;
130   }
131   return ModelAPI_AttributeRefAttrList::isInitialized();
132 }
133
134 std::list<std::pair<ObjectPtr, AttributePtr> > Model_AttributeRefAttrList::list()
135 {
136   std::list<std::pair<ObjectPtr, AttributePtr> > aResult;
137   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
138       owner()->document());
139   if (aDoc) {
140     const TDF_LabelList& aList = myRef->List();
141     const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
142     TDF_ListIteratorOfLabelList aLIter(aList);
143     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
144     for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
145       ObjectPtr anObj;
146       if (!aLIter.Value().IsNull()) {
147         anObj = aDoc->objects()->object(aLIter.Value());
148         aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj, 
149           anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
150       } else {
151         aResult.push_back(std::pair<ObjectPtr, AttributePtr>(ObjectPtr(), AttributePtr()));
152       }
153     }
154   }
155   return aResult;
156 }
157
158 bool Model_AttributeRefAttrList::isInList(const ObjectPtr& theObj)
159 {
160   if(!theObj.get()) {
161     return false;
162   }
163   std::list<ObjectPtr> aResult;
164   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
165       owner()->document());
166   if (aDoc) {
167     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
168     if (aData.get() && aData->isValid()) {
169       TDF_Label anObjLab = aData->label().Father();
170       const TDF_LabelList& aList = myRef->List();
171       const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
172       TDF_ListIteratorOfLabelList aLIter(aList);
173       TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
174       for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
175         if (anIDIter.Value().IsEmpty() && aLIter.Value().IsEqual(anObjLab)) {
176           return true;
177         }
178       }
179     }
180   }
181   return false;
182 }
183
184 bool Model_AttributeRefAttrList::isInList(const AttributePtr& theAttr)
185 {
186   if (!theAttr->owner().get()) {
187     return false;
188   }
189   std::list<ObjectPtr> aResult;
190   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
191       owner()->document());
192   if (aDoc) {
193     std::shared_ptr<Model_Data> aData = 
194       std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
195     if (aData.get() && aData->isValid()) {
196       TDF_Label anObjLab = aData->label().Father();
197       const TDF_LabelList& aList = myRef->List();
198       const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
199       TDF_ListIteratorOfLabelList aLIter(aList);
200       TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
201       for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
202         if (anIDIter.Value() == theAttr->id().c_str() && aLIter.Value().IsEqual(anObjLab)) {
203           return true;
204         }
205       }
206     }
207   }
208   return false;
209 }
210
211 bool Model_AttributeRefAttrList::isAttribute(const int theIndex) const
212 {
213   const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
214   TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
215   int anIndex = -1;
216   for (; anIDIter.More(); anIDIter.Next()) {
217     anIndex++;
218     if (anIndex == theIndex) {
219       return !anIDIter.Value().IsEmpty();
220     }
221   }
222   return false;
223 }
224
225 ObjectPtr Model_AttributeRefAttrList::object(const int theIndex) const
226 {
227   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
228       owner()->document());
229   if (aDoc) {
230     const TDF_LabelList& aList = myRef->List();
231     int anIndex = -1;
232     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
233       anIndex++;
234       if (anIndex == theIndex) {
235         if (aLIter.Value().IsNull()) { // null label => null sub
236           return ObjectPtr();
237         }
238         return aDoc->objects()->object(aLIter.Value());
239       }
240     }
241   }
242   return ObjectPtr();
243 }
244
245 AttributePtr Model_AttributeRefAttrList::attribute(const int theIndex) const
246 {
247   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
248       owner()->document());
249   if (aDoc) {
250     int anIndex = -1;
251     const TDF_LabelList& aList = myRef->List();
252     const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
253     TDF_ListIteratorOfLabelList aLIter(aList);
254     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
255     for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
256       anIndex++;
257       if (anIndex == theIndex) {
258         if (aLIter.Value().IsNull()) { // null label => null sub
259           return AttributePtr();
260         }
261         return aDoc->objects()->object(aLIter.Value())->data()->
262           attribute(TCollection_AsciiString(anIDIter.Value().ToExtString()).ToCString());
263       }
264     }
265   }
266   return AttributePtr();
267 }
268
269 void Model_AttributeRefAttrList::removeLast()
270 {
271   // remove from the both lists by clearing the list and then appending one by one
272   // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
273   std::set<int> aLastSet;
274   aLastSet.insert(size() - 1);
275   remove(aLastSet);
276 }
277
278 void Model_AttributeRefAttrList::remove(const std::set<int>& theIndices)
279 {
280   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
281       owner()->document());
282   if (aDoc && !myRef->IsEmpty()) {
283     // remove from the both lists by clearing the list and then appending one by one
284     // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
285     TDF_LabelList aRefList = myRef->List();
286     myRef->Clear();
287     TDataStd_ListOfExtendedString anIDList = myIDs->List();
288     myIDs->Clear();
289     bool aOneisDeleted = false;
290     TDF_ListIteratorOfLabelList aRefIter(aRefList);
291     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
292     for (int anIndex = 0; aRefIter.More(); aRefIter.Next(), anIDIter.Next(), anIndex++) {
293       if (theIndices.find(anIndex) == theIndices.end()) { // not found
294         myRef->Append(aRefIter.Value());
295         myIDs->Append(anIDIter.Value());
296       } else { // found, so need to update the dependencies
297         aOneisDeleted = true;
298         ObjectPtr anObj = aDoc->objects()->object(aRefIter.Value());
299         if (anObj.get()) {
300           REMOVE_BACK_REF(anObj);
301         }
302       }
303     }
304     if (aOneisDeleted) {
305       owner()->data()->sendAttributeUpdated(this);
306     }
307   }
308 }
309
310 Model_AttributeRefAttrList::Model_AttributeRefAttrList(TDF_Label& theLabel)
311 {
312   myLab = theLabel;
313   reinit();
314 }
315
316 void Model_AttributeRefAttrList::reinit()
317 {
318   myIsInitialized = myLab.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
319   if (!myIsInitialized) {
320     myRef = TDataStd_ReferenceList::Set(myLab);
321     myIDs = TDataStd_ExtStringList::Set(myLab);
322   } else {
323     myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myIDs);
324   }
325 }