]> SALOME platform Git repositories - modules/shaper.git/blob - src/Model/Model_Update.cpp
Salome HOME
Sources formated according to the codeing standards
[modules/shaper.git] / src / Model / Model_Update.cpp
1 // File:        Model_Update.cxx
2 // Created:     25 Jun 2014
3 // Author:      Mikhail PONIKAROV
4
5 #include <Model_Update.h>
6 #include <ModelAPI_Feature.h>
7 #include <ModelAPI_Data.h>
8 #include <ModelAPI_Document.h>
9 #include <ModelAPI_Events.h>
10 #include <ModelAPI_AttributeReference.h>
11 #include <ModelAPI_AttributeRefList.h>
12 #include <ModelAPI_Result.h>
13 #include <Events_Loop.h>
14 #include <Events_LongOp.h>
15
16 using namespace std;
17
18 Model_Update MY_INSTANCE;  /// the only one instance initialized on load of the library
19
20 Model_Update::Model_Update()
21 {
22   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
23   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
24 }
25
26 void Model_Update::processEvent(const Events_Message* theMessage)
27 {
28   if (isExecuted)
29     return;  // nothing to do: it is executed now
30   //Events_LongOp::start(this);
31   isExecuted = true;
32   const ModelAPI_ObjectUpdatedMessage* aMsg =
33       dynamic_cast<const ModelAPI_ObjectUpdatedMessage*>(theMessage);
34   myInitial = aMsg->objects();
35   // collect all documents involved into the update
36   set<boost::shared_ptr<ModelAPI_Document> > aDocs;
37   set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter = myInitial.begin();
38   for (; aFIter != myInitial.end(); aFIter++) {
39     aDocs.insert((*aFIter)->document());
40   }
41   // iterate all features of features-documents to update them (including hidden)
42   set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
43   for (; aDIter != aDocs.end(); aDIter++) {
44     int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
45     for (int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
46       FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(
47           (*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
48       if (aFeature)
49         updateFeature(aFeature);
50     }
51   }
52   myUpdated.clear();
53   // flush
54   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
55   Events_Loop::loop()->flush(EVENT_DISP);
56   //Events_LongOp::end(this);
57   isExecuted = false;
58 }
59
60 bool Model_Update::updateFeature(FeaturePtr theFeature)
61 {
62   // check it is already processed
63   if (myUpdated.find(theFeature) != myUpdated.end())
64     return myUpdated[theFeature];
65   // check all features this feature depended on (recursive call of updateFeature)
66   bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
67   if (theFeature) {  // only real feature contains references to other objects
68     // references
69     list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = theFeature->data()->attributes(
70         ModelAPI_AttributeReference::type());
71     list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
72     for (; aRefsIter != aRefs.end(); aRefsIter++) {
73       boost::shared_ptr<ModelAPI_Object> aSub = boost::dynamic_pointer_cast<
74           ModelAPI_AttributeReference>(*aRefsIter)->value();
75       if (updateObject(aSub)) {
76         aMustbeUpdated = true;
77       }
78     }
79     // lists of references
80     aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
81     for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
82       list<ObjectPtr> aListRef = boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)
83           ->list();
84       list<ObjectPtr>::iterator aListIter = aListRef.begin();
85       for (; aListIter != aListRef.end(); aListIter++) {
86         boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
87         if (updateObject(aSub)) {
88           aMustbeUpdated = true;
89         }
90       }
91     }
92     // execute feature if it must be updated
93     if (aMustbeUpdated) {
94       theFeature->execute();
95       // redisplay all results
96       static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
97       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
98       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
99       for (; aRIter != aResults.cend(); aRIter++) {
100         boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
101         myUpdated[aRes] = true;
102         ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
103       }
104       // to redisplay "presentable" feature (for ex. distance constraint)
105       ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
106     } else {  // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
107       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
108       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
109       for (; aRIter != aResults.cend(); aRIter++) {
110         if (myInitial.find(*aRIter) != myInitial.end()) {
111           aMustbeUpdated = true;
112           break;
113         }
114       }
115     }
116   }
117   myUpdated[theFeature] = aMustbeUpdated;
118   return aMustbeUpdated;
119 }
120
121 bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
122 {
123   if (!theObject)
124     return false;
125   FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
126   if (aFeature) {  // for feature just call update Feature
127     return updateFeature(aFeature);
128   }
129   // check general object, possible just a result
130   if (myUpdated.find(theObject) != myUpdated.end())
131     return myUpdated[theObject];  // already processed
132   // check the feature of this object must be executed
133   ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
134   if (aResult) {
135     FeaturePtr aResFeature = aResult->document()->feature(aResult);
136     if (aResFeature) {
137       return updateFeature(aResFeature);
138     }
139   }
140   if (myInitial.find(theObject) != myInitial.end())
141     return true;
142   return false;  // nothing is known
143 }