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