1 // File: Model_Update.cxx
2 // Created: 25 Jun 2014
3 // Author: Mikhail PONIKAROV
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>
17 Model_Update MY_INSTANCE; /// the only one instance initialized on load of the library
19 Model_Update::Model_Update()
21 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
22 Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
25 void Model_Update::processEvent(const Events_Message* theMessage)
27 if (isExecuted) return; // nothing to do: it is executed now
29 const ModelAPI_ObjectUpdatedMessage* aMsg =
30 dynamic_cast<const ModelAPI_ObjectUpdatedMessage*>(theMessage);
31 myInitial = aMsg->objects();
32 // collect all documents involved into the update
33 set<boost::shared_ptr<ModelAPI_Document> > aDocs;
34 set<boost::shared_ptr<ModelAPI_Object> >::iterator aFIter = myInitial.begin();
35 for(; aFIter != myInitial.end(); aFIter++) {
36 aDocs.insert((*aFIter)->document());
38 // iterate all features of features-documents to update them (including hidden)
39 set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
40 for(; aDIter != aDocs.end(); aDIter++) {
41 int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
42 for(int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
43 FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>
44 ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
46 updateFeature(aFeature);
51 static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
52 Events_Loop::loop()->flush(EVENT_DISP);
56 bool Model_Update::updateFeature(FeaturePtr theFeature)
58 // check it is already processed
59 if (myUpdated.find(theFeature) != myUpdated.end())
60 return myUpdated[theFeature];
61 // check all features this feature depended on (recursive call of updateFeature)
62 bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
63 if (theFeature) { // only real feature contains references to other objects
65 list<boost::shared_ptr<ModelAPI_Attribute> > aRefs =
66 theFeature->data()->attributes(ModelAPI_AttributeReference::type());
67 list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
68 for(; aRefsIter != aRefs.end(); aRefsIter++) {
69 boost::shared_ptr<ModelAPI_Object> aSub =
70 boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRefsIter)->value();
71 if (updateObject(aSub)) {
72 aMustbeUpdated = true;
75 // lists of references
76 aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
77 for(aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
78 list<ObjectPtr> aListRef =
79 boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)->list();
80 list<ObjectPtr>::iterator aListIter = aListRef.begin();
81 for(; aListIter != aListRef.end(); aListIter++) {
82 boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
83 if (updateObject(aSub)) {
84 aMustbeUpdated = true;
88 // execute feature if it must be updated
90 theFeature->execute();
91 // redisplay all results
92 static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
93 const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
94 std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
95 for(; aRIter != aResults.cend(); aRIter++) {
96 boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
97 myUpdated[aRes] = true;
98 ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
100 } else { // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
101 const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
102 std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
103 for(; aRIter != aResults.cend(); aRIter++) {
104 if (myInitial.find(*aRIter) != myInitial.end()) {
105 aMustbeUpdated = true;
111 myUpdated[theFeature] = aMustbeUpdated;
112 return aMustbeUpdated;
115 bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
119 FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
120 if (aFeature) { // for feature just call update Feature
121 return updateFeature(aFeature);
123 // check general object, possible just a result
124 if (myUpdated.find(theObject) != myUpdated.end())
125 return myUpdated[theObject]; // already processed
126 // check the feature of this object must be executed
127 ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
129 FeaturePtr aResFeature = aResult->document()->feature(aResult);
131 return updateFeature(aResFeature);
134 if (myInitial.find(theObject) != myInitial.end())
136 return false; // nothing is known