Salome HOME
Implementation of "isDisplayed" persistent flag
[modules/shaper.git] / src / Model / Model_Data.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_Data.hxx
4 // Created:     21 Mar 2014
5 // Author:      Mikhail PONIKAROV
6
7 #include <Model_Data.h>
8 #include <Model_AttributeDocRef.h>
9 #include <Model_AttributeInteger.h>
10 #include <Model_AttributeDouble.h>
11 #include <Model_AttributeReference.h>
12 #include <Model_AttributeRefAttr.h>
13 #include <Model_AttributeRefList.h>
14 #include <Model_AttributeBoolean.h>
15 #include <Model_AttributeString.h>
16 #include <Model_AttributeSelection.h>
17 #include <Model_AttributeSelectionList.h>
18 #include <Model_AttributeIntArray.h>
19 #include <Model_Events.h>
20 #include <ModelAPI_Feature.h>
21 #include <ModelAPI_Result.h>
22 #include <ModelAPI_Validator.h>
23 #include <ModelAPI_Session.h>
24
25 #include <GeomData_Point.h>
26 #include <GeomData_Point2D.h>
27 #include <GeomData_Dir.h>
28 #include <Events_Loop.h>
29 #include <Events_Error.h>
30
31 #include <TDataStd_Name.hxx>
32 #include <TDataStd_AsciiString.hxx>
33 #include <TDF_AttributeIterator.hxx>
34 #include <TDF_ChildIterator.hxx>
35 #include <TDF_RelocationTable.hxx>
36
37 #include <string>
38
39 // myLab contains:
40 // TDataStd_Name - name of the object
41 // TDataStd_Integer - state of the object execution
42 // TDataStd_BooleanArray - array of flags of this data:
43 //                             0 - is in history or not
44 static const int kFlagInHistory = 0;
45 //                             1 - is displayed or not
46 static const int kFlagDisplayed = 1;
47
48 Model_Data::Model_Data() : mySendAttributeUpdated(true)
49 {
50 }
51
52 void Model_Data::setLabel(TDF_Label theLab)
53 {
54   myLab = theLab;
55   // set or get the default flags
56   if (!myLab.FindAttribute(TDataStd_BooleanArray::GetID(), myFlags)) {
57     // set default values if not found
58     Handle(TDataStd_BooleanArray) myFlags = TDataStd_BooleanArray::Set(myLab, 0, 1);
59     myFlags->SetValue(kFlagInHistory, Standard_True); // is in history by default is true
60     myFlags->SetValue(kFlagDisplayed, Standard_True); // is displayed by default is true
61   }
62 }
63
64 std::string Model_Data::name()
65 {
66   Handle(TDataStd_Name) aName;
67   if (myLab.FindAttribute(TDataStd_Name::GetID(), aName))
68     return std::string(TCollection_AsciiString(aName->Get()).ToCString());
69   return "";  // not defined
70 }
71
72 void Model_Data::setName(const std::string& theName)
73 {
74   bool isModified = false;
75   Handle(TDataStd_Name) aName;
76   if (!myLab.FindAttribute(TDataStd_Name::GetID(), aName)) {
77     TDataStd_Name::Set(myLab, theName.c_str());
78     isModified = true;
79   } else {
80     isModified = !aName->Get().IsEqual(theName.c_str());
81     if (isModified)
82       aName->Set(theName.c_str());
83   }
84 }
85
86 AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType)
87 {
88   AttributePtr aResult;
89   TDF_Label anAttrLab = myLab.FindChild(myAttrs.size() + 1);
90   ModelAPI_Attribute* anAttr = 0;
91   if (theAttrType == ModelAPI_AttributeDocRef::typeId()) {
92     anAttr = new Model_AttributeDocRef(anAttrLab);
93   } else if (theAttrType == Model_AttributeInteger::typeId()) {
94     anAttr = new Model_AttributeInteger(anAttrLab);
95   } else if (theAttrType == ModelAPI_AttributeDouble::typeId()) {
96     anAttr = new Model_AttributeDouble(anAttrLab);
97   } else if (theAttrType == Model_AttributeBoolean::typeId()) {
98     anAttr = new Model_AttributeBoolean(anAttrLab);
99   } else if (theAttrType == Model_AttributeString::typeId()) {
100     anAttr = new Model_AttributeString(anAttrLab);
101   } else if (theAttrType == ModelAPI_AttributeReference::typeId()) {
102     anAttr = new Model_AttributeReference(anAttrLab);
103   } else if (theAttrType == ModelAPI_AttributeSelection::typeId()) {
104     anAttr = new Model_AttributeSelection(anAttrLab);
105   } else if (theAttrType == ModelAPI_AttributeSelectionList::typeId()) {
106     anAttr = new Model_AttributeSelectionList(anAttrLab);
107   } else if (theAttrType == ModelAPI_AttributeRefAttr::typeId()) {
108     anAttr = new Model_AttributeRefAttr(anAttrLab);
109   } else if (theAttrType == ModelAPI_AttributeRefList::typeId()) {
110     anAttr = new Model_AttributeRefList(anAttrLab);
111   } else if (theAttrType == ModelAPI_AttributeIntArray::typeId()) {
112     anAttr = new Model_AttributeIntArray(anAttrLab);
113   } 
114   // create also GeomData attributes here because only here the OCAF strucure is known
115   else if (theAttrType == GeomData_Point::typeId()) {
116     anAttr = new GeomData_Point(anAttrLab);
117   } else if (theAttrType == GeomData_Dir::typeId()) {
118     anAttr = new GeomData_Dir(anAttrLab);
119   } else if (theAttrType == GeomData_Point2D::typeId()) {
120     anAttr = new GeomData_Point2D(anAttrLab);
121   }
122   if (anAttr) {
123     aResult = std::shared_ptr<ModelAPI_Attribute>(anAttr);
124     myAttrs[theID] = aResult;
125     anAttr->setObject(myObject);
126     anAttr->setID(theID);
127   } else {
128     Events_Error::send("Can not create unknown type of attribute " + theAttrType);
129   }
130   return aResult;
131 }
132
133 // macro for gthe generic returning of the attribute by the ID
134 #define GET_ATTRIBUTE_BY_ID(ATTR_TYPE, METHOD_NAME) \
135   std::shared_ptr<ATTR_TYPE> Model_Data::METHOD_NAME(const std::string& theID) { \
136     std::shared_ptr<ATTR_TYPE> aRes; \
137     std::map<std::string, AttributePtr >::iterator aFound = \
138       myAttrs.find(theID); \
139     if (aFound != myAttrs.end()) { \
140       aRes = std::dynamic_pointer_cast<ATTR_TYPE>(aFound->second); \
141     } \
142     return aRes; \
143   }
144 // implement nice getting methods for all ModelAPI attributes
145 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDocRef, document);
146 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDouble, real);
147 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeInteger, integer);
148 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeBoolean, boolean);
149 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeString, string);
150 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeReference, reference);
151 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeSelection, selection);
152 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeSelectionList, selectionList);
153 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefAttr, refattr);
154 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefList, reflist);
155 GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeIntArray, intArray);
156
157 std::shared_ptr<ModelAPI_Attribute> Model_Data::attribute(const std::string& theID)
158 {
159   std::shared_ptr<ModelAPI_Attribute> aResult;
160   if (myAttrs.find(theID) == myAttrs.end())  // no such attribute
161     return aResult;
162   return myAttrs[theID];
163 }
164
165 const std::string& Model_Data::id(const std::shared_ptr<ModelAPI_Attribute>& theAttr)
166 {
167   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = 
168     myAttrs.begin();
169   for (; anAttr != myAttrs.end(); anAttr++) {
170     if (anAttr->second == theAttr)
171       return anAttr->first;
172   }
173   // not found
174   static std::string anEmpty;
175   return anEmpty;
176 }
177
178 bool Model_Data::isEqual(const std::shared_ptr<ModelAPI_Data>& theData)
179 {
180   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theData);
181   if (aData)
182     return myLab.IsEqual(aData->myLab) == Standard_True ;
183   return false;
184 }
185
186 bool Model_Data::isValid()
187 {
188   return !myLab.IsNull() && myLab.HasAttribute();
189 }
190
191 std::list<std::shared_ptr<ModelAPI_Attribute> > Model_Data::attributes(const std::string& theType)
192 {
193   std::list<std::shared_ptr<ModelAPI_Attribute> > aResult;
194   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrsIter = 
195     myAttrs.begin();
196   for (; anAttrsIter != myAttrs.end(); anAttrsIter++) {
197     if (theType.empty() || anAttrsIter->second->attributeType() == theType) {
198       aResult.push_back(anAttrsIter->second);
199     }
200   }
201   return aResult;
202 }
203
204 std::list<std::string> Model_Data::attributesIDs(const std::string& theType) 
205 {
206   std::list<std::string> aResult;
207   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrsIter = 
208     myAttrs.begin();
209   for (; anAttrsIter != myAttrs.end(); anAttrsIter++) {
210     if (theType.empty() || anAttrsIter->second->attributeType() == theType) {
211       aResult.push_back(anAttrsIter->first);
212     }
213   }
214   return aResult;
215 }
216
217 void Model_Data::sendAttributeUpdated(ModelAPI_Attribute* theAttr)
218 {
219   theAttr->setInitialized();
220   if (theAttr->isArgument()) {
221     static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
222     ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
223     if (mySendAttributeUpdated && myObject) {
224       myObject->attributeChanged(theAttr->id());
225     }
226   }
227 }
228
229 void Model_Data::blockSendAttributeUpdated(const bool theBlock)
230 {
231   mySendAttributeUpdated = !theBlock;
232 }
233
234 void Model_Data::erase()
235 {
236   if (!myLab.IsNull())
237     myLab.ForgetAllAttributes();
238 }
239
240 void Model_Data::execState(const ModelAPI_ExecState theState)
241 {
242   if (theState != ModelAPI_StateNothing)
243     TDataStd_Integer::Set(myLab, (int)theState);
244 }
245
246 ModelAPI_ExecState Model_Data::execState()
247 {
248   Handle(TDataStd_Integer) aStateAttr;
249   if (myLab.FindAttribute(TDataStd_Integer::GetID(), aStateAttr)) {
250     return ModelAPI_ExecState(aStateAttr->Get());
251   }
252   return ModelAPI_StateMustBeUpdated; // default value
253 }
254
255 void Model_Data::setError(const std::string& theError, bool theSend)
256 {
257   execState(ModelAPI_StateExecFailed);
258   if (theSend) {
259     Events_Error::send(theError);
260   }
261   TDataStd_AsciiString::Set(myLab, theError.c_str());
262 }
263
264 std::string Model_Data::error() const
265 {
266   Handle(TDataStd_AsciiString) anErrorAttr;
267   if (myLab.FindAttribute(TDataStd_AsciiString::GetID(), anErrorAttr)) {
268     return std::string(anErrorAttr->Get().ToCString());
269   }
270   return std::string();
271 }
272
273 int Model_Data::featureId() const
274 {
275   return myLab.Father().Tag(); // tag of the feature label
276 }
277
278 void Model_Data::eraseBackReferences()
279 {
280   myRefsToMe.clear();
281   std::shared_ptr<ModelAPI_Result> aRes = 
282     std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
283   if (aRes)
284     aRes->setIsConcealed(false);
285 }
286
287 void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID)
288 {
289   AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
290   if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
291     return;
292
293   myRefsToMe.erase(anAttribute);
294 }
295
296 void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID, 
297    const bool theApplyConcealment)
298 {
299   // do not add the same attribute twice
300   AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
301   if (myRefsToMe.find(anAttribute) != myRefsToMe.end())
302     return;
303
304   myRefsToMe.insert(theFeature->data()->attribute(theAttrID));
305   if (theApplyConcealment && 
306       ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) {
307     std::shared_ptr<ModelAPI_Result> aRes = 
308       std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
309     if (aRes) {
310       aRes->setIsConcealed(true);
311     }
312   }
313 }
314
315 void Model_Data::referencesToObjects(
316   std::list<std::pair<std::string, std::list<ObjectPtr> > >& theRefs)
317 {
318   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = myAttrs.begin();
319   std::list<ObjectPtr> aReferenced; // not inside of cycle to avoid excess memory menagement
320   for(; anAttr != myAttrs.end(); anAttr++) {
321     std::string aType = anAttr->second->attributeType();
322     if (aType == ModelAPI_AttributeReference::typeId()) { // reference to object
323       std::shared_ptr<ModelAPI_AttributeReference> aRef = std::dynamic_pointer_cast<
324           ModelAPI_AttributeReference>(anAttr->second);
325       aReferenced.push_back(aRef->value());
326     } else if (aType == ModelAPI_AttributeRefAttr::typeId()) { // reference to attribute or object
327       std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
328           ModelAPI_AttributeRefAttr>(anAttr->second);
329       aReferenced.push_back(aRef->isObject() ? aRef->object() : aRef->attr()->owner());
330     } else if (aType == ModelAPI_AttributeRefList::typeId()) { // list of references
331       aReferenced = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttr->second)->list();
332     } else if (aType == ModelAPI_AttributeSelection::typeId()) { // selection attribute
333       std::shared_ptr<ModelAPI_AttributeSelection> aRef = std::dynamic_pointer_cast<
334           ModelAPI_AttributeSelection>(anAttr->second);
335       aReferenced.push_back(aRef->context());
336     } else if (aType == ModelAPI_AttributeSelectionList::typeId()) { // list of selection attributes
337       std::shared_ptr<ModelAPI_AttributeSelectionList> aRef = std::dynamic_pointer_cast<
338           ModelAPI_AttributeSelectionList>(anAttr->second);
339       for(int a = aRef->size() - 1; a >= 0; a--) {
340         aReferenced.push_back(aRef->value(a)->context());
341       }
342     } else
343       continue; // nothing to do, not reference
344
345     if (!aReferenced.empty()) {
346       theRefs.push_back(std::pair<std::string, std::list<ObjectPtr> >(anAttr->first, aReferenced));
347       aReferenced.clear();
348     }
349   }
350 }
351
352 /// makes copy of all attributes on the given label and all sub-labels
353 static void copyAttrs(TDF_Label theSource, TDF_Label theDestination) {
354   TDF_AttributeIterator anAttrIter(theSource);
355   for(; anAttrIter.More(); anAttrIter.Next()) {
356     Handle(TDF_Attribute) aTargetAttr;
357     if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
358       // create a new attribute if not yet exists in the destination
359             aTargetAttr = anAttrIter.Value()->NewEmpty();
360       theDestination.AddAttribute(aTargetAttr);
361     }
362     Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(); // no relocation, empty map
363     anAttrIter.Value()->Paste(aTargetAttr, aRelocTable);
364   }
365   // copy the sub-labels content
366   TDF_ChildIterator aSubLabsIter(theSource);
367   for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
368     copyAttrs(aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()));
369   }
370 }
371
372 void Model_Data::copyTo(std::shared_ptr<ModelAPI_Data> theTarget)
373 {
374   TDF_Label aTargetRoot = std::dynamic_pointer_cast<Model_Data>(theTarget)->label();
375   copyAttrs(myLab, aTargetRoot);
376   // make initialized the initialized attributes
377   std::map<std::string, std::shared_ptr<ModelAPI_Attribute> >::iterator aMyIter = myAttrs.begin();
378   for(; aMyIter != myAttrs.end(); aMyIter++) {
379     if (aMyIter->second->isInitialized()) {
380       theTarget->attribute(aMyIter->first)->setInitialized();
381     }
382   }
383 }
384
385 bool Model_Data::isInHistory()
386 {
387   return myFlags->Value(kFlagInHistory) == Standard_True;
388 }
389
390 void Model_Data::setIsInHistory(const bool theFlag)
391 {
392   return myFlags->SetValue(kFlagInHistory, theFlag);
393 }
394
395 bool Model_Data::isDisplayed()
396 {
397   return myFlags->Value(kFlagDisplayed) == Standard_True;
398 }
399
400 void Model_Data::setDisplayed(const bool theDisplay)
401 {
402   if (theDisplay != isDisplayed()) {
403     myFlags->SetValue(kFlagDisplayed, theDisplay);
404     static Events_Loop* aLoop = Events_Loop::loop();
405     static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
406     static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
407     aECreator->sendUpdated(myObject, EVENT_DISP);
408   }
409 }