Salome HOME
Implementation of AttributeRefAttrList for a fillet created in the list of points.
[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 if (aTheObjLab.IsNull() && aDoc->objects()->object(aRefIter.Value()) != NULL) {
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     }
150   }
151   return aResult;
152 }
153
154 bool Model_AttributeRefAttrList::isInList(const ObjectPtr& theObj)
155 {
156   if(!theObj.get()) {
157     return false;
158   }
159   std::list<ObjectPtr> aResult;
160   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
161       owner()->document());
162   if (aDoc) {
163     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
164     if (aData.get() && aData->isValid()) {
165       TDF_Label anObjLab = aData->label().Father();
166       const TDF_LabelList& aList = myRef->List();
167       const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
168       TDF_ListIteratorOfLabelList aLIter(aList);
169       TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
170       for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
171         if (anIDIter.Value().IsEmpty() && aLIter.Value().IsEqual(anObjLab)) {
172           return true;
173         }
174       }
175     }
176   }
177   return false;
178 }
179
180 bool Model_AttributeRefAttrList::isInList(const AttributePtr& theAttr)
181 {
182   if (!theAttr->owner().get()) {
183     return false;
184   }
185   std::list<ObjectPtr> aResult;
186   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
187       owner()->document());
188   if (aDoc) {
189     std::shared_ptr<Model_Data> aData = 
190       std::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
191     if (aData.get() && aData->isValid()) {
192       TDF_Label anObjLab = aData->label().Father();
193       const TDF_LabelList& aList = myRef->List();
194       const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
195       TDF_ListIteratorOfLabelList aLIter(aList);
196       TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
197       for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
198         if (anIDIter.Value() == theAttr->id().c_str() && aLIter.Value().IsEqual(anObjLab)) {
199           return true;
200         }
201       }
202     }
203   }
204   return false;
205 }
206
207 bool Model_AttributeRefAttrList::isAttribute(const int theIndex) const
208 {
209   const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
210   TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
211   int anIndex = -1;
212   for (; anIDIter.More(); anIDIter.Next()) {
213     anIndex++;
214     if (anIndex == theIndex) {
215       return !anIDIter.Value().IsEmpty();
216     }
217   }
218   return false;
219 }
220
221 ObjectPtr Model_AttributeRefAttrList::object(const int theIndex) const
222 {
223   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
224       owner()->document());
225   if (aDoc) {
226     const TDF_LabelList& aList = myRef->List();
227     int anIndex = -1;
228     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
229       anIndex++;
230       if (anIndex == theIndex) {
231         if (aLIter.Value().IsNull()) { // null label => null sub
232           return ObjectPtr();
233         }
234         return aDoc->objects()->object(aLIter.Value());
235       }
236     }
237   }
238   return ObjectPtr();
239 }
240
241 AttributePtr Model_AttributeRefAttrList::attribute(const int theIndex) const
242 {
243   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
244       owner()->document());
245   if (aDoc) {
246     int anIndex = -1;
247     const TDF_LabelList& aList = myRef->List();
248     const TDataStd_ListOfExtendedString& anIDList = myIDs->List();
249     TDF_ListIteratorOfLabelList aLIter(aList);
250     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
251     for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
252       anIndex++;
253       if (anIndex == theIndex) {
254         if (aLIter.Value().IsNull()) { // null label => null sub
255           return AttributePtr();
256         }
257         return aDoc->objects()->object(aLIter.Value())->data()->
258           attribute(TCollection_AsciiString(anIDIter.Value().ToExtString()).ToCString());
259       }
260     }
261   }
262   return AttributePtr();
263 }
264
265 void Model_AttributeRefAttrList::removeLast()
266 {
267   // remove from the both lists by clearing the list and then appending one by one
268   // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
269   std::set<int> aLastSet;
270   aLastSet.insert(size() - 1);
271   remove(aLastSet);
272 }
273
274 void Model_AttributeRefAttrList::remove(const std::set<int>& theIndices)
275 {
276   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
277       owner()->document());
278   if (aDoc && !myRef->IsEmpty()) {
279     // remove from the both lists by clearing the list and then appending one by one
280     // TODO: in OCCT 7.0 there are methods for removing by index, seems will be more optimal
281     TDF_LabelList aRefList = myRef->List();
282     myRef->Clear();
283     TDataStd_ListOfExtendedString anIDList = myIDs->List();
284     myIDs->Clear();
285     bool aOneisDeleted = false;
286     TDF_ListIteratorOfLabelList aRefIter(aRefList);
287     TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
288     for (int anIndex = 0; aRefIter.More(); aRefIter.Next(), anIDIter.Next(), anIndex++) {
289       if (theIndices.find(anIndex) == theIndices.end()) { // not found
290         myRef->Append(aRefIter.Value());
291         myIDs->Append(anIDIter.Value());
292       } else { // found, so need to update the dependencies
293         aOneisDeleted = true;
294         ObjectPtr anObj = aDoc->objects()->object(aRefIter.Value());
295         if (anObj.get()) {
296           myRef->Remove(aRefIter.Value());
297           REMOVE_BACK_REF(anObj);
298         }
299       }
300     }
301     if (aOneisDeleted) {
302       owner()->data()->sendAttributeUpdated(this);
303     }
304   }
305 }
306
307 Model_AttributeRefAttrList::Model_AttributeRefAttrList(TDF_Label& theLabel)
308 {
309   myIsInitialized = theLabel.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
310   if (!myIsInitialized) {
311     myRef = TDataStd_ReferenceList::Set(theLabel);
312     myIDs = TDataStd_ExtStringList::Set(theLabel);
313   } else {
314     theLabel.FindAttribute(TDataStd_ExtStringList::GetID(), myIDs);
315   }
316 }