Salome HOME
Issue #1305: Make different gray color for selectable and non-selectable items
[modules/shaper.git] / src / Model / Model_AttributeRefList.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModelAPI_AttributeRefList.cxx
4 // Created:     8 May 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include "Model_AttributeRefList.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
14 using namespace std;
15
16 void Model_AttributeRefList::append(ObjectPtr theObject)
17 {
18   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
19   myRef->Append(aData->label().Father());  // store label of the object
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_AttributeRefList::remove(ObjectPtr theObject)
28 {
29   std::shared_ptr<Model_Data> aData;
30   if (theObject.get() != NULL) {
31     aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
32     myRef->Remove(aData->label().Father());
33     REMOVE_BACK_REF(theObject);
34   }
35   else { // in case of empty object remove, the first empty object is removed from the list
36     std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
37         owner()->document());
38     if (aDoc) {
39       const TDF_LabelList& aList = myRef->List();
40       for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
41         ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
42         if (anObj.get() == NULL) {
43           myRef->Remove(aLIter.Value());
44           REMOVE_BACK_REF(theObject);
45           break;
46         }
47       }
48     }
49   }
50   owner()->data()->sendAttributeUpdated(this);
51 }
52
53 void Model_AttributeRefList::clear()
54 {
55   std::list<ObjectPtr> anOldList = list();
56   myRef->Clear();
57   std::list<ObjectPtr>::iterator anOldIter = anOldList.begin();
58   for(; anOldIter != anOldList.end(); anOldIter++) {
59     REMOVE_BACK_REF((*anOldIter));
60   }
61   owner()->data()->sendAttributeUpdated(this);
62 }
63
64 int Model_AttributeRefList::size(const bool theWithEmpty) const
65 {
66   if (theWithEmpty)
67     return myRef->Extent();
68   int aResult = 0;
69   const TDF_LabelList& aList = myRef->List();
70   for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
71     if (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()) aResult++;
72   }
73   return aResult;
74 }
75
76 bool Model_AttributeRefList::isInitialized()
77 {
78   if (size(false) == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
79     return false;
80   }
81   return ModelAPI_AttributeRefList::isInitialized();
82 }
83
84 list<ObjectPtr> Model_AttributeRefList::list()
85 {
86   std::list<ObjectPtr> aResult;
87   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
88       owner()->document());
89   if (aDoc) {
90     const TDF_LabelList& aList = myRef->List();
91     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
92       ObjectPtr anObj;
93       if (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot())
94         anObj = aDoc->objects()->object(aLIter.Value());
95       aResult.push_back(anObj);
96     }
97   }
98   return aResult;
99 }
100
101 bool Model_AttributeRefList::isInList(const ObjectPtr& theObj)
102 {
103   if(!theObj.get()) {
104     return false;
105   }
106   std::list<ObjectPtr> aResult;
107   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
108       owner()->document());
109   if (aDoc) {
110     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObj->data());
111     if (aData.get() && aData->isValid()) {
112       TDF_Label anObjLab = aData->label().Father();
113       const TDF_LabelList& aList = myRef->List();
114       for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
115         if (aLIter.Value().IsEqual(anObjLab)) {
116           return true;
117         }
118       }
119     }
120   }
121   return false;
122 }
123
124 ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) const
125 {
126   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
127       owner()->document());
128   if (aDoc) {
129     const TDF_LabelList& aList = myRef->List();
130     int anIndex = -1;
131     for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
132       if (theWithEmpty || (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()))
133         anIndex++;
134       if (anIndex == theIndex) {
135         if (aLIter.Value().IsNull() || aLIter.Value().IsRoot()) { // null label => null sub
136           return ObjectPtr();
137         }
138         return aDoc->objects()->object(aLIter.Value());
139       }
140     }
141   }
142   return ObjectPtr();
143 }
144
145 void Model_AttributeRefList::substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew)
146 {
147   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
148       owner()->document());
149   if (aDoc) {
150     std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theCurrent->data());
151     if (aData.get() && aData->isValid()) {
152       TDF_Label aCurrentLab = aData->label().Father();
153       TDF_Label aNewLab;
154       if (theNew.get() && theNew->data()->isValid()) { // the new may be null
155         std::shared_ptr<Model_Data> aNewData = 
156           std::dynamic_pointer_cast<Model_Data>(theNew->data());
157         aNewLab = aNewData->label().Father();
158       } else {
159         aNewLab = aCurrentLab.Root(); // root means null object
160       }
161       // do the substitution
162       ADD_BACK_REF(theNew);
163       if (myRef->InsertAfter(aNewLab, aCurrentLab)) {
164         myRef->Remove(aCurrentLab);
165         REMOVE_BACK_REF(theCurrent);
166       }
167       owner()->data()->sendAttributeUpdated(this);
168     }
169   }
170 }
171
172 void Model_AttributeRefList::exchange(const ObjectPtr& theObject1, const ObjectPtr& theObject2)
173 {
174   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
175       owner()->document());
176   if (aDoc) {
177     std::shared_ptr<Model_Data> aData1 = std::dynamic_pointer_cast<Model_Data>(theObject1->data());
178     if (aData1.get() && aData1->isValid()) {
179       TDF_Label aLab1 = aData1->label().Father();
180       if (theObject2.get() && theObject2->data()->isValid()) { // the new may be null
181         std::shared_ptr<Model_Data> aData2 = 
182           std::dynamic_pointer_cast<Model_Data>(theObject2->data());
183         if (aData2.get() && aData2->isValid()) {
184           TDF_Label aLab2 = aData2->label().Father();
185           // do the substitution: use the temporary label, as usually in exchange
186           TDF_Label aTmpLab = aLab1.Root();
187           if (myRef->InsertAfter(aTmpLab, aLab1)) {
188             myRef->Remove(aLab1);
189           }
190           if (myRef->InsertAfter(aLab1, aLab2)) {
191             myRef->Remove(aLab2);
192           }
193           if (myRef->InsertAfter(aLab2, aTmpLab)) {
194             myRef->Remove(aTmpLab);
195           }
196           owner()->data()->sendAttributeUpdated(this);
197         }
198       }
199     }
200   }
201 }
202
203 void Model_AttributeRefList::removeLast()
204 {
205   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
206       owner()->document());
207   if (aDoc && !myRef->IsEmpty()) {
208     ObjectPtr anObj = aDoc->objects()->object(myRef->Last());
209     if (anObj.get()) {
210       myRef->Remove(myRef->Last());
211       REMOVE_BACK_REF(anObj);
212       owner()->data()->sendAttributeUpdated(this);
213     }
214   }
215 }
216
217 void Model_AttributeRefList::remove(const std::set<int>& theIndices)
218 {
219   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
220       owner()->document());
221   if (aDoc && !myRef->IsEmpty()) {
222     // collet labels that will be removed
223     TDF_LabelList aLabelsToRemove;
224     TDF_ListIteratorOfLabelList aLabIter(myRef->List());
225     for(int aCurrent = 0; aLabIter.More(); aLabIter.Next(), aCurrent++) {
226       if (theIndices.find(aCurrent) != theIndices.end())
227         aLabelsToRemove.Append(aLabIter.Value());
228     }
229     // remove labels
230     for(aLabIter.Initialize(aLabelsToRemove); aLabIter.More(); aLabIter.Next()) {
231       ObjectPtr anObj = aDoc->objects()->object(aLabIter.Value());
232       if (anObj.get()) {
233         myRef->Remove(aLabIter.Value());
234         REMOVE_BACK_REF(anObj);
235       }
236     }
237     if (!aLabelsToRemove.IsEmpty()) {
238       owner()->data()->sendAttributeUpdated(this);
239     }
240   }
241 }
242
243 Model_AttributeRefList::Model_AttributeRefList(TDF_Label& theLabel)
244 {
245   myIsInitialized = theLabel.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
246   if (!myIsInitialized) {
247     myRef = TDataStd_ReferenceList::Set(theLabel);
248   }
249 }