]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Make the invalid selection makes the referenced object in state "invalid arguments"
authormpv <mpv@opencascade.com>
Tue, 25 Aug 2015 07:23:53 +0000 (10:23 +0300)
committermpv <mpv@opencascade.com>
Tue, 25 Aug 2015 07:23:53 +0000 (10:23 +0300)
src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_ResultConstruction.cpp
src/Model/Model_Update.cpp
src/ModelAPI/ModelAPI_AttributeSelection.h

index f76a684602255745e58703aa983a288aee70b138..c9c567081aebac34fb88e782100d39ca66af53d2 100644 (file)
@@ -86,7 +86,9 @@ void FeaturesPlugin_Extrusion::execute()
     for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) {
       std::shared_ptr<GeomAPI_Shape> aBaseShape;
       if (aFacesNum == -1) {
-        aFacesList.push_back(aFaceShape);
+        if (!aFaceShape->isNull()) {
+          aFacesList.push_back(aFaceShape);
+        }
         break;
       } else {
         aFaceShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
index 07b91316184cd4f77305d81f429a1812770f9e26..4fcb26fae33236e9d6918f2e7f192b8a4d6a20a3 100644 (file)
@@ -68,6 +68,8 @@ Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29");
 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");
+// selection is invalid after recomputation
+Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d");
 
 // on this label is stored:
 // TNaming_NamedShape - selected shape
@@ -101,6 +103,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
   TDF_Label aSelLab = selectionLabel();
   aSelLab.ForgetAttribute(kSIMPLE_REF_ID);
   aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID);
+  aSelLab.ForgetAttribute(kINVALID_SELECTION);
 
   bool isDegeneratedEdge = false;
   // do not use the degenerated edge as a shape, a null context and shape is used in the case
@@ -157,8 +160,11 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
   }
 
   std::shared_ptr<GeomAPI_Shape> aResult;
+  TDF_Label aSelLab = selectionLabel();
+  if (aSelLab.IsAttribute(kINVALID_SELECTION))
+    return 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();
       if (!aContext.get()) 
@@ -201,6 +207,11 @@ std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
   return aResult;
 }
 
+bool Model_AttributeSelection::isInvalid()
+{
+  return selectionLabel().IsAttribute(kINVALID_SELECTION) == Standard_True;
+}
+
 bool Model_AttributeSelection::isInitialized()
 {
   if (ModelAPI_AttributeSelection::isInitialized()) { // additional checkings if it is initialized
@@ -311,21 +322,33 @@ int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge)
   return 0; // unknown
 }
 
+/// Sets the invalid flag if flag is false, or removes it if "true"
+/// Returns theFlag
+static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) {
+  if (theFlag) {
+    theLab.ForgetAttribute(kINVALID_SELECTION);
+  } else {
+    TDataStd_UAttribute::Set(theLab, kINVALID_SELECTION);
+  }
+  return theFlag;
+}
+
 bool Model_AttributeSelection::update()
 {
-  ResultPtr aContext = context();
-  if (!aContext.get()) return false;
   TDF_Label aSelLab = selectionLabel();
+  ResultPtr aContext = context();
+  if (!aContext.get()) 
+    return setInvalidIfFalse(aSelLab, false);
   if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
-    return aContext->shape() && !aContext->shape()->isNull();
+    return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull());
   }
   if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape
-    return aContext->shape() && !aContext->shape()->isNull();
+    return setInvalidIfFalse(aSelLab, 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);
+    return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true));
   }
 
   if (aContext->groupName() == ModelAPI_ResultBody::group()) {
@@ -333,7 +356,7 @@ bool Model_AttributeSelection::update()
     TNaming_Selector aSelector(aSelLab);
     bool aResult = aSelector.Solve(scope()) == Standard_True;
     owner()->data()->sendAttributeUpdated(this);
-    return aResult;
+    return setInvalidIfFalse(aSelLab, aResult);
   } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
     // construction: identification by the results indexes, recompute faces and
     // take the face that more close by the indexes
@@ -348,7 +371,7 @@ bool Model_AttributeSelection::update()
       // getting a type of selected shape
       Handle(TDataStd_Integer) aTypeAttr;
       if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) {
-        return false;
+        return setInvalidIfFalse(aSelLab, false);
       }
       TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get());
       // selected indexes will be needed in each "if"
