Salome HOME
Issue #637: Create visualization properties at Workshop constructor
[modules/shaper.git] / src / Model / Model_Update.cpp
index e710c5a876693c6ce87fee66ec6aa5769621e1a2..d3cc6c9c166782b76a9148ccd46bfdf7cbab6740 100644 (file)
@@ -58,6 +58,7 @@ Model_Update::Model_Update()
                                    Config_Prop::Boolean, "false");
   myIsAutomatic =
     Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
+  myIsParamUpdated = false;
 }
 
 void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessage)
@@ -93,6 +94,9 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
       if (!std::dynamic_pointer_cast<ModelAPI_Result>(*anObjIter).get()) {
         isOnlyResults = false;
       }
+      if ((*anObjIter)->groupName() == ModelAPI_ResultParameter::group()) {
+        myIsParamUpdated = true;
+      }
       // created objects are always must be up to date (python box feature)
       // and updated not in internal uptation chain
       if (theMessage->eventID() == kCreatedEvent) {
@@ -136,6 +140,7 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     }
     myJustCreated.clear();
     myJustUpdated.clear();
+    myIsParamUpdated = false;
   }
 }
 
@@ -191,6 +196,8 @@ void Model_Update::updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc)
   if (!anObjs) return;
   FeaturePtr aFeatureIter = anObjs->firstFeature();
   for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) {
+    if (!aFeatureIter->data()->isValid()) // this may be on close of the document
+      continue;
     if (aFeatureIter && alreadyProcessed.find(aFeatureIter) == alreadyProcessed.end()) {
       // update selection and parameters attributes first, before sub-features analysis (sketch plane)
       updateArguments(aFeatureIter);
@@ -214,7 +221,7 @@ void Model_Update::updateInDoc(std::shared_ptr<ModelAPI_Document> theDoc)
       for (; aRIter != aResults.cend(); aRIter++) {
         ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
         if (aPart.get()) {
-          if (!aPart->isDisabled() && aPart->isActivated()) {
+          if (!aPart->isDisabled() && aPart->partDoc().get()) {
             updateInDoc(aPart->partDoc());
           }
         }
@@ -273,6 +280,9 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
     AttributeDoublePtr aDouble =
       std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
     if (aDouble.get() && !aDouble->text().empty()) {
+      if (myIsParamUpdated) {
+        ModelAPI_AttributeEvalMessage::send(aDouble, this);
+      }
       if (aDouble->expressionInvalid()) {
         aState = ModelAPI_StateInvalidArgument;
       }
@@ -287,6 +297,9 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       AttributePointPtr aPointAttribute =
         std::dynamic_pointer_cast<GeomDataAPI_Point>(*anIter);
       if (aPointAttribute.get()) {
+        if (myIsParamUpdated) {
+          ModelAPI_AttributeEvalMessage::send(aPointAttribute, this);
+        }
         if ((!aPointAttribute->textX().empty() && aPointAttribute->expressionInvalid(0)) ||
             (!aPointAttribute->textY().empty() && aPointAttribute->expressionInvalid(1)) ||
             (!aPointAttribute->textZ().empty() && aPointAttribute->expressionInvalid(2)))
@@ -303,6 +316,9 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       AttributePoint2DPtr aPoint2DAttribute =
         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIter);
       if (aPoint2DAttribute.get()) {
+        if (myIsParamUpdated) {
+          ModelAPI_AttributeEvalMessage::send(aPoint2DAttribute, this);
+        }
         if ((!aPoint2DAttribute->textX().empty() && aPoint2DAttribute->expressionInvalid(0)) ||
             (!aPoint2DAttribute->textY().empty() && aPoint2DAttribute->expressionInvalid(1)))
           aState = ModelAPI_StateInvalidArgument;
@@ -366,8 +382,7 @@ void Model_Update::updateFeature(FeaturePtr theFeature)
   // check all features this feature depended on (recursive call of updateFeature)
   static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
 
-  if (theFeature->isDisabled() ||  // nothing to do with disabled feature
-      theFeature->data()->execState() == ModelAPI_StateInvalidArgument)
+  if (theFeature->data()->execState() == ModelAPI_StateInvalidArgument)
     return;
   bool aJustUpdated = false;
 
@@ -387,8 +402,13 @@ void Model_Update::updateFeature(FeaturePtr theFeature)
     for(; aRef != aRefs.end(); aRef++) {
       std::list<ObjectPtr>::iterator aRefObj = aRef->second.begin();
       for(; aRefObj != aRef->second.end(); aRefObj++) {
-        if (myJustCreated.find(*aRefObj) != myJustCreated.end() ||
-            myJustUpdated.find(*aRefObj) != myJustUpdated.end()) {
+        // if reference is null, it may mean that this reference is to other document
+        // the does not supported by RefList: peremeters may be recomputed
+        if (!aRefObj->get() && theFeature->firstResult().get() && 
+            theFeature->firstResult()->groupName() == ModelAPI_ResultParameter::group()) {
+          aJustUpdated = true;
+        } else if (myJustCreated.find(*aRefObj) != myJustCreated.end() ||
+            myJustUpdated.find(*aRefObj) != myJustUpdated.end()) { 
           aJustUpdated = true;
         }
         aState = stateByReference(*aRefObj, aState);
@@ -409,37 +429,45 @@ void Model_Update::updateFeature(FeaturePtr theFeature)
     //std::cout<<"Update feature "<<theFeature->getKind()<<" must be updated = "<<aMustbeUpdated<<std::endl;
     // execute feature if it must be updated
     if (aJustUpdated) {
-      if (theFeature->isPreviewNeeded()) {
-        if (std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
-            !theFeature->isPersistentResult()) {
-          if (aFactory->validate(theFeature)) {
-            if (myIsAutomatic || !theFeature->isPersistentResult() /* execute quick, not persistent results */
-                || (isUpdated(theFeature) && 
-                     (theFeature == theFeature->document()->currentFeature(false) || 
-                      theFeature->document()->currentFeature(false)->isMacro()))) // currently edited
-            {
-              if (aState == ModelAPI_StateDone || aState == ModelAPI_StateMustBeUpdated) {
-                executeFeature(theFeature);
-              }
-            } else { // must be updatet, but not updated yet
-              theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
-              const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
-              std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-              for (; aRIter != aResults.cend(); aRIter++) {
-                std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
-                aRes->data()->execState(ModelAPI_StateMustBeUpdated);
+      if (theFeature->isDisabled()) {  // do not execute the disabled feature
+        // the disabled features must be updated after enabling anyway if their arguments were changed
+        if (theFeature->data()->execState() == ModelAPI_StateDone &&
+          aState == ModelAPI_StateMustBeUpdated)
+          theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
+      } else {
+        if (theFeature->isPreviewNeeded()) {
+          if (std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
+              !theFeature->isPersistentResult()) {
+            if (aFactory->validate(theFeature)) {
+              FeaturePtr aCurrent = theFeature->document()->currentFeature(false);
+              if (myIsAutomatic || !theFeature->isPersistentResult() /* execute quick, not persistent results */
+                  || (isUpdated(theFeature) && 
+                       (theFeature == aCurrent || 
+                        (aCurrent.get() && aCurrent->isMacro())))) // currently edited
+              {
+                if (aState == ModelAPI_StateDone || aState == ModelAPI_StateMustBeUpdated) {
+                  executeFeature(theFeature);
+                }
+              } else { // must be updatet, but not updated yet
+                theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
+                const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+                std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+                for (; aRIter != aResults.cend(); aRIter++) {
+                  std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+                  aRes->data()->execState(ModelAPI_StateMustBeUpdated);
+                }
               }
+            } else {
+              theFeature->eraseResults();
+              redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
             }
-          } else {
-            theFeature->eraseResults();
-            redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
+          } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway
+            redisplayWithResults(theFeature, ModelAPI_StateNothing);
           }
-        } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway
-          redisplayWithResults(theFeature, ModelAPI_StateNothing);
+        } else { // preview is not needed => make state Done
+          if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated)
+            theFeature->data()->execState(ModelAPI_StateDone);
         }
-      } else { // preview is not needed => make state Done
-        if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated)
-          theFeature->data()->execState(ModelAPI_StateDone);
       }
     }
   }