Salome HOME
Documentation update
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
index ac66944c56b40d3a4f15ece7dcf2ef0bfc89587f..f3851036973ef034a351227afe2cbec72ec01719 100644 (file)
@@ -10,6 +10,7 @@
 #include "Model_Data.h"
 #include "Model_Document.h"
 #include "Model_SelectionNaming.h"
+#include <Model_Objects.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
@@ -17,6 +18,7 @@
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Tools.h>
 #include <GeomAPI_Shape.h>
+#include <ModelAPI_Session.h>
 #include <GeomAPI_PlanarEdges.h>
 #include <Events_InfoMessage.h>
 
@@ -54,9 +56,9 @@
 #include <TDataStd_Name.hxx>
 #include <TopAbs_ShapeEnum.hxx>
 #include <TopoDS_Iterator.hxx>
-#include <TNaming_Iterator.hxx>
 #include <BRep_Builder.hxx>
-#include <ModelAPI_Session.h>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Iterator.hxx>
 
 using namespace std;
 //#define DEB_NAMING 1
@@ -506,16 +508,10 @@ bool Model_AttributeSelection::update()
               }
             }
           }
-          aNewSelected = Model_SelectionNaming::findAppropriateFace(aContext, allCurves);
+          aNewSelected = Model_SelectionNaming::findAppropriateFace(
+            aContext, allCurves, aShapeType == TopAbs_WIRE);
         }
         if (aNewSelected) { // store this new selection
-          if (aShapeType == TopAbs_WIRE) { // just get a wire from face to have wire
-            TopExp_Explorer aWireExp(aNewSelected->impl<TopoDS_Shape>(), TopAbs_WIRE);
-            if (aWireExp.More()) {
-              aNewSelected.reset(new GeomAPI_Shape);
-              aNewSelected->setImpl<TopoDS_Shape>(new TopoDS_Shape(aWireExp.Current()));
-            }
-          }
           selectConstruction(aContext, aNewSelected);
           setInvalidIfFalse(aSelLab, true);
           owner()->data()->sendAttributeUpdated(this);
@@ -602,7 +598,6 @@ bool Model_AttributeSelection::update()
   return setInvalidIfFalse(aSelLab, false); // unknown case
 }
 
-
 void Model_AttributeSelection::selectBody(
   const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape)
 {
@@ -623,13 +618,65 @@ void Model_AttributeSelection::selectBody(
       return;
     }
   }
-  TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl<TopoDS_Shape>() : aContext;
+
+  // with "recover" feature the selected context may be not up to date (issue 1710)
+  Handle(TNaming_NamedShape) aResult;
+  TDF_Label aSelLab = selectionLabel();
+  TopoDS_Shape aNewContext = aContext;
+  bool isUpdated = true;
+  while(!aNewContext.IsNull() && isUpdated) { // searching for the very last shape that was produced from this one
+    isUpdated = false;
+    if (!TNaming_Tool::HasLabel(aSelLab, aNewContext)) // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists
+      break;
+    for(TNaming_SameShapeIterator anIter(aNewContext, aSelLab); anIter.More(); anIter.Next()) {
+      TDF_Label aNSLab = anIter.Label();
+      if (!scope().Contains(aNSLab))
+        continue;
+      Handle(TNaming_NamedShape) aNS;
+      if (aNSLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+        for(TNaming_Iterator aShapesIter(aNS); aShapesIter.More(); aShapesIter.Next()) {
+          if (aShapesIter.Evolution() == TNaming_SELECTED)
+            continue; // don't use the selection evolution
+          if (!aShapesIter.OldShape().IsNull() && aShapesIter.OldShape().IsSame(aNewContext)) {
+             // found the original shape
+            aNewContext = aShapesIter.NewShape(); // go to the newer shape
+            isUpdated = true;
+            break;
+          }
+        }
+      }
+    }
+  }
+  if (aNewContext.IsNull()) { // a context is already deleted
+    setInvalidIfFalse(aSelLab, false);
+    Events_InfoMessage("Model_AttributeSelection", "Failed to select shape already deleted").send();
+    return;
+  }
+
+  TopoDS_Shape aNewSub = theSubShape ? theSubShape->impl<TopoDS_Shape>() : aContext;
+  if (!aNewSub.IsEqual(aContext)) { // searching for subshape in the new context
+    bool isFound = false;
+    TopExp_Explorer anExp(aNewContext, aNewSub.ShapeType());
+    for(; anExp.More(); anExp.Next()) {
+      if (anExp.Current().IsEqual(aNewSub)) {
+        isFound = true;
+        break;
+      }
+    }
+    if (!isFound) { // sub-shape is not found in the up-to-date instance of the context shape
+      setInvalidIfFalse(aSelLab, false);
+      Events_InfoMessage("Model_AttributeSelection", "Failed to select sub-shape already modified").send();
+      return;
+    }
+  }
+
+
   /// fix for issue 411: result modified shapes must not participate in this selection mechanism
   FeaturePtr aFeatureOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
   if (aFeatureOwner.get())
     aFeatureOwner->eraseResults();
   if (!aContext.IsNull()) {
-    aSel.Select(aNewShape, aContext); 
+    aSel.Select(aNewSub, aNewContext); 
   }
 }
 
@@ -877,7 +924,8 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa
   ResultPtr aCont = context();
 
   Model_SelectionNaming aSelNaming(selectionLabel());
-  return aSelNaming.namingName(aCont, aSubSh, theDefaultName);
+  return aSelNaming.namingName(
+    aCont, aSubSh, theDefaultName, owner()->document() != aCont->document());
 }
 
 // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT
@@ -910,6 +958,28 @@ void Model_AttributeSelection::selectSubShape(
   std::shared_ptr<GeomAPI_Shape> aShapeToBeSelected;
   ResultPtr aCont;
   if (aSelNaming.selectSubShape(theType, theSubShapeName, aDoc, aShapeToBeSelected, aCont)) {
+    // try to find the last context to find the up to dat shape
+    if (aCont->shape().get() && !aCont->shape()->isNull() &&
+      aCont->groupName() == ModelAPI_ResultBody::group() && aDoc == owner()->document()) {
+      const TopoDS_Shape aConShape = aCont->shape()->impl<TopoDS_Shape>();
+      if (!aConShape.IsNull()) {
+        Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aConShape, selectionLabel());
+        if (!aNS.IsNull()) {
+          aNS = TNaming_Tool::CurrentNamedShape(aNS);
+          if (!aNS.IsNull()) {
+            TDF_Label aLab = aNS->Label();
+            while(aLab.Depth() != 7 && aLab.Depth() > 5)
+              aLab = aLab.Father();
+            ObjectPtr anObj = aDoc->objects()->object(aLab);
+            if (anObj.get()) {
+              ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(anObj);
+              if (aRes)
+                aCont = aRes;
+            }
+          }
+        }
+      }
+    }
     setValue(aCont, aShapeToBeSelected);
   }
 }