Salome HOME
Make the movement, placement and rotation 3D features may be applied to the Part...
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
index 6ff60d02e363dde45d66a62466e116f72c006518..864975b2e420376c6e57cdaf72d97e2de995c274 100644 (file)
@@ -12,6 +12,7 @@
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultPart.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <GeomAPI_Shape.h>
 #include <GeomAPI_PlanarEdges.h>
@@ -61,7 +62,10 @@ using namespace std;
 static const int kSTART_VERTEX_DELTA = 1000000;
 // identifier that there is simple reference: selection equals to context
 Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29");
+// simple reference in the construction
 Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28");
+// reference to Part sub-object
+Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27");
 
 // on this label is stored:
 // TNaming_NamedShape - selected shape
@@ -69,7 +73,6 @@ Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28")
 // TDataStd_IntPackedMap - indexes of edges in composite element (for construction)
 // TDataStd_Integer - type of the selected shape (for construction)
 // TDF_Reference - from ReferenceAttribute, the context
-#define DDDD 1
 void Model_AttributeSelection::setValue(const ResultPtr& theContext,
   const std::shared_ptr<GeomAPI_Shape>& theSubShape)
 {
@@ -103,7 +106,10 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
   }
   if (theContext->groupName() == ModelAPI_ResultBody::group()) {
     // do not select the whole shape for body:it is already must be in the data framework
-    if (theContext->shape().get() && theContext->shape()->isEqual(theSubShape)) {
+    // equal and null selected objects mean the same: object is equal to context,
+    // TODO: synchronize with GUI later that it must be null always
+    if (theContext->shape().get() && 
+        (theContext->shape()->isEqual(theSubShape) || !theSubShape.get())) {
       aSelLab.ForgetAllAttributes(true);
       TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
     } else {
@@ -117,6 +123,10 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
     } else {
       selectConstruction(theContext, theSubShape);
     }
+  } else if (theContext->groupName() == ModelAPI_ResultPart::group()) {
+    aSelLab.ForgetAllAttributes(true);
+    TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
+    selectPart(theContext, theSubShape);
   }
   //the attribute initialized state should be changed by sendAttributeUpdated only
   //myIsInitialized = true;
@@ -126,13 +136,6 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
   std::string aSelName = namingName();
   if(!aSelName.empty())
     TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name
-#ifdef DDDD
-  //####
-  //selectSubShape("FACE",  "Extrusion_1/LateralFace_3");
-  //selectSubShape("FACE",  "Extrusion_1/TopFace");
-  //selectSubShape("EDGE", "Extrusion_1/TopFace|Extrusion_1/LateralFace_1");
-  //selectSubShape("EDGE", "Sketch_1/Edge_6");
-#endif
 }
 
 std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
@@ -149,6 +152,22 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
     if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value
         return aResult; // empty result
     }
+    if (aSelLab.IsAttribute(kPART_REF_ID)) {
+      /* TODO: implement used text here
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(context());
+      if (!aPart.get() || !aPart->isActivated())
+        return std::shared_ptr<GeomAPI_Shape>(); // postponed naming needed
+      Handle(TDataStd_Integer) anIndex;
+      if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) {
+        return aPart->selectionValue(anIndex->Get());
+      }
+      Handle(TDataStd_Name) aName;
+      if (!selectionLabel().FindAttribute(TDataStd_Name::GetID(), aName)) {
+        return std::shared_ptr<GeomAPI_Shape>(); // something is wrong
+      }
+      return aPart->shapeInPart(TCollection_AsciiString(aName).ToCString());
+      */
+    }
 
     Handle(TNaming_NamedShape) aSelection;
     if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
@@ -166,6 +185,35 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
   return aResult;
 }
 
+bool Model_AttributeSelection::isInitialized()
+{
+  if (ModelAPI_AttributeSelection::isInitialized()) { // additional checkings if it is initialized
+    std::shared_ptr<GeomAPI_Shape> aResult;
+    if (myRef.isInitialized()) {
+      TDF_Label aSelLab = selectionLabel();
+      if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
+        ResultPtr aContext = context();
+        return aContext.get();
+      }
+      if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value
+          return true;
+      }
+
+      Handle(TNaming_NamedShape) aSelection;
+      if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
+        return !aSelection->Get().IsNull();
+      } else { // for simple construction element: just shape of this construction element
+        ResultConstructionPtr aConstr = 
+          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(context());
+        if (aConstr.get()) {
+          return aConstr->shape().get();
+        }
+      }
+    }
+  }
+  return false;
+}
+
 Model_AttributeSelection::Model_AttributeSelection(TDF_Label& theLabel)
   : myRef(theLabel)
 {
@@ -224,6 +272,11 @@ bool Model_AttributeSelection::update()
     return aContext->shape() && !aContext->shape()->isNull();
   }
 
+  if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object
+    std::shared_ptr<GeomAPI_Shape> aNoSelection;
+    return selectPart(aContext, aNoSelection, true);
+  }
+
   if (aContext->groupName() == ModelAPI_ResultBody::group()) {
     // body: just a named shape, use selection mechanism from OCCT
     TNaming_Selector aSelector(aSelLab);
@@ -419,9 +472,11 @@ void Model_AttributeSelection::selectBody(
   }
   TopoDS_Shape aNewShape = theSubShape ? theSubShape->impl<TopoDS_Shape>() : aContext;
   /// 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); 
   }
@@ -572,6 +627,43 @@ void Model_AttributeSelection::selectConstruction(
   registerSubShape(selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", aRefs);
 }
 
+bool Model_AttributeSelection::selectPart(
+  const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
+  const bool theUpdate)
+{
+  ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theContext);
+  if (!aPart.get() || !aPart->isActivated())
+    return true; // postponed naming
+  if (theUpdate) {
+    Handle(TDataStd_Integer) anIndex;
+    if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { // by internal selection
+      if (anIndex->Get() > 0) {
+        // update the selection by index
+        return aPart->updateInPart(anIndex->Get());
+      } else {
+        return true; // nothing to do, referencing just by name
+      }
+    }
+    return true; // nothing to do, referencing just by name
+  }
+  // store the shape (in case part is not loaded it should be usefull
+  TopoDS_Shape aShape;
+  std::string aName = theContext->data()->name();
+  if (theSubShape->isNull()) {// the whole part shape is selected
+    aShape = theContext->shape()->impl<TopoDS_Shape>();
+  } else {
+    aShape = theSubShape->impl<TopoDS_Shape>();
+    int anIndex;
+    aName += "/" + aPart->nameInPart(theSubShape, anIndex);
+    TDataStd_Integer::Set(selectionLabel(), anIndex);
+  }
+  TNaming_Builder aBuilder(selectionLabel());
+  aBuilder.Select(aShape, aShape);
+  // identify by name in the part
+  TDataStd_Name::Set(selectionLabel(), aName.c_str());
+  return !aName.empty();
+}
+
 TDF_Label Model_AttributeSelection::selectionLabel()
 {
   return myRef.myRef->Label().FindChild(1);