Salome HOME
Added the system of reinitialization of attributes instead of re-creation of them...
[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() ||  // append now only not removed
94         aRefIter.Value() != aTheObjLab || // append now only not removed
95         (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL)) {
96       myRef->Append(aRefIter.Value());
97       myIDs->Append(anIDIter.Value());
98     } else {
99       aOneisDeleted = true;
100     }
101   }
102   if (aOneisDeleted) {
103     REMOVE_BACK_REF(theAttr->owner());
104     owner()->data()->sendAttributeUpdated(this);
105   }
106 }
107
108 void Model_AttributeRefAttrList::clear()
109 {
110   std::list<std::pair<ObjectPtr, AttributePtr> > anOldList = list();
111   myRef->Clear();
112   myIDs->Clear();
113   std::list<std::pair<ObjectPtr, AttributePtr> >::iterator anOldIter = anOldList.begin();
114   for(; anOldIter != anOldList.end(); anOldIter++) {
115     REMOVE_BACK_REF((anOldIter->first));
116   }
117   owner()->data()->sendAttributeUpdated(this);
118 }
119
120 int Model_AttributeRefAttrList::size() const
121 {
122   return myRef->Extent();
123 }
124
125 bool Model_AttributeRefAttrList::isInitialized()
126 {
127   if (size() == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
128     return false;
129   }
130   return ModelAPI_AttributeRefAttrList::isInitialized();
131 }
132
133 std::list<std::pair<ObjectPtr, AttributePtr> > Model_AttributeRefAttrList::list()
134 {
135   std::list<std::pair<ObjectPtr, AttributePtr> > aResult;
136   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
137       owner()->document());
138   if (aDoc) {
139     const TDF_LabelList& aList = myRef->List();
140     const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
141     TDF_ListIteratorOfLabelList aLIter(aList);
142     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
143     for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
144       ObjectPtr anObj;
145       if (!aLIter.Value().IsNull()) {
146         anObj = aDoc->objects()->object(aLIter.Value());
147         aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj, 
148           anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
149       } else {
150         aResult.push_back(std::pair<ObjectPtr, AttributePtr>(ObjectPtr(), AttributePtr()));
151       }
152     }
153   }
154   return aResult;
155 }
156
157 bool Model_AttributeRefAttrList::isInList(const ObjectPtr& theObj)
158 {
159   if(!theObj.get()) {
160     return false;
161   }
162   std::list<ObjectPtr> aResult;
163   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
164       owner()->document());
165   if (aDoc) {
166     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
167     if (aData.get() && aData->isValid()) {
168       TDF_Label anObjLab = aData->label().Father();
169       const TDF_LabelList& aList = myRef->List();
170       const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
171       TDF_ListIteratorOfLabelList aLIter(aList);
172       TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
173       for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
174         if (anIDIter.Value().IsEmpty() && aLIter.Value().IsEqual(anObjLab)) {
175           return true;
176         }
177       }
178     }
179   }
180   return false;
181 }
182
183 bool Model_AttributeRefAttrList::isInList(const AttributePtr& theAttr)
184 {
185   if (!theAttr->owner().get()) {
186     return false;
187   }
188   std::list<ObjectPtr> aResult;
189   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
190       owner()->document());
191   if (aDoc) {
192     std::shared_ptr<Model_Data> aData = 
193       std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
194     if (aData.get() && aData->isValid()) {
195       TDF_Label anObjLab = aData->label().Father();
196       const TDF_LabelList& aList = myRef->List();
197       const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
198       TDF_ListIteratorOfLabelList aLIter(aList);
199       TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
200       for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
201         if (anIDIter.Value() == theAttr->id().c_str() && aLIter.Value().IsEqual(anObjLab)) {
202           return true;
203         }
204       }
205     }
206   }
207   return false;
208 }
209
210 bool Model_AttributeRefAttrList::isAttribute(const int theIndex) const
211 {
212   const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
213   TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
214   int anIndex = -1;
215   for (; anIDIter.More(); anIDIter.Next()) {
216     anIndex++;
217     if (anIndex == theIndex) {
218       return !anIDIter.Value().IsEmpty();
219     }
220   }
221   return false;
222 }
223
224 ObjectPtr Model_AttributeRefAttrList::object(const int theIndex) const
225 {
226   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
227       owner()->document());
228   if (aDoc) {
229     const TDF_LabelList& aList = myRef->List();
230     int anIndex = -1;
231     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
232       anIndex++;
233       if (anIndex == theIndex) {
234         if (aLIter.Value().IsNull()) { // null label => null sub
235           return ObjectPtr();
236         }
237         return aDoc->objects()->object(aLIter.Value());
238       }
239     }
240   }
241   return ObjectPtr();
242 }
243
244 AttributePtr Model_AttributeRefAttrList::attribute(const int theIndex) const
245 {
246   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
247       owner()->document());
248   if (aDoc) {
249     int anIndex = -1;
250     const TDF_LabelList& aList = myRef->List();
251     const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
252     TDF_ListIteratorOfLabelList aLIter(aList);
253     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
254     for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
255       anIndex++;
256       if (anIndex == theIndex) {
257         if (aLIter.Value().IsNull()) { // null label => null sub
258           return AttributePtr();
259         }
260         return aDoc->objects()->object(aLIter.Value())->data()->
261           attribute(TCollection_AsciiString(anIDIter.Value().ToExtString()).ToCString());
262       }
263     }
264   }
265   return AttributePtr();
266 }
267
268 void Model_AttributeRefAttrList::removeLast()
269 {
270   // remove from the both lists by clearing the list and then appending one by one
271   // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
272   std::set<int> aLastSet;
273   aLastSet.insert(size() - 1);
274   remove(aLastSet);
275 }
276
277 void Model_AttributeRefAttrList::remove(const std::set<int>& theIndices)
278 {
279   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
280       owner()->document());
281   if (aDoc && !myRef->IsEmpty()) {
282     // remove from the both lists by clearing the list and then appending one by one
283     // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
284     TDF_LabelList aRefList = myRef->List();
285     myRef->Clear();
286     TDataStd_ListOfExtendedString anIDList = myIDs->List();
287     myIDs->Clear();
288     bool aOneisDeleted = false;
289     TDF_ListIteratorOfLabelList aRefIter(aRefList);
290     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
291     for (int anIndex = 0; aRefIter.More(); aRefIter.Next(), anIDIter.Next(), anIndex++) {
292       if (theIndices.find(anIndex) == theIndices.end()) { // not found
293         myRef->Append(aRefIter.Value());
294         myIDs->Append(anIDIter.Value());
295       } else { // found, so need to update the dependencies
296         aOneisDeleted = true;
297         ObjectPtr anObj = aDoc->objects()->object(aRefIter.Value());
298         if (anObj.get()) {
299           REMOVE_BACK_REF(anObj);
300         }
301       }
302     }
303     if (aOneisDeleted) {
304       owner()->data()->sendAttributeUpdated(this);
305     }
306   }
307 }
308
309 Model_AttributeRefAttrList::Model_AttributeRefAttrList(TDF_Label& theLabel)
310 {
311   myLab = theLabel;
312   reinit();
313 }
314
315 void Model_AttributeRefAttrList::reinit()
316 {
317   myIsInitialized = myLab.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
318   if (!myIsInitialized) {
319     myRef = TDataStd_ReferenceList::Set(myLab);
320     myIDs = TDataStd_ExtStringList::Set(myLab);
321   } else {
322     myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myIDs);
323   }
324 }