@@ -360,13 +383,13 @@ bool Model_AttributeSelection::update()
       CompositeFeaturePtr aComposite = 
         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
       if (!aComposite.get() || aComposite->numberOfSubs() == 0) {
-        return false;
+        return setInvalidIfFalse(aSelLab, false);
       }
 
       if (aShapeType == TopAbs_FACE) { // compound is for the whole sketch selection
         // If this is a wire with plane defined thin it is a sketch-like object
         if (!aConstructionContext->facesNum()) // no faces, update can not work correctly
-          return false;
+          return setInvalidIfFalse(aSelLab, false);
         // if there is no edges indexes, any face can be used: take the first
         std::shared_ptr<GeomAPI_Shape> aNewSelected;
         if (aNoIndexes) {
@@ -446,7 +469,10 @@ bool Model_AttributeSelection::update()
         if (aNewSelected) { // store this new selection
           selectConstruction(aContext, aNewSelected);
           owner()->data()->sendAttributeUpdated(this);
-          return true;
+          return setInvalidIfFalse(aSelLab, true);
+        } else { // if the selection is not found, put the empty shape: it's better to have disappeared shape, than the old, the lost one
+          TNaming_Builder anEmptyBuilder(selectionLabel());
+          return setInvalidIfFalse(aSelLab, false);
         }
       } else if (aShapeType == TopAbs_EDGE) {
         // just reselect the edge by the id
@@ -464,7 +490,7 @@ bool Model_AttributeSelection::update()
               if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
                 selectConstruction(aContext, aRes->shape());
                 owner()->data()->sendAttributeUpdated(this);
-                return true;
+                return setInvalidIfFalse(aSelLab, true);
               }
             }
           }
@@ -493,7 +519,7 @@ bool Model_AttributeSelection::update()
                   if (aRes->shape()->isVertex() && aVertexNum == 0) { // found!
                     selectConstruction(aContext, aRes->shape());
                     owner()->data()->sendAttributeUpdated(this);
-                    return true;
+                    return setInvalidIfFalse(aSelLab, true);
                   } else if (aRes->shape()->isEdge() && aVertexNum > 0) {
                     const TopoDS_Shape& anEdge = aRes->shape()->impl<TopoDS_Shape>();
                     int aVIndex = 1;
@@ -503,7 +529,7 @@ bool Model_AttributeSelection::update()
                         aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
                         selectConstruction(aContext, aVertex);
                         owner()->data()->sendAttributeUpdated(this);
-                        return true;
+                        return setInvalidIfFalse(aSelLab, true);
                       }
                       aVIndex++;
                     }
@@ -516,10 +542,10 @@ bool Model_AttributeSelection::update()
     } else { // simple construction element: the selected is that needed
       selectConstruction(aContext, aContext->shape());
       owner()->data()->sendAttributeUpdated(this);
-      return true;
+      return setInvalidIfFalse(aSelLab, true);
     }
   }
-  return false; // unknown case
+  return setInvalidIfFalse(aSelLab, false); // unknown case
 }
 
 
index 1340a34d00e1fe1d226c47bf17afc58c2436e4d8..fba911b921e872892cd15c6dc209f646dab239b1 100644 (file)
@@ -64,6 +64,10 @@ public:
   /// Returns true if attribute was  initialized by some value
   MODEL_EXPORT virtual bool isInitialized();
 
+  /// Returns true if recomute of selection become impossible
+  MODEL_EXPORT virtual bool isInvalid();
+
+
 protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel);
index 41e1a9b166a43771fac03ba55775eae2b17f9c5c..11cf883cd60908c0915e0fbf373948d640b0cf24 100644 (file)
@@ -68,7 +68,7 @@ int Model_ResultConstruction::facesNum()
       std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFIter = aFaces.begin();
       for(; aFIter != aFaces.end(); aFIter++) {
         std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(*aFIter));
-        if (aFace.get())
+        if (aFace.get() && !aFace->isNull())
           myFaces.push_back(aFace);
       }
     }
