Salome HOME
Documentation update
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
index 923b2cd48ee10399871c5022f32fb9f88727f008..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>
 
 #include <TDataStd_Name.hxx>
 #include <TopAbs_ShapeEnum.hxx>
 #include <TopoDS_Iterator.hxx>
-#include <TNaming_Iterator.hxx>
 #include <BRep_Builder.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Iterator.hxx>
+
 using namespace std;
 //#define DEB_NAMING 1
 #ifdef DEB_NAMING
@@ -146,7 +150,8 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
         aBuilder.Generated(theContext->shape()->impl<TopoDS_Shape>());
         std::shared_ptr<Model_Document> aMyDoc = 
           std::dynamic_pointer_cast<Model_Document>(owner()->document());
-        std::string aName = theContext->data()->name();
+        std::string aName = contextName(theContext);
+        // for selection in different document, add the document name
         aMyDoc->addNamingName(aSelLab, aName);
         TDataStd_Name::Set(aSelLab, aName.c_str());
       } else {  // for sketch the naming is needed in DS
@@ -173,10 +178,6 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
   //myIsInitialized = true;
 
   owner()->data()->sendAttributeUpdated(this);
-
-  std::string aSelName = namingName();
-  if(!aSelName.empty())
-    TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name
 }
 
 std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
@@ -415,7 +416,7 @@ bool Model_AttributeSelection::update()
       aBuilder.Generated(aContext->shape()->impl<TopoDS_Shape>());
       std::shared_ptr<Model_Document> aMyDoc = 
         std::dynamic_pointer_cast<Model_Document>(owner()->document());
-      std::string aName = aContext->data()->name();
+      std::string aName = contextName(aContext);
       aMyDoc->addNamingName(aSelLab, aName);
       TDataStd_Name::Set(aSelLab, aName.c_str());
     }
@@ -507,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);
@@ -603,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)
 {
@@ -624,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); 
   }
 }
 
@@ -653,6 +699,18 @@ static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape,
   TNaming_Builder aBuilder(aLab);
   aBuilder.Generated(theShape);
   std::stringstream aName;
+  // add the part name if the selected object is located in other part
+  if (theDoc != theContextFeature->document()) {
+    if (theContextFeature->document() == ModelAPI_Session::get()->moduleDocument()) {
+      aName<<theContextFeature->document()->kind()<<"/";
+    } else {
+      ResultPtr aDocRes = ModelAPI_Tools::findPartResult(
+        ModelAPI_Session::get()->moduleDocument(), theContextFeature->document());
+      if (aDocRes.get()) {
+        aName<<aDocRes->data()->name()<<"/";
+      }
+    }
+  }
   aName<<theContextFeature->name();
   if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction
     aName<<"/";
@@ -700,8 +758,9 @@ void Model_AttributeSelection::selectConstruction(
     // saving of context is enough: result construction contains exactly the needed shape
     TNaming_Builder aBuilder(selectionLabel());
     aBuilder.Generated(aSubShape);
-    aMyDoc->addNamingName(selectionLabel(), theContext->data()->name());
-    TDataStd_Name::Set(selectionLabel(), theContext->data()->name().c_str());
+    std::string aName = contextName(theContext);
+    aMyDoc->addNamingName(selectionLabel(), aName);
+    TDataStd_Name::Set(selectionLabel(), aName.c_str());
     return;
   }
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(owner()->data());
@@ -860,17 +919,13 @@ std::string Model_AttributeSelection::namingName(const std::string& theDefaultNa
   std::string aName("");
   if(!this->isInitialized())
     return !theDefaultName.empty() ? theDefaultName : aName;
-  Handle(TDataStd_Name) anAtt;
-  if(selectionLabel().FindAttribute(TDataStd_Name::GetID(), anAtt)) {
-    aName = TCollection_AsciiString(anAtt->Get()).ToCString();
-    return aName;
-  }
 
   std::shared_ptr<GeomAPI_Shape> aSubSh = value();
   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
@@ -903,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);
   }
 }
@@ -976,3 +1053,20 @@ void Model_AttributeSelection::setId(int theID)
   setValue(aContext, aSelection);
 }
 
+std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) const
+{
+  std::string aResult;
+  if (owner()->document() != theContext->document()) {
+    if (theContext->document() == ModelAPI_Session::get()->moduleDocument()) {
+      aResult = theContext->document()->kind() + "/";
+    } else {
+      ResultPtr aDocRes = ModelAPI_Tools::findPartResult(
+        ModelAPI_Session::get()->moduleDocument(), theContext->document());
+      if (aDocRes.get()) {
+        aResult = aDocRes->data()->name() + "/";
+      }
+    }
+  }
+  aResult += theContext->data()->name();
+  return aResult;
+}