1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: ModelAPI_AttributeRefList.cxx
5 // Author: Mikhail PONIKAROV
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>
16 void Model_AttributeRefList::append(ObjectPtr theObject)
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);
24 owner()->data()->sendAttributeUpdated(this);
27 void Model_AttributeRefList::remove(ObjectPtr theObject)
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);
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>(
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);
50 owner()->data()->sendAttributeUpdated(this);
53 void Model_AttributeRefList::clear()
55 std::list<ObjectPtr> anOldList = list();
57 std::list<ObjectPtr>::iterator anOldIter = anOldList.begin();
58 for(; anOldIter != anOldList.end(); anOldIter++) {
59 REMOVE_BACK_REF((*anOldIter));
61 owner()->data()->sendAttributeUpdated(this);
64 int Model_AttributeRefList::size(const bool theWithEmpty) const
67 return myRef->Extent();
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++;
76 bool Model_AttributeRefList::isInitialized()
78 if (size(false) == 0) { // empty list is not initialized list: sketch will be not valid after add/undo
81 return ModelAPI_AttributeRefList::isInitialized();
84 list<ObjectPtr> Model_AttributeRefList::list()
86 std::list<ObjectPtr> aResult;
87 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
90 const TDF_LabelList& aList = myRef->List();
91 for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
93 if (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot())
94 anObj = aDoc->objects()->object(aLIter.Value());
95 aResult.push_back(anObj);
101 bool Model_AttributeRefList::isInList(const ObjectPtr& theObj)
106 std::list<ObjectPtr> aResult;
107 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
108 owner()->document());
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)) {
124 ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) const
126 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
127 owner()->document());
129 const TDF_LabelList& aList = myRef->List();
131 for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
132 if (theWithEmpty || (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot()))
134 if (anIndex == theIndex) {
135 if (aLIter.Value().IsNull() || aLIter.Value().IsRoot()) { // null label => null sub
138 return aDoc->objects()->object(aLIter.Value());
145 void Model_AttributeRefList::substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew)
147 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
148 owner()->document());
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();
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();
159 aNewLab = aCurrentLab.Root(); // root means null object
161 // do the substitution
162 ADD_BACK_REF(theNew);
163 if (myRef->InsertAfter(aNewLab, aCurrentLab)) {
164 myRef->Remove(aCurrentLab);
165 REMOVE_BACK_REF(theCurrent);
167 owner()->data()->sendAttributeUpdated(this);
172 void Model_AttributeRefList::exchange(const ObjectPtr& theObject1, const ObjectPtr& theObject2)
174 std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(
175 owner()->document());
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);
190 if (myRef->InsertAfter(aLab1, aLab2)) {
191 myRef->Remove(aLab2);
193 if (myRef->InsertAfter(aLab2, aTmpLab)) {
194 myRef->Remove(aTmpLab);
196 owner()->data()->sendAttributeUpdated(this);
203 void Model_AttributeRefList::removeLast()
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());
210 myRef->Remove(myRef->Last());
211 REMOVE_BACK_REF(anObj);
212 owner()->data()->sendAttributeUpdated(this);
217 void Model_AttributeRefList::remove(const std::set<int>& theIndices)
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());
230 for(aLabIter.Initialize(aLabelsToRemove); aLabIter.More(); aLabIter.Next()) {
231 ObjectPtr anObj = aDoc->objects()->object(aLabIter.Value());
233 myRef->Remove(aLabIter.Value());
234 REMOVE_BACK_REF(anObj);
237 if (!aLabelsToRemove.IsEmpty()) {
238 owner()->data()->sendAttributeUpdated(this);
243 Model_AttributeRefList::Model_AttributeRefList(TDF_Label& theLabel)
245 myIsInitialized = theLabel.FindAttribute(TDataStd_ReferenceList::GetID(), myRef) == Standard_True;
246 if (!myIsInitialized) {
247 myRef = TDataStd_ReferenceList::Set(theLabel);