index a1a840381d6cf3e96d2b7207204cee61b72a182e..25dc969b772a40a6ca7fe186bca68c13a24f688f 100644 (file)
@@ -110,7 +110,7 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
             if (anUpdated->isPreviewNeeded() || myIsFinish) {
               ModelAPI_ExecState aState = anUpdated->data()->execState();
               static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
-              if (aFactory->validate(anUpdated)) {
+              if (aFactory->validate(anUpdated) && aState != ModelAPI_StateInvalidArgument) {
                 #ifdef DEB_UPDATE
                   std::cout<<"Execute immideately "<<anUpdated->name()<<std::endl;
                 #endif
@@ -450,19 +450,25 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
   list<AttributePtr>::iterator aRefsIter = aRefs.begin();
   for (; aRefsIter != aRefs.end(); aRefsIter++) {
     std::shared_ptr<ModelAPI_AttributeSelection> aSel =
-      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
-    ObjectPtr aContext = aSel->context();
-    // update argument only if the referenced object is changed
-    if (aContext.get() && !aContext->isDisabled() && 
-      (myJustUpdated.find(aContext) != myJustUpdated.end() ||
-      aContext->data()->updateID() > theFeature->data()->updateID())) {
-        if (aState == ModelAPI_StateDone)
-          aState = ModelAPI_StateMustBeUpdated;
-        if (!aSel->update()) { // this must be done on execution since it may be long operation
-          if (!aFactory->isNotObligatory(theFeature->getKind(), theFeature->data()->id(aSel)) &&
-            aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
-            aState = ModelAPI_StateInvalidArgument;
-        }
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*aRefsIter);
+    bool isObligatory = !aFactory->isNotObligatory(
+            theFeature->getKind(), theFeature->data()->id(aSel)) &&
+            aFactory->isCase(theFeature, theFeature->data()->id(aSel));
+    if (aSel->isInvalid()) {
+      aState = ModelAPI_StateInvalidArgument;
+    } else {
+      ObjectPtr aContext = aSel->context();
+      // update argument only if the referenced object is changed
+      if (aContext.get() && !aContext->isDisabled() && 
+        (myJustUpdated.find(aContext) != myJustUpdated.end() ||
+        aContext->data()->updateID() > theFeature->data()->updateID())) {
+          if (aState == ModelAPI_StateDone)
+            aState = ModelAPI_StateMustBeUpdated;
+          if (!aSel->update()) { // this must be done on execution since it may be long operation
+            if (isObligatory)
+              aState = ModelAPI_StateInvalidArgument;
+          }
+      }
     }
   }
   aRefs = theFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
@@ -473,19 +479,24 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
       if (aSelAttr) {
-        ObjectPtr aContext = aSelAttr->context();
-        // update argument onlt if the referenced object is changed
-        if (aContext.get() && !aContext->isDisabled() &&
-            (myJustUpdated.find(aContext) != myJustUpdated.end() ||
-             aContext->data()->updateID() > theFeature->data()->updateID())) {
-            if (aState == ModelAPI_StateDone)
-              aState = ModelAPI_StateMustBeUpdated;
-            if (!aSelAttr->update()) {
-              if (!aFactory->isNotObligatory(
+        bool isObligatory = !aFactory->isNotObligatory(
                 theFeature->getKind(), theFeature->data()->id(aSel)) &&
-                aFactory->isCase(theFeature, theFeature->data()->id(aSel)))
-                aState = ModelAPI_StateInvalidArgument;
-            }
+                aFactory->isCase(theFeature, theFeature->data()->id(aSel));
+        if (aSelAttr->isInvalid()) {
+          aState = ModelAPI_StateInvalidArgument;
+        } else {
+          ObjectPtr aContext = aSelAttr->context();
+          // update argument onlt if the referenced object is changed
+          if (aContext.get() && !aContext->isDisabled() &&
+              (myJustUpdated.find(aContext) != myJustUpdated.end() ||
+               aContext->data()->updateID() > theFeature->data()->updateID())) {
+              if (aState == ModelAPI_StateDone)
+                aState = ModelAPI_StateMustBeUpdated;
+              if (!aSelAttr->update()) {
+                if (isObligatory)
+                  aState = ModelAPI_StateInvalidArgument;
+              }
+          }
         }
       }
     }
index eccafa5f69dcc3dd7cd55fdbfb94216fb630ac31..fccb6b018f8196d1b89644390f35d3861a8a6449 100644 (file)
@@ -57,6 +57,9 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   /// Selects sub-shape by the textual Name
   virtual void selectSubShape(const std::string& theType, const std::string& theSubShapeName) = 0;
 
+  /// Returns true if recomute of selection become impossible
+  virtual bool isInvalid() = 0;
+
   /// To virtually destroy the fields of successors
   MODELAPI_EXPORT virtual ~ModelAPI_AttributeSelection();