Salome HOME
Updater mechanism update
[modules/shaper.git] / src / Model / Model_Update.cpp
index 25ecbbeb5113919893e9da76eadec0bb41a177d0..a50f19c6a2ba91767aee44ca7ad51e17b4b03349 100644 (file)
@@ -9,6 +9,7 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeRefList.h>
+#include <ModelAPI_Result.h>
 #include <Events_Loop.h>
 
 using namespace std;
@@ -17,6 +18,7 @@ Model_Update MY_INSTANCE; /// the only one instance initialized on load of the l
 
 Model_Update::Model_Update()
 {
+  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
 }
 
@@ -31,15 +33,15 @@ void Model_Update::processEvent(const Events_Message* theMessage)
   for(; aFIter != myInitial.end(); aFIter++) {
     aDocs.insert((*aFIter)->document());
   }
-  // iterate all features of features-documents to update them
+  // iterate all features of features-documents to update them (including hidden)
   set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
   for(; aDIter != aDocs.end(); aDIter++) {
-    int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group());
+    int aNbFeatures = (*aDIter)->size(ModelAPI_Feature::group(), true);
     for(int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
-      boost::shared_ptr<ModelAPI_Object> aFeature = boost::dynamic_pointer_cast<ModelAPI_Object>
-        ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex));
+      FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>
+        ((*aDIter)->object(ModelAPI_Feature::group(), aFIndex, true));
       if (aFeature)
-        updateObject(aFeature);
+        updateFeature(aFeature);
     }
   }
   myUpdated.clear();
@@ -48,46 +50,85 @@ void Model_Update::processEvent(const Events_Message* theMessage)
   Events_Loop::loop()->flush(EVENT_DISP);
 }
 
-bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
+bool Model_Update::updateFeature(FeaturePtr theFeature)
 {
   // check it is already processed
-  if (myUpdated.find(theObject) != myUpdated.end())
-    return myUpdated[theObject];
+  if (myUpdated.find(theFeature) != myUpdated.end())
+    return myUpdated[theFeature];
   // check all features this feature depended on (recursive call of updateFeature)
-  bool anExecute = myInitial.find(theObject) != myInitial.end();
-  bool aMustbeUpdated = myInitial.find(theObject) != myInitial.end();
-  FeaturePtr aRealFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
-  if (aRealFeature) { // only real feature contains references to other objects
+  bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
+  if (theFeature) { // only real feature contains references to other objects
     // references
     list<boost::shared_ptr<ModelAPI_Attribute> > aRefs = 
-      theObject->data()->attributes(ModelAPI_AttributeReference::type());
+      theFeature->data()->attributes(ModelAPI_AttributeReference::type());
     list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
     for(; aRefsIter != aRefs.end(); aRefsIter++) {
       boost::shared_ptr<ModelAPI_Object> aSub =
         boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRefsIter)->value();
-      if (aSub && aSub != theObject && updateObject(aSub))
+      if (updateObject(aSub)) {
         aMustbeUpdated = true;
+      }
     }
     // lists of references
-    aRefs = theObject->data()->attributes(ModelAPI_AttributeRefList::type());
+    aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
     for(aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
       list<ObjectPtr> aListRef = 
         boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)->list();
       list<ObjectPtr>::iterator aListIter = aListRef.begin();
       for(; aListIter != aListRef.end(); aListIter++) {
         boost::shared_ptr<ModelAPI_Object> aSub = *aListIter;
-        if (aSub && updateObject(aSub))
+        if (updateObject(aSub)) {
           aMustbeUpdated = true;
+        }
       }
     }
     // execute feature if it must be updated
-    anExecute = aMustbeUpdated || anExecute;
-    if (anExecute) {
-      aRealFeature->execute();
+    if (aMustbeUpdated) {
+      theFeature->execute();
+      // redisplay all results
       static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-      ModelAPI_EventCreator::get()->sendUpdated(theObject, EVENT_DISP);
+      const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+      std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      for(; aRIter != aResults.cend(); aRIter++) {
+        boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+        myUpdated[aRes] = true;
+        ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
+      }
+    } else { // returns also true is results were updated: for sketch that refers to sub-features but results of sub-features were changed
+      const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+      std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      for(; aRIter != aResults.cend(); aRIter++) {
+        if (myInitial.find(*aRIter) != myInitial.end()) {
+          aMustbeUpdated = true;
+          break;
+        }
+      }
+    }
+  }
+  myUpdated[theFeature] = aMustbeUpdated;
+  return aMustbeUpdated;
+}
+
+bool Model_Update::updateObject(boost::shared_ptr<ModelAPI_Object> theObject)
+{
+  if (!theObject) 
+    return false;
+  FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+  if (aFeature) { // for feature just call update Feature
+    return updateFeature(aFeature);
+  }
+  // check general object, possible just a result
+  if (myUpdated.find(theObject) != myUpdated.end())
+    return myUpdated[theObject]; // already processed
+  // check the feature of this object must be executed
+  ResultPtr aResult = boost::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+  if (aResult) {
+    FeaturePtr aResFeature = aResult->document()->feature(aResult);
+    if (aResFeature) {
+      return updateFeature(aResFeature);
     }
   }
-  myUpdated[theObject] = anExecute;
-  return anExecute;
+  if (myInitial.find(theObject) != myInitial.end())
+    return true;
+  return false; // nothing is known
 }