Salome HOME
setDisplayed has to be called in order to synchronize internal state of the object
[modules/shaper.git] / src / Model / Model_Document.cpp
index 4bf71d0346a33bc709a7d05e9d0c4cc0b3a6860f..0d35b4533b38d851d93a1bd76261738d40d90746 100644 (file)
@@ -171,7 +171,8 @@ bool Model_Document::load(const char* theFileName, DocumentPtr theThis)
     setCurrentFeature(currentFeature(false), false);
     aSession->setCheckTransactions(true);
     aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
-    aSession->setActiveDocument(anApp->getDocument(myID), true);
+    // this is done in Part result "activate", so no needed here. Causes not-blue active part.
+    //aSession->setActiveDocument(anApp->getDocument(myID), true); 
   }
   return !isError;
 }
@@ -324,7 +325,6 @@ bool Model_Document::finishOperation()
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
   aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
   // this must be here just after everything is finished but before real transaction stop
   // to avoid messages about modifications outside of the transaction
@@ -450,9 +450,9 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron
   }
   // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
   if (theSynchronize) {
+    myObjs->synchronizeFeatures(true, true, isRoot());
     // update the current features status
     setCurrentFeature(currentFeature(false), false);
-    myObjs->synchronizeFeatures(true, true, isRoot());
   }
 }
 
@@ -490,10 +490,10 @@ void Model_Document::redo()
   for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->redo();
 
-  // update the current features status
-  setCurrentFeature(currentFeature(false), false);
   // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
   myObjs->synchronizeFeatures(true, true, isRoot());
+  // update the current features status
+  setCurrentFeature(currentFeature(false), false);
 }
 
 std::list<std::string> Model_Document::undoList() const
@@ -527,7 +527,7 @@ void Model_Document::operationId(const std::string& theId)
   myTransactions.rbegin()->myId = theId;
 }
 
-FeaturePtr Model_Document::addFeature(std::string theID)
+FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurrent)
 {
   std::shared_ptr<Model_Session> aSession = 
     std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
@@ -545,9 +545,10 @@ FeaturePtr Model_Document::addFeature(std::string theID)
     aDocToAdd = this;
   }
   if (aFeature) {
-    aDocToAdd->myObjs->addFeature(aFeature, currentFeature(false));
+    aDocToAdd->myObjs->addFeature(aFeature, aDocToAdd->currentFeature(false));
     if (!aFeature->isAction()) {  // do not add action to the data model
-      setCurrentFeature(aFeature, false); // after all this feature stays in the document, so make it current
+      if (theMakeCurrent)  // after all this feature stays in the document, so make it current
+        aDocToAdd->setCurrentFeature(aFeature, false);
     } else { // feature must be executed
        // no creation event => updater not working, problem with remove part
       aFeature->execute();
@@ -567,11 +568,8 @@ void Model_Document::removeFeature(FeaturePtr theFeature)
 {
   // if this feature is current, make the current the previous feature
   if (theFeature == currentFeature(false)) {
-    int aCurrentIndex = index(theFeature);
-    if (aCurrentIndex != -1) {
-      setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(
-        object(ModelAPI_Feature::group(), aCurrentIndex - 1)), false);
-    }
+    FeaturePtr aPrev = myObjs->nextFeature(theFeature, true);
+    setCurrentFeature(aPrev, false);
   }
   myObjs->removeFeature(theFeature);
 }
@@ -654,17 +652,36 @@ void Model_Document::setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurr
   const bool theVisible)
 {
   TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE);
+  CompositeFeaturePtr aMain; // main feature that may nest the new current
   if (theCurrent.get()) {
-    if (theVisible) { // make features below which are not in history also enabled: sketch subs
-      FeaturePtr aNext = myObjs->nextFeature(theCurrent);
-      for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) {
-        if (aNext->isInHistory()) {
-          break; // next in history is not needed
-        } else { // next not in history is good for making current
-          theCurrent = aNext;
+    aMain = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theCurrent);
+    if (!aMain.get()) {
+      // if feature nests into compisite feature, make the composite feature as current
+      const std::set<AttributePtr>& aRefsToMe = theCurrent->data()->refsToMe();
+      std::set<AttributePtr>::const_iterator aRefToMe = aRefsToMe.begin();
+      for(; aRefToMe != aRefsToMe.end(); aRefToMe++) {
+        CompositeFeaturePtr aComposite = 
+          std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*aRefToMe)->owner());
+        if (aComposite.get() && aComposite->isSub(theCurrent)) {
+          aMain = aComposite;
+          break;
         }
       }
     }
+  }
+
+  if (theVisible) { // make features below which are not in history also enabled: sketch subs
+    FeaturePtr aNext = 
+      theCurrent.get() ? myObjs->nextFeature(theCurrent) : myObjs->firstFeature();
+    for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) {
+      if (aNext->isInHistory()) {
+        break; // next in history is not needed
+      } else { // next not in history is good for making current
+        theCurrent = aNext;
+      }
+    }
+  }
+  if (theCurrent.get()) {
     std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
     if (!aData.get()) return; // unknown case
     TDF_Label aFeatureLabel = aData->label().Father();
@@ -679,19 +696,29 @@ void Model_Document::setCurrentFeature(std::shared_ptr<ModelAPI_Feature> theCurr
     aRefLab.ForgetAttribute(TDF_Reference::GetID());
   }
   // make all features after this feature disabled in reversed order (to remove results without deps)
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+
   bool aPassed = false; // flag that the current object is already passed in cycle
   FeaturePtr anIter = myObjs->lastFeature();
   for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) {
     // check this before passed become enabled: the current feature is enabled!
     if (anIter == theCurrent) aPassed = true;
 
-    if (anIter->setDisabled(!aPassed)) {
+    bool aDisabledFlag = !aPassed;
+    if (aMain.get() && aMain->isSub(anIter)) // sub-elements of not-disabled feature are not disabled
+      aDisabledFlag = false;
+    if (anIter->getKind() == "Parameter") // parameters are always out of the history
+      aDisabledFlag = false;
+    if (anIter->setDisabled(aDisabledFlag)) {
       // state of feature is changed => so feature become updated
-      static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+      static Events_ID anUpdateEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED);
       ModelAPI_EventCreator::get()->sendUpdated(anIter, anUpdateEvent);
-
+      // flush is in the end of this method
+      ModelAPI_EventCreator::get()->sendUpdated(anIter, aRedispEvent /*, false*/);
     }
   }
+  aLoop->flush(aRedispEvent);
 }
 
 TDF_Label Model_Document::generalLabel